← back to Model Arena

data/artifacts/04692f72ef1d/gemma3-12b.html

260 lines

<!DOCTYPE html>
<html>
<head>
<title>Tetris</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
canvas { display: block; }
#score { position: absolute; top: 10px; left: 10px; color: white; font-family: sans-serif; font-size: 20px; }
</style>
</head>
<body>

<div id="score">Score: 0</div>
<canvas id="tetrisCanvas" width="240" height="400"></canvas>

<script>
const canvas = document.getElementById('tetrisCanvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('score');

const gridWidth = 10;
const gridHeight = 20;
const blockSize = 24;
const grid = Array(gridHeight).fill(null).map(() => Array(gridWidth).fill(0));
let currentPiece = null;
let nextPiece = null;
let score = 0;
let speed = 500; // milliseconds
let lastTime = 0;
let gameOver = false;
let paused = false;

const pieces = [
  [[1, 1, 1, 1]], // I
  [[1, 1], [1, 1]], // O
  [[1, 1, 0], [0, 1, 1]], // S
  [[0, 1, 1], [1, 1, 0]], // Z
  [[1, 1, 1], [0, 0, 1]], // J
  [[1, 1, 1], [1, 0, 0]], // L
  [[1, 1, 1], [0, 1, 0]]  // T
];

function getRandomPiece() {
    return pieces[Math.floor(Math.random() * pieces.length)];
}


function drawGrid() {
    ctx.fillStyle = '#222';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    ctx.strokeStyle = '#555';
    for (let i = 0; i < gridHeight; i++) {
        for (let j = 0; j < gridWidth; j++) {
            if (grid[i][j] !== 0) {
                ctx.fillStyle = getColor(grid[i][j]);
                ctx.fillRect(j * blockSize, i * blockSize, blockSize, blockSize);
            }
            ctx.strokeRect(j * blockSize, i * blockSize, blockSize, blockSize);
        }
    }
}

function drawPiece(piece, x, y) {
    for (let row = 0; row < piece.length; row++) {
        for (let col = 0; col < piece[row].length; col++) {
            if (piece[row][col]) {
                ctx.fillStyle = getColor(1); // Color for the current piece.  Could be dynamic later
                ctx.fillRect((x + col) * blockSize, (y + row) * blockSize, blockSize, blockSize);
            }
        }
    }
}

function getColor(value) {
    switch (value) {
        case 1: return 'blue';
        case 2: return 'orange';
        case 3: return 'yellow';
        case 4: return 'purple';
        case 5: return 'green';
        case 6: return 'red';
        case 7: return 'cyan';
        default: return 'black';
    }
}

function isValidMove(piece, x, y) {
    for (let row = 0; row < piece.length; row++) {
        for (let col = 0; col < piece[row].length; col++) {
            if (piece[row][col]) {
                const gridX = x + col;
                const gridY = y + row;

                if (gridX < 0 || gridX >= gridWidth || gridY >= gridHeight) {
                    return false;
                }
                if (gridY >= 0 && grid[gridY][gridX] !== 0) { // Check only if within bounds
                    return false;
                }
            }
        }
    }
    return true;
}

function rotatePiece(piece) {
    const rotated = [];
    for (let col = 0; col < piece[0].length; col++) {
        rotated.push([]);
        for (let row = piece.length - 1; row >= 0; row--) {
            rotated[col].push(piece[row][col]);
        }
    }
    return rotated;
}

function placePiece(piece, x, y) {
    for (let row = 0; row < piece.length; row++) {
        for (let col = 0; col < piece[row].length; col++) {
            if (piece[row][col]) {
                grid[y + row][x + col] = 1; // Assign a color ID
            }
        }
    }
}

function clearLines() {
    let linesCleared = 0;
    for (let i = gridHeight - 1; i >= 0; i--) {
        let full = true;
        for (let j = 0; j < gridWidth; j++) {
            if (grid[i][j] === 0) {
                full = false;
                break;
            }
        }

        if (full) {
            linesCleared++;
            // Shift lines down
            for (let k = i; k < gridHeight - 1; k++) {
                grid[k] = grid[k + 1].slice();
            }
            grid[gridHeight - 1] = Array(gridWidth).fill(0);
        }
    }

    score += linesCleared * (Math.pow(2, linesCleared));
    scoreDisplay.textContent = `Score: ${score}`;
}

function spawnNextPiece() {
  nextPiece = getRandomPiece();
}


function newGame() {
    grid.forEach(row => row.fill(0));
    score = 0;
    speed = 500;
    gameOver = false;
    paused = false;

    currentPiece = getRandomPiece();
    nextPiece = getRandomPiece();

    scoreDisplay.textContent = `Score: ${score}`;
    drawGrid();
    drawPiece(currentPiece, gridWidth / 2 - 1, 0);
}


function gameLoop(timestamp) {
    if (!gameOver && !paused) {
        const deltaTime = timestamp - lastTime;
        lastTime = timestamp;

        if (deltaTime >= speed) {
            moveDown();
        }

        drawGrid();
        if (currentPiece) drawPiece(currentPiece, currentPiece.x, currentPiece.y);

        requestAnimationFrame(gameLoop);
    } else if (gameOver) {
      // Game over screen could be added here.  For now, just show the grid.
       drawGrid();
       scoreDisplay.textContent = `Game Over - Score: ${score}`;
    }
}


function moveDown() {
    if (!currentPiece || !isValidMove(currentPiece.piece, currentPiece.x, currentPiece.y + 1)) {
        placePiece(currentPiece.piece, currentPiece.x, currentPiece.y);
        clearLines();
        spawnNextPiece();

        currentPiece = { piece: nextPiece, x: gridWidth / 2 - 1, y: 0 };
        if (!isValidMove(currentPiece.piece, currentPiece.x, currentPiece.y)) {
            gameOver = true;
        }
    } else {
        currentPiece.y++;
    }
}

function moveLeft() {
    if (currentPiece && isValidMove(currentPiece.piece, currentPiece.x - 1, currentPiece.y)) {
        currentPiece.x--;
    }
}

function moveRight() {
    if (currentPiece && isValidMove(currentPiece.piece, currentPiece.x + 1, currentPiece.y)) {
        currentPiece.x++;
    }
}


function rotate() {
    const rotatedPiece = rotatePiece(currentPiece.piece);
    if (isValidMove(rotatedPiece, currentPiece.x, currentPiece.y)) {
        currentPiece.piece = rotatedPiece;
    }
}

document.addEventListener('keydown', function(event) {
    if (!gameOver && !paused) {
        switch (event.key) {
            case 'ArrowLeft': moveLeft(); break;
            case 'ArrowRight': moveRight(); break;
            case 'ArrowDown': speed = Math.max(100, speed - 50); break; // Speed up
            case 'ArrowUp': rotate(); break;
            case ' ': pauseGame(); break;
        }
    } else if (gameOver) {
      if (event.key === "Enter") {
          newGame();
      }
    }
});

function pauseGame() {
  paused = !paused;
  if(paused){
     scoreDisplay.textContent = `Paused - Score: ${score}`;
  } else {
     scoreDisplay.textContent = `Score: ${score}`;
  }
}


newGame(); // Start the game

</script>
</body>
</html>