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\$
8
  • \$\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, 2018 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, 2018 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, 2018 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, 2018 at 12:18
  • \$\begingroup\$ Actually I have made it work should I post the code to it as an answer. \$\endgroup\$
    – Ameer
    Sep 27, 2018 at 12:20

3 Answers 3

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.

\$\endgroup\$
1
  • \$\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, 2018 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);
         }
      }
     }
\$\endgroup\$
0
-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.

\$\endgroup\$
2
  • \$\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, 2018 at 14:24
  • \$\begingroup\$ @DMGregory that is genius if you don't care about order! \$\endgroup\$
    – Ibrahim
    May 3, 2020 at 9:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .