gpt4 book ai didi

javascript - 贪吃蛇游戏 : how to check if the head collides with its own body

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:41:58 24 4
gpt4 key购买 nike

你可能玩过贪吃蛇,这是一款你必须吃食物才能成长的游戏,如果你撞到蛇的 body 或某些障碍物,你就会失败。第一部分很容易,但后者似乎不可能实现。

我尝试使用 for 循环检查我的蛇数组的最后一个元素是否与它的其他部分发生冲突。我的情况是这样的:如果我数组中最后一项的 x 位置大于任何数组项的 x 位置,并且小于它们的 x 位置加上它们的宽度,等等。那没有用。

这是我的代码:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<canvas id="myCanvas" width="200px" height="200px" style="border:1px solid black"/>
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var yPos = 20;
var width = 15;
var variable = 1;
var currentDir = 1;
//var xPos = (width+5)*variable;
var xPos = 20;
var myArr = [{myX:xPos,myY:yPos},{myX:xPos,myY:yPos},{myX:xPos,myY:yPos}];
var downPressed = false;
var upPressed = false;
var leftPressed = false;
var rightPressed = false;
var first = [0,20,40,60,80,100,120,140,160,180];
var firstX = Math.floor(Math.random()*10);
var firstY = Math.floor(Math.random()*10);
var okayed = first[firstX];
var notOkayed = first[firstY];
var maths = myArr[myArr.length-1];
function drawFood() {
ctx.beginPath();
ctx.rect(okayed,notOkayed,15,15);
ctx.fillStyle = "red";
ctx.fill();
ctx.closePath();
}

function drawRectangle() {

ctx.clearRect(0,0,200,200);
drawFood();

for(var i = 0;i<myArr.length;i++) {
ctx.beginPath();
ctx.rect(myArr[i].myX,myArr[i].myY,width,15);
ctx.fillStyle = "blue";
ctx.fill();
ctx.closePath();
}

requestAnimationFrame(drawRectangle);
}


setInterval("calledin()",100);
function calledin() {
var secondX = Math.floor(Math.random()*10);
var secondY = Math.floor(Math.random()*10);
var newobj = {myX:myArr[myArr.length-1].myX+20,myY:myArr[myArr.length-1].myY};
var newobjTwo = {myX:myArr[myArr.length-1].myX,myY:myArr[myArr.length-1].myY+20};
var newobjLeft = {myX:myArr[myArr.length-1].myX-20,myY:myArr[myArr.length-1].myY};
var newobjUp = {myX:myArr[myArr.length-1].myX,myY:myArr[myArr.length-1].myY-20};
var okayNewObj = {myX:myArr[1].myX - 20,myY:myArr[1].myY};


if(myArr[myArr.length-1].myX > 180 || myArr[myArr.length-1].myX < 0 || myArr[myArr.length-1].myY > 180 || myArr[myArr.length-1].myY < 0)
{alert("Game Over");window.location.reload();}

if(myArr[myArr.length-1].myX > okayed-5 && myArr[myArr.length-1].myX < okayed+20 && myArr[myArr.length-1].myY < notOkayed+20 &&
myArr[myArr.length-1].myY > notOkayed-5) {
okayed = first[secondX];
notOkayed = first[secondY];
myArr.unshift(okayNewObj);
}

if(currentDir == 1) {
myArr.push(newobj);
myArr.shift();}

if(currentDir == 2) {
myArr.push(newobjTwo);
myArr.shift();
}

if(currentDir == 4) {
myArr.push(newobjLeft);
myArr.shift();
}


if(currentDir == 3) {
myArr.push(newobjUp);
myArr.shift();
}

for(var i = 0;i<myArr.length-2;i++) {
if(myArr[myArr.length-1].myX > myArr[i].myX &&
myArr[myArr.length-1].myX < myArr[i].myX + 15 && myArr[myArr.length-1].myY > myArr[i].myY && myArr[myArr.length-1].myY > myArr[i].myY + 15)
{alert("Game over");window.location.reload();}
}

}


function downed(e) {
if(e.keyCode==40) {if(currentDir != 3) {currentDir = 2;}}
if(e.keyCode==38) {if(currentDir != 2) {currentDir = 3;}}
if(e.keyCode==39) {if(currentDir != 4) {currentDir = 1;}}
if(e.keyCode==37) {if(currentDir != 1) {currentDir = 4;}}

}

function upped(e) {
if(e.keyCode == 40) {downPressed = false;}
}
document.addEventListener("keydown",downed,false);
document.addEventListener("keyup",upped,false);

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

最佳答案

假设蛇由一个名为 snake 的数组表示,其中头部位于索引 snake.length - 1 处。我们必须将头部的位置与索引 0snake.length - 2 的 body 部分的位置进行比较。

如果蛇头与 body 部分发生碰撞,以下代码将 okay 设置为 false。否则,okay 仍然是 true

var head = snake[snake.length - 1],
x = head.x,
y = head.y,
okay = true;
for (var i = snake.length - 2; i >= 0; --i) {
if (snake[i].x == x && snake[i].y == y) {
okay = false;
break;
}
}

下面是一个片段,我在其中修改了您的代码以阐明游戏逻辑并简化许多计算。

