YuShaN Posted October 23, 2015 Share Posted October 23, 2015 Hi everyone. I have a trouble with funtion update. This is my code.launchEnemy: function() { this.enemy = this.enemyGroup.getFirstExists(false); if (this.enemy) { this.enemy.reset(this.game.rnd.integerInRange(0, 480), -10); this.enemy.body.velocity.x = this.game.rnd.integerInRange(-200, 200); if (this.enemy.body.velocity.x >0) { this.enemy.scale.x = -1; } else { this.enemy.scale.x = 1; } this.enemy.body.velocity.y = this.game.rnd.integerInRange(10, 50); } // time creat enemy this.enemyTimer = this.game.time.events.add(this.game.rnd.integerInRange(1500, 3000), this.launchEnemy, this); }}Now i want my enemy can shoot bullet. I wrote a group bullet for enemy in funtion creat this.enemyBullets = this.game.add.group(); this.enemyBullets .enableBody = true; this.enemyBullets .physicsBodyType = Phaser.Physics.ARCADE; this.enemyBullets .createMultiple(300, 'lunaBullet'); this.enemyBullets .setAll('alpha', 0.9); this.enemyBullets .setAll('anchor.x', 0.5); this.enemyBullets .setAll('anchor.y', 0.5); this.enemyBullets .setAll('outOfBoundsKill', true); this.enemyBullets .setAll('checkWorldBounds', true); this.enemyBullets .forEach(function(enemy){ enemy.body.setSize(15, 15); });Now i wrote a function update for my enemy launchEnemy: function() { this.enemy = this.enemyGroup.getFirstExists(false); if (this.enemy) { this.enemy.reset(this.game.rnd.integerInRange(0, 480), -10); this.enemy.body.velocity.x = this.game.rnd.integerInRange(-200, 200); if (this.enemy.body.velocity.x >0) { this.enemy.scale.x = -1; } else { this.enemy.scale.x = 1; } this.enemy.body.velocity.y = this.game.rnd.integerInRange(10, 50); this.enemy.update = function() { this.enemyBullet = this.enemyBullets.getFirstExists(false); if (this.enemyBullet && this.alive && this.y > 0 && this.game.time.now > 2000 + this.lastShot){ this.lastShot = this.game.time.now; this.enemyBullet.reset(this.enemy.x, this.enemy.y + this.enemy.height / 2); this.enemyBullet.damageAmount = 20; this.angle = this.game.physics.arcade.moveToObject(this.lunaBullet, this.player, 150); this.enemyBullet.angle = this.game.math.radToDeg(this.angle); this.enemyBullet.update = function() { if (this.x > (this.game.width-320)) { this.kill(); } } } } } // time creat enemy this.enemyTimer = this.game.time.events.add(this.game.rnd.integerInRange(1500, 3000), this.launchEnemy); }}I don't know how to call enemyBulets. I can't write this.this.enemyBullets. Someone help me. Thank you! Link to comment Share on other sites More sharing options...
chongdashu Posted October 23, 2015 Share Posted October 23, 2015 Hi, I think it's the same issue from your previous thread.this.enemyTimer = this.game.time.events.add(this.game.rnd.integerInRange(1500, 3000), this.launchEnemy);You are again not setting the context for the callback. Hence, the "this" in this.enemyBullets will be referring to the Window and not the state object itself. Link to comment Share on other sites More sharing options...
YuShaN Posted October 23, 2015 Author Share Posted October 23, 2015 Hi, I think it's the same issue from your previous thread.this.enemyTimer = this.game.time.events.add(this.game.rnd.integerInRange(1500, 3000), this.launchEnemy);You are again not setting the context for the callback. Hence, the "this" in this.enemyBullets will be referring to the Window and not the state object itself. Yes. I know but how to call enemybullets to state object Link to comment Share on other sites More sharing options...
chongdashu Posted October 23, 2015 Share Posted October 23, 2015 As mentioned, you need to make sure you pass in this as the third parameter to the events.add() method in order to to use this.enemyBullets. When launchEnemy gets called in your current version of the code, the "this" will refer to the Window, which doesn't have the enemyBullets group. If you change your code to pass in "this" as the third param, it will ensure that the context of "this" in enemyBullets refers to the state object, and not the window. Link to comment Share on other sites More sharing options...
YuShaN Posted October 23, 2015 Author Share Posted October 23, 2015 As mentioned, you need to make sure you pass in this as the third parameter to the events.add() method in order to to use this.enemyBullets. When launchEnemy gets called in your current version of the code, the "this" will refer to the Window, which doesn't have the enemyBullets group. If you change your code to pass in "this" as the third param, it will ensure that the context of "this" in enemyBullets refers to the state object, and not the window. launchEnemy: function() { this.enemy = this.enemyGroup.getFirstExists(false); this.enemyBullet = this.enemyBullets.getFirstExists(false); if (this.enemy) { this.enemy.reset(this.game.rnd.integerInRange(0, 480), -10); this.enemy.body.velocity.x = this.game.rnd.integerInRange(-200, 200); if (this.enemy.body.velocity.x >0) { this.enemy.scale.x = -1; } else { this.enemy.scale.x = 1; } this.enemy.body.velocity.y = this.game.rnd.integerInRange(10, 50); this.enemy.update = function() { if (this.enemyBullet && this.alive && this.y > 0 && this.game.time.now > 2000 + this.lastShot){ this.lastShot = this.game.time.now; this.enemyBullet.reset(this.enemy.x, this.enemy.y + this.enemy.height / 2); this.enemyBullet.damageAmount = 20; this.angle = this.game.physics.arcade.moveToObject(this.lunaBullet, this.player, 150); this.enemyBullet.angle = this.game.math.radToDeg(this.angle); this.enemyBullet.update = function() { if (this.x > (this.game.width-320)) { this.kill(); } } } } } // time creat enemy this.enemyTimer = this.game.time.events.add(this.game.rnd.integerInRange(1500, 3000), this.launchEnemy, this); }}I changed like it. Enemy appear but they don't shoot. My brain hurt Link to comment Share on other sites More sharing options...
chongdashu Posted October 23, 2015 Share Posted October 23, 2015 Hi, I'm not sure what was changed -- but what's being suggested is still not being addressed.this.enemyTimer = this.game.time.events.add(this.game.rnd.integerInRange(1500, 3000), this.launchEnemy);should be this.enemyTimer = this.game.time.events.add(this.game.rnd.integerInRange(1500, 3000), this.launchEnemy, this);Take a look at the documentation of Phaser.Timer's add() method here: http://phaser.io/docs/2.4.4/Phaser.Timer.html#add It states that it takes three compulsory arguments: delay, callback, and context. In your code, you are never setting the context. If you do not set the context parameter to "this" when you call it, it will never know to use the State object as opposed to the Window object. In the suggested fix, it adds "this" as the context for the callback. This means when you do this.enemyBullets, the this will be in the context of the State object (because you passed it in as the third parameter) Link to comment Share on other sites More sharing options...
YuShaN Posted October 23, 2015 Author Share Posted October 23, 2015 Hi, I'm not sure what was changed -- but what's being suggested is still not being addressed.this.enemyTimer = this.game.time.events.add(this.game.rnd.integerInRange(1500, 3000), this.launchEnemy);should be this.enemyTimer = this.game.time.events.add(this.game.rnd.integerInRange(1500, 3000), this.launchEnemy, this);Take a look at the documentation of Phaser.Timer's add() method here: http://phaser.io/docs/2.4.4/Phaser.Timer.html#add It states that it takes three compulsory arguments: delay, callback, and context. In your code, you are never setting the context. If you do not set the context parameter to "this" when you call it, it will never know to use the State object as opposed to the Window object. In the suggested fix, it adds "this" as the context for the callback. This means when you do this.enemyBullets, the this will be in the context of the State object (because you passed it in as the third parameter)If don't use this how to call bulletEnemy to use for update function of enemy? I really don't understand. Link to comment Share on other sites More sharing options...
chongdashu Posted October 23, 2015 Share Posted October 23, 2015 Let me set up a fiddle and see if i can replicate it. Link to comment Share on other sites More sharing options...
YuShaN Posted October 23, 2015 Author Share Posted October 23, 2015 I can't upload my project to forum so this is link download it. Please check it for me. Thank youhttp://www.mediafire.com/download/87j9kwq4hv3gflw/demo.rar Link to comment Share on other sites More sharing options...
chongdashu Posted October 23, 2015 Share Posted October 23, 2015 Hi, sorry about my mistake. I realized that you did indeed make the change as I suggested - I just didn't realize it. Sorry about that. However, I spotted where your error is - please take a look:var state = this;this.enemy.update = function () { // Note: // You are now within an inner function of a Phaser.Sprite of the enemy // Thus, if you use "this" here, it will be referring to the Phaser.Sprite, not the GameState. // You need to use "state" here, which was created above before entering the function. this.enemyBullet = state.enemyBullets.getFirstExists(false, true, this.x, this.y, "bullet"); if (!this.lastShot) { this.lastShot = 0; } if (this.enemyBullet && this.alive && this.y > 0 && state.game.time.now > 2000 + this.lastShot) { this.lastShot = state.game.time.now; //this.enemyBullet.reset(this.x, this.y + this.height / 2); this.enemyBullet.damageAmount = 20; this.angle = state.game.physics.arcade.moveToObject(this.enemyBullet, state.player, 150); this.enemyBullet.angle = state.game.math.radToDeg(this.angle); this.enemyBullet.update = function () { // Note: // You are now within a Phaser.Sprite of an enemy bullet. // So you can not use "this" here to refer to the state. // (e.g., state.game is needed, *not* this.game if (this.x > (state.game.width - 320)) { this.kill(); } } }}I've got a (semi) working example here: https://jsfiddle.net/chongdashu/yt9rLfuf/ YuShaN 1 Link to comment Share on other sites More sharing options...
YuShaN Posted October 23, 2015 Author Share Posted October 23, 2015 Hi, sorry about my mistake. I realized that you did indeed make the change as I suggested - I just didn't realize it. Sorry about that. However, I spotted where your error is - please take a look:var state = this;this.enemy.update = function () { // Note: // You are now within an inner function of a Phaser.Sprite of the enemy // Thus, if you use "this" here, it will be referring to the Phaser.Sprite, not the GameState. // You need to use "state" here, which was created above before entering the function. this.enemyBullet = state.enemyBullets.getFirstExists(false, true, this.x, this.y, "bullet"); if (!this.lastShot) { this.lastShot = 0; } if (this.enemyBullet && this.alive && this.y > 0 && state.game.time.now > 2000 + this.lastShot) { this.lastShot = state.game.time.now; //this.enemyBullet.reset(this.x, this.y + this.height / 2); this.enemyBullet.damageAmount = 20; this.angle = state.game.physics.arcade.moveToObject(this.enemyBullet, state.player, 150); this.enemyBullet.angle = state.game.math.radToDeg(this.angle); this.enemyBullet.update = function () { // Note: // You are now within a Phaser.Sprite of an enemy bullet. // So you can not use "this" here to refer to the state. // (e.g., state.game is needed, *not* this.game if (this.x > (state.game.width - 320)) { this.kill(); } } }}I've got a (semi) working example here: https://jsfiddle.net/chongdashu/yt9rLfuf/Yeah! var state = this. Then use it. Why i don't think about it. I feel so stupid (Thank you so much. Link to comment Share on other sites More sharing options...
chongdashu Posted October 23, 2015 Share Posted October 23, 2015 No, it was my fault for not checking your code earlier. Anyway, I updated the jsFiddle: https://jsfiddle.net/chongdashu/yt9rLfuf/ It has better logic to handle the shooting of bullets and some graphics. It's not well commented though. But hope it helps!Good work! YuShaN 1 Link to comment Share on other sites More sharing options...
Recommended Posts