Jump to content

  • Log In with Google      Sign In   
  • Create Account


Sprite Facing Mouse


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 nooblet   Members   -  Reputation: 167

Like
0Likes
Like

Posted 13 November 2012 - 01:44 PM

Hey all,

So I'm trying to have a sprite face my mouse cursor, but with my current code, the sprite is -close-, but it's not fully rotating to face my cursor. I've pasted my Player.cs class below. Right now, I initialize the direction and rotation variables within my Update(GameTime gameTime) class. I've already set the origin to be in the center of the sprite, so I don't think that's causing the issue. Thanks!

[source lang="csharp"]using System;using System.Collections.Generic;using System.Linq;using System.Text;using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Input;using Microsoft.Xna.Framework.Content;using Microsoft.Xna.Framework.Graphics;namespace MyTerribleGame{ class Player { #region Data Fields private Texture2D texture; private Rectangle position; private int health; private int armor; private int lives; private int velocity; private Vector2 direction; private float rotation; #endregion #region Properties public Texture2D Texture { get { return texture; } set { texture = value; } } public Rectangle Position { get { return position; } set { position = value; } } public int Health { get { return health; } set { health = value; } } public int Armor { get { return armor; } set { armor = value; } } public int Lives { get { return lives; } set { lives = value; } } public int Velocity { get { return velocity; } set { velocity = value; } } #endregion #region Constructors // Default Constructor. Will be removed when there's more implementation. public Player() { health = 100; armor = 100; lives = 100; velocity = 10; } // Overloaded Constructor. Possibly will become the new default. public Player(Rectangle position, int health, int armor, int lives, int velocity) { this.position = position; this.health = health; this.armor = armor; this.lives = lives; this.velocity = velocity; } #endregion #region Methods // Load the content of the player class. public void LoadContent(ContentManager Content) { texture = Content.Load<Texture2D>("Player/playerRed"); } // Update the player, such as input, collision detection, etc. public void Update(GameTime gameTime) { direction.X = Input.MousePos.X - position.X; direction.Y = Input.MousePos.Y - position.Y; direction.Normalize(); if (Input.IsKeyDown(Keys.W)) { position.Y -= velocity; } if (Input.IsKeyDown(Keys.S)) { position.Y += velocity; } if (Input.IsKeyDown(Keys.D)) { position.X += velocity; } if (Input.IsKeyDown(Keys.A)) { position.X -= velocity; } rotation = (float)Math.Atan2(direction.Y, direction.X); } // Draw the player to the screen. public void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(texture, position, null, Color.White, rotation, new Vector2(position.Width / 2, position.Height / 2), SpriteEffects.None, 0); } // This version of CheckCollision is used to check for collision between the screen and the player. public void CheckCollision(GraphicsDeviceManager graphics) { if (position.X <= 0) position.X += velocity; if (this.position.Y <= 0) position.Y += velocity; if (this.position.X + this.position.Width >= graphics.PreferredBackBufferWidth) position.X -= velocity; if (this.position.Y + this.position.Height >= graphics.PreferredBackBufferHeight) position.Y -= velocity; } // 2D Bounding Box collision b/w the player and an object. public void CheckCollision(Rectangle obj) { // Player -> Object // Right -> Left if (position.Right > obj.Left &amp;amp;&amp;amp; position.Left < obj.Left &amp;amp;&amp;amp; position.Bottom > obj.Top &amp;amp;&amp;amp; position.Top < obj.Bottom) { position.X -= velocity; } // Left -> Right if (position.Left < obj.Right &amp;amp;&amp;amp; position.Right > obj.Right &amp;amp;&amp;amp; position.Bottom > obj.Top &amp;amp;&amp;amp; position.Top < obj.Bottom) { position.X += velocity; } // Top -> Bottom if (position.Top < obj.Bottom &amp;amp;&amp;amp; position.Bottom > obj.Bottom &amp;amp;&amp;amp; position.Right > obj.Left &amp;amp;&amp;amp; position.Left < obj.Right) { position.Y += velocity; } // Bottom -> Top if (position.Bottom > obj.Top &amp;amp;&amp;amp; position.Top < obj.Top &amp;amp;&amp;amp; position.Right > obj.Left &amp;amp;&amp;amp; position.Left < obj.Right) { position.Y -= velocity; } } #endregion }}[/source]

Edited by nooblet, 13 November 2012 - 01:46 PM.


Sponsor:

#2 NickJohns   Members   -  Reputation: 137

Like
0Likes
Like

Posted 14 November 2012 - 12:07 PM

This is how I do it in most of my games:

float dx = Player.Position.X - MouseLocation.X;
float dy = Player.Position.Y - MouseLocation.Y;

float angle = (float)Math.Atan2(dy, dx);

The only thing you really need to change, is switching your :
direction.X = Input.MousePos.X - position.X;
direction.Y = Input.MousePos.Y - position.Y;
to
direction.X = position.X - Input.MousePos.X;
direction.Y = position.Y - InputMousePos.X;

Hope that helps!

#3 Aliii   Members   -  Reputation: 1440

Like
0Likes
Like

Posted 14 November 2012 - 04:27 PM

Have you tried to debug it?

#4 nooblet   Members   -  Reputation: 167

Like
0Likes
Like

Posted 14 November 2012 - 11:12 PM

This is how I do it in most of my games:
float dx = Player.Position.X - MouseLocation.X;
float dy = Player.Position.Y - MouseLocation.Y;
float angle = (float)Math.Atan2(dy, dx);
The only thing you really need to change, is switching your :
direction.X = Input.MousePos.X - position.X;
direction.Y = Input.MousePos.Y - position.Y;
to
direction.X = position.X - Input.MousePos.X;
direction.Y = position.Y - InputMousePos.X;
Hope that helps!



Thanks for the suggestion! I've switched them around as recommended, but unfortunately, it's not giving me the correct results :(. Anything else come to mind?

#5 Khatharr   Crossbones+   -  Reputation: 2940

Like
1Likes
Like

Posted 15 November 2012 - 12:23 AM

Did someone seriously downvote Aliii for asking the most sane question in the circumstance? OP did not specify that debugging had happened, and debugging will reveal the point at which the data is becoming incorrect.

...

There's no reason to normalize the vector. This may be causing slight inaccuracies in the angle since all it's really doing is changing the granularity of the arc-tangent calculation. Also, try calculating the vector after the motion is processed. Is this a consistent problem or does it only occur while you're moving?

I'm curious as to why you separate the atan2 from the vector calculation. It seems confusing to do part of a calculation, then do some different calculation and then finish the first one.

Edited by Khatharr, 15 November 2012 - 12:34 AM.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

#6 nooblet   Members   -  Reputation: 167

Like
0Likes
Like

Posted 15 November 2012 - 03:11 AM

Did someone seriously downvote Aliii for asking the most sane question in the circumstance? OP did not specify that debugging had happened, and debugging will reveal the point at which the data is becoming incorrect.

...

There's no reason to normalize the vector. This may be causing slight inaccuracies in the angle since all it's really doing is changing the granularity of the arc-tangent calculation. Also, try calculating the vector after the motion is processed. Is this a consistent problem or does it only occur while you're moving?

I'm curious as to why you separate the atan2 from the vector calculation. It seems confusing to do part of a calculation, then do some different calculation and then finish the first one.


I've removed the normalization and it's still not working. Essentially, if my mouse cursor is at the top right, the sprite is looking at the top left. When I rotate the sprite using my mouse, it slowly catches up to the cursor, but then slows down again. I can provide more source code if needed? As for debugging - I've tried watching the rotation and direction.x and direction.y, but I'm not sure where they should be at. Finally, I moved the rotation calculation under the direction to avoid ambiguity. I'm still pretty new to this, so this is just for a learning experience.

#7 Aliii   Members   -  Reputation: 1440

Like
1Likes
Like

Posted 15 November 2012 - 03:40 AM

Is the mouse position translated to the world coordinate system or is it just the cursor position on the screen?

#8 nooblet   Members   -  Reputation: 167

Like
0Likes
Like

Posted 15 November 2012 - 03:44 AM

Currently it's the cursor position on the screen. Input.MousePos is a read-only property that returns a new Vector2 of Mouse.GetState().X and Mouse.GetState().Y. Thanks for all the help so far!

Edited by nooblet, 15 November 2012 - 03:45 AM.


#9 Aliii   Members   -  Reputation: 1440

Like
0Likes
Like

Posted 15 November 2012 - 04:14 AM

If your character is always in the middle of the screen, then determine the cursor distance from the centre of the screen and call atan2 on that.
Vector2 cursor_direction;
cursor_direction.x = mousePos.x - screen_width / 2.0
cursor_direction.y = screen_height / 2.0 - mousePos.y

I guess mousePos is in pixels and is measured from the top left corner.

Edited by Aliii, 15 November 2012 - 04:15 AM.


#10 Khatharr   Crossbones+   -  Reputation: 2940

Like
0Likes
Like

Posted 15 November 2012 - 05:01 AM

If it's a problem of being on the wrong side of the x axis then you need to invert your vector's x magnitude. (direction.X = position.X - Input.MousePos.X;)

That's quite different than "-close-, but it's not fully rotating to face".

Of course it will be correct in certain positions because, as they say, even a stopped clock is right twice a day. If your x is inverted from what it needs to be then when its magnitude approaches zero you'll have more 'correct-looking' results, but as it approaches extremes from your rotation point you'll get increasingly bad results.

For future reference, familiarize yourself with the direction of rotation and zero position in your render calls whenever you use a new API. atan2 is going to give you results based on a 4 quadrant graph like the ones from high-school geometry class. If your zero position is straight upward and your direction of rotation is clockwise then you should rotate through the xy quadrants in the order ++, +-, --, -+. Make sure that the coordinates you're feeding to atan2 match signage appropriately for the quadrant your cursor is in.

In other words, for upward zero with clockwise rotation, the vector's x should be negative to the left of the sprite and positive to the right. The y should be positive above and negative below. Order your subtractions to make that happen and you should get the correct result.

Also, please ensure that both your render call and atan2 are using the same unit - either radians or degrees. (I believe they both use radians in this case, but idk for sure.)

Edited by Khatharr, 15 November 2012 - 05:22 AM.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS