← back to Model Arena

data/artifacts/172f180e3161/gemma3-12b.html

245 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Two-Player Pong</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      overflow: hidden;
      background: #111; /* Darker background */
      color: #fff;
      font-family: 'Press Start 2P', monospace; /* Retro font */
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
    }

    canvas {
      background: #000;
      display: block;
      image-rendering: pixelated; /* Sharpens pixels */
    }

    #gameOver, #restart {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      text-align: center;
      font-size: 2em;
      width: 100%;
      color: #f0f0f0;
      cursor: pointer;
      padding: 10px;
      border: 1px solid #444; /* Subtle border */
      background: rgba(0, 0, 0, 0.7); /* Semi-transparent background */
    }

    #restart {
      display: none;
    }
  </style>
  <link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
</head>
<body>
  <canvas id="pongCanvas" width="800" height="400"></canvas>
  <div id="gameOver" style="display:none;">Game Over</div>
  <div id="restart" style="display:none;" onclick="init()">Press to Restart</div>

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

    const width = canvas.width;
    const height = canvas.height;

    let leftPaddle = { x: 10, y: 150, width: 8, height: 80, dy: 0 };
    let rightPaddle = { x: width - 20, y: 150, width: 8, height: 80, dy: 0 };
    let ball = {
      x: width / 2,
      y: height / 2,
      radius: 8,
      dx: 3,
      dy: 3,
      speed: 3
    };
    let leftScore = 0;
    let rightScore = 0;
    let gameOver = false;
    const winScore = 11;

    function drawPaddle(paddle) {
      ctx.fillStyle = '#fff'; /* White paddles */
      ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
    }

    function drawBall() {
      ctx.beginPath();
      ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
      ctx.fillStyle = '#fff'; /* White ball */
      ctx.fill();
      ctx.closePath();
    }

    function drawNet() {
      ctx.strokeStyle = '#fff';
      ctx.lineWidth = 1;
      for (let i = 0; i < height; i += 25) {
        ctx.beginPath();
        ctx.moveTo(width / 2, i);
        ctx.lineTo(width / 2, i + 12);
        ctx.stroke();
      }
    }

    function drawScore() {
      ctx.font = '32px "Press Start 2P", monospace'; /* Retro font */
      ctx.fillStyle = '#fff';
      ctx.fillText(leftScore, width / 4 - 20, 50);
      ctx.fillText(rightScore, 3 * width / 4 + 20, 50);
    }

    function movePaddles() {
      leftPaddle.y += leftPaddle.dy;
      rightPaddle.y += rightPaddle.dy;

      // Prevent paddles from moving out of bounds
      if (leftPaddle.y < 0) leftPaddle.y = 0;
      if (leftPaddle.y + leftPaddle.height > height) leftPaddle.y = height - leftPaddle.height;
      if (rightPaddle.y < 0) rightPaddle.y = 0;
      if (rightPaddle.y + rightPaddle.height > height) rightPaddle.y = height - rightPaddle.height;
    }

    function moveBall() {
      ball.x += ball.dx;
      ball.y += ball.dy;

      // Bounce off top and bottom
      if (ball.y - ball.radius < 0 || ball.y + ball.radius > height) {
        ball.dy *= -1;
        playSound('hit');
      }

      // Paddle collision
      let leftPaddleCollision = ball.x - ball.radius < leftPaddle.x + leftPaddle.width &&
        ball.y > leftPaddle.y && ball.y < leftPaddle.y + leftPaddle.height;
      if (leftPaddleCollision) {
        ball.dx *= -1;
        let relativeY = (ball.y - (leftPaddle.y + leftPaddle.height / 2)) / (leftPaddle.height / 2);
        ball.dy = relativeY * 4; // Adjusted angle
        ball.speed += 0.15;
        playSound('hit');
      }

      let rightPaddleCollision = ball.x + ball.radius > rightPaddle.x &&
        ball.y > rightPaddle.y && ball.y < rightPaddle.y + rightPaddle.height;
      if (rightPaddleCollision) {
        ball.dx *= -1;
        let relativeY = (ball.y - (rightPaddle.y + rightPaddle.height / 2)) / (rightPaddle.height / 2);
        ball.dy = relativeY * 4; // Adjusted angle
        ball.speed += 0.15;
        playSound('hit');
      }

      // Score
      if (ball.x - ball.radius < 0) {
        rightScore++;
        resetBall();
        playSound('score');
      }

      if (ball.x + ball.radius > width) {
        leftScore++;
        resetBall();
        playSound('score');
      }
    }

    function resetBall() {
      ball.x = width / 2;
      ball.y = height / 2;
      ball.dx = (Math.random() > 0.5 ? -1 : 1) * ball.speed;
      ball.dy = (Math.random() - 0.5) * 6;
    }

    function draw() {
      ctx.clearRect(0, 0, width, height);
      drawNet();
      drawPaddle(leftPaddle);
      drawPaddle(rightPaddle);
      drawBall();
      drawScore();
    }

    function update() {
      movePaddles();
      moveBall();
      draw();
    }

    function gameLoop() {
      if (gameOver) return;
      update();
      requestAnimationFrame(gameLoop);
    }

    function checkWin() {
      if (leftScore >= winScore || rightScore >= winScore) {
        gameOver = true;
        document.getElementById('gameOver').style.display = 'block';
        document.getElementById('restart').style.display = 'block';
      }
    }

    function init() {
      leftScore = 0;
      rightScore = 0;
      gameOver = false;
      resetBall();
      ball.speed = 3; // Reset ball speed on restart
      document.getElementById('gameOver').style.display = 'none';
      document.getElementById('restart').style.display = 'none';
      gameLoop();
    }

    document.addEventListener('keydown', function(e) {
      if (e.key === 'w') leftPaddle.dy = -6;
      if (e.key === 's') leftPaddle.dy = 6;
      if (e.key === 'ArrowUp') rightPaddle.dy = -6;
      if (e.key === 'ArrowDown') rightPaddle.dy = 6;
    });

    document.addEventListener('keyup', function(e) {
      if (e.key === 'w' || e.key === 's') leftPaddle.dy = 0;
      if (e.key === 'ArrowUp' || e.key === 'ArrowDown') rightPaddle.dy = 0;
    });

    const audioCtx = new (window.AudioContext || window.webkitAudioContext)();

    function playSound(type) {
      if (!audioCtx) return;
      if (audioCtx.state === 'suspended') {
        audioCtx.resume();
      }

      const osc = audioCtx.createOscillator();
      const gain = audioCtx.createGain();

      osc.type = type === 'hit' ? 'square' : 'sine';
      osc.frequency.value = type === 'hit' ? 1200 : 440;
      gain.gain.setValueAtTime(0.3, audioCtx.currentTime);
      gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.2);

      osc.connect(gain);
      gain.connect(audioCtx.destination);

      osc.start();
      osc.stop(audioCtx.currentTime + 0.2);
    }

    init();
  </script>
</body>
</html>