简体   繁体   中英

JavaScript canvas: “Random” errors with collision detection

Working on a simple canvas application where the user can shoot bullets with a gun. (click = new bullet, arrow key = new direction)

Works almost perfectly except there are seemingly "random" occurrences of where if the direction is changed, collision will fail.

Here's my jsFiddle . Relevant snippets:

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

Key handling:

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

How do I figure out why this is happening and how I can stop it?

Ok I had a look and found your bug.

You have bullets that you have given the property speed that is two values x, and y You also have a direction. When you animate the bullets you check the direction and move the bullet in the correct direction by adding only to x or y depending on direction. But then when you test if the bullets hit the wall you ignore the direction and test against the bullets speed. The whole time you have the bullets x and y speed both not equal to zero. You collision test is testing bullets moving diagonally.

If you add this bit of code

    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();

where you render the bullets, you will see that the bullets are not traveling in the direction indicated by this.velocity.speed , but you use these values to test for the wall.

There is to much to change for a simple fix.

What to do.

For each bullet Keep speed as a single number. Create delta.x , and delta.y as the bullets vector. Keep direction as a single value. As you already have.

When you shoot you use the direction to set the bullet vector (delta); up set delta {x:0,y:-1}, down set delta {x:0,y:1}, left set delta {x:-1,y:0}, right set delta {x:1,y:0},

To move the bullet just add the deltas times the speed;

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

Speed has nothing to do with direction. It is a positive value describing distance over time.

Delta x and y is really all you need for the bullets direction, but no harm in holding the direction as a single value as well as long as the two match.

To test for the wall

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

do the same for the y direction.

I don't know if it is your intention to change all the bullet directions when you press a key. If it is just go through all the bullets and change there deltas when a key is pressed.

Hope this is clear. Do ask if you need more info.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM