Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript JS snake游戏中的碰撞检测漏洞_Javascript_Canvas_Collision Detection - Fatal编程技术网

Javascript JS snake游戏中的碰撞检测漏洞

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;">

我想写一个蛇的变体,蛇从墙上弹下来

它大部分时间都有效,但偶尔蛇会逃跑,我不知道为什么。最初,我将collison检测函数中的不等式设置为严格意义上的不等式,我认为这是问题的原因,但我将它们更改为=并且问题仍然存在

有人能解释一下为什么会这样吗?在蛇逃跑之前,你通常要玩一分钟左右

<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;
}