Sign in to follow this  
SuperMarco

How to get the direction of a sprite

Recommended Posts

Hi,

 

I have searched inside the documention but I couldn't find anything about it. I'm using the method moveToPointer to move my character (so it will follow the mouse and shoot in that direction).

And what I was trying to achieve is that to set a different animation depending of the direction that my sprite is going.

 

I already know how to set and play the animation but, is there is any way to know if my sprite is going left, right, up or down ?

 

I could try to do a trick such as looking the position of the mouse and compare it to the sprite, but I'm not really sure its really pretty to do it this way.

 

Thanks for the help !

Share this post


Link to post
Share on other sites

SebastianNette, 

 

I manage to set up the calcul but I have one problem, the angle doesn't go over 180 degrees.

 

I made a small example to explain :

 

IlNCSIs.png

 

if I put my mouse at the point where the 2 arrow touch, it will be 180 degrees. but if I go on one way or the other, the angle decrease instead of increasing on one side, and decrease on the other. Is there is a trick to avoid this problem ?

Share this post


Link to post
Share on other sites

Well you don't really need angles. You could just compare the position of the sprite and the mouse.

 

The angle is calculated like this:

 

var angle = Math.atan2(mouse y - sprite y, mouse x - sprite x ) * (180/Math.PI);

 

Where the sprite coordinates have to be at the center of the sprite.

Share this post


Link to post
Share on other sites

Where the sprite coordinates have to be at the center of the sprite.

 

Damn ok, I did something so much complicated instead of something simple..

 

To get the center of my sprite, there is a method in the doc ? or I should find it by myself hard coded ?

 

Thank you very much for your help :) !!

Share this post


Link to post
Share on other sites

To test if a point is in front of or behind you, just dot product the two points. If it is positive, the point is in front of you; if negative it is behind you; if zero the point is directly on the same Y axis:

var val = (new Phaser.Point()).copyFrom(player).dot(mousePosition);if (val < 0) { /* BEHIND */ }else if (val > 0) { /* IN FRONT */ }else { /* SAME Y PLANE */ }
Similarly to check if they are right or left, you take the dot product of your position with the vector perpendicular to the target:

var val = (new Phaser.Point()).copyFrom(player).dot(Phaser.Point.perp(mousePosition));if (val < 0) { /* LEFT */ }else if (val > 0) { /* RIGHT */ }else { /* SAME X PLANE */ }
You will probably want to change that to use the center of the sprite instead of the x/y values, but you get the idea.

Share this post


Link to post
Share on other sites

The moveToPointer function returns the angle (in radians) that the object needs to move to reach the pointer, so that calculation is already done for you. What you need to do is quantise that value to determine cardinal directions. The value, being in radians, will be between -Math.PI and Math.PI. Here's a little example with some probably rather poor and inefficient maths, but it works and demonstrates a possible way to do it: http://jsfiddle.net/lewster32/vL7r71z9/

Share this post


Link to post
Share on other sites

The moveToPointer function returns the angle (in radians) that the object needs to move to reach the pointer, so that calculation is already done for you. What you need to do is quantise that value to determine cardinal directions. The value, being in radians, will be between -Math.PI and Math.PI. Here's a little example with some probably rather poor and inefficient maths, but it works and demonstrates a possible way to do it: http://jsfiddle.net/lewster32/vL7r71z9/

 

Thanks lewster32 ! Unfortunately I decided to change the way to move my character, so it no longer use moveToPointer (at least for now). But this will be very useful for my ennemies in the game ! :) (but I will use the technic of the carnidal point ^^

 

To test if a point is in front of or behind you, just dot product the two points. If it is positive, the point is in front of you; if negative it is behind you; if zero the point is directly on the same Y axis:

var val = (new Phaser.Point()).copyFrom(player).dot(mousePosition);if (val < 0) { /* BEHIND */ }else if (val > 0) { /* IN FRONT */ }else { /* SAME Y PLANE */ }
Similarly to check if they are right or left, you take the dot product of your position with the vector perpendicular to the target:

var val = (new Phaser.Point()).copyFrom(player).dot(Phaser.Point.perp(mousePosition));if (val < 0) { /* LEFT */ }else if (val > 0) { /* RIGHT */ }else { /* SAME X PLANE */ }
You will probably want to change that to use the center of the sprite instead of the x/y values, but you get the idea.

 

 

I didn't manage to make it work this way, it keep telling me that "Uncaught TypeError: undefined is not a function" I don't know why...

 

Well you don't really need angles. You could just compare the position of the sprite and the mouse.

 

The angle is calculated like this:

 

var angle = Math.atan2(mouse y - sprite y, mouse x - sprite x ) * (180/Math.PI);

 

Where the sprite coordinates have to be at the center of the sprite.

 

Thank you SebastianNette, I will use your way I think :) 

 

 

