Rectangle Geometry and Rotation

Topics: Developer Forum
Dec 25, 2007 at 4:25 PM
I searched around but couldn't find anything related to the issue I am having, it might be just my limited knowledge and ability with physics and the physics engine but I thought I would throw this out and see if I can find and answer. I am building a Silverlight Pirate game.

My problem is that I am creating a rectangle geometry and then rotating the body of my sprite but the geometry does not rotate along with the sprite. I am hoping that I am just coding the logic wrong as I am trying to fit the Farseer engine into existing code.

Here is the code I used to create the body and geometry, this is in the constructor of the Ship sprite:

this.Body = BodyFactory.Instance.CreateRectangleBody(this.PhysicsSimulator, (float)this.Root.Width, (float)this.Root.Height, 200);
fsc.Geometry geometry = fsc.GeometryFactory.Instance.CreateRectangleGeometry(this.PhysicsSimulator, this.Body, (float)this.Root.Width, (float)this.Root.Height);
geometry.CollisionHandler += new FarseerGames.FarseerPhysics.Collisions.Geometry.CollisionHandlerDelegate(this.HandleCollision);

Here is my movement code, the sprite rotates correctly on screen but the underlying geometry is not rotating the same way. I tried setting the Body.Rotation value equal to the RotateTransform.Angle but that made the sprite start spinning around rather than rotate with a key press.

if (this.IsKeyPressed(Key.Left) || this.IsKeyPressed(Key.A))
sprite.Body.Rotation -= 0.5f * (float)elapsedTime.TotalSeconds;
//this.Ship.RotationAngle -= this.Ship.RotationSpeed * elapsedTime.TotalSeconds;
if (this.IsKeyPressed(Key.Right) || this.IsKeyPressed(Key.D))
sprite.Body.Rotation += 0.5f * (float)elapsedTime.TotalSeconds;
//this.Ship.RotationAngle += this.Ship.RotationSpeed * elapsedTime.TotalSeconds;
if (this.IsKeyPressed(Key.Up) || this.IsKeyPressed(Key.W))
sprite.Body.Position += Radiance.Silverlight.MathHelper.CreateVector2FromAngle((float)sprite.Body.Rotation, 50 * elapsedTime.TotalSeconds);
//this.Ship.Position += MathHelper.CreateVectorFromAngle(this.Ship.RotationAngle, elapsedTime.TotalSeconds * this.Ship.MovementSpeed);
if (this.IsKeyPressed(Key.Down) || this.IsKeyPressed(Key.S))
sprite.Body.Position -= Radiance.Silverlight.MathHelper.CreateVector2FromAngle((float)sprite.Body.Rotation, 50 * elapsedTime.TotalSeconds);

Any help would be appreciated, hopefully I am just coding it wrong :)
Dec 25, 2007 at 7:23 PM
That may be because silverlight uses a different unit than farseer.

Try converting between degrees and radians.
Here is the C# code for converting between the units.
public static double ConvertDegreesToRadians (double degrees)
return ((Math.PI / 180) * degrees);

public static double ConvertRadiansToDegrees(double radians)
return ((180 / Math.PI) * radians);
Dec 25, 2007 at 10:32 PM
I do have the rotation value converting to degrees when I set the Angle value of the RotateTransform and the sprite rotates correctly. When I convert the rotation to degrees and set the Body.Rotation value the sprite just starts spinning around. Here is my code I use to update the sprite position based on the Body values:

public virtual void Update(TimeSpan elapsedTime)
if (this.Body == null) return;

if (_x != this.Body.Position.X)
_x = this.Body.Position.X;
this.Canvas.SetValue<double>(Canvas.LeftProperty, _x);
if (_y != this.Body.Position.Y)
_y = this.Body.Position.Y;
this.Canvas.SetValue<double>(Canvas.TopProperty, _y);
if (_rotation != this.Body.Rotation)
_rotation = this.Body.Rotation;
this.RotateTransform.Angle = (_rotation * 360) / (2 * Math.PI);
Dec 26, 2007 at 10:39 AM
It do it like this in my applications:

public void Update(Vector2 position, double rotationAngle)
if (LastPosition != position || LastRotation != rotationAngle)
TransformGroup group = new TransformGroup();
TranslateTransform translate = new TranslateTransform(position.X - (Path.Data.Bounds.Width / 2), position.Y - (Path.Data.Bounds.Height / 2));
LastPosition = position;
RotateTransform rotate = new RotateTransform(rotationAngle * (180 / Math.PI), position.X, position.Y);
Path.RenderTransform = group;
LastRotation = rotationAngle;

I use Path's instead of Shapes in WPF. The Path's rendertransform gets updated with the position and rotation of the physics element. BTW: I started out checking each value and only updating if they are changed, just like you ( if (_rotation != this.Body.Rotation) and so on). That turned out to be a bad idea and falls in the premature optimization category.
Dec 27, 2007 at 2:43 PM
Edited Dec 27, 2007 at 3:34 PM
I don't think the problem is the sprite rotation and movement, since that was working fine before I added the Farseer code. I think the problem is a disconnect somewhere, something I missed when attempting to merge my SL code with the Farseer code. I had my sprite working fine before, it would rotate and move in the direction it was rotated in until I plugged in the Farseer body and collision geometry. I think I need to re-examine the code I have that actually causes the sprite to move to make sure it works correctly with the farseer body. I had plugged in your code above and still had the same results so I think I just broke it when I tried to just add the farseer logic into my existing code. I am going to step back a little and try to build from the farseer logic and see if I can get somewhere with it.

Anyway, thanks for the help, I will post again if I am unable to figure out what is actually wrong.

EDIT: I got is figured out, the problem was in my code where I figured out the position based on the rotation. I was passing the raw Body.Rotation value but my method expected a converted value. Now that I have that worked out the geometry collides correctly with the sprite movement. Thanks again for your help!