OnCollision works not correctly

Topics: User Forum
May 24, 2013 at 4:34 PM
"Coin_OnCollision" is released directly after the start of the game. But there could be no collision between playerrect and a coin, because the start position of playerrect is completely different from the coin position.
I don't know why "Coin_OnCollision" is released. Why is it released after the start of the game?
It should just be released when there is a collision between the playerrect and a coin. After the collision, the coin should be removed.
What is wrong? I don't want that "Coin_OnCollision" is released at the start of the game.

Game1:
public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        World world;
        Body playerrect;
        Texture2D playerSprite, coinSprite;
        public List<Coins> CoinsList = new List<Coins>();

        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>("retromario");
            coinSprite = Content.Load<Texture2D>("mariocoin");

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

            playerrect = BodyFactory.CreateRectangle(world, 0.64f, 0.64f, 1.0f);
            playerrect.BodyType = BodyType.Dynamic;
            playerrect.Position = new Vector2(0.22f, 0f);
            playerrect.CollisionCategories = Category.Cat15;
            playerrect.FixedRotation = true;

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

            CoinsList.Add(new Coins(world, BodyFactory.CreateRectangle(world, 0.64f, 0.64f, 1.0f), BodyType.Static, true, new Vector2(1.60f, 4.16f), 0, false, playerrect));
        }

        protected override void Update(GameTime gameTime)
        {
            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
            world.Step(Math.Min(elapsed, (1f / 60f)));
            for (int i = 0; i <= CoinsList.Count -1; i++)
            {
                if (CoinsList[i].Remove == true)
                    CoinsList.Remove(CoinsList[i]);
            }
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
            for (int i = 0; i <= CoinsList.Count -1; i++)
                {
                    CoinsList[i].Draw(spriteBatch,coinSprite);
                }
            spriteBatch.Draw(playerSprite, ConvertUnits.ToDisplayUnits(playerrect.Position), null, Color.White, playerrect.Rotation, new Vector2(playerSprite.Width / 2.0f, playerSprite.Height / 2.0f), 1f, SpriteEffects.None, 0f);
           spriteBatch.End();

            base.Draw(gameTime);
        }
    }
Coin class:
public class Coins
    {
       Body Coin;
       BodyType Cointype;
       Vector2 Coinposition;
       float Coinrotation;
       public bool Remove;
       World world1;
       Body playerrect;

       public Coins(World world,Body coin, BodyType cointype, bool coinsensor, Vector2 coinposition, float coinrotation, bool remove, Body playerr)
       {
         playerrect = playerr;
         world1 = world;
         this.Coin = coin;
         this.Cointype = cointype;
         this.Coin.IsSensor = coinsensor;
         this.Coinposition = coinposition;
         this.Coinrotation = coinrotation;
         this.Remove = remove;
         Coin.OnCollision += Coin_OnCollision;
       }

         bool Coin_OnCollision(Fixture fixtureA, Fixture fixtureB, FarseerPhysics.Dynamics.Contacts.Contact contact)
        {
           if (fixtureB.CollisionCategories == Category.Cat15)
            {
                world1.RemoveBody(fixtureA.Body);
                Remove = true;
            }
            return true;
        }

        public void Draw(SpriteBatch batch, Texture2D coinSprite)
        {
            if (Remove == false)
            {
              batch.Draw(coinSprite, ConvertUnits.ToDisplayUnits(Coinposition), null, Color.White, Coinrotation, new Vector2(coinSprite.Width / 2.0f, coinSprite.Height / 2.0f), 1f, SpriteEffects.None, 0f);
            }
        }
   }
May 27, 2013 at 12:22 AM
From the looks of it you never assign the position of your CoinPosition variable to the coin body so it's placed at (0, 0) which does overlap your playerRect

Replace

this.Coinposition = coinposition;

with

this.Coin.Position = coinposition;

Remove the Coinposition variable entirely and just use Coin.Body.Position as it's this value that will get updated on each step. And the same for Coinrotation.

Have fun
May 27, 2013 at 9:10 AM
Thanx. That solved the problem.