0
\$\begingroup\$

I created a ball that is rolling over platforms. When it falls from one platform to another, it should bounce just like in real life, but the ball keeps bouncing constantly and I don't know how to recreate a realistic bounce-behaviour in Farseer. In addition, the ball sometimes bounces higher but I don't know the reason for this. How can I improve the bouncing of the ball?

In this video, you can see how it bounces: http://www.vidup.de/v/I55qn/

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    World world;
    Body rectangle, rectangle2, rectangle3, rectangle4, rectangle5, playerrect;
    Texture2D rectangleSprite, playerSprite;

    private static float _displayUnitsToSimUnitsRatio = 100f;

    public static Vector2 ToDisplayUnits(Vector2 simUnits)
    {
        return simUnits * _displayUnitsToSimUnitsRatio;
    }

    private bool isOnGround;

    bool Player_OnCollision(Fixture fixtureA, Fixture fixtureB, FarseerPhysics.Dynamics.Contacts.Contact contact)
    {
        if (fixtureB.CollisionCategories == Category.Cat5)
        {
            isOnGround = true;
        }
        return true;
    }
    void Player_OnSeparation(Fixture fixtureA, Fixture fixtureB)
    {
        if (fixtureB.CollisionCategories == Category.Cat5)
        {
            isOnGround = false;
        }
    }

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void Initialize()
    {
        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        playerSprite = Content.Load<Texture2D>("ball");
        rectangleSprite = Content.Load<Texture2D>("tile");

        if (world == null)
        {
            world = new World(new Vector2(0, 1));
        }
        else
        {
            world.Clear();
        }

        playerrect = BodyFactory.CreateCircle(world, 0.25f, 1.0f);
        playerrect.BodyType = BodyType.Dynamic;
        playerrect.Position = new Vector2(2.76f, 0f);

        rectangle = BodyFactory.CreateRectangle(world, 1.50f, 0.50f, 1.0f);
        rectangle.BodyType = BodyType.Static;
        rectangle.Position = new Vector2(2.96f, 1.16f);
        rectangle.Rotation = -0.3f;
        rectangle.CollisionCategories = Category.Cat5;

        rectangle2 = BodyFactory.CreateRectangle(world, 1.50f, 0.50f, 1.0f);
        rectangle2.BodyType = BodyType.Static;
        rectangle2.Position = new Vector2(1.0f, 1.80f);
        rectangle2.Rotation = 1.0f;
        rectangle2.CollisionCategories = Category.Cat5;

        rectangle3 = BodyFactory.CreateRectangle(world, 1.50f, 0.50f, 1.0f);
        rectangle3.BodyType = BodyType.Static;
        rectangle3.Position = new Vector2(4.1f, 4.80f);
        rectangle3.CollisionCategories = Category.Cat5;

        rectangle4 = BodyFactory.CreateRectangle(world, 1.50f, 0.50f, 1.0f);
        rectangle4.BodyType = BodyType.Static;
        rectangle4.Position = new Vector2(2.6f, 4.80f);
        rectangle4.CollisionCategories = Category.Cat5;

        rectangle5 = BodyFactory.CreateRectangle(world, 1.50f, 0.50f, 1.0f);
        rectangle5.BodyType = BodyType.Static;
        rectangle5.Position = new Vector2(5.6f, 4.80f);
        rectangle5.CollisionCategories = Category.Cat5;

        playerrect.OnCollision += Player_OnCollision;
        playerrect.OnSeparation += Player_OnSeparation;
    }

    protected override void Update(GameTime gameTime)
    {
        float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
        world.Step(Math.Min(elapsed, (1f / 60f)));
        KeyboardState kbState = Keyboard.GetState();       

        if (isOnGround == true)
        {
          playerrect.ApplyForce(new Vector2(0, -4.5f));
        }

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        spriteBatch.Draw(playerSprite, ConvertUnits.ToDisplayUnits(playerrect.Position),
                                       null,
                                       Color.White, playerrect.Rotation, new Vector2(playerSprite.Width / 2.0f, playerSprite.Height / 2.0f), 1.0f,
                                       SpriteEffects.None, 0f);

        spriteBatch.Draw(rectangleSprite, ConvertUnits.ToDisplayUnits(rectangle.Position),
                                        null,
                                        Color.White, rectangle.Rotation, new Vector2(rectangleSprite.Width / 2.0f, rectangleSprite.Height / 2.0f), 1f,
                                        SpriteEffects.None, 0f);

        spriteBatch.Draw(rectangleSprite, ConvertUnits.ToDisplayUnits(rectangle2.Position),
                                        null,
                                        Color.White, rectangle2.Rotation, new Vector2(rectangleSprite.Width / 2.0f, rectangleSprite.Height / 2.0f), 1f,
                                        SpriteEffects.None, 0f);

        spriteBatch.Draw(rectangleSprite, ConvertUnits.ToDisplayUnits(rectangle3.Position),
                                        null,
                                        Color.White, rectangle3.Rotation, new Vector2(rectangleSprite.Width / 2.0f, rectangleSprite.Height / 2.0f), 1f,
                                        SpriteEffects.None, 0f);

        spriteBatch.Draw(rectangleSprite, ConvertUnits.ToDisplayUnits(rectangle4.Position),
                                        null,
                                        Color.White, rectangle4.Rotation, new Vector2(rectangleSprite.Width / 2.0f, rectangleSprite.Height / 2.0f), 1f,
                                        SpriteEffects.None, 0f);
        spriteBatch.Draw(rectangleSprite, ConvertUnits.ToDisplayUnits(rectangle5.Position),
                                       null,
                                       Color.White, rectangle5.Rotation, new Vector2(rectangleSprite.Width / 2.0f, rectangleSprite.Height / 2.0f), 1f,
                                       SpriteEffects.None, 0f);
        spriteBatch.End();

        base.Draw(gameTime);
    }
}
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Are you just adding force to the ball? If you need elastic collisions don't do this. Farseer body has property called restitution, it controls ratio of the speed before and after collision.

\$\endgroup\$
1
  • \$\begingroup\$ Thanx. It works. \$\endgroup\$
    – Bryan
    Commented May 12, 2013 at 18:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .