JavaScript画布:碰撞检测中的“随机”错误

时间:2015-11-05 06:42:03

标签: javascript html5 canvas

使用简单的画布应用程序,用户可以用枪射击子弹。 (click = new bullet,arrow key = new direction)

几乎完美地工作除了看似“随机”出现的情况如果方向改变了,碰撞就会失败。

这是我的jsFiddle。相关摘要:

Bullet.prototype - animate():

animate: function () {
    if (gun.velocity.direction === keys.left) {
        this.coordinates.x -= this.velocity.speed.x;
    } else if (gun.velocity.direction === keys.up) {
        this.coordinates.y += this.velocity.speed.y;
    } else if (gun.velocity.direction === keys.right) {
        this.coordinates.x += this.velocity.speed.x;
    } else if (gun.velocity.direction === keys.down) {
        this.coordinates.y -= this.velocity.speed.y;
    }
    return this;
},

Bullet.prototype - collision():

collision: function (str) {
    if (str === 'boundary') {
        if (this.coordinates.x + this.velocity.speed.x > canvas.width || this.coordinates.x + this.velocity.speed.x < 0) {
                this.velocity.speed.x = -this.velocity.speed.x;
            } else if (this.coordinates.y + this.velocity.speed.y > canvas.height || this.coordinates.y + this.velocity.speed.y < 0) {
                this.velocity.speed.y = -this.velocity.speed.y;
            }
        }
    }

钥匙处理:

document.onkeydown = function (e) {
    e = e.keyCode;
    if (e === keys.left) {
        gun.velocity.direction = keys.left;
    } else if (e === keys.up) {
        gun.velocity.direction = keys.up;
    } else if (e === keys.right) {
        gun.velocity.direction = keys.right;
    } else if (e === keys.down) {
        gun.velocity.direction = keys.down;
    }
};

我如何弄清楚为什么会发生这种情况以及如何阻止它?

1 个答案:

答案 0 :(得分:1)

好的,我看了一下,发现了你的错误。

你有子弹,你已经给出了两个值x的属性速度,你也有一个方向。当您为子弹设置动画时,您可以检查方向并通过仅根据方向添加到x或y来以正确的方向移动子弹。但是当你测试子弹击中墙壁时,你会忽略方向并测试子弹速度。你有子弹x和y的速度都不等于零。你的碰撞测试是测试对角移动的子弹。

如果你添加这段代码

    ctx.strokeStyle = this.color;
    ctx.beginPath();
    // draw a line in the direction you are testing the wall to be
    ctx.moveTo(this.coordinates.x, this.coordinates.y);
    ctx.lineTo(this.coordinates.x + this.velocity.speed.x*10, this.coordinates.y + this.velocity.speed.y*10);
    ctx.stroke();

在渲染项目符号的情况下,您会看到项目符号没有按this.velocity.speed指示的方向行进,但您可以使用这些值来测试墙。

要进行简单的修复,还有很多需要改变的地方。

怎么做。

每个子弹 将速度保持为单个数字。 创建delta.xdelta.y作为项目符号向量。 将方向保持为单个值。正如你已经拥有的那样。

拍摄时,使用方向设置子弹矢量(delta); up set delta {x:0,y:-1}, 下集delta {x:0,y:1}, left set delta {x:-1,y:0}, 右设置delta {x:1,y:0},

要移动子弹,只需按速度添加增量;

bullet.pos.x += bullet.delta.x * bullet.speed;
bullet.pos.y += bullet.delta.y * bullet.speed;

速度与方向无关。它是描述距离随时间变化的正值。

Delta x和y实际上是你所需要的子弹方向,但是将方向保持为单个值并且只要两个匹配就没有任何害处。

测试墙壁

// check if the bullet is moving in the x direction 
// then check if it's about to hit the wall
if(bullet.delta.x !== 0 && (bullet.pos.x + bullet.delta.x * bullet.speed > wallLoc ||
    bullet.pos.x + bullet.delta.x * bullet.speed < 0)){
     bullet.delta.x = -bullet.delta.x; // reverse bullet
}

为y方向做同样的事。

我不知道当你按一个键时是否打算更改所有子弹方向。如果它只是通过所有子弹并在按下​​键时改变那些增量。

希望这很清楚。请问您是否需要更多信息。