Just a last question (I know I'm a newbie...), to set the coordinate of the sprite at its center it's sprite.anchor.setTo(0.5, 0.5) ? Because I feel like my sprite loose in quality ..

Share this post


Link to post
Share on other sites

I didn't manage to make it work this way, it keep telling me that "Uncaught TypeError: undefined is not a function" I don't know why...

 

Obviously you need to change "player" and "mousePosition" to your objects. Calculating the angle via arctan is expensive, and overkill if all you want is up/down/right/left. If you need the exact angle though, you will need to use arctan.

 

 

Thanks lewster32 ! Unfortunately I decided to change the way to move my character, so it no longer use moveToPointer (at least for now). But this will be very useful for my ennemies in the game !  :) (but I will use the technic of the carnidal point ^^

 

 

I didn't manage to make it work this way, it keep telling me that "Uncaught TypeError: undefined is not a function" I don't know why...

 

 

Thank you SebastianNette, I will use your way I think  :)

 

 

Just a last question (I know I'm a newbie...), to set the coordinate of the sprite at its center it's sprite.anchor.setTo(0.5, 0.5) ? Because I feel like my sprite loose in quality ..

It will make it seems like your coords are at the center of the texture, but it doesn't move the position it moves the texture around. The coords are still the top-left of your sprite, the texture has just moved up-left so the middle of the texture (0.5,0.5) is on the coords origin (top-left). Which may be good enough for your purposes.

Share this post


Link to post
Share on other sites

 Of course I did :), but I still got the error..

Can you give any more information than "I got an error"? Code that you used, the error and line that caused it, etc? "Undefined is not a function" with no context is not helpful at all. I ran the code I posted above on a couple objects and it worked fine.

Share this post


Link to post
Share on other sites

Can you give any more information than "I got an error"? Code that you used, the error and line that caused it, etc? "Undefined is not a function" with no context is not helpful at all. I ran the code I posted above on a couple objects and it worked fine.

I apologies, I'm using my code into classes, here is the Player one : ( I removed some line, to make it cleaner (such as input keys etc..))

Player = function(game) {	this.game = game;	this.sprite = null;	this.group = null;};Player.prototype = { 	preload: function() {		this.game.load.spritesheet('survivor', 'assets/survivor.png', 23, 46);	},	create: function() {		this.group = this.game.add.group();				this.sprite = this.group.create(300, 28, 'survivor');		this.sprite.anchor.setTo(0.5, 0.5);			this.sprite.animations.add('left', [0, 1, 2, 3], 10, true);		this.sprite.animations.add('down', [4, 5, 6, 7], 10, true);		this.sprite.animations.add('up', [8, 9, 10, 11], 10, true);		this.sprite.animations.add('right', [12, 13, 14, 15], 10, true);				},	update: function() {		var mouse = game.input.mousePointer;		var val = (new Phaser.Point()).copyFrom(this.sprite).dot(mouse);			console.log(val);	}};

With this code, the console is giving me this error :

 

Uncaught TypeError: undefined is not a function Player.js:37

Player.update        Player.js:37

update          (index):41

b.StateManager.update          phaser.min.js:6

b.Game.update           phaser.min.js:8

b.RequestAnimationFrame.updateRAF          phaser.min.js:11

window.requestAnimationFrame.forceSetTimeOut._onLoop         phaser.min.js:11

 

I did something wrong probably, but I don't know where :S

 

[Edit] I did some test, and it seems that is coming from the dot method.

Share this post


Link to post
Share on other sites

You are using an old version of phaser, the dot method was added in v2.0.4. The latest version is v2.1.1, you should probably upgrade.

 

You were right ! I thought that I download the one from git... hmm weird.

However, the value return but the point are very big, and always over 0, how is that possible ? :s

Share this post


Link to post
Share on other sites

I had a closer look to the dot and the source code too to see what's everything were doing, and I also try to test by myself the calculus that the dot is doing and I don't get the same result as you said xerver.

 

For example, my origin is upper left give me 0.

The point down the origin (down left corner) is 18000 ish.

The point corner up right is 32000.

And the point bottom right is around 50000.

(When my sprite is in the middle or my plan)

 

I did the same thing as you did I guess here :

		var val = new Phaser.Point().copyFrom(this.sprite).dot(this.game.input.mousePointer);		console.log(val);

I also tried the second calculus to detect left or right, but my map is divided in 2 part in diagonal like this:

 

haMG96e.png

 

The red line is moving with my sprite, so if I move my char up, the positive area become smaller, but it always start from the origin..

The value over the right line is positive, and the value below is negative.

 

It seems that the perp line is not set properly or something ?

Share this post


Link to post
Share on other sites

I though you were trying to get left/right, which is:

 

new Phaser.Point().copyFrom(this.sprite).dot(Phaser.Point.perp(this.game.input.mousePointer));
Also this is linear algebra, not calculus. Look it up "how to find if vector is left of another vector" it is a pretty common problem.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.