Dinfio Playground

Let's play with Dinfio!




Tetris Game

This is a Classic Tetris game example.

#!/usr/bin/env dinfio
 
' Tetris in Dinfio
 
import math, gui
import fileio, json
 
var canvas_spec = {
    x: 20,
    y: 20,
    width: 240,
    height: 480,
    colour: colour.hex("fafafa")
}
 
var scaling = 16
var t_width = canvas_spec.width \ scaling
var t_height = canvas_spec.height \ scaling
var speed = 700
var round_radius = 4
var score = 0
var score_lines = 0
var level = 1
 
var arena = array2d(t_height + 3, t_width + 2)
 
var rand = 0
var wiped_lines = []
var wiped_index = 0
 
var player = {
    pos: {x: 0, y: 0},
    matrix: nothing,
    colour: nothing
}
 
var pieces = [
    [
        [1, 1],
        [1, 1]
    ],
    [
        [0, 2, 0, 0],
        [0, 2, 0, 0],
        [0, 2, 0, 0],
        [0, 2, 0, 0]
    ],
    [
        [0, 0, 0],
        [3, 3, 0],
        [0, 3, 3]
    ],
    [
        [0, 0, 0],
        [0, 4, 4],
        [4, 4, 0]
    ],
    [
        [5, 0, 0],
        [5, 0, 0],
        [5, 5, 0]
    ],
    [
        [0, 0, 6],
        [0, 0, 6],
        [0, 6, 6]
    ],
    [
        [0, 0, 0],
        [7, 7, 7],
        [0, 7, 0]
    ]
]
var piece_colours = [
    canvas_spec.colour,
    colour.hex("ff0d72"),
    colour.hex("0dc2ff"),
    colour.hex("33ab5f"),
    colour.hex("33ab5f"),
    colour.hex("ff8e0d"),
    colour.hex("ff8e0d"),
    colour.hex("2877af")
]
 
start
    create_gui()
    init_arena()
    update()
stop
 
function create_gui()
    global window = gui_window("Tetris in Dinfio", canvas_spec.x * 2 + canvas_spec.width + 128, canvas_spec.y * 2 + canvas_spec.height, false)
 
    global canvas = gui_panel(window, canvas_spec.x, canvas_spec.y, canvas_spec.width, canvas_spec.height, true)
    global label_score = gui_label("Score: " & score, window, canvas_spec.x * 2 + canvas_spec.width, 20, 140, 32)
    global label_score_lines = gui_label("Lines: " & score_lines, window, canvas_spec.x * 2 + canvas_spec.width, 46, 140, 32)
    global label_level = gui_label("Level: " & level, window, canvas_spec.x * 2 + canvas_spec.width, 72, 140, 32)
    global label_info = gui_label("Press Space to\npause/resume", window, canvas_spec.x * 2 + canvas_spec.width, 436, 140, 64)
 
    global button_load = gui_button("Load", window, canvas_spec.x * 2 + canvas_spec.width, 120, 100, 24)
    global button_save = gui_button("Save", window, canvas_spec.x * 2 + canvas_spec.width, 150, 100, 24)
 
    global timer = gui_timer(speed, update())
    global timer_wipe = gui_timer(11, wipe_lines())
 
    label_score.setfontsize(16)
    label_score.setfontbold(true)
    label_score_lines.setfontsize(16)
    label_score_lines.setfontbold(true)
    label_level.setfontsize(16)
    label_level.setfontbold(true)
 
    window.setbackgroundcolour(colour.white)
    canvas.setbackgroundcolour(colour.white)
 
    button_save.addevent(event.click, save_game())
    button_load.addevent(event.click, load_game())
 
    timer.run()
 
    if !dinfio.is_windows
        window.addevent(event.keydown, keypress())
        canvas.addevent(event.keydown, keypress())
    else
        window.addevent(event.keyup, keypress())
        canvas.addevent(event.keydown, keypress())
    endif
 
    window.show()
    canvas.setfocus()
stop
 
function draw_matrix(matrix, x, y)
    canvas.draw_setbrush(player.colour)
 
    for i, 0, size(matrix) - 1
        for j, 0, size(matrix[i]) - 1
            if matrix[i][j] != 0
                canvas.draw_roundedrectangle((x + j) * t_width, (y + i) * t_width, t_width, t_width, round_radius)
            endif
        endfor
    endfor
stop
 
