とぅとと「玉をうちあう pong を webgl で作って」
chatGPT にこんな指示をするだけで html 1枚で動く玉うち返しゲームを作ってみた。いわゆる Pong である。
以下 chatGPT からの説明
「このコードでは、ボールと2つのプレイヤー(1つはキーボードの上下キーで操作可能、もう1つはキーボードのWとSキーで操作可能)が描画されます。ボールは上下の壁およびプレイヤーに反射します。」
「このコードを使用して、Pong(ポン)ゲームをWebGLで作成しました。さらにゲームを拡張したい場合は、スコアカウンター、ボールの速度変更、衝突判定の強化など、さまざまな要素を追加することができます。必要に応じてコードをカスタマイズしてゲームを進化させてください。」
とぅとと「パドルが2つとも右に出ているが」
とぅとと「パドルは左右にわかれるべきでは」
とぅとと「一回打ち返すたびに点数が1点入って画面に点数を表示させたい」
とぅとと「玉を打ち返した時に「ポン!」という音を出したい」
とぅとと「打ちそこねたときに「ぶーっ!」って音を出すようにして」
とぅとと「先に3点取った方が勝ちでゲームオーバー表示を追加」
こんな感じで確実に動くのを確認しながら1つ1つ指示を追加するだけでまったくソースコードには手を加えずに作れてしまった。
これは やばい ですね ( ;˘ω˘)
<!DOCTYPE html>
<html>
<head>
<title>Pong</title>
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="800" height="400"></canvas>
<p id="score" style="font-size: 24px; font-weight: bold; text-align: center;"></p>
<p id="gameOver" style="font-size: 36px; font-weight: bold; text-align: center; display: none;">Game Over</p>
<script>
// Canvas要素と2Dコンテキストを取得
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
// ゲームの初期化
function initGame() {
// ボールの初期位置と速度を定義
let ballX = canvas.width / 2;
let ballY = canvas.height / 2;
let ballDX = 2;
let ballDY = -2;
const ballRadius = 10;
// プレイヤーの初期位置とサイズを定義
const playerWidth = 10;
const playerHeight = 80;
let player1Y = (canvas.height - playerHeight) / 2;
let player2Y = (canvas.height - playerHeight) / 2;
const playerSpeed = 5;
// キーの状態を保持するオブジェクト
const keys = {};
// ゲームのスコアと勝利条件を初期化
let score1 = 0;
let score2 = 0;
const winningScore = 3;
// キーイベントのハンドラを登録
document.addEventListener("keydown", function (event) {
keys[event.keyCode] = true;
});
document.addEventListener("keyup", function (event) {
keys[event.keyCode] = false;
});
// 「ポン!」の音声ファイルを読み込む
const pongSound = new Audio("pong_sound.mp3");
// 「ぶーっ!」の音声ファイルを読み込む
const booSound = new Audio("boo_sound.mp3");
// ボールを描画する関数
function drawBall() {
ctx.beginPath();
ctx.arc(ballX, ballY, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
// プレイヤー1のパドルを描画する関数
function drawPlayer1() {
ctx.beginPath();
ctx.rect(0, player1Y, playerWidth, playerHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
// プレイヤー2のパドルを描画する関数
function drawPlayer2() {
ctx.beginPath();
ctx.rect(canvas.width - playerWidth, player2Y, playerWidth, playerHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
// スコアを表示する関数
function drawScore() {
ctx.font = "24px Arial";
ctx.fillStyle = "#0095DD";
ctx.textAlign = "center";
ctx.fillText(score1 + " - " + score2, canvas.width / 2, 30);
}
// ゲームオーバーを表示する関数
function drawGameOver() {
ctx.font = "36px Arial";
ctx.fillStyle = "#0095DD";
ctx.textAlign = "center";
ctx.fillText("Game Over", canvas.width / 2, canvas.height / 2);
}
// ゲームのメインループ
function draw() {
// Canvasをクリア
ctx.clearRect(0, 0, canvas.width, canvas.height);
// ボールを描画
drawBall();
// プレイヤー1のパドルを描画
drawPlayer1();
// プレイヤー2のパドルを描画
drawPlayer2();
// スコアを描画
drawScore();
// ゲームオーバー時にはゲームオーバーメッセージを描画
if (score1 >= winningScore || score2 >= winningScore) {
drawGameOver();
return;
}
// ボールの移動
ballX += ballDX;
ballY += ballDY;
// ボールの反射(上下の壁との衝突)
if (ballY + ballRadius > canvas.height || ballY - ballRadius < 0) {
ballDY = -ballDY;
}
// ボールの反射(プレイヤー1との衝突)
if (
ballX - ballRadius < playerWidth &&
ballY > player1Y &&
ballY < player1Y + playerHeight
) {
ballDX = -ballDX;
playSound(pongSound);
}
// ボールの反射(プレイヤー2との衝突)
if (
ballX + ballRadius > canvas.width - playerWidth &&
ballY > player2Y &&
ballY < player2Y + playerHeight
) {
ballDX = -ballDX;
playSound(pongSound);
}
// ボールが左側の壁に当たった場合(プレイヤー2が得点)
if (ballX - ballRadius < 0) {
score2++;
playSound(booSound);
resetBall();
}
// ボールが右側の壁に当たった場合(プレイヤー1が得点)
if (ballX + ballRadius > canvas.width) {
score1++;
playSound(booSound);
resetBall();
}
// プレイヤーの移動
if (keys[87]) {
// 上キー(プレイヤー1)
player1Y -= playerSpeed;
if (player1Y < 0) {
player1Y = 0;
}
}
if (keys[83]) {
// 下キー(プレイヤー1)
player1Y += playerSpeed;
if (player1Y + playerHeight > canvas.height) {
player1Y = canvas.height - playerHeight;
}
}
if (keys[38]) {
// Wキー(プレイヤー2)
player2Y -= playerSpeed;
if (player2Y < 0) {
player2Y = 0;
}
}
if (keys[40]) {
// Sキー(プレイヤー2)
player2Y += playerSpeed;
if (player2Y + playerHeight > canvas.height) {
player2Y = canvas.height - playerHeight;
}
}
requestAnimationFrame(draw);
}
// ボールをリセットする関数
function resetBall() {
ballX = canvas.width / 2;
ballY = canvas.height / 2;
ballDX = -ballDX;
ballDY = -ballDY;
}
// サウンドを再生する関数
function playSound(sound) {
sound.currentTime = 0;
sound.play();
}
// ゲームの初期化を行う
draw();
}
// ゲームの初期化を行う
initGame();
</script>
</body>
</html>