<!DOCTYPE html>
<html lang="ja">
<!-- 蛇ゲーム 画面外は反対側に出現 ゲームオーバーをつけた -->
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Retro Snake Game Final</title>
<style>
body {
background-color: #222;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
color: white;
font-family: 'Courier New', Courier, monospace;
position: relative;
}
#scoreBoard {
font-size: 24px;
margin-bottom: 10px;
}
canvas {
border: 2px solid #555;
box-shadow: 0 0 20px rgba(0, 255, 255, 0.2);
background-color: #000;
}
#gameOverScreen {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
background-color: rgba(0, 0, 0, 0.85);
padding: 30px;
border: 2px solid #fff;
z-index: 10;
min-width: 200px;
}
#gameOverScreen h2 {
color: red;
font-size: 36px;
margin-top: 0;
}
#replayBtn {
padding: 10px 20px;
font-size: 18px;
font-family: inherit;
cursor: pointer;
background-color: #fff;
border: none;
color: #000;
margin-top: 20px;
width: 100%;
}
#replayBtn:hover {
background-color: #ccc;
}
/* 開始時のメッセージ */
#startMessage {
margin-top: 10px;
color: #888;
font-size: 14px;
}
</style>
</head>
<body>
<div id="scoreBoard">Score: <span id="scoreVal">0</span></div>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div id="startMessage">矢印キーを押してスタート</div>
<div id="gameOverScreen">
<h2>GAME OVER</h2>
<p>Final Score: <span id="finalScore">0</span></p>
<button id="replayBtn">REPLAY</button>
</div>
<script>
let canvas, ctx;
let gameInterval;
const gs = 20; // グリッドサイズ
const tc = 20; // タイルカウント
let px, py;
let ax, ay;
let xv, yv;
let trail;
let tail;
let score;
let isGameOver = false;
let isGameStarted = false; // ゲームが開始されたかどうかのフラグ
window.onload = function() {
canvas = document.getElementById("gameCanvas");
ctx = canvas.getContext("2d");
document.addEventListener("keydown", keyPush);
document.getElementById("replayBtn").addEventListener("click", resetGame);
resetGame();
}
function resetGame() {
px = py = 10;
ax = ay = 15;
xv = yv = 0;
trail = [];
tail = 5;
score = 0;
isGameOver = false;
isGameStarted = false; // リセット時は未開始状態にする
updateScore(0);
document.getElementById("gameOverScreen").style.display = "none";
document.getElementById("startMessage").style.visibility = "visible"; // メッセージ表示
clearInterval(gameInterval);
gameInterval = setInterval(game, 1000 / 15);
}
function game() {
px += xv;
py += yv;
if (px < 0) px = tc - 1;
if (px > tc - 1) px = 0;
if (py < 0) py = tc - 1;
if (py > tc - 1) py = 0;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "lime";
for (var i = 0; i < trail.length; i++) {
ctx.fillRect(trail[i].x * gs, trail[i].y * gs, gs - 2, gs - 2);
// 【修正箇所】
// ゲームが始まっていて(動いていて)、かつ自分の体に当たったらゲームオーバー
// start状態かつ衝突判定
if (isGameStarted && trail[i].x == px && trail[i].y == py) {
gameOver();
return;
}
}
trail.push({ x: px, y: py });
while (trail.length > tail) {
trail.shift();
}
ctx.fillStyle = "cyan";
ctx.fillRect(ax * gs + 1, ay * gs + 1, gs - 4, gs - 4);
if (ax == px && ay == py) {
tail++;
score += 10;
updateScore(score);
do {
ax = Math.floor(Math.random() * tc);
ay = Math.floor(Math.random() * tc);
} while(isPositionOnSnake(ax, ay));
}
}
function isPositionOnSnake(x, y) {
for (let i = 0; i < trail.length; i++) {
if (trail[i].x === x && trail[i].y === y) {
return true;
}
}
return false;
}
function updateScore(newScore) {
document.getElementById("scoreVal").innerText = newScore;
}
function gameOver() {
isGameOver = true;
clearInterval(gameInterval);
document.getElementById("finalScore").innerText = score;
document.getElementById("gameOverScreen").style.display = "block";
document.getElementById("startMessage").style.visibility = "hidden";
}
function keyPush(evt) {
if (isGameOver) return;
// キーが押されたらゲーム開始フラグを立てる
if (!isGameStarted) {
isGameStarted = true;
document.getElementById("startMessage").style.visibility = "hidden";
}
switch (evt.keyCode) {
case 37:
if (xv !== 1) { xv = -1; yv = 0; }
break;
case 38:
if (yv !== 1) { xv = 0; yv = -1; }
break;
case 39:
if (xv !== -1) { xv = 1; yv = 0; }
break;
case 40:
if (yv !== -1) { xv = 0; yv = 1; }
break;
}
}
</script>
</body>
</html>
使用変数
| ax | |
| ay | |
| canvas | |
| charset | |
| content | |
| ctx | |
| display | |
| fillStyle | |
| game -------( Function ) | |
| gameInterval | |
| gameOver -------( Function ) | |
| gs | |
| height | |
| i | |
| id | |
| innerText | |
| isGameOver | |
| isGameStarted | |
| isPositionOnSnake -------( Function ) | |
| keyPush -------( Function ) | |
| lang | |
| name | |
| onload | |
| px | |
| py | |
| resetGame -------( Function ) | |
| scale | |
| score | |
| tail | |
| tc | |
| trail | |
| updateScore -------( Function ) | |
| visibility | |
| width | |
| x | |
| xv | |
| y | |
| yv |