function draw_arena()
    canvas.draw_clear()
    canvas.draw_setpen(colour.white, 1)
 
    for i, 1, size(arena) - 3
        for j, 1, size(arena[i]) - 2
            canvas.draw_setbrush(piece_colours[arena[i][j]])
            canvas.draw_roundedrectangle((j - 1) * t_width, (i - 1) * t_width, t_width, t_width, round_radius)
        endfor
    endfor
stop
 
function rotate_matrix(matrix, dir)
    var new_matrix = array2d(size(matrix), size(matrix))
 
    if dir == 1
        for i, 0, size(matrix) - 1
            for j, 0, size(matrix[i]) - 1
                new_matrix[j][size(matrix) - i - 1] = matrix[i][j]
            endfor
        endfor
    else
        for i, 0, size(matrix) - 1
            for j, 0, size(matrix[i]) - 1
                new_matrix[size(matrix) - j - 1][i] = matrix[i][j]
            endfor
        endfor
    endif
 
    return new_matrix
stop
 
function collides(p, a)
    yield false
 
    for i, 0, size(p.matrix) - 1
        for j, 0, size(p.matrix[0]) - 1
            ii = p.pos.y + i + 1
            jj = p.pos.x + j + 1
 
            if ii >= 0 && jj >= 0
                if jj < size(a[ii])
                    if p.matrix[i][j] != 0 && a[ii][jj] != 0
                        return true
                    endif
                endif
            endif
        endfor
    endfor
stop
 
function merge_arena(matrix, x, y)
    for i, 0, size(matrix) - 1
        for j, 0, size(matrix[0]) - 1
            ii = y + i + 1
            jj = x + j + 1
 
            if ii >= 0 && jj >= 0
                if ii < size(arena) && jj < size(arena[ii])
                    if arena[ii][jj] == 0
                        arena[ii][jj] = matrix[i][j]
                        score += 1
                    endif
                endif
            endif
        endfor
    endfor
 
    label_score.settext("Score: " & score)
    label_score_lines.settext("Lines: " & score_lines)
    label_level.settext("Level: " & level)
stop
 
function clear_blocks()
    wiped_index = 1
    total_lines = 0
 
    clear(wiped_lines)
 
    for i, 1, size(arena) - 3
        clear = true
 
        for j, 1, size(arena[i]) - 2
            if arena[i][j] == 0; clear = false; endif
        endfor
 
        if clear
            for j, i, 1, -1
                for k, 0, size(arena[j]) - 1
                    arena[j][k] = arena[j - 1][k]
                endfor
            endfor
 
            top_row = array(size(arena[0]))
 
            for j, 0, size(top_row) - 1
                top_row[j] = 0
            endfor
 
            top_row[0] = 1
            top_row[size(top_row) - 1] = 1
 
            arena[1] = top_row
 
            total_lines += 1
            score_lines += 1
 
            append(wiped_lines, i)
        endif
    endfor
 
    if total_lines == 1
        score += 40 * level
    elseif total_lines == 2
        score += 100 * level
    elseif total_lines == 3
        score += 300 * level
    elseif total_lines == 4
        score += 1200 * level
    endif
 
    if total_lines > 0
        level = score_lines \ 10 + 1
        speed = 700 - 60 * (level - 1)
        if speed <= 100; speed = 100; endif
 
        label_score.settext("Score: " & score)
        label_score_lines.settext("Lines: " & score_lines)
        label_level.settext("Level: " & level)
 
        timer.setinterval(speed)
 
        timer_wipe.run()
        timer.pause()
        wipe_lines()
    endif
stop
 
function is_game_over()
    for j, 1, size(arena[1]) - 2
        if arena[2][j] != 0
            timer.pause()
 
            messagebox("Game over!", "Tetris in Dinfio")
 
            init_arena()
            update()
            timer.run()
        endif
    endfor
stop
 
function init_arena()
    for i, 0, size(arena) - 1
        for j, 0, size(arena[i]) - 1
            arena[i][j] = 0
        endfor
 
        arena[i][0] = 1
        arena[i][size(arena[i]) - 1] = 1
    endfor
 
    for j, 0, size(arena[0]) - 1
        arena[0][j] = 1
        arena[size(arena) - 1][j] = 1
        arena[size(arena) - 2][j] = 1
    endfor
 
    score = 0
    score_lines = 0
    level = 1
    speed = 700 - 60 * (level - 1)
 
    label_score.settext("Score: " & score)
    label_score_lines.settext("Lines: " & score_lines)
    label_level.settext("Level: " & level)
    timer.setinterval(speed)
 
    rand = randomint(0, size(pieces) - 1)
 
    player.matrix = pieces[rand]
    player.colour = piece_colours[rand + 1]
 
    canvas.draw_setpen(colour.white, 1)
