PabloK Posted April 6, 2016 Share Posted April 6, 2016 Hi! I'm new to Phaser and have had great fun learning the engine. I recently started separating the code for my game into prefab files by extending Phaser.Sprite but I have run in to trouble. When Trying create the movement for the player I have a problem where the player starts moving randomly up or down on the y-scale. When inspecting my Player.prototype.update method in chrome I can see that this.body.velocity.y is NaN. I have no Idea how it got to be NaN pheraps some issue with the gravity? I have tried various fixes but I can't find the bug in my code. I have looked at numerous tutorials and they all look similar to what Im doing. Please help. Below is my code. player.js // Private var leftKey; var rightKey; var jumpKey; var speed = 150; var jumpSpeed = 250; // Constructor function Player (game, x, y) { Phaser.Sprite.call(this, game, x, y, Player.key); this.anchor.set(0.5,0.5); game.physics.arcade.enableBody(this); this.body.bounce = 0; this.body.collideWorldBounds = true; this.body.allowGravity = true; leftKey = game.input.keyboard.addKey(Phaser.Keyboard.A); rightKey = game.input.keyboard.addKey(Phaser.Keyboard.D); jumpKey = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR); game.add.existing(this); } Player.prototype = Object.create(Phaser.Sprite.prototype); Player.prototype.constructor = Player; // Static Player.preload = function(game) { game.load.image(Player.key, "images/block.png"); }; Player.key = "Player"; Player.prototype.update = function() { this.body.velocity.x = 0; if (leftKey.isDown) { this.body.velocity.x = -speed; } else if (rightKey.isDown) { this.body.velocity.x = speed; } if (jumpKey.isDown && (this.body.onFloor() || this.body.touching.down)) { this.body.velocity.y = -jumpSpeed; } }; module.exports = Player; var Player = require('../models/player.js'); var destiny = {}; /* The main game */ destiny.create = function () { console.info("Find out your destiny!"); // World this.game.stage.backgroundColor = "#5599CC"; this.game.world.setBounds(0, 0, 1000, 500); this.game.physics.startSystem(Phaser.Physics.ARCADE); this.game.time.desiredFPS = 30; this.game.physics.arcade.gravity.y = 200; this.allSprites = {}; // Player this.allSprites.destinyPlayer = new Player(this.game,2000,900); // Camera this.game.camera.follow(this.allSprites.destinyPlayer,Phaser.Camera.FOLLOW_PLATFORMER); }; destiny.update = function() { }; destiny.render = function() { this.game.debug.spriteInfo(this.allSprites.destinyPlayer,32,32); this.game.debug.cameraInfo(this.game.camera,32,128); }; module.exports = destiny; My game is loaded in a series of game states (boot, preload, startscreen, preload, game). I have previously not had any problems with that part but if you want to see that code please ask. Here is the error in chrome. Any help is appreciated. Link to comment Share on other sites More sharing options...
drhayes Posted April 6, 2016 Share Posted April 6, 2016 I'm not seeing anything there that would mess up your player sprite's y velocity. Are you sure nothing else assigns to it? Is anything else modifying jumpSpeed? Link to comment Share on other sites More sharing options...
Chazlodian Posted August 28, 2016 Share Posted August 28, 2016 (edited) I've experienced a velocity.y of NaN when one sprite collides with another. I'm on Phaser 2.6.1, by the way. Here's a video of what is happening (with some debug info at the top). The "jitter" on the X access when they collide is a work-in-progress feedback action that happens when a player collides with an enemy. This problem happens with or without that "jitter" added to the player on collision with an enemy. http://cloud.carlfurrow.com/2F2k423G0p2s Here's some example code that is similar to what I'm running. create() { player = new Player(100, 100); baddy = new Baddy(300, 100); game.physics.arcade.enable([player, baddy]) game.world.add(player); game.world.add(baddy); } collideCallback(player, baddy) { console.log(player.body.velocity.y); // NaN } update() { game.physics.arcade.collide(player, baddy, collideCallback); } I have not found the cause of this yet, but would be curious if someone else understands what is going on. Edited August 28, 2016 by Chazlodian add phaser version Link to comment Share on other sites More sharing options...
symof Posted August 29, 2016 Share Posted August 29, 2016 NaN errors happen when you try to use a string or undefined variable as a number. In your case(2nd example) it's because player and baddy are declared in the create function, and then used outside their scope in the update function, where they are undefined. In essence it's a variable scope issue in both cases. You are trying to use a 'undefined' as a number. Link to comment Share on other sites More sharing options...
Chazlodian Posted August 29, 2016 Share Posted August 29, 2016 Thanks for taking the time to reply! In this case, scope is not the issue. The example above was a "toy" one, because the variables are all declared in the same scope, at the same level as the functions are defined. let game, player, baddy = null; create() { //..snip } collideCallback(player, baddy) { //..snip } update() { //..snip } I agree that at some point either `undefined` or a string is attempting to be added/multiplied/whatever to a number, but exactly where is the mystery, because I do no such manipulations myself other than movement. I'm simply adding velocity to X to move the player left/right, and then on "jump", the player gets a negative Y velocity to counter-act the gravity. Jumping and movement work and have always worked, the problem comes into play during the collision between the player and the "baddy". The player collides appropriately with the tiles I've setup, but somehow the collision with the other sprite entity (which also has arcade physics enabled on it) is causing an issue *somewhere*. I'll continue to do more investigation, but I am assured it is not a scoping issue within my own code, as I'm well-aware of what that looks like and where it could arise. Thank you all the same. Link to comment Share on other sites More sharing options...
symof Posted August 29, 2016 Share Posted August 29, 2016 I don't know why people insist it's not scope when it is. https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let You are using let, the scope of let is not like the scope of var. You are also declaring baddy = null which is 'undefined'. var game; var player; var baddy; create() { player = new Player(100, 100); baddy = new Baddy(300, 100); game.physics.arcade.enable([player, baddy]) game.world.add(player); game.world.add(baddy); } collideCallback(player, baddy) { console.log(player.body.velocity.y); } update() { game.physics.arcade.collide(player, baddy, collideCallback); } Another good practice is to not have variables declared on the same line unless they share some traits. Game, Player and Baddy are in noway alike so you should place them on different lines. Javascript might not care, but people reading your code will appreciate it. Link to comment Share on other sites More sharing options...
Chazlodian Posted August 29, 2016 Share Posted August 29, 2016 Hey again symof, thanks for the reply and the link. I've copied the relevant content below. Quote Variables declared by let have as their scope the block in which they are defined, as well as in any contained sub-blocks . In this way, let works very much like var. The main difference is that the scope of a var variable is the entire enclosing function: function varTest() { var x = 1; if (true) { var x = 2; // same variable! console.log(x); // 2 } console.log(x); // 2 } function letTest() { let x = 1; if (true) { let x = 2; // different variable console.log(x); // 2 } console.log(x); // 1 } Again, the code I've supplied in previous replies is toy code that is representative of the issues I'm seeing. I will update said toy code to further illustrate the layout of my own code: window.onload = function() { let game, preload, create, update, baddyCollide, player, baddy; preload = function() { // do preload things }; create = function() { // snip... do create stuff player = new Player(game, 50, 100); baddy = new Baddy(game, 250, 200); game.physics.arcade.enable([player, baddy]); game.world.add(stickman); game.world.add(baddy); }; baddyCollide = function(player, baddy) { console.log(player); console.log(baddy); }; update = function() { game.physics.arcade.collide(player, baddy, collideCallback); stickman.update(); baddy.update(); }; game = new Phaser.Game(640, 480, Phaser.AUTO, '', { preload: preload, create: create, update: update }); } I hope that clears up the confusion around scope. Since all the variables are declared (with let or otherwise) inside of the onload function, they are sharing the same scope at this time. The `baddyCollide` method is called on collision, and outputs each sprite to the console. They are not null, or undefined, but sprites. I appreciate the time you're taking to sort out the scope issue, but I do believe it is misplaced at this time. It seems to be upsetting you, and I don't want it to be a bother. Link to comment Share on other sites More sharing options...
Chazlodian Posted August 29, 2016 Share Posted August 29, 2016 I may have found an issue. I see that I enable gravity at the game-level in my create method: create = function(){ game.physics.startSystem(Phaser.Physics.ARCADE); game.physics.arcade.gravity.y = 250; //snip } But I also was incorrectly setting gravity on the baddy object, during it's initialization, after physics was enabled on its body. this.body.gravity = 250; It should have been "this.body.gravity.y". That is probably where the undefined is coming into play. When the physics bodies were colliding, the physics system didn't know how to apply force against the incoming body, since gravity was invalid. Awesome. Link to comment Share on other sites More sharing options...
samme Posted August 29, 2016 Share Posted August 29, 2016 On April 5, 2016 at 8:20 PM, PabloK said: When inspecting my Player.prototype.update method in chrome I can see that this.body.velocity.y is NaN. […] body.bounce should be a Point, not a number: this.body.bounce = 0; this.body.bounce.set(0); // or this.body.bounce.x = this.body.bounce.y = 0 // or this.body.bounce = new Phaser.Point(0, 0); Chazlodian 1 Link to comment Share on other sites More sharing options...
Recommended Posts