• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
nooblet

Sprite Facing Mouse

9 posts in this topic

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 [b]Update(GameTime gameTime)[/b] 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
0

Share this post


Link to post
Share on other sites
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!
0

Share this post


Link to post
Share on other sites
[quote name='NickJohns' timestamp='1352916469' post='5000971']
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!
[/quote]


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?
0

Share this post


Link to post
Share on other sites
Did someone seriously downvote Aliii for asking the most sane question in the circumstance? OP did not specify that debugging had happened, and debugging [i]will[/i] 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
1

Share this post


Link to post
Share on other sites
[quote name='Khatharr' timestamp='1352960598' post='5001119']
Did someone seriously downvote Aliii for asking the most sane question in the circumstance? OP did not specify that debugging had happened, and debugging [i]will[/i] 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.
[/quote]

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.
0

Share this post


Link to post
Share on other sites
Is the mouse position translated to the world coordinate system or is it just the cursor position on the screen?
1

Share this post


Link to post
Share on other sites
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
0

Share this post


Link to post
Share on other sites
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
0

Share this post


Link to post
Share on other sites
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
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0