From bba8e32fb78b34237752702809cdb98931443371 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Sun, 28 Sep 2025 23:42:13 -0700 Subject: [PATCH] more tetris --- app/nose/bin/tetris.ts | 83 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/app/nose/bin/tetris.ts b/app/nose/bin/tetris.ts index daca53d..1201b28 100644 --- a/app/nose/bin/tetris.ts +++ b/app/nose/bin/tetris.ts @@ -9,12 +9,17 @@ const ROWS = 20 const CELL = 25 const DOWN_TICK = 10 const MOVE_TICK = 3 +const TETRIS_FRAMES = 5 -let player: { x: number, y: number, shape: string, rotation: number } +type Shape = { x: number, y: number, shape: string, rotation: number } + +let player: Shape let grid: string[][] = [] let dead = false let downTick = 0 let moveTick = 0 +let tetrisRows: number[] = [] +let tetrisTimer = 0 const COLORS: Record = { I: "cyan", @@ -148,6 +153,22 @@ export function init() { dead = false downTick = 0 moveTick = 0 + tetrisTimer = TETRIS_FRAMES + tetrisRows.length = 0 + grid.length = 0 + + grid[ROWS - 1] = [ + "magenta", + "magenta", + "magenta", + "magenta", + "", + "magenta", + "magenta", + "magenta", + "magenta", + "magenta", + ] player = newShape() } @@ -182,6 +203,17 @@ export function update(_delta: number, input: InputState) { } } + if (tetrisRows.length > 0) { + tetrisTimer-- + if (tetrisTimer <= 0) { + removeTetrisRows() + tetrisRows = [] + } + } else if (anyFullRows()) { + tetrisRows = findFullRows() + tetrisTimer = TETRIS_FRAMES + } + if (hit) { const shape = SHAPES[player.shape]![player.rotation]! for (const row in shape) { @@ -197,7 +229,6 @@ export function update(_delta: number, input: InputState) { } } - player = newShape() } } @@ -232,7 +263,9 @@ export function draw(game: GameContext) { // draw board for (let row = 0; row < ROWS; row++) { for (let col = 0; col < COLS; col++) { - drawBlock(game, col, row, grid[row]?.[col] || "gray") + let color = grid[row]?.[col] || "gray" + if (tetrisRows.includes(row)) color = "white" + drawBlock(game, col, row, color) } } @@ -258,15 +291,47 @@ export function draw(game: GameContext) { } } -function newShape() { +function newShape(): Shape { const shape = randomElement(Object.keys(SHAPES))! - const newShape = { x: 3, y: 0, shape, rotation: randomIndex(SHAPES[shape]!)! } - // const shape = SHAPES["O"] - // const newShape = { x: 3, y: 0, shape, rotation: randomIndex(SHAPES[shape]!)! } - console.log("new shape", newShape) - return newShape + return { x: 3, y: 0, shape, rotation: randomIndex(SHAPES[shape]!)! } } +function anyFullRows(): boolean { + return findFullRows().length > 0 +} + +function findFullRows(): number[] { + const rows: number[] = [] + for (let y = 0; y < ROWS; y++) { + let full = true + for (let x = 0; x < COLS; x++) { + if (!grid[y]?.[x]) { + full = false + break + } + } + if (full) rows.push(y) + } + return rows +} + + +function removeTetrisRows() { + const newGrid: string[][] = [] + + for (let y = 0; y < ROWS; y++) + if (!tetrisRows.includes(y)) + newGrid.push(grid[y] ?? []) + + // add empty rows on top to restore height + while (newGrid.length < ROWS) + newGrid.unshift([]) + + grid = newGrid + tetrisRows = [] +} + + function drawBlock(game: GameContext, x: number, y: number, color: string) { game.rectfill( x * CELL,