CharlesCraft50 Posted December 22, 2016 Share Posted December 22, 2016 I don't know why this error is happening: Quote Uncaught TypeError: Cannot read property 'name' of undefined at StickmansDatas.js:222 at Phaser.Physics.P2.impactHandler (phaser.js:89211) at World.emit (phaser.js:6407) at World.internalStep (phaser.js:13152) at World.step (phaser.js:12890) at Phaser.Physics.P2.update (phaser.js:89494) at Phaser.Physics.update (phaser.js:84565) at Phaser.Game.updateLogic (phaser.js:36342) at Phaser.Game.update (phaser.js:36280) at Phaser.RequestAnimationFrame.updateRAF (phaser.js:61979) at _onLoop (phaser.js:61962) This code has a problem and I don't know why: this.enemy.body.collides(objectsCollisionGroup, function(){enemies[this.enemy.name].jump();}); My full code: Enemy_1 = function (index, game, player) { var x = game.world.randomX; var y = game.world.randomY-50; this.game = game; this.health = Math.floor((Math.random() * 20) + 5);; this.player = player; this.alive = true; this.punchedCount = 0; this.enemy = game.add.sprite(x, y, 'stickman_2'); this.enemy.name = index.toString(); this.enemy.punching = false; game.physics.p2.enable(this.enemy); this.enemy.animations.add('left', Phaser.Animation.generateFrameNames('walk/left_', 1, 8), 10, true); this.enemy.animations.add('right', Phaser.Animation.generateFrameNames('walk/right_', 1, 8), 10, true); this.enemy.animations.add('sprint_left', Phaser.Animation.generateFrameNames('walk/left_', 1, 8), 20, true); this.enemy.animations.add('sprint_right', Phaser.Animation.generateFrameNames('walk/right_', 1, 8), 20, true); this.enemy.animations.add('punch_1_left', Phaser.Animation.generateFrameNames('punch_1/left_', 1, 3), 20, true); this.enemy.animations.add('punch_1_right', Phaser.Animation.generateFrameNames('punch_1/right_', 1, 3), 20, true); this.enemy.checkWorldBounds = true; this.enemy.body.collideWorldBounds = true; this.enemy.body.fixedRotation = true; this.enemy.body.damping = 0.5; this.enemy.body.setCollisionGroup(enemies_1ColisionGroup); this.enemy.body.collides(blockCollisionGroup); this.enemy.body.collides(objectsCollisionGroup, function(){enemies[this.enemy.name].jump();}); this.enemy.healthBar = game.add.text(0, 0, 'HP: ' + this.health + '%', {font: "10px Arial", fill: "#ffffff"}); this.enemy.addChild(this.enemy.healthBar); this.enemy.healthBar.position.y = this.enemy.healthBar.position.y-80; }; Enemy_1.prototype.damage = function() { this.health -= 1; if (this.health <= 0) { this.alive = false; this.enemy.kill(); return true; } return false; }; Enemy_1.prototype.punch = function () { if(this.enemy.facing == 'left') { this.enemy.animations.play('punch_1_left'); this.enemy.punching = true; if(this.player.facing == 'left') { this.player.body.x += 1; } else { this.player.body.x -= 1; } } else { this.enemy.animations.play('punch_1_right'); this.enemy.punching = true; } }; Enemy_1.prototype.jump = function () { if(checkIfCanJump(this.enemy)) { this.enemy.body.moveUp(300); } }; Enemy_1.prototype.update = function() { this.enemyMoves = false; //<Enemy_Punch> if(checkOverlap(this.enemy, player)) { if(playerPunching == true){ if(this.enemy.body.velocity.x < 0 && this.enemy.body.velocity.y < 150 && this.enemy.body.velocity.y > 0) { this.enemy.body.x += 30; } else if(this.enemy.body.velocity.x > 0 && this.enemy.body.velocity.y < 150 && this.enemy.body.velocity.y > 0) { this.enemy.body.x -= 30; } enemies[this.enemy.name].damage(); } else { playerPunching = false; } game.time.events.add(Phaser.Timer.SECOND * 0.5, function(){enemies[this.enemy.name].punch();}, this); } else { this.enemy.punching = false; this.enemyMoves = true; if(this.enemyMoves != false) { accelerateToObject(this.enemy, this.player, 200); } if(this.enemy.body.velocity.x < 0 && this.enemy.body.velocity.y < 150 && this.enemy.body.velocity.y > 0) { this.enemy.animations.play('left'); this.enemy.facing = 'left'; } else if(this.enemy.body.velocity.x > 0 && this.enemy.body.velocity.y < 150 && this.enemy.body.velocity.y > 0) { this.enemy.animations.play('right'); this.enemy.facing = 'right'; } } //</Enemy_Punch> if(this.enemy.punching != false) { playerSubtractHealthBar(0.5); } this.enemy.healthBar.setText('HP: ' + this.health + '%'); }; Add the enemies in the game: Quote enemies = []; enemiesTotal = 4; for (var i = 0; i < enemiesTotal; i++) { enemies.push(new Enemy_1(i, game, player)); } Thanks in advance Link to comment Share on other sites More sharing options...
CharlesCraft50 Posted December 22, 2016 Author Share Posted December 22, 2016 Ok..., No answers but I already solved it : Quote this.enemy.body.collides(objectsCollisionGroup, function(){enemies[this].jump();}, this.enemy.name); Link to comment Share on other sites More sharing options...
mattstyles Posted December 22, 2016 Share Posted December 22, 2016 2 hours ago, CharlesCraft50 said: Quote this.enemy.body.collides(objectsCollisionGroup, function(){enemies[this].jump();}, this.enemy.name); That is probably a really bad way to fix it. You're fixing the context of the function to `this.enemy.name`, which isn't a great idea. The issue is that the function gets invoked in a different context, likely `window`, so, `this` references the window, which is standard JS behaviour (in the browser, it defaults to root, which in the case of executing in the browser is usually `window`) for invoking non-explicitly scoped functions. Yes, JS scoping can be confusing. A better way would be to bind the function to the context you want, .bind is your friend here (if you don't know how bind, call and apply work, learn, immediately, they are absolutely necessary for attempting class-based programming in JS): this.enemy.body.collides(objectsCollisionGroup, function () { enemies[this.enemy.name].jump() }.bind(this)) Alternatively it looks like you can pass in a context, I expect under the hood Phaser will invoke it using .bind to bind the context (again, this is fairly common for stuff like event emitters, which this is): this.enemy.body.collides(objectsCollisionGroup, function () { enemies[this.enemy.name].jump() }, this) Not that the above simply references how you would bind a function in JS, and thus is general advice, in your case you don't have to go through the jump of performing a lookup, you're already in the scope of the `enemy` object you want so I think the following would work: this.enemy.body.collides(objectsCollisionGroup, function () { this.enemy.jump() }.bind(this)) This does throw up other concerns, like why your enemy class has a member enemy??? If you're going for a classical style of programming that isn't right, although it might look a little better just by renaming `enemy` to `sprite`, still, I guess thats up to you, there are few rules written in stone. All this horror reminds me why I write in a functional style rather than classical OOP. CharlesCraft50 1 Link to comment Share on other sites More sharing options...
Recommended Posts