Heppell08 Posted May 23, 2014 Share Posted May 23, 2014 I've been working on this for a bit of time, used the EXACT same code i have in another project that works perfectly and does what i need. The only differences being the phaser versions.My old project was a 1.1.4 phaser game and my current is 2.0.4. Now i can reference each enemy to die when show, thats simple enough. I have assigned them all health in my group creation, the console tells me they have 100 health. I then in another function i'm using with arcade physics overlap callback, telling the bullet to image itself to kill(); and to the hurt the enemy it overlapped with.It kills the enemy instantly without even touching the health! This is not the expected behaviour i had considering ive done the same code that worked previously. Not sure if damage wants to be done differently or something else but i just cant get it to do what i require. I've checked http://docs.phaser.io/Phaser.Sprite.html#damage and it seems the same as it always was by calling .damage(5); Heres my code: enemies = this.add.group();for(var j = 0; j < enemyRound; j++){enemy = this.add.sprite(this.world.randomX, this.world.randomY, 'enemy1');enemy.anchor.setTo(0.5,0.5);enemy.health = 100;this.physics.arcade.enable(enemy); enemies.add(enemy);}Then in the overlap for arcade i call this on overlap: enemyShot: function(enemy, bullet01){ var j; for(j = 0; j < enemies.length; j++) { enemies.getAt(j).damage(1); } console.log('Life:' + enemy.health); bullet01.kill();}If you see what im doing wrong please let me know ASAP becasue this has really got me thinking what i may have done differently or not. Thanks Update: i did notice that if i put the core function code in my update,it would take the health from the robots, it just wont do it in my function when its outside the update. EDIT: Took enemy out the parameter of the function, works ok, just now that the enemies are not dying 1 by 1... Link to comment Share on other sites More sharing options...
j0hnskot Posted May 23, 2014 Share Posted May 23, 2014 Try swapping the order of your arguements.enemyShot: function(bullet01,enemy)Does this work? Link to comment Share on other sites More sharing options...
Heppell08 Posted May 23, 2014 Author Share Posted May 23, 2014 Makes no difference, if i take the full health of a single enemy within the group, it kills all the enemies in the group and not the sinlge enemy that been hit. Link to comment Share on other sites More sharing options...
j0hnskot Posted May 23, 2014 Share Posted May 23, 2014 can you show me the overlap code? Is the bullet you are checking a group? Is the check between groups or between group-sprite? Can you comment out the bullet01.kill() and tell me what changes? Link to comment Share on other sites More sharing options...
Heppell08 Posted May 23, 2014 Author Share Posted May 23, 2014 The overlapping bullet is in a group of bullets called bulletgroup.this.physics.arcade.overlap(bulletGroup, enemies, this.enemyShot, null, this);I create my bullets like so:bulletGroup = this.add.group(player) bulletGroup.enableBody = true; bulletGroup.physicsBodyType = Phaser.Physics.ARCADE; bulletGroup.createMultiple(30, 'bullet01', 0, false); bulletGroup.setAll('anchor.x', 0.5); bulletGroup.setAll('anchor.y', 0.5); bulletGroup.setAll('scale.x', 0.5); bulletGroup.setAll('scale.y', 0.5); bulletGroup.setAll('outOfBoundsKill', true); bulletGroup.setAll('checkWorldBounds', true);then i call this on the overlap of the bullet and the enemy:enemyShot: function(bullet01){ var j; for(j = 0; j < enemies.length; j++) { enemies.getAt(j).damage(1); } console.log('Life:' + enemy.health); bullet01.kill();}I've done the exact same code before in a previous project but for some reason it wont work in 2.0.4 of phaser. Link to comment Share on other sites More sharing options...
Heppell08 Posted May 23, 2014 Author Share Posted May 23, 2014 what i believe is happening is the health im trying to pass to each robot is actually the health of the whole group, hence the reason why they all die at once and not seperately like they should. Link to comment Share on other sites More sharing options...
j0hnskot Posted May 23, 2014 Share Posted May 23, 2014 Is it possible to see the code of enemy creation? Link to comment Share on other sites More sharing options...
Heppell08 Posted May 23, 2014 Author Share Posted May 23, 2014 enemies = this.add.group(); for(var j = 0; j < enemyRound; j++) { enemy = this.add.sprite(this.world.randomX, this.world.randomY, 'enemy1'); enemy.anchor.setTo(0.5,0.5); this.physics.arcade.enable(enemy); enemies.add(enemy); } enemies.setAll('health', 100); enemies.callAll('animations.add','animations','enemywalk',[0,1,2,3,4,5,6,7], 12, true); Link to comment Share on other sites More sharing options...
j0hnskot Posted May 23, 2014 Share Posted May 23, 2014 What i guess here is that the way your code first was it killed the ENEMY when you called the bullet01.kill(). Are you sure the order you passed the group was correct?When you ruled out the enemy by only passing the bullet inside the enemyShot you say that all of the enemies died like they should (not only with 1 damage) but they died all together. I think it's possible for it to work correctly but the execution is so fast that you can't see the difference of them when they die. Link to comment Share on other sites More sharing options...
lewster32 Posted May 23, 2014 Share Posted May 23, 2014 I think the problem lies in this part:enemyShot: function(bullet01){ var j; for(j = 0; j < enemies.length; j++) { enemies.getAt(j).damage(1); } console.log('Life:' + enemy.health); bullet01.kill();}This is included in the overlap callback, which is called continuously while the objects overlap. In it, you're looping through every enemy and inflicting 1 damage. At 60fps, this will do 60 damage per second to every enemy on the screen until the bullet is killed (which is not necessarily instantly in the case of physics calculations). I'm not entirely sure why you're looping through all the enemies as surely you only want to damage the one enemy that's hit? In which case the function should probably be like so:enemyShot: function(currentEnemy, currentBullet){ if (currentBullet.alive && currentEnemy.alive) { // ensure both are alive to prevent unwanted calls currentEnemy.damage(1); console.log('Life:' + currentEnemy.health); currentBullet.kill(); }} Link to comment Share on other sites More sharing options...
Heppell08 Posted May 23, 2014 Author Share Posted May 23, 2014 @Lewster32 But when i do it like that, the health isnt reduced at all. I have removed the loop and got a function pretty similar to what you have and still i do not removed the health from the enemy within the group. Link to comment Share on other sites More sharing options...
lewster32 Posted May 23, 2014 Share Posted May 23, 2014 Could you possibly upload this so we could take a look at it? Link to comment Share on other sites More sharing options...
Heppell08 Posted May 23, 2014 Author Share Posted May 23, 2014 I got it 70% working. The problem i face now is when i go to kill the bullet, it kills the enemy too in a single hit on impact with the enemy.If i dont kill the bullet, the health is removed as it should be from the enemy in the way you and i would predict. Its very strange behaviour and im starting to think its because of my bullet group creation. bulletGroup = this.add.group(player)bulletGroup.enableBody = true; bulletGroup.physicsBodyType = Phaser.Physics.ARCADE; bulletGroup.createMultiple(30, 'bullet01', 0, false); bulletGroup.setAll('anchor.x', 0.5); bulletGroup.setAll('anchor.y', 0.5); bulletGroup.setAll('scale.x', 0.5); bulletGroup.setAll('scale.y', 0.5); bulletGroup.setAll('outOfBoundsKill', true); bulletGroup.setAll('checkWorldBounds', true);so what imn going to try now is removing the whole setAll stuff, and coding it in like a standard group to see the results after that. Link to comment Share on other sites More sharing options...
lewster32 Posted May 23, 2014 Share Posted May 23, 2014 I'd maybe set enemy.isEnemy = true on all enemies during creation, and only call .kill() if enemy.isEnemy === true just to get some sanity checking going, and make sure that only bullets are being directly killed, whereas enemies are being killed as a result of their health reaching zero. Link to comment Share on other sites More sharing options...
Heppell08 Posted May 23, 2014 Author Share Posted May 23, 2014 I'd maybe set enemy.isEnemy = true on all enemies during creation, and only call .kill() if enemy.isEnemy === true just to get some sanity checking going, and make sure that only bullets are being directly killed, whereas enemies are being killed as a result of their health reaching zero. Even setting an isEnemy flag does nothing.Heres a gif of it happening with console showing too. http://imgur.com/WbfxnAc Link to comment Share on other sites More sharing options...
Heppell08 Posted May 23, 2014 Author Share Posted May 23, 2014 I uploaded to dropbox https://dl.dropboxusercontent.com/u/257829727/Neonizer/index.html Cursor up to go Left/Right to turn Click screen to shoot Link to comment Share on other sites More sharing options...
lewster32 Posted May 23, 2014 Share Posted May 23, 2014 Afraid I can't view the gif or the content on DropBox because of my work's proxy but I'll take a look when I get home later. I think in the mean time you just need to keep trying to rule out all other factors that are causing kill() to be invoked. You may want to try calling game.enableStep() when a bullet is fired to pause the game, and set something up outside of Phaser to call game.step() (onClick on a button maybe) so you can systematically step through the game updates and see what's happening at each frame. Link to comment Share on other sites More sharing options...
lewster32 Posted May 23, 2014 Share Posted May 23, 2014 I've taken a look and the issue here is globals. 'enemy' is defined globally, and is populated with the last created enemy. When you run the callback function, 'enemy' isn't what you expect it to be. Changing the callback to this seems to fix the problem:enemyShot: function(thisBullet, thisEnemy){ if(thisEnemy.isEnemy === true) { thisEnemy.damage(1); } thisBullet.kill(); console.log('Enemy:' + thisEnemy.health);}You have to be careful about where you define variables, as a global variable will supersede any local variables or function parameters with the same name. I'd recommend taking 'var enemy;' out at line 27 and instead defining it inside the create function as follows: enemies = this.add.group(); var enemy; for(var j = 0; j < enemyRound; j++) { enemy = this.add.sprite(this.world.randomX, this.world.randomY, 'enemy1'); this.physics.arcade.enable(enemy); enemy.isEnemy = true; enemies.add(enemy); } Link to comment Share on other sites More sharing options...
lewster32 Posted May 23, 2014 Share Posted May 23, 2014 The same goes for all of the other globally defined variables in your game; try to encapsulate as much as possible. Define variables only inside functions (preferably at the top of the function, just to keep them all together) and if you need to access something outside of that function, consider whether you can pass it to the function you need to call via its parameters; and if that's impractical then make it a property of your state so it can be accessed pretty much anywhere so long as it's in the state. It's possible to write JavaScript with virtually no pollution of the global namespace, and it's very good practice to try and achieve that. Link to comment Share on other sites More sharing options...
Recommended Posts