Issue in first simple program

Topics: Developer Forum, User Forum
Jul 14, 2013 at 4:00 AM
This is my first Farseer Physics engine program and I am seeing some issue in the sample program.

Can somebody tell me if I am missing some cruicial settings or is it justa bug in the code.
  1. I have a circle object
  2. I have a rectangle object which has a non-zero rotation
  3. The circle object is dropped onto the rectangle object.
  4. The circle object collides with the rectangle and starts rolling on the inclined surface of rectangle object.
Issue:
  1. The circle object falls off the rectangle object before the end of rectangle object (at around 3/4 of the width of the rectangle object.)
Some global variables:
    static int PixelinMeters = 10;
    Texture2D myTexture, groundTexture;
    SpriteBatch s;
    int width = 20;
    int height = 2;
    int radius = 2;
Following is my Initialize function:
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        world = new World(new Vector2(0f, 9.82f));

        myBody = BodyFactory.CreateCircle(world,radius,1);
        myBody.BodyType = BodyType.Dynamic;
        myBody.Position = new Vector2(3, 1);



        ground = BodyFactory.CreateRectangle(world, width , height, 1f,1);
        ground.BodyType = BodyType.Static;
        ground.Rotation = 0.1f;
        ground.Position = new Vector2(1, 10);

        myTexture = Content.Load<Texture2D>("ConcreteSphereBrick");
        groundTexture = Content.Load<Texture2D>("pixel");
        spriteBatch = new SpriteBatch(GraphicsDevice);


        base.Initialize();
    }
Following is my Draw function:
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        Rectangle destinationRectangle = new Rectangle((int)myBody.Position.X * PixelinMeters, (int)myBody.Position.Y * PixelinMeters, radius *2 * PixelinMeters, radius*2 * PixelinMeters);
        spriteBatch.Draw(myTexture, destinationRectangle, Color.White);
        destinationRectangle = new Rectangle((int)ground.Position.X * PixelinMeters, (int)ground.Position.Y * PixelinMeters, width * PixelinMeters, height * PixelinMeters);

        spriteBatch.Draw(groundTexture, destinationRectangle, null, Color.White, ground.Rotation, Vector2.Zero, SpriteEffects.None, 0);
        spriteBatch.End();

        // TODO: Add your drawing code here

        base.Draw(gameTime);
    }
Jul 14, 2013 at 9:10 AM
You have to keep in mind that Farseer uses object centers for position tracking, whereas when you draw a texture or a rectangle, its position considered top left rather than a center.

You have to specify the origin of the texture in the spritebach.draw() method
Jul 14, 2013 at 6:58 PM
Hi Entrio,

Many thanks for your concise reply.
Objects look better but still have a minor issue.

Based upon your feedback, I changed the Draw logic so that it subtracts the half of height and width from the Position's X and Y co-ordinate (since Position would contain center of the object)

My changed Draw function looks like this:
        Rectangle destinationRectangle = new Rectangle((int)(myBody.Position.X - radius) * PixelinMeters, (int)(myBody.Position.Y -radius) * PixelinMeters, radius *2 * PixelinMeters, radius*2 * PixelinMeters);
        spriteBatch.Draw(myTexture, destinationRectangle, Color.White);


        destinationRectangle = new Rectangle((int)(ground.Position.X -(width/2))* PixelinMeters, (int)(ground.Position.Y - (height/2))* PixelinMeters, width * PixelinMeters, height * PixelinMeters);
        spriteBatch.Draw(groundTexture, destinationRectangle, null, Color.White, ground.Rotation, Vector2.Zero, SpriteEffects.None, 0);
After this change it looks a lot better. However, the rectangle object looks like floating below the circle object (by half of its height). If I change the Draw logic for rectangle like this then it looks perfect:
        destinationRectangle = new Rectangle((int)(ground.Position.X -(width/2))* PixelinMeters, (int)(ground.Position.Y - (height))* PixelinMeters, width * PixelinMeters, height * PixelinMeters);
        spriteBatch.Draw(groundTexture, destinationRectangle, null, Color.White, ground.Rotation, Vector2.Zero, SpriteEffects.None, 0);
Do you know why this would be happening.
Jul 14, 2013 at 7:40 PM
Edited Jul 14, 2013 at 7:40 PM
Just having a look at your code, you forgot to divide the height by half. That hopefully should fix your problem.

Also, note there is an offset vector2 in spritebatch draw you can specify, this is precisely what its for. It takes top left of the specified rectangle and offsets it by the specified amount.

Instead of
 destinationRectangle = new Rectangle((int)(ground.Position.X -(width/2))* PixelinMeters, (int)(ground.Position.Y - (height))* PixelinMeters, width * PixelinMeters, height * PixelinMeters);
        spriteBatch.Draw(groundTexture, destinationRectangle, null, Color.White, ground.Rotation, Vector2.Zero, SpriteEffects.None, 0);
Try (assuming that width and height are your width and height of the groundTexture)
 destinationRectangle = new Rectangle((int)(ground.Position.X)* PixelinMeters, (int)(ground.Position.Y)* PixelinMeters, width * PixelinMeters, height * PixelinMeters);
        spriteBatch.Draw(groundTexture, destinationRectangle, null, Color.White, ground.Rotation, new vector2(width/2* PixelinMeters, height/2* PixelinMeters ), SpriteEffects.None, 0);
Let us know how that works out for you
Jul 14, 2013 at 8:02 PM
Hi Entrio,

Thanks for trying to help me out.
  1. I think I didn't make it clear enough in my previous email, but when I divide the height be half, then the rectangle object seem to be floating below where the circle object stops falling (i.e. it detects the rectangle object a little above where Draw function places it.) However, if I don't divide the height by half, the the circle object rests exactly above the rectangle object.
  2. I tried you code sample and with that the circle object is not even rendered on the screen. I figure my original code was written to place the object considering the origin was at 0,0. Your sample code changes the origin (in Draw method) which cause the object to go off the screen.
Thanks again for looking and responding to my post.
Jul 14, 2013 at 8:14 PM
Sorry, I did miss that.

I can't try your code atm, as its 2am here. What I would recommend though is to add a debug view to your project and that will show you exactly where your shapes are and what they are doing.

I will try your code in the morning and see how it goes.
Jul 14, 2013 at 8:20 PM
No worries. There's no hurry.

I appreciate all your help.
In the meantime let me try to figure out the debug view.

Thanks again.
Jul 16, 2013 at 5:01 AM
Hi Entrio,

I found my issue. It was the following piece of code:
(int)(ground.Position.Y - (height/2))* PixelinMeters

The issue was that Position.Y is float and I am converting it to integer which was rounding it off to nearest lowest integer.
In my case the (ground.Position.Y - (height/2)) was 7.99 and was getting converted to 7 and thus was a meter off from the actual collision point.
Sorry to bother you with possible one of the earliest forms of bugs.

Thanks for your help again.
Jul 16, 2013 at 9:50 AM
Hey mate,

I am glad you got your problem sorted, it was a nice little gotcha there!