more tetris

This commit is contained in:
Chris Wanstrath 2025-09-28 23:42:13 -07:00
parent 3f6bacfcd3
commit bba8e32fb7

View File

@ -9,12 +9,17 @@ const ROWS = 20
const CELL = 25 const CELL = 25
const DOWN_TICK = 10 const DOWN_TICK = 10
const MOVE_TICK = 3 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 grid: string[][] = []
let dead = false let dead = false
let downTick = 0 let downTick = 0
let moveTick = 0 let moveTick = 0
let tetrisRows: number[] = []
let tetrisTimer = 0
const COLORS: Record<string, string> = { const COLORS: Record<string, string> = {
I: "cyan", I: "cyan",
@ -148,6 +153,22 @@ export function init() {
dead = false dead = false
downTick = 0 downTick = 0
moveTick = 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() 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) { if (hit) {
const shape = SHAPES[player.shape]![player.rotation]! const shape = SHAPES[player.shape]![player.rotation]!
for (const row in shape) { for (const row in shape) {
@ -197,7 +229,6 @@ export function update(_delta: number, input: InputState) {
} }
} }
player = newShape() player = newShape()
} }
} }
@ -232,7 +263,9 @@ export function draw(game: GameContext) {
// draw board // draw board
for (let row = 0; row < ROWS; row++) { for (let row = 0; row < ROWS; row++) {
for (let col = 0; col < COLS; col++) { 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 shape = randomElement(Object.keys(SHAPES))!
const newShape = { x: 3, y: 0, shape, rotation: randomIndex(SHAPES[shape]!)! } return { 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
} }
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) { function drawBlock(game: GameContext, x: number, y: number, color: string) {
game.rectfill( game.rectfill(
x * CELL, x * CELL,