Jump to content

Laser keeps hitting enemies even though destroyed


Ninjadoodle
 Share

Recommended Posts

Hi @enpu / Panda People

I'm not really sure what I'm doing wrong here. I'm trying to remove a laser when it hits an enemy, but it seems like the sprite gets removed and the laser keeps destroying enemies even though its gone.

Here is how I set it up ...

game.createClass('Laser', {
    
    init: function() {
        
        this.sprite = new game.Sprite('spinvader.png');
        
        this.sprite.position.set(game.scene.playerShip.sprite.x, game.scene.playerShip.sprite.y);
        this.sprite.anchorCenter();
        this.sprite.scale.set(0.5);
        this.sprite.rotation = game.scene.playerShip.sprite.rotation;
        this.sprite.addTo(game.scene.mg);
        
        game.Timer.add(10000, function() {
            this.remove();
        }.bind(this.sprite));
    },
    
    update: function() {
        
        this.sprite.position.x += game.scene.laserSpeed * Math.cos(this.sprite.rotation - (0.5 * Math.PI)) * game.delta;
        this.sprite.position.y += game.scene.laserSpeed * Math.sin(this.sprite.rotation - (0.5 * Math.PI)) * game.delta;
        
        for (var i = 0; i < game.scene.spinvaders.length; i++) {
            var enemy = game.scene.spinvaders[i];
            var distance = this.sprite.position.distance(enemy.sprite.position);
            if (distance < 64 + 128) {
                game.Tween.stopTweensForObject(enemy.sprite)
                game.scene.spinvaders.erase(enemy);
                enemy.sprite.remove();
                this.sprite.remove();
            }
        }
    }
});

Thank you for any feedback :)

Link to comment
Share on other sites

Just removing the sprite won't stop scene from calling laser's update function (it keeps checking for more collisions). You can use removeObject to do that:

https://www.panda2.io/examples#scene-removeObject

Also as said above, removing elements from array while in for loop should be done in reverse. Otherwise you might skip some elements in the array. 

Also your Timer also just removes the sprite.

I would add custom remove function to both Laser and Enemy (or whatever you have named it) classes to keep everything clean:

game.createClass('Laser', {
    init: function() {
        this.sprite = new game.Sprite('spinvader.png');
        
        this.sprite.position.set(game.scene.playerShip.sprite.x, game.scene.playerShip.sprite.y);
        this.sprite.anchorCenter();
        this.sprite.scale.set(0.5);
        this.sprite.rotation = game.scene.playerShip.sprite.rotation;
        this.sprite.addTo(game.scene.mg);
        
        game.Timer.add(10000, this.remove.bind(this));
    },
    
    remove: function() {
        this.sprite.remove();
        game.scene.removeObject(this);
    },
    
    update: function() {
        this.sprite.position.x += game.scene.laserSpeed * Math.cos(this.sprite.rotation - (0.5 * Math.PI)) * game.delta;
        this.sprite.position.y += game.scene.laserSpeed * Math.sin(this.sprite.rotation - (0.5 * Math.PI)) * game.delta;
        
        // Reverse for loop
        for (var i = game.scene.spinvaders.length - 1; i >= 0; i--) {
            var enemy = game.scene.spinvaders[i];
            var distance = this.sprite.position.distance(enemy.sprite.position);
            if (distance < 64 + 128) {
                enemy.remove();
                this.remove();
            }
        }
    }
});

game.createClass('Enemy', {
    remove: function() {
        game.Tween.stopTweensForObject(this.sprite);
        game.scene.spinvaders.erase(this);
        this.sprite.remove();
    }
});

 

Link to comment
Share on other sites

Hi @enpu

Thanks that's nice of you!

I guess I understand why you have to remove both the sprite and the object (even though it doesn't really make sense to me). I guess the sprite is just a visual representation of the object, but the object holds all the properties (eg. height / height).

remove: function() {
    this.sprite.remove();
    game.scene.removeObject(this);
},

I don't really understand what this does ...

game.scene.spinvaders.erase(this);

Also, I don't get why you have to reverse loop to destroy.

Thanks heaps!

Link to comment
Share on other sites

1 hour ago, Ninjadoodle said:

I don't really understand what this does ...


game.scene.spinvaders.erase(this);

Also, I don't get why you have to reverse loop to destroy.

I didn't understand erase either, so what did I do. I went to the panda github, looked how erase was defined, and it's just a splice helper.
That means it alters an array. And thus messes up your spinvaders.length, and your index. Try to figure out the next and last index when you remove something inbetween...
Javascript is very forgiving, in compiled languages this would give at least an out of bounds, and probably a segment violation error.

Link to comment
Share on other sites

@Ninjadoodle

Let me try to explain why you should reverse loop when removing items from array.

First let's say we have a simple array that contains four strings:

var array = [
    'one',
    'two',
    'three',
    'four'
];

Now when we start to go through the array with for loop, starting from index 0 (first item). In the first loop we are at the string 'one':

var array = [
    'one', // <-- For loop is at index 0
    'two',
    'three',
    'four'
];

Then in the second loop we are at index 1, which is the string 'two'

var array = [
    'one',
    'two', // <-- For loop is at index 1
    'three',
    'four'
];

Now if while in that loop we remove the item at index 1 (string 'two'), JavaScript will re-index the array so it will then look like this:

var array = [
    'one',
    'three',  // <-- For loop is at index 1
    'four'
];

Now if we continue the for loop to next index.

var array = [
    'one',
    'three',
    'four' // <-- For loop is at index 2
];

Now we are at third loop, but we have completely skipped the string 'three', because we removed one item from the array while in the loop.

Does that make sense at all? :D

Link to comment
Share on other sites

35 minutes ago, enpu said:

Now we are at third loop, but we have completely skipped the string 'three', because we removed one item from the array while in the loop.

I find that the lesser of two evils...
I wonder what undefined result 'var enemy = game.scene.spinvaders[ i ];' etc, gives when 'i' exceeds the original length.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...