1
votes

I realize this may be a common question however after looking at the other answers i'm not sure my implementation benefits from the answers.

My game has the player shooting from its X Y position towards the mouse X Y position, with the enemies falling linearly down the Y axis.

However it seems only the first shot or a random shot in on the screen will sometimes hit and remove an enemy, with some bullets passing straight through with a direct hit and not invoking the removal of the enemy.

The game can be seen here: https://liammorgan.github.io/wave_defence/

And the snippet for hit detection is here, which works around 20% of the time, or on the first bullet shot.

Each shot has an X,Y,bulletSpeed, xVelocity, yVelocity

Each enemy has an X,Y,speed

shot.js -
this.hit = function() {
        for(enemy in enemies) {
            let e = enemies[enemy];
            if(e != null) {             
                if(this.x+this.size > e.x && this.x-this.size < e.x && 
                this.y+this.size > e.y && this.y-this.size < e.y) {
                    enemies[enemy] = null;
                    return true;                    
                } else {
                    return false;
                }
            }
        }
    }

sketch.js -
let shots = [];
let enemies = [];
if(player.lives > 0) {
        player.update();
        player.draw();
        for(shot in shots) {
            let s = shots[shot];
            if(s != null) {                
                if(s.hit() && s != null) {
                    shots[shot] = null;
                    continue;
                }
                shots[shot].update();
                shots[shot].draw();
                if(s.remove() && s != null) {
                    shots[shot] = null;
                }
            }
        }
    }
1
Collision detection can be niggly. What if your bullet of diameter 2 moves from [5,10] to [5, 20] in one game tick, when the target is at [5,15]? Maybe you need to check if the target is on a line between the current and last bullet positions. But that's more code. Put together a tiny demo that demonstrates the problem. Make it log coordinates -- or just step through the scenario in a debugger -- work out the actual problem, then decide what approach to collision detection your game needs. - slim
Your code also assumes that all game objects are rectangular. This might be good enough for your game, or it might not be. Some of the classic Japanese shooters have complicated shaped sprites, but the hit area is a square in the middle of the sprite. - slim
Further to the fast-moving-object issue I mentioned above -- you can of course work around it by setting a speed limit, ensuring no object moves fast enough that it can pass over an enemy. - slim
@slim that was my first thought, however i tried setting speeds of enemy and shots to 1 and they still would pass through, i find it weird that if firing slowly the first bullet will always hit properly, makes me think its a looping issue. - Liam Morgan
Use a debugger. - slim

1 Answers

2
votes

It seems to me that in your collision logic, you're not accounting for the size of the enemy itself. So for the collision to count, the shot has to PERFECTLY hit almost the exact center of the enemy.

A better way to do it would be to measure the distance from the center the bullet to the center of the enemy, and check that to their known sizes, since both the enemy and bullet are circles. This also means that you would have to include a radius or size field to the enemy objects.