← back to Model Arena

data/artifacts/172f180e3161/qwen25-7b.html

228 lines

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Two-Player Pong</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      overflow: hidden;
      background: black;
      color: white;
      font-family: monospace;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
    }
    canvas {
      background: #000;
      display: block;
    }
    #gameOver, #restart {
      position: absolute;
      top: 40%;
      text-align: center;
      font-size: 3em;
      width: 100%;
    }
    #restart {
      top: 50%;
      cursor: pointer;
    }
  </style>
</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: 10, height: 100, dy: 0 };
let rightPaddle = { x: width - 20, y: 150, width: 10, height: 100, dy: 0 };
let ball = {
  x: width / 2,
  y: height / 2,
  radius: 10,
  dx: 4,
  dy: 4,
  speed: 4
};
let leftScore = 0;
let rightScore = 0;
let gameOver = false;

const paddleSpeed = 6;
const winScore = 11;

function drawPaddle(paddle) {
  ctx.fillStyle = 'white';
  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 = 'white';
  ctx.fill();
  ctx.closePath();
}

function drawNet() {
  ctx.strokeStyle = 'white';
  ctx.lineWidth = 2;
  for (let i = 0; i < height; i += 20) {
    ctx.beginPath();
    ctx.moveTo(width / 2, i);
    ctx.lineTo(width / 2, i + 10);
    ctx.stroke();
  }
}

function drawScore() {
  ctx.font = '32px monospace';
  ctx.fillText(leftScore, width / 4, 50);
  ctx.fillText(rightScore, 3 * width / 4, 50);
}

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

  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;

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

  if (
    ball.x - ball.radius < leftPaddle.x + leftPaddle.width &&
    ball.y > leftPaddle.y &&
    ball.y < leftPaddle.y + leftPaddle.height
  ) {
    ball.dx *= -1;
    let relativeY = (ball.y - (leftPaddle.y + leftPaddle.height / 2)) / (leftPaddle.height / 2);
    ball.dy = relativeY * 6;
    ball.speed += 0.1;
    playSound('hit');
  }

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

  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) * 8;
}

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();
  document.getElementById('gameOver').style.display = 'none';
  document.getElementById('restart').style.display = 'none';
  gameLoop();
}

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

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;
});

function playSound(type) {
  const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
  const osc = audioCtx.createOscillator();
  const gain = audioCtx.createGain();

  osc.type = type === 'hit' ? 'square' : 'sine';
  osc.frequency.value = type === 'hit' ? 1000 : 500;
  gain.gain.setValueAtTime(0.1, audioCtx.currentTime);
  gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.2);

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

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

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