Jump to content

Method behaves differently depending on where it's called from. Why?


Reign_of_Light
 Share

Recommended Posts

Hi,
   
I'm fairly new to Phaser (but love it already!) and I'm facing a really weird issue where one and the same method behaves differently depending on whether it's called by mouse-click or keyboard.
    
Please view my (broken down) code below.
  
It's describing the player-character in a top-down tile-based game. If you hit the left cursor-button the character is moving one tile to the left (60px) and the camera follows along. Likewise if you click on the tile left to the character, it is supposed to move there as well (but I removed the code for the sake of simplicity, now simply clicking anywhere should move the character 60px to the left).
   
The problem that occurs is that if you use the left cursor key everything works perfectly as expected. BUT if you use your mouse the very same function moveInDirection() with the very same parameter "left" is being called, but does NOT behave as expected (nothing happens). To make things more strange, the console output is absolutely similar in both cases. See the lines with the console.log()s? Console output is first "360" followed by "300". So the charakter-sprites body IS indeed moved, but this movement is not being rendered in case I called the method by mouse-click whereas it is being rendered if I called it by pressing my keyboards left cursor key.
    
Does that make any sense to anybody?? To me it does not. I guarantee you that there's nothing else in my games code that moves the player sprite. 
  
Why is the character moving correctly when moveInDirection() is called by keyboard, but not when it's called by mouse?
    
 

Player = function(game) {	this.game = game;	this.sprite = null;	this.cursors = null;}Player.prototype = {	preload: function() {		this.game.load.image('player', 'assets/game_character.png');	},	create: function() {		this.sprite = this.game.add.sprite(360, 240, 'player');		this.game.physics.enable(this.sprite, Phaser.Physics.ARCADE);		this.sprite.body.setSize(60, 60, 0, 60);    	        this.sprite.body.collideWorldBounds = true;    	        this.cursors = this.game.input.keyboard.createCursorKeys();    	        this.game.input.onDown.add(this.mouseClickToMovement, this);	},	update: function() {		this.keyboardToMovement();	},	keyboardToMovement: function() {	    if (this.cursors.left.isDown) 	        this.moveInDirection("left"); 	},	moveInDirection: function(dir) {//dir="left"/"right"/"top"/"bottom"		var mod = (dir === "left" || dir === "top")? -1 : 1;		var axis = (dir === "left" || dir === "right")? "x" : "y";		var key = null;		console.log(this.sprite.body.x); // "360" regardless if called by keyboard or mouse		this.sprite.body[axis] += 60 * mod;		console.log(this.sprite.body.x); // "300" regardless if called by keyboard or mouse                this.game.camera.x = this.sprite.body.x - 360;                this.game.camera.y = this.sprite.body.y - 300;		this.timerOn = true;	},	mouseClickToMovement: function() {		this.moveInDirection("left");	}}
Link to comment
Share on other sites

One thing that differs here is that the keyboard version of the move command will be fired continuously up to 60 times per second as long as the key is held down, whereas the mouse version is a distinct, single event. It would be fairer to compare them if you used the Key.onDown signal:

this.cursors.left.onDown.add(this.mouseClickToMovement, this);

Also, as you're forcibly moving the sprite with a physics body, you should have body.moves set to false, otherwise the physics system will try to get involved in the positioning of the object, making it either snap back to the original position, jerk about or fly off the screen depending on where in the frame phase you pressed the input. When body.moves = false, just use the sprite's x and y position (sprite[axis]) rather than the body.

 

As to answer the 'why' part, I guess because the keyboard event in your current code is being hammered, it eventually lands on the right part of the frame phase where it can override the physics, basically via brute force. The mouse event however only gets once chance.

Link to comment
Share on other sites

Hey lewster,
 
thank you very much. To be fair, in my code (you couldn't know this) the keyboard-event wasn't hammered, since keyboardToMovement() in its unshortened version looked like this:
 
 

keyboardToMovement: function() {        if (this.timerOn && this.timer < 10) {        	this.timer++;    	} else {        	this.timerOn = false;        	this.timer = 0;    	}      	if (!this.timerOn) {	        if (this.cursors.left.isDown) 	            this.moveInDirection("left");	        else if (this.cursors.right.isDown) 	            this.moveInDirection("right");	        if (this.cursors.up.isDown) 	            this.moveInDirection("top");	        else if (this.cursors.down.isDown)	            this.moveInDirection("bottom");    	}}

 
And inside moveInDirection() the this.timerOn-boolean was set to true again, resulting in one step every 10 frames if the user presses the key that long. So hammering wasn't the issue. But with body.moves set to false and now directly moving the sprite (instead of the sprites body) everything works fine now :) . I still don't get the "why", but I'm very happy that the problem ist solved for me. So again, thank you very much :) !!

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...