stop
 
function update()
    if !timer.isrunning(); return; endif
    player.pos.y += 1
 
    if collides(player, arena)
        merge_arena(player.matrix, player.pos.x, player.pos.y - 1)
        clear_blocks()
        is_game_over()
 
        rand = randomint(0, size(pieces) - 1)
 
        player.pos.x = 0
        player.pos.y = 1
        player.matrix = pieces[rand]
        player.colour = piece_colours[rand + 1]
    endif
 
    if !timer.isrunning(); return; endif
 
    draw_arena()
    draw_matrix(player.matrix, player.pos.x, player.pos.y)
 
    canvas.refresh()
stop
 
function pre_update()
    draw_arena()
    draw_matrix(player.matrix, player.pos.x, player.pos.y)
 
    canvas.refresh()
stop
 
function wipe_lines()
    if wiped_index > size(arena[0]) - 2
        wiped_index = 1
 
        timer_wipe.pause()
        timer.run()
        update()
 
        label_score.settext("Score: " & score)
        label_score_lines.settext("Lines: " & score_lines)
        label_level.settext("Level: " & level)
 
        return
    endif
 
    for i, 0, size(wiped_lines) - 1
        canvas.draw_setbrush(canvas_spec.colour)
        canvas.draw_roundedrectangle((wiped_index - 1) * t_width, (wiped_lines[i] - 1) * t_width, t_width, t_width, round_radius)
    endfor
 
    canvas.refresh()
    wiped_index += 1
stop
 
function load_game()
    canvas.setfocus()
    json_data = filecontent(getfoldername(getcurrentfile()) & "/tetris.json")
 
    if json_data != ""
        json_data = json.decode(json_data)
 
        score = json_data.score
        score_lines = json_data.score_lines
        level = json_data.level
        arena = json_data.arena
        player = json_data.player
        rand = json_data.current_piece
 
        player.colour = piece_colours[rand + 1]
        speed = 700 - 60 * (level - 1)
 
        pre_update()
        timer.pause()
 
        label_score.settext("Score: " & score)
        label_score_lines.settext("Lines: " & score_lines)
        label_level.settext("Level: " & level)
 
        messagebox("Saved state is successfully loaded.", "Tetris in Dinfio")
 
        timer.setinterval(speed)
        timer.run()
 
        window.settitle("Tetris in Dinfio")
    else
        messagebox("No saved state.", "Tetris in Dinfio")
    endif
stop
 
function save_game()
    canvas.setfocus()
 
    json_data = filecontent(getfoldername(getcurrentfile()) & "/tetris.json")
    saved_score = 0
 
    if json_data != ""
        json_data = json.decode(json_data)
        saved_score = json_data.score
    endif
 
    if saved_score > score
        i = messagebox("Your saved score is higher than the current score. Are you sure you want to continue?", "Tetris in Dinfio", message.question + message.yesno)
        if i == message.no; return; endif
    endif
 
    json_data = json.encode({
        score: score,
        score_lines: score_lines,
        level: level,
        arena: arena,
        player: player,
        current_piece: rand
    })
 
    fileput(getfoldername(getcurrentfile()) & "/tetris.json", json_data)
    messagebox("Game state is successfully saved.", "Tetris in Dinfio")
stop
 
function keypress()
    key = getkeycode()
 
    if key == keycode.space
        if timer.isrunning()
            timer.pause()
            window.settitle("Tetris in Dinfio - Paused")
        else
            timer.run()
            window.settitle("Tetris in Dinfio")
        endif
    endif
 
    if timer.isrunning()
        if key == keycode.up
            player.matrix = rotate_matrix(player.matrix, 1)
            if collides(player, arena); player.matrix = rotate_matrix(player.matrix, -1); endif
 
            update()
        elseif key == keycode.down
            player.pos.y += 1
            if collides(player, arena); player.pos.y -= 1; endif
 
            update()
        elseif key == keycode.left
            player.pos.x -= 1
            if collides(player, arena); player.pos.x += 1; endif
 
            pre_update()
        elseif key == keycode.right
            player.pos.x += 1
            if collides(player, arena); player.pos.x -= 1; endif
 
            pre_update()
        endif
    endif
stop

Screenshot:

Requirement: Dinfio 3.1.06 or later.


← Back to the Dinfio Playground / Download this program