Javascript JS snake游戏中的碰撞检测漏洞
我想写一个蛇的变体,蛇从墙上弹下来 它大部分时间都有效,但偶尔蛇会逃跑,我不知道为什么。最初,我将collison检测函数中的不等式设置为严格意义上的不等式,我认为这是问题的原因,但我将它们更改为=并且问题仍然存在 有人能解释一下为什么会这样吗?在蛇逃跑之前,你通常要玩一分钟左右Javascript JS snake游戏中的碰撞检测漏洞,javascript,canvas,collision-detection,Javascript,Canvas,Collision Detection,我想写一个蛇的变体,蛇从墙上弹下来 它大部分时间都有效,但偶尔蛇会逃跑,我不知道为什么。最初,我将collison检测函数中的不等式设置为严格意义上的不等式,我认为这是问题的原因,但我将它们更改为=并且问题仍然存在 有人能解释一下为什么会这样吗?在蛇逃跑之前,你通常要玩一分钟左右 <canvas id="canvas" width=500 height=500 style="display: block; border: 1px solid green; margin: auto;">
<canvas id="canvas" width=500 height=500 style="display: block; border: 1px solid green; margin: auto;"></canvas>
<script>
var ctx = document.getElementById('canvas').getContext('2d');
ctx.font = '30px Arial';
var HEIGHT = 500;
var WIDTH = 500;
var SEGMENT_WIDTH = 30;
var snakeVelocity = {
i: 1,
j: 0
};
var snakeArray = createSnake();
function createSnake() {
var snakeArray = [];
var length = 5; // Initial length of snake
for (var i = 0; i < length; i++) {
snakeArray.push({
x: i + 1,
y: 1
});
}
return snakeArray;
}
function moveSnake(arr) {
var head = arr.slice(-1)[0];
var tail = arr[0];
var newHead = arr.shift();
// check for wall collision, which also updates velocity if needed
snakeWallCollision(head);
newHead.x = head.x + snakeVelocity.i;
newHead.y = head.y + + snakeVelocity.j;
arr.push(newHead);
return arr;
}
function snakeWallCollision(obj) {
var collision = false;
if (obj.x >= WIDTH / SEGMENT_WIDTH || obj.x <= 0) {
snakeVelocity.i *= -1;
collision = true;
}
if (obj.y >= HEIGHT / SEGMENT_WIDTH || obj.y <= 0) {
snakeVelocity.j *= -1;
collision = true;
}
return collision;
}
function drawSnake() {
console.log(snakeArray[0]);
for (var i = 0; i < snakeArray.length; i++) {
var segment = snakeArray[i];
ctx.fillText('S', segment.x * SEGMENT_WIDTH, segment.y * SEGMENT_WIDTH + 30);
}
}
function update() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
moveSnake(snakeArray);
drawSnake();
}
function checkKey(e) {
e = e || window.event;
if ([38, 40, 37, 39].includes(e.keyCode)) {
e.preventDefault();
}
if (e.keyCode == '38') {
snakeVelocity = {
i: 0,
j: -1
};
} else if (e.keyCode == '40') {
snakeVelocity = {
i: 0,
j: 1
};
} else if (e.keyCode == '37') {
snakeVelocity = {
i: -1,
j: 0
};
} else if (e.keyCode == '39') {
snakeVelocity = {
i: 1,
j: 0
};
}
}
document.onkeydown = checkKey;
setInterval(update, 1000 / 20);
drawSnake();
</script>
如果交换这些行,会发生什么情况:
newHead.x = head.x + snakeVelocity.i;
newHead.y = head.y + + snakeVelocity.j;
// check for wall collision, which also updates velocity if needed
snakeWallCollision(head);
问题似乎是,如果用户按下与碰撞检查同步的键,方向会改变两次,蛇就会越过墙 也许这个可以帮助你我添加了一个测试变量USER_ACTION来检查用户是否按下了键,如果是,不要执行冲突检查:
如果在撞到墙之前改变方向远离墙,则会出现问题 例如,假设蛇头刚刚移动到x=0,并在下一个更新帧之前向左移动,用户按向右箭头键。现在,蛇行速度。i设置为1,远离墙 然后测试墙壁
if (obj.x >= WIDTH / SEGMENT_WIDTH || obj.x <= 0) {
snakeVelocity.i *= -1; // negate the direction
// but the direction is already away from the
// wall due to user input. This will turn it back
// onto the wall
}
同样的情况也发生在上下
您需要让碰撞测试知道蛇的前进方向,然后根据该测试确定该移动是否会导致碰撞
如果允许蛇头按照当前状态移动,则更改测试功能以查找蛇头的下一个位置。只有当移动导致头部超出游戏边界时,你才能改变方向
function snakeWallCollision(head) {
var x = head.x + snakeVelocity.i; // find out where the head will be
var y = head.y + snakeVelocity.j; // next frame
if (x > WIDTH / SEGMENT_WIDTH || x < 0) {
snakeVelocity.i *= -1;
return true;
}
if (y > HEIGHT / SEGMENT_WIDTH || y < 0) {
snakeVelocity.j *= -1;
return true;
}
return false;
}
这似乎很好地解决了问题。谢谢。如果您使用snakeWallCollisionnewHead;,这看起来应该有效;,但我认为,由于newHead的值已经提交,蛇仍然逃脱了…不幸的是,这个问题仍然存在于这个版本中。无论如何,谢谢你。
function snakeWallCollision(head) {
var x = head.x + snakeVelocity.i; // find out where the head will be
var y = head.y + snakeVelocity.j; // next frame
if (x > WIDTH / SEGMENT_WIDTH || x < 0) {
snakeVelocity.i *= -1;
return true;
}
if (y > HEIGHT / SEGMENT_WIDTH || y < 0) {
snakeVelocity.j *= -1;
return true;
}
return false;
}