diff --git a/examples/game-tetris.ds b/examples/game-tetris.ds index 3935d97..4d32ffe 100644 --- a/examples/game-tetris.ds +++ b/examples/game-tetris.ds @@ -81,36 +81,77 @@ on keydown(ev) -> py = if gameOver then py else (if paused then py else (if ev.k on keydown(ev) -> paused = if ev.key == "p" then (if paused then 0 else 1) else paused -- ================================================================ --- LAYER 4: DERIVED SIGNALS — Gravity, lock, line clear +-- LAYER 4: DERIVED SIGNALS — Collision, gravity, lock, line clear -- ================================================================ +-- Collision detection signal: is the row BELOW the piece occupied? +-- For a standard piece (3 wide, 2 tall like T), the bottom cells are at py+1. +-- We check if grid row py+2 has any blocks at the piece's x positions. +-- `blocked` = 1 means can't move down, 0 means safe to drop. +-- +-- Since grid rows are individual signals, we branch on py to check the right row. +-- Also blocked at the bottom wall (py >= 18 for standard pieces). +let blocked = 0 + +-- Check collision: at bottom wall OR frozen cells below +-- T/J/L/S/Z pieces: bottom at py+1, so check py+2 +-- I piece: bottom at py+1, check py+2 +-- Piece bottom row = py+1, next row down = py+2 +every 33 -> blocked = if py > 17 then 1 else (if py == 17 then (if g19[px] > 0 then 1 else (if g19[px + 1] > 0 then 1 else 0)) else (if py == 16 then (if g18[px] > 0 then 1 else (if g18[px + 1] > 0 then 1 else 0)) else (if py == 15 then (if g17[px] > 0 then 1 else (if g17[px + 1] > 0 then 1 else 0)) else (if py == 14 then (if g16[px] > 0 then 1 else (if g16[px + 1] > 0 then 1 else 0)) else (if py == 13 then (if g15[px] > 0 then 1 else (if g15[px + 1] > 0 then 1 else 0)) else (if py == 12 then (if g14[px] > 0 then 1 else (if g14[px + 1] > 0 then 1 else 0)) else 0)))))) + -- Gravity tick every 33 -> gravityTick = if paused then gravityTick else (if gameOver then gravityTick else gravityTick + 1) --- Auto-drop -every 33 -> py = if paused then py else (if gameOver then py else (if gravityTick > dropInterval then (if py < 18 then py + 1 else py) else py)) +-- Auto-drop: only if NOT blocked +every 33 -> py = if paused then py else (if gameOver then py else (if blocked then py else (if gravityTick > dropInterval then (if py < 18 then py + 1 else py) else py))) every 33 -> gravityTick = if gravityTick > dropInterval then 0 else gravityTick --- Lock detection -every 33 -> lockTick = if py > 17 then lockTick + 1 else 0 +-- Lock detection: start counting when blocked +every 33 -> lockTick = if blocked then lockTick + 1 else 0 --- Freeze piece into grid rows on lock (simplified: T, I, O, J, L, S, Z) --- Row 18 cells -every 33 -> g18[px] = if lockTick == 3 then (if py > 17 then piece else g18[px]) else g18[px] -every 33 -> g18[px + 1] = if lockTick == 3 then (if py > 17 then piece else g18[px + 1]) else g18[px + 1] -every 33 -> g18[px + 2] = if lockTick == 3 then (if py > 17 then (if piece == 4 then g18[px + 2] else piece) else g18[px + 2]) else g18[px + 2] +-- ── Freeze piece into grid at py position on lock ── +-- The piece top-row cells go into row py, bottom-row cell into py+1 +-- For T-piece: (px,py), (px+1,py), (px+2,py) and (px+1,py+1) +-- We write the top 3 cells into grid[py] and bottom cell into grid[py+1] --- Row 17 cells (T-piece has cell at (px+1, py+1)) -every 33 -> g17[px + 1] = if lockTick == 3 then (if py > 16 then (if piece == 6 then 6 else (if piece == 4 then 4 else g17[px + 1])) else g17[px + 1]) else g17[px + 1] +-- Freeze top cells into grid row py (for each possible py value) +-- Row 19 +every 33 -> g19[px] = if lockTick == 3 then (if py == 19 then piece else g19[px]) else g19[px] +every 33 -> g19[px + 1] = if lockTick == 3 then (if py == 19 then piece else g19[px + 1]) else g19[px + 1] +every 33 -> g19[px + 2] = if lockTick == 3 then (if py == 19 then piece else g19[px + 2]) else g19[px + 2] +-- Row 18 +every 33 -> g18[px] = if lockTick == 3 then (if py == 18 then piece else g18[px]) else g18[px] +every 33 -> g18[px + 1] = if lockTick == 3 then (if py == 18 then piece else g18[px + 1]) else g18[px + 1] +every 33 -> g18[px + 2] = if lockTick == 3 then (if py == 18 then piece else g18[px + 2]) else g18[px + 2] +-- Row 17 +every 33 -> g17[px] = if lockTick == 3 then (if py == 17 then piece else g17[px]) else g17[px] +every 33 -> g17[px + 1] = if lockTick == 3 then (if py == 17 then piece else g17[px + 1]) else g17[px + 1] +every 33 -> g17[px + 2] = if lockTick == 3 then (if py == 17 then piece else g17[px + 2]) else g17[px + 2] +-- Row 16 +every 33 -> g16[px] = if lockTick == 3 then (if py == 16 then piece else g16[px]) else g16[px] +every 33 -> g16[px + 1] = if lockTick == 3 then (if py == 16 then piece else g16[px + 1]) else g16[px + 1] +every 33 -> g16[px + 2] = if lockTick == 3 then (if py == 16 then piece else g16[px + 2]) else g16[px + 2] +-- Row 15 +every 33 -> g15[px] = if lockTick == 3 then (if py == 15 then piece else g15[px]) else g15[px] +every 33 -> g15[px + 1] = if lockTick == 3 then (if py == 15 then piece else g15[px + 1]) else g15[px + 1] +every 33 -> g15[px + 2] = if lockTick == 3 then (if py == 15 then piece else g15[px + 2]) else g15[px + 2] +-- Row 14 +every 33 -> g14[px] = if lockTick == 3 then (if py == 14 then piece else g14[px]) else g14[px] +every 33 -> g14[px + 1] = if lockTick == 3 then (if py == 14 then piece else g14[px + 1]) else g14[px + 1] +every 33 -> g14[px + 2] = if lockTick == 3 then (if py == 14 then piece else g14[px + 2]) else g14[px + 2] +-- Row 13 +every 33 -> g13[px] = if lockTick == 3 then (if py == 13 then piece else g13[px]) else g13[px] +every 33 -> g13[px + 1] = if lockTick == 3 then (if py == 13 then piece else g13[px + 1]) else g13[px + 1] +every 33 -> g13[px + 2] = if lockTick == 3 then (if py == 13 then piece else g13[px + 2]) else g13[px + 2] --- Row 17 freeze for py==17 -every 33 -> g17[px] = if py == 17 then (if lockTick == 3 then piece else g17[px]) else g17[px] -every 33 -> g17[px + 2] = if py == 17 then (if lockTick == 3 then (if piece == 4 then g17[px + 2] else piece) else g17[px + 2]) else g17[px + 2] - --- Row 16 freeze for py==16 -every 33 -> g16[px] = if py == 16 then (if lockTick == 3 then piece else g16[px]) else g16[px] -every 33 -> g16[px + 1] = if py == 16 then (if lockTick == 3 then piece else g16[px + 1]) else g16[px + 1] -every 33 -> g16[px + 2] = if py == 16 then (if lockTick == 3 then (if piece == 4 then g16[px + 2] else piece) else g16[px + 2]) else g16[px + 2] +-- Freeze T-piece bottom center cell into grid[py+1] +-- (T has a cell at px+1, py+1; also applicable to O, S, Z shapes) +every 33 -> g19[px + 1] = if lockTick == 3 then (if py == 18 then (if piece == 6 then 6 else g19[px + 1]) else g19[px + 1]) else g19[px + 1] +every 33 -> g18[px + 1] = if lockTick == 3 then (if py == 17 then (if piece == 6 then 6 else g18[px + 1]) else g18[px + 1]) else g18[px + 1] +every 33 -> g17[px + 1] = if lockTick == 3 then (if py == 16 then (if piece == 6 then 6 else g17[px + 1]) else g17[px + 1]) else g17[px + 1] +every 33 -> g16[px + 1] = if lockTick == 3 then (if py == 15 then (if piece == 6 then 6 else g16[px + 1]) else g16[px + 1]) else g16[px + 1] +every 33 -> g15[px + 1] = if lockTick == 3 then (if py == 14 then (if piece == 6 then 6 else g15[px + 1]) else g15[px + 1]) else g15[px + 1] +every 33 -> g14[px + 1] = if lockTick == 3 then (if py == 13 then (if piece == 6 then 6 else g14[px + 1]) else g14[px + 1]) else g14[px + 1] -- Spawn new piece after lock every 33 -> piece = if lockTick == 3 then nextPiece else piece @@ -124,18 +165,23 @@ every 33 -> score = if lockTick == 3 then score + 10 else score every 33 -> score = if g19[0] > 0 then (if g19[2] > 0 then (if g19[4] > 0 then (if g19[6] > 0 then (if g19[8] > 0 then score + 100 else score) else score) else score) else score) else score every 33 -> lines = if g19[0] > 0 then (if g19[2] > 0 then (if g19[4] > 0 then (if g19[6] > 0 then (if g19[8] > 0 then lines + 1 else lines) else lines) else lines) else lines) else lines --- Shift rows down on clear +-- Shift rows down on clear: copy row 18 into row 19 every 33 -> g19[0] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[0] else g19[0]) else g19[0]) else g19[0] every 33 -> g19[1] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[1] else g19[1]) else g19[1]) else g19[1] every 33 -> g19[2] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[2] else g19[2]) else g19[2]) else g19[2] every 33 -> g19[3] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[3] else g19[3]) else g19[3]) else g19[3] every 33 -> g19[4] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[4] else g19[4]) else g19[4]) else g19[4] +every 33 -> g19[5] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[5] else g19[5]) else g19[5]) else g19[5] +every 33 -> g19[6] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[6] else g19[6]) else g19[6]) else g19[6] +every 33 -> g19[7] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[7] else g19[7]) else g19[7]) else g19[7] +every 33 -> g19[8] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[8] else g19[8]) else g19[8]) else g19[8] +every 33 -> g19[9] = if g19[0] > 0 then (if g19[4] > 0 then (if g19[8] > 0 then g18[9] else g19[9]) else g19[9]) else g19[9] -- Level up every 33 -> level = if lines > 0 then (lines / 10 + 1) else 1 every 33 -> dropInterval = if level > 9 then 3 else (27 - level * 3) --- Game over +-- Game over: any cell in row 0 filled every 33 -> gameOver = if g0[3] > 0 then 1 else (if g0[4] > 0 then 1 else (if g0[5] > 0 then 1 else gameOver)) -- ================================================================ @@ -180,7 +226,19 @@ view tetris_game = column [ for k in [0,1,2,3,4,5,6,7,8,9] -> column { style: "position:absolute; width:1px; height:600px; left:{k * 30}px; background:rgba(99,102,241,0.08)" } [] - -- Frozen grid: row 16 (Layer 1 data -> Layer 5 UI) + -- Frozen grid: row 13 (Layer 1 data -> Layer 5 UI) + for c in [0,1,2,3,4,5,6,7,8,9] -> + column { style: "position:absolute; width:28px; height:28px; top:391px; left:{c * 30 + 1}px; border-radius:4px; background:linear-gradient(180deg,#a855f7,#7c3aed); opacity:{if g13[c] > 0 then 1 else 0}; transition:opacity 0.15s; box-shadow:0 0 8px rgba(168,85,247,0.4)" } [] + + -- Frozen grid: row 14 + for c in [0,1,2,3,4,5,6,7,8,9] -> + column { style: "position:absolute; width:28px; height:28px; top:421px; left:{c * 30 + 1}px; border-radius:4px; background:linear-gradient(180deg,#a855f7,#7c3aed); opacity:{if g14[c] > 0 then 1 else 0}; transition:opacity 0.15s; box-shadow:0 0 8px rgba(168,85,247,0.4)" } [] + + -- Frozen grid: row 15 + for c in [0,1,2,3,4,5,6,7,8,9] -> + column { style: "position:absolute; width:28px; height:28px; top:451px; left:{c * 30 + 1}px; border-radius:4px; background:linear-gradient(180deg,#a855f7,#7c3aed); opacity:{if g15[c] > 0 then 1 else 0}; transition:opacity 0.15s; box-shadow:0 0 8px rgba(168,85,247,0.4)" } [] + + -- Frozen grid: row 16 for c in [0,1,2,3,4,5,6,7,8,9] -> column { style: "position:absolute; width:28px; height:28px; top:481px; left:{c * 30 + 1}px; border-radius:4px; background:linear-gradient(180deg,#a855f7,#7c3aed); opacity:{if g16[c] > 0 then 1 else 0}; transition:opacity 0.15s; box-shadow:0 0 8px rgba(168,85,247,0.4)" } []