William Blackburn
William Blackburn

Reputation: 21

mouse picking a rotating sprite in an Xna game

I am working on a simple game where you click on square sprites before they disappear. I decided to get fancy and make the squares rotate. Now, when I click on the squares, they don't always respond to the click. I think that I need to rotate the click position around the center of the rectangle(square) but I am not sure how to do this. Here is my code for the mouse click:

    if ((mouse.LeftButton == ButtonState.Pressed) &&
    (currentSquare.Contains(mouse.X , mouse.Y )))

And here is the rotation logic:

    float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

        RotationAngle += elapsed;
        float circle = MathHelper.Pi * 2;
        RotationAngle = RotationAngle % circle;

I am new to Xna and programming in general, so any help is appreciated.

Thanks a lot,

Bill

Upvotes: 2

Views: 1289

Answers (3)

David Jazbec
David Jazbec

Reputation: 167

If you dont need pixel pefect detection you can create bounding sphere for each piece like this.

        var PieceSphere = new BoundingSphere()
                         {
                             Center =new Vector3(new Vector2(Position.X + Width/2, Position.Y + Height/2), 0f),
                             Radius = Width / 2
                         };

Then create another bounding sphere around mouse pointer.For position use mouse coordinates and for radius 1f. Because mouse pointer will be moving it will change its coordinates so you have to also update the sphere's center on each update.

Checking for clicks would be realy simple then.

foreach( Piece p in AllPieces )
{
    if ((mouse.LeftButton == ButtonState.Pressed) && p.BoundingSphere.Intersects(MouseBoundingSphere))
    {
        //Do stuff 
    }
} 

Upvotes: 1

ClassicThunder
ClassicThunder

Reputation: 1936

If you are lazy like me you could just do a circular distance check.

Assuming mouse and box.center are Vector2

#gets us C^2 according to the pythagorean Theorem
var radius = (box.width / 2).squared() + (box.height / 2).square 

#distance check
(mouse - box.center).LengthSquared() < radius

Not perfectly accurate but the user would have a hard time noticing and inaccuracies that leave a hitbox slightly too large are always forgiven. Not to mention the check is incredibly fast just calculate the radius when the square is created.

Upvotes: 0

Msonic
Msonic

Reputation: 1456

So you're trying to determine if a point is in a rectangle, but when the rectangle is rotated?

The Contains() method will only work if the current rotation is 0 (I guess currentSquare is a rectangle representing the image position without rotation?).

What you will have to do is do the opposite rotation of the image on the mouse coordinates (the mouse coordinates should rotate around the origin of your image), then calculate if the new position is within currentSquare. You should be able to do all of this using vectors. (Untested)

bool MouseWithinRotatedRectangle(Rectangle area, Vector2 tmp_mousePosition, float angleRotation)
{
    Vector2 mousePosition = tmp_mousePosition - currentSquare.Origin;
    float mouseOriginalAngle = (float)Math.Atan(mousePosition.Y / mousePosition.X);
    mousePosition = new Vector2((float)(Math.Cos(-angleRotation + mouseOriginalAngle) * mousePosition.Length()), 
                                (float)(Math.Sin(-angleRotation + mouseOriginalAngle) * , mousePosition.Length()));
    return area.Contains(mousePosition);
}

Upvotes: 1

Related Questions