1
\$\begingroup\$

I am currently working on a basic space invaders game. So far I have created the enemies, a main character, and a laser beam, collision detection between enemy and bullet, however when my bullet collides with my enemy sometimes one enemy is destroyed other times all or a couple of enemies are destroyed. Can you please inform me in what I am doing wrong.

this.crashWith = function(otherobj) {
    var myleft = this.x;
    var myright = this.x + (this.width);
    var mytop = this.y;
    var mybottom = this.y + (this.height);
    var otherleft = otherobj.x;
    var otherright = otherobj.x + (otherobj.width);
    var othertop = otherobj.y;
    var otherbottom = otherobj.y + (otherobj.height);
    var crash = true;
    if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) {
        crash = false;
    }
    return crash;
}
}

 function updateGameArea() {
var x, y;
for (y = 0; y < myObstacles.length; y += 1) {
    if (myGamePiece.crashWith(myObstacles[y])) {
        var ctx = myGameArea.context;
         ctx.fillText("Game Over", 150, 150);
         myGameArea.stop();

    } 
 for (i = 0; i < bullets.length; i += 1) {
  if(myObstacles[y].crashWith(bullets[i])) {
   myObstacles.splice(myObstacles[y], 1);
}
}
}

Thank you in advance.

\$\endgroup\$
  • \$\begingroup\$ It looks like you've found a way to check your game piece against all obstacles. Have you tried doing the same thing for each bullet in the bullets array? \$\endgroup\$ – DMGregory Sep 26 '18 at 15:10
  • \$\begingroup\$ No not yet however I'll try that now. Does it work by checking crash detection then splicing the bullet. \$\endgroup\$ – Ameer Sep 27 '18 at 12:12
  • \$\begingroup\$ You mean using array.splice to remove a bullet once it's hit something and expired, so that it no longer needs further simulation? That's certainly not forbidden to you. \$\endgroup\$ – DMGregory Sep 27 '18 at 12:17
  • \$\begingroup\$ I am not familiar with the splice function, can you explain a little more how I would be able to use it. \$\endgroup\$ – Ameer Sep 27 '18 at 12:18
  • \$\begingroup\$ Actually I have made it work should I post the code to it as an answer. \$\endgroup\$ – Ameer Sep 27 '18 at 12:20
0
\$\begingroup\$

When you splice array, you remove the element. In your case, you are iterating over 'myObstacles' from 0 to length-1. When splicing arrray in such manner you need to iterate from length-1 to 0, so the indexes od 'myObstacles' are not changed. Like this:

for (y = myObstacles.length - 1; y >=0; y--)

Then you continue to iterate bullets over the myObstacles[y], which might at that point already be removed. After splicing array, you need to break from the for loop.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I deleted the answer due to destroying all the enemies when destroying one, however i have found a new one. \$\endgroup\$ – Ameer Nov 17 '18 at 19:17
0
\$\begingroup\$

The way I solved this is by splicing one enemy from the array of enemies when they collide with the bullet array. Then I would splice one bullet as well. Below is the basic collision and removal of the enemy.

this.crashWith = function(otherobj) {
    var myleft = this.x;
    var myright = this.x + (this.width);
    var mytop = this.y;
    var mybottom = this.y + (this.height);
    var otherleft = otherobj.x;
    var otherright = otherobj.x + (otherobj.width);
    var othertop = otherobj.y;
    var otherbottom = otherobj.y + (otherobj.height);
    var crash = true;
    if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) {
        crash = false;
    }
    return crash;
}
}

  function updateGameArea() {
   var x, height, gap, minHeight, maxHeight, minGap, maxGap;
   for (y = 0; y < myObstacles.length; y += 1) {
        if (myGamePiece.crashWith(myObstacles[y])) {
           myGameArea.stop();
           return;
       } 
     for (i = 0; i < bullets.length; i += 1) {
        if(myObstacles[y].crashWith(bullets[i])) {
          myObstacles.splice(y, 1);
          bullets.splice(i, 1);
         }
      }
     }
| improve this answer | |
\$\endgroup\$
-1
\$\begingroup\$

You can try to use other iterable objects than arrays, they allow faster and easier deletion and accessing of elements, which makes them more suitable for handling collections of game objects. Check Map or Set API.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Myself, I would generally not recommend maps or sets for maintaining a local collection of objects for collision checks. They're usually considerably slower to iterate over. We can get fast removal with arrays by swapping the item to be removed to the last occupied index then decreasing our occupied index count. \$\endgroup\$ – DMGregory Nov 14 '18 at 14:24
  • \$\begingroup\$ @DMGregory that is genius if you don't care about order! \$\endgroup\$ – Ibrahim May 3 at 9:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.