■Claudeが作ってくれたやつ
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PONG Game</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #000;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: 'Courier New', monospace;
color: white;
}
```
.game-container {
text-align: center;
}
canvas {
border: 2px solid white;
background-color: #000;
}
.score {
font-size: 24px;
margin: 20px 0;
letter-spacing: 2px;
}
.controls {
margin-top: 20px;
font-size: 14px;
opacity: 0.8;
}
.start-button {
background-color: #333;
color: white;
border: 2px solid white;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
font-family: 'Courier New', monospace;
margin: 10px;
}
.start-button:hover {
background-color: white;
color: black;
}
</style>
```
</head>
<body>
```
<script>
// Canvas要素とコンテキストの取得
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// ゲームの状態管理
let gameRunning = false;
let animationId;
// スコア要素の取得
const playerScoreElement = document.getElementById('playerScore');
const computerScoreElement = document.getElementById('computerScore');
// ゲームオブジェクトの定義
const game = {
// プレイヤーのパドル(左側)
playerPaddle: {
x: 10,
y: canvas.height / 2 - 50,
width: 10,
height: 100,
speed: 5,
upPressed: false,
downPressed: false
},
// コンピューターのパドル(右側)
computerPaddle: {
x: canvas.width - 20,
y: canvas.height / 2 - 50,
width: 10,
height: 100,
speed: 3.5, // プレイヤーより少し遅く設定
targetY: canvas.height / 2 - 50
},
// ボールの設定
ball: {
x: canvas.width / 2,
y: canvas.height / 2,
radius: 8,
speedX: 4,
speedY: 3,
maxSpeed: 8
},
// スコアの管理
score: {
player: 0,
computer: 0
}
};
// キーボード入力の処理
const keys = {};
// キーが押されたときの処理
document.addEventListener('keydown', (e) => {
keys[e.key.toLowerCase()] = true;
// ゲームが停止中にスペースキーでゲーム開始
if (e.key === ' ' && !gameRunning) {
startGame();
}
});
// キーが離されたときの処理
document.addEventListener('keyup', (e) => {
keys[e.key.toLowerCase()] = false;
});
// パドルの移動処理
function updatePaddles() {
// プレイヤーパドルの移動(W/S キーまたは矢印キー)
if (keys['w'] || keys['arrowup']) {
game.playerPaddle.y -= game.playerPaddle.speed;
}
if (keys['s'] || keys['arrowdown']) {
game.playerPaddle.y += game.playerPaddle.speed;
}
// プレイヤーパドルの画面外移動を防ぐ
if (game.playerPaddle.y < 0) {
game.playerPaddle.y = 0;
}
if (game.playerPaddle.y > canvas.height - game.playerPaddle.height) {
game.playerPaddle.y = canvas.height - game.playerPaddle.height;
}
// コンピューターパドルのAI処理
// ボールの位置を追跡するが、完璧ではない動きを実装
const ballCenterY = game.ball.y;
const paddleCenterY = game.computerPaddle.y + game.computerPaddle.height / 2;
// ボールとパドルの中心の差を計算
const difference = ballCenterY - paddleCenterY;
// 反応に少し遅れを持たせる(人間らしい動き)
if (Math.abs(difference) > 10) {
if (difference > 0) {
game.computerPaddle.y += game.computerPaddle.speed;
} else {
game.computerPaddle.y -= game.computerPaddle.speed;
}
}
// コンピューターパドルの画面外移動を防ぐ
if (game.computerPaddle.y < 0) {
game.computerPaddle.y = 0;
}
if (game.computerPaddle.y > canvas.height - game.computerPaddle.height) {
game.computerPaddle.y = canvas.height - game.computerPaddle.height;
}
}
// ボールの移動と衝突判定
function updateBall() {
// ボールの位置を更新
game.ball.x += game.ball.speedX;
game.ball.y += game.ball.speedY;
// 上下の壁との衝突判定
if (game.ball.y - game.ball.radius < 0 || game.ball.y + game.ball.radius > canvas.height) {
game.ball.speedY = -game.ball.speedY;
}
// プレイヤーパドルとの衝突判定
if (game.ball.x - game.ball.radius < game.playerPaddle.x + game.playerPaddle.width &&
game.ball.x + game.ball.radius > game.playerPaddle.x &&
game.ball.y + game.ball.radius > game.playerPaddle.y &&
game.ball.y - game.ball.radius < game.playerPaddle.y + game.playerPaddle.height) {
// ボールがパドルに当たった位置によって跳ね返り角度を調整
const hitPos = (game.ball.y - (game.playerPaddle.y + game.playerPaddle.height / 2)) / (game.playerPaddle.height / 2);
game.ball.speedX = Math.abs(game.ball.speedX);
game.ball.speedY = hitPos * 4;
// ボールの速度を少し上げる(ゲームをエキサイティングに)
if (Math.abs(game.ball.speedX) < game.ball.maxSpeed) {
game.ball.speedX *= 1.02;
}
}
// コンピューターパドルとの衝突判定
if (game.ball.x + game.ball.radius > game.computerPaddle.x &&
game.ball.x - game.ball.radius < game.computerPaddle.x + game.computerPaddle.width &&
game.ball.y + game.ball.radius > game.computerPaddle.y &&
game.ball.y - game.ball.radius < game.computerPaddle.y + game.computerPaddle.height) {
// ボールがパドルに当たった位置によって跳ね返り角度を調整
const hitPos = (game.ball.y - (game.computerPaddle.y + game.computerPaddle.height / 2)) / (game.computerPaddle.height / 2);
game.ball.speedX = -Math.abs(game.ball.speedX);
game.ball.speedY = hitPos * 4;
// ボールの速度を少し上げる
if (Math.abs(game.ball.speedX) < game.ball.maxSpeed) {
game.ball.speedX *= 1.02;
}
}
// ボールが左右の壁を越えた場合(得点処理)
if (game.ball.x < 0) {
// コンピューターの得点
game.score.computer++;
updateScore();
resetBall();
} else if (game.ball.x > canvas.width) {
// プレイヤーの得点
game.score.player++;
updateScore();
resetBall();
}
}
// ボールをリセット(得点後の処理)
function resetBall() {
game.ball.x = canvas.width / 2;
game.ball.y = canvas.height / 2;
// ランダムな方向でボールを発射
game.ball.speedX = (Math.random() > 0.5 ? 4 : -4);
game.ball.speedY = (Math.random() - 0.5) * 6;
}
// スコア表示の更新
function updateScore() {
playerScoreElement.textContent = game.score.player;
computerScoreElement.textContent = game.score.computer;
}
// 描画処理
function draw() {
// 画面をクリア
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 中央の点線を描画
ctx.setLineDash([5, 5]);
ctx.beginPath();
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width / 2, canvas.height);
ctx.strokeStyle = '#fff';
ctx.stroke();
ctx.setLineDash([]);
// プレイヤーパドルを描画
ctx.fillStyle = '#fff';
ctx.fillRect(game.playerPaddle.x, game.playerPaddle.y, game.playerPaddle.width, game.playerPaddle.height);
// コンピューターパドルを描画
ctx.fillRect(game.computerPaddle.x, game.computerPaddle.y, game.computerPaddle.width, game.computerPaddle.height);
// ボールを描画
ctx.beginPath();
ctx.arc(game.ball.x, game.ball.y, game.ball.radius, 0, Math.PI * 2);
ctx.fillStyle = '#fff';
ctx.fill();
// ゲームが停止中の場合、メッセージを表示
if (!gameRunning) {
ctx.fillStyle = '#fff';
ctx.font = '20px Courier New';
ctx.textAlign = 'center';
ctx.fillText('ゲーム開始ボタンを押してください', canvas.width / 2, canvas.height / 2 + 60);
}
}
// ゲームのメインループ
function gameLoop() {
if (!gameRunning) return;
updatePaddles();
updateBall();
draw();
animationId = requestAnimationFrame(gameLoop);
}
// ゲーム開始
function startGame() {
gameRunning = true;
gameLoop();
}
// ゲームリセット
function resetGame() {
gameRunning = false;
if (animationId) {
cancelAnimationFrame(animationId);
}
// スコアをリセット
game.score.player = 0;
game.score.computer = 0;
updateScore();
// ボールとパドルの位置をリセット
game.ball.x = canvas.width / 2;
game.ball.y = canvas.height / 2;
game.ball.speedX = 4;
game.ball.speedY = 3;
game.playerPaddle.y = canvas.height / 2 - 50;
game.computerPaddle.y = canvas.height / 2 - 50;
draw();
}
// 初期描画
draw();
</script>
```
</body>
</html>
https://anond.hatelabo.jp/20250706011306#
ツイートシェア