I'm working on a simple Sinistar-style shooter in XNA, and I'm constantly running into trouble with transformations. I feel like I'll get it eventually, but this problem is really bending my mind.
My little ship has two states: idle and engines-firing. Idle is a single frame, and engines is a few frames that animate. Got all that. Part 1 of the issue: Instead of using rotated images, I just use XNA's rotation to orient the ship. Seems to work ok, but I think my origin point is off because it seems to rotate at a point just below the vertical axis of the ship (default orientation is ship's nose pointing up), instead of in the dead center of the ship. Likewise, when I switch to engines, the sprites are different heights (due to the flames) so the origin of rotation doesn't seem like it would be constant. Do I need to specify all my frames the same size so as to preserve the origin point?
Second bit: The gun turret sits on top of the ship, as a separate sprite. With a bit of trial-and-error and calculation, I can get the gun to align on top where I want it. But then when the ship rotates, it rotates out from under the gun! Would fixing the first problem adequately cover this one, or is there some trick to getting the gun's position to translate properly?
So:
- Do I need to have all my sprite's frame-rectangles be the same dimensions?
- Is there a standard technique in XNA for stacking multiple sprites so they act as one unit, including for rotations?
Answer
What you want to do is get the center coordinate for you ship sprite and turn it on that point. I don't have the code with my here at work, but when I get home I'll share a little snippet that I made that does just want you want.
For this to work however your sprite has to be well centered in the first place. Your image needs to be very aligned and centered using Photoshop or whatever program you use. If your image is not aligned correctly then using the established techniques to rotate won't work because your picture center won't be the same as your pictureContent center.
Edit
Ok, I got back from work and here's a little example. I'm going to rotate a cannon barrel on a given point using the following code:
//Angle is just a float variable that saves the angle the cannon is facing.
players[currentPlayer].Angle -= 0.1f;
The code above is only run when the left key is pressed. I'm moving the angle to the left or counter-clockwise.
Now in the Draw method which in XNA is called 60 times every second I redraw the cannon. Using the .Angle property I modified earlier I know exactly where to draw it and at what angle.
spriteBatch.Draw(CannonBody, player.Position, null, player.Color, 0, new Vector2(0, CannonBody.Height), playerScaling, SpriteEffects.None, 0);
spriteBatch.Draw(CannonBarrel, new Vector2(xPosition + 20, yPosition - 10), null, player.Color, player.Angle, cannonOrigin, playerScaling, SpriteEffects.None, 1);
Basically, you want to draw the cannon using modified positions every given second; then each second modify the position so you get that fluid movement effect.
No comments:
Post a Comment