Javascript game hit detection only works on first object

Viewed 49

I've been a lurker for a long time but just registered here. This site has helped tremendously with work and personal projects involving VBA, PHP, MySQL and CSS.

I am in the early stages of learning Javascript and I learn best by tackling real projects so I'm working on a Galaga-style game with a Coronavirus theme called Coronaga. I followed along with the HTML/JS game tutorial on w3schools so the general framework started out like their example game. I'd prefer to be able to use arrays of objects to make for actual lengthy and challenging gameplay without lots of repetitive code but that's another battle for another time.

I've got five "baddies" displaying and moving in downward circles towards the protagonist, but despite lots of fiddling with the hit detection code I can only get it to work on the leftmost "baddie". I previously had it working on other "baddies" but you had to hit the left one first so that was useless.

I'm using SVG images for the objects, so CodePen is not really an effective demo, but it's live at this link: http://hwmp.hopto.org:100/coronaga/coronaga.html

I've also put all the code and resources on GitHub: https://github.com/jonbuder/coronaga

Here's the game area update including hit detection code:

function updateGameArea() {
    
    myGameArea.clear();
    //myScore.text = "SCORE: ";
    //myScore.update();
    
    ctx = myGameArea.context;
    ctx.font = '20px Consolas';
    ctx.fillStyle = '#FFFFFF';
    ctx.fillText(("Coronavirus: " + score +"   Humanity: " + peoplePoint), 80, 20);
    

    myGamePiece.speedX = 0;
    myGamePiece.speedY = 0;    
    if (myGameArea.key && myGameArea.key == 37) {myGamePiece.speedX = -4; }
    if (myGameArea.key && myGameArea.key == 39) {myGamePiece.speedX = 4; }
    if (myGameArea.key && myGameArea.key == 38) {myGamePiece.speedY = -4; }
    if (myGameArea.key && myGameArea.key == 40) {myGamePiece.speedY = 4; }
    myGamePiece.newPos();    
    myGamePiece.update();
    myBaddie1.newPos();
    myBaddie1.update();
    myBaddie2.newPos();
    myBaddie2.update();
    myBaddie3.newPos();
    myBaddie3.update();
    myBaddie4.newPos();
    myBaddie4.update();
    myBaddie5.newPos();
    myBaddie5.update();
    //myVirus.newPos();
   if (myGameArea.key && myGameArea.key == 32) {myVirus.launch(); }
    myVirus.reloadVirus();
    myVirus.newPos();
    myVirus.update();
    
    
    if  (score < 5) {
    if (myVirus.crashWith(myBaddie1) == 1) { myBaddie1.hit(); score++; myVirus.reloadVirus(); }
    else { myVirus.reloadVirus(); }
    if (myVirus.crashWith(myBaddie2) == 1) { myBaddie2.hit(); score++; myVirus.reloadVirus(); }
    else { myVirus.reloadVirus(); }
    if (myVirus.crashWith(myBaddie3) == 1) { myBaddie3.hit(); score++; myVirus.reloadVirus(); }
    else { myVirus.reloadVirus(); }
    if (myVirus.crashWith(myBaddie4) == 1) { myBaddie4.hit(); score++; myVirus.reloadVirus(); }
    else { myVirus.reloadVirus(); }
    if (myVirus.crashWith(myBaddie5) == 1) { myBaddie5.hit(); score++; myVirus.reloadVirus(); }
    
    }

    //else { myVirus.reloadVirus(); }
    /*else { hit = 0;}
     if (myVirus.crashWith(wave1[1]) == 1) { 
        baddieVar = "myBaddie";
        wave1[1].hit();
        score++;
    }*/
    if (myBaddie1.y >= 640) {
            peoplePoint++;
        }

       

    
    //myBaddie = new baddie(30, 70, "baddie.svg", 200, 100, "image");
    //myBaddie2 = new baddie2(30, 70, "baddie.svg", 240, 180, "image");
    
    
    
}

Here's the baddie object creations:

