/// export const game = true import type { GameContext, InputState } from "@/shared/game" const CELL = 20 const COLS = 30 // 600 px wide const ROWS = 12 // 240 px tall of bricks const PADDLE_W = 6 const PADDLE_H = 1 const BALL_SPEED = 4 const ROW_COLORS = ["red", "orange", "yellow", "green", "blue", "magenta"] let paddleX = 0 let ball = { x: 0, y: 0, dx: BALL_SPEED, dy: -BALL_SPEED } let bricks: { x: number, y: number, alive: boolean }[] = [] let score = 0 let dead = false export function init() { paddleX = (COLS * CELL - PADDLE_W * CELL) / 2 ball = { x: COLS * CELL / 2, y: ROWS * CELL + 60, dx: BALL_SPEED, dy: -BALL_SPEED } bricks = [] for (let r = 0; r < ROWS; r++) { for (let c = 0; c < COLS; c += 2) { bricks.push({ x: c * CELL, y: r * CELL, alive: true }) } } dead = false } export function update(_delta: number, input: InputState) { if (dead) return if (input.pressed.has("ArrowLeft") || input.pressed.has("a")) { paddleX -= 6 } if (input.pressed.has("ArrowRight") || input.pressed.has("d")) { paddleX += 6 } // keep paddle on screen paddleX = Math.max(0, Math.min(paddleX, COLS * CELL - PADDLE_W * CELL)) // move ball ball.x += ball.dx ball.y += ball.dy // wall bounce if (ball.x < 0 || ball.x > COLS * CELL) ball.dx *= -1 if (ball.y < 0) ball.dy *= -1 // paddle bounce const paddleY = ROWS * CELL + 60 const paddleH = CELL if ( ball.x > paddleX && ball.x < paddleX + PADDLE_W * CELL && ball.y + 6 >= paddleY && ball.y - 6 <= paddleY + paddleH ) { ball.dy *= -1 ball.y = paddleY - 6 } // brick collision for (const b of bricks) { if (!b.alive) continue if ( ball.x > b.x && ball.x < b.x + (CELL * 2) && ball.y > b.y && ball.y < b.y + CELL ) { score += 100 b.alive = false ball.dy *= -1 } } // death if (ball.y > ROWS * CELL + 100) dead = true } export function draw(game: GameContext) { game.clear("#6C6FF6") const boardW = COLS * CELL const boardH = ROWS * CELL + 100 const offsetX = (game.width - boardW) / 2 const offsetY = (game.height - boardH) / 2 const c = game.ctx c.save() c.translate(offsetX, offsetY) // background game.rectfill(0, 0, boardW, boardH, "black") // paddle game.rectfill( paddleX, ROWS * CELL + 60, paddleX + PADDLE_W * CELL, ROWS * CELL + 60 + CELL, "white" ) // ball game.circfill(ball.x, ball.y, 6, "red") // bricks for (const b of bricks) { if (b.alive) { const color = pickColor(b.x, b.y) game.rectfill(b.x, b.y, (b.x + (CELL * 2)) - .5, (b.y + CELL) - .5, color) } } // score! game.text(`Score: ${score}`, 5, boardH - 18, "cyan", 12) c.restore() // ya dead if (dead) { game.centerTextX("GAME OVER", boardH + 30, "red", 24) } } function pickColor(x: number, y: number): string { const row = Math.floor(y / CELL) const colorIndex = Math.floor(row / 2) % ROW_COLORS.length return ROW_COLORS[colorIndex] || "white" }