我没有直接使用 Canvas 坐标,而是使用虚拟网格单元格的列索引 x 和行索引 y 表示每个位置。这让我们可以通过将 1 或 -1 添加到 xy 来计算相邻的网格位置。当需要绘制 Canvas 时,我们将虚拟坐标乘以单元格大小。

我已经用变量替换了你的大部分文字值。例如,我们可以这样做,而不是将 Canvas 尺寸设置为 200 x 200:

canvas.width = numCols * cellSize;
canvas.height = numRows * cellSize;

这让我们可以在一个地方更改 numColsnumRows 以调整整个游戏网格的大小。所有的计算都成功了,因为它们评估变量而不是使用文字。

除了箭头键之外,我还更改了键事件处理以识别 W-A-S-D 键的键码。当游戏嵌入到一个长网页中时(如此处所示),您可能需要使用 W-A-S-D 键,这样页面就不会在您玩游戏时上下滚动。

var canvas,
ctx,
currentDir,
startX = 1,
startY = 1,
startSnakeLength = 3,
snake,
cellSize = 18,
cellGap = 1,
foodColor = '#a2302a',
snakeBodyColor = '#2255a2',
snakeHeadColor = '#0f266b',
numRows = 10,
numCols = 10,
canvasWidth = numCols * cellSize,
canvasHeight = numRows * cellSize;

var food = {};

function placeFood() {
// Find a random location that isn't occupied by the snake.
var okay = false;
while (!okay) {
food.x = Math.floor(Math.random() * numCols);
food.y = Math.floor(Math.random() * numRows);
okay = true;
for (var i = 0; i < snake.length; ++i) {
if (snake[i].x == food.x && snake[i].y == food.y) {
okay = false;
break;
}
}
}
}

function paintCell(x, y, color) {
ctx.fillStyle = color;
ctx.fillRect(x * cellSize + cellGap,
y * cellSize + cellGap,
cellSize - cellGap,
cellSize - cellGap);
}

function paintCanvas() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
paintCell(food.x, food.y, foodColor);
var head = snake[snake.length - 1];
paintCell(head.x, head.y, snakeHeadColor);
for (var i = snake.length - 2; i >= 0; --i) {
paintCell(snake[i].x, snake[i].y, snakeBodyColor);
}
}

function updateGame() {
var head = snake[snake.length - 1],
x = head.x,
y = head.y;

// Move the snake.
var tail = snake.shift();
switch (currentDir) {
case 'up':
snake.push(head = { x: x, y: y - 1 });
break;
case 'right':
snake.push(head = { x: x + 1, y: y });
break;
case 'down':
snake.push(head = { x: x, y: y + 1 });
break;
case 'left':
snake.push(head = { x: x - 1, y: y });
break;
}
paintCanvas();
x = head.x;
y = head.y;

// Check for wall collision.
if (x < 0 || x >= numCols || y < 0 || y >= numRows) {
stopGame('wall collision');
return;
}

// Check for snake head colliding with snake body.
for (var i = snake.length - 2; i >= 0; --i) {
if (snake[i].x == x && snake[i].y == y) {
stopGame('self-collision');
return;
}
}

// Check for food.
if (x == food.x && y == food.y) {
placeFood();
snake.unshift(tail);
setMessage(snake.length + ' segments');
}
}

var dirToKeyCode = { // Codes for arrow keys and W-A-S-D.
up: [38, 87],
right: [39, 68],
down: [40, 83],
left: [37, 65]
},
keyCodeToDir = {}; // Fill this from dirToKeyCode on page load.

function keyDownHandler(e) {
var keyCode = e.keyCode;
if (keyCode in keyCodeToDir) {
currentDir = keyCodeToDir[keyCode];
}
}

function setMessage(s) {
document.getElementById('messageBox').innerHTML = s;
}

function startGame() {
currentDir = 'right';
snake = new Array(startSnakeLength);
snake[snake.length - 1] = { x: startX, y: startY };
for (var i = snake.length - 2; i >= 0; --i) {
snake[i] = { x: snake[i + 1].x, y: snake[i + 1].y + 1 };
}
placeFood();
paintCanvas();
setMessage('');
gameInterval = setInterval(updateGame, 200);
startGameButton.disabled = true;
}

function stopGame(message) {
setMessage(message + '<br> ended with ' + snake.length + ' segments');
clearInterval(gameInterval);
startGameButton.disabled = false;
}

var gameInterval,
startGameButton;

window.onload = function () {
canvas = document.getElementById('gameCanvas'),
ctx = canvas.getContext('2d');
canvas.width = numCols * cellSize;
canvas.height = numRows * cellSize;
Object.keys(dirToKeyCode).forEach(function (dir) {
dirToKeyCode[dir].forEach(function (keyCode) {
keyCodeToDir[keyCode] = dir;
})
});
document.addEventListener("keydown", keyDownHandler, false);
startGameButton = document.getElementById('startGameButton');
startGameButton.onclick = startGame;
}
body {
font-family: sans-serif;
}
#gameCanvas {
border: 1px solid #000;
float: left;
margin-right: 15px;
}
#startGameButton, #messageBox {
font-size: 16px;
margin-top: 15px;
}
#messageBox {
line-height: 24px;
}
<canvas id="gameCanvas"></canvas>

<button id="startGameButton">Start game</button>

<div id="messageBox"></div>

关于javascript - 贪吃蛇游戏 : how to check if the head collides with its own body,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34469763/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com