myBaddie1 = new baddie(30, 70, "baddie.svg", 20, 100, "image", "1");
    myBaddie2 = new baddie(30, 70, "baddie.svg", 80, 100, "image", "1");
    myBaddie3 = new baddie(30, 70, "baddie.svg", 140, 100, "image", "1");
    myBaddie4 = new baddie(30, 70, "baddie.svg", 200, 100, "image", "1");
    myBaddie5 = new baddie(30, 70, "baddie.svg", 260, 100, "image", "1");

And the baddie function:

function baddie(width, height, color, x, y, type) {
        this.type = type;
        if (type == "image") {
            this.image = new Image();
            this.image.src = color;
        }
        this.width = width;
        this.height = height;
        this.speed = 1;
        this.angle = 0;
        this.moveAngle = 1;
        this.x = x;
        this.y = y;
        this.hit = function()
        {
            hitCode = 1;
            //this.baddienum = num;
            //var whichBaddie = "MyBaddie" + baddienum;
            this.x = -666;
            this.y = -666;          
        }


        this.update = function() {
            
            
            ctx = myGameArea.context;
            if (type == "image") {
                ctx.drawImage(this.image,
                    this.x,
                    this.y,
                    this.width, this.height);
            } else {
                ctx.fillStyle = '#000000';
                ctx.fillRect(this.x, this.y, this.width, this.height);
            }
        } 
        
    
        this.newPos = function() {
            this.angle += this.moveAngle * Math.PI / 180;
            this.x += this.speed * Math.sin(this.angle);
            this.y -= this.speed * Math.cos(this.angle);
            this.y += 0.2;
        }
        if (this.y >= 640) { peoplePoint++; }

        

        
    }

Thank you in advance! This'll be an open-source project and I hope people will get a kick out of it and want to pitch in with making in better.

-Jon

edit to add myVirus.CrashWith code

this.crashWith = function(otherobject) {
      var tip = myAimVirusY;
      var leftedge = myAimVirusX;
      var rightedge = (myAimVirusX + 30);
      var otherbottom = otherobject.y + (otherobject.height);
      var otherleft = otherobject.x;
      var otherright = (otherobject.x + 30);
      if (hit == 0) {
      if(tip <= otherbottom) { 
            if(leftedge <= otherright) {
                
                hit = 1;
                //return hit;
                myAimVirusX = -999;
                myAimVirusY = -999;
                
            }
            else { hit = 0; delete myVirus;}
            if(rightedge >= otherleft) {
                
                hit = 1;
                //return hit;
                myAimVirusX = -999;
                myAimVirusY = -999;
                
            }
            else { hit = 0;}
                             } 
      return hit;
      hit = 0;
      tip = 0;
      //leftedge = 0;
      //rightedge = 0;
      otherbottom = 0;
      otherleft = 0;
      otherright = 0;

    }
1 Answers

OK so if you don't mind, I will try to answer this question in a general way, and the specific code used to make this game can try to adapt to it.

Basically, assuming you want to do bounding-box collision (box to box) you need to check the x and y of each, and the width and height of each.

meaning, assuming I have two objects, each object has x, y, width and height properties, with x and y being at the top left corner, then to check if they are colliding, make a function:

function areBoxesColliding(box1, box2) {
    return (
        box1.x < box2.x + box2.width &&
        box1.x + box1.width > box2.x &&
        box1.y < box2.y + box2.height &&
        box1.y + box1.height > box2.y
    )
}

now, whenever you want to check if two object are hitting (Whether it be the bullet, or the character itself), just first make sure that each objet has the x, y, width and height properties, that match up to their actual position and size, then in the loop (or whenever you are checking), simply check

if(areBoxesColliding(someObjectLikePlayerOrBullet, someObjectLikeAnEnemy)) doIt();

just adapt this basic method to your current code, I don't know what myVirus.crashWith looks like in your code, but just make sure its like this, basically, as well as the code that checks if your bullet hits the enemy.

And BTW you mentioned putting your characters in arrays another time, but its really quite simple, just make a class constructor for each enemy, loop through that list when rendering, and loop through it when checking for collisions, and when u want to add a new enemy, just call .push to the array

Related