Ninjadoodle Posted March 25, 2018 Share Posted March 25, 2018 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 Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted March 26, 2018 Author Share Posted March 26, 2018 Hi @enpu / Panda People Still trying to slowly learn how to make this work, but no luck. Just wanted to bump this topic to see if anyone has made something similar / has had the same issue. Thanks! Quote Link to comment Share on other sites More sharing options...
Milton Posted March 26, 2018 Share Posted March 26, 2018 Having a 'for' loop while removing elements seems dodgy... Try iterating in reverse. Ninjadoodle 1 Quote Link to comment Share on other sites More sharing options...
enpu Posted March 26, 2018 Share Posted March 26, 2018 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(); } }); Ninjadoodle 1 Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted March 27, 2018 Author Share Posted March 27, 2018 Hi @enpu Thanks heaps for the snippet, I managed to get a rough version working I'm still not however sure if I completely understand what I'm doing, when it comes to removing bullet type sprites and enemies. Hopefully with a little bit more practice, it will sink in. Quote Link to comment Share on other sites More sharing options...
enpu Posted March 27, 2018 Share Posted March 27, 2018 @Ninjadoodle What part you don't understand? I can try to explain Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted March 27, 2018 Author Share Posted March 27, 2018 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! Quote Link to comment Share on other sites More sharing options...
Milton Posted March 27, 2018 Share Posted March 27, 2018 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. Ninjadoodle 1 Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted March 27, 2018 Author Share Posted March 27, 2018 @Milton - Thanks for the explanation, half of this stuff goes over my head lol. I've mainly been making puzzle games and haven't really needed to use bullets/enemies, so this is all pretty new. Quote Link to comment Share on other sites More sharing options...
Milton Posted March 27, 2018 Share Posted March 27, 2018 Hi Ninja, This has nothing to do with Panda specifics. To become a better programmer you should understand memory... I grew up with assembly and C, so I guess it's not really fair, but maybe you could read some early Kernighan and Ritchie book. Ninjadoodle 1 Quote Link to comment Share on other sites More sharing options...
enpu Posted March 28, 2018 Share Posted March 28, 2018 @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? Ninjadoodle 1 Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted March 28, 2018 Author Share Posted March 28, 2018 @enpu - That was an awesome way of explaining it and I completely understand!! Thanks heaps for that Quote Link to comment Share on other sites More sharing options...
Milton Posted March 28, 2018 Share Posted March 28, 2018 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. Quote Link to comment Share on other sites More sharing options...
PsichiX Posted March 28, 2018 Share Posted March 28, 2018 @Milton it gives exactly `undefined` object, because JS internals do not throw exceptions, so this is the way to tell developer that he is iterating over out of range of container. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.