Collision Detection - Null Reference Exception

Nov 29, 2010 at 11:59 PM

Hey guys,

Im still picking up how farseer works bit by bit. My player collides with enemies and there forces bounce off each other which causes them to stop each other moving. However I trying to load a method once this collision has happened.

I have tried

            if (enemyCollision.geom.Collide(PlayerCollision.geom))
            {

            }

 

and AABB intersection

        if (AABB.Intersect(ref PlayerCollision.geom.AABB, ref enemyCollision.geom.AABB))
            {
              Enemy.Die();

            }

 

however everytime i run the game once i load up my level i get an output saying Null Reference, so i was woundering what i have to link the geomtry of the player and enemy to in order for there collision to output the method.

 

This is what my player class looks like

        public EnemyCollision(PhysicsSimulator physics, Vector2 position, float width, float height, float mass, Texture2D texture)
            : base(physics, position, width, height, mass, texture)
        {
            geom.CollisionCategories = CollisionCategory.Cat3;
            geom.CollidesWith = CollisionCategory.Cat1;
            wheelGeom.CollisionCategories = CollisionCategory.Cat4;
            wheelGeom.CollidesWith = (CollisionCategory.None);
          //  AABB aabb = new AABB();
               
           // geom.WorldVertices = aabb.GetVertices();
            wheelGeom.OnCollision += new CollisionEventHandler(OnCollision);
           
        }
        protected override void SetupPhysics(PhysicsSimulator physics, Vector2 position, float width, float height, float mass)
        {
            //Create a body that is almost the size of the entire object
            //but with the bottom part cut off.
            float upperBodyHeight = height - (width / 2);
            body = BodyFactory.Instance.CreateRectangleBody(physics, width, upperBodyHeight, mass / 2);
            //also shift it up a tiny bit to keep the new object's center correct
            body.Position = position - Vector2.UnitY * (width / 4);
            centerOffset = position.Y - body.Position.Y; //remember the offset from the center for drawing
          
            //Now let's make sure our upperbody is always facing up.
            fixedAngleJoint = JointFactory.Instance.CreateFixedAngleJoint(physics, body);
           
           
            //Create a wheel as wide as the whole object
            wheelBody = BodyFactory.Instance.CreateCircleBody(physics, width / 2, mass / 2);
            //And position its center at the bottom of the upper body
            wheelBody.Position = body.Position + Vector2.UnitY * (upperBodyHeight / 2);

            //These two bodies together are width wide and height high :)
            //So let's connect them together.
            motor = JointFactory.Instance.CreateRevoluteJoint(physics, body, wheelBody, wheelBody.Position);
            motor.Motor_Enabled = true;
            motor.Motor_MaxTorque = 500f; //set this higher for some more juice
            motor.Motor_Speed = 0;

            //Create geomitries.           
            wheelGeom = GeomFactory.Instance.CreateCircleGeom(physics, wheelBody, width / 2, 16);
            geom = GeomFactory.Instance.CreateRectangleGeom(physics, body, width, upperBodyHeight);

            wheelGeom.IgnoreCollisionWith(geom);
            geom.IgnoreCollisionWith(wheelGeom);

            //Set the friction of the wheelGeom to float.MaxValue for fast stopping/starting
            //or set it higher to make the character slip.
            wheelGeom.FrictionCoefficient = float.MaxValue;

        }

 

Your help would be greatly appreciated

 

Thank You

Lucy

Coordinator
Nov 30, 2010 at 12:28 AM

I've seen this code before. I think someone was in here to get that tutorial code updated to Farseer Physics Engine 3.x.

I'm not really able to figure out what you want, but from what you write, you want the enemy to die when there is a collision between the player and enemy right?

The most efficient way of doing that is to subscribe to the OnCollision event on the player geom. Inside the event method you check if the collision is with the enemy. If it is, you run your "die" logic. If this makes no sense to you, upload your code somewhere or drop me an email and I will take a look at it.

Nov 30, 2010 at 3:06 PM

Im now using the Oncollision event as such:

        public bool OnCollision(Geom geom1, Geom geom2, ContactList contactList)
        {
             enemyCollision.geom = geom1;
            playerCollision.geom = geom2;

           if (geom1.Collide(geom2))
             {
            OnKilled();

             }
            return true;
        }

How ever i get a Null Reference on playerCollision. This how Oncollision is done in my Enemy class and the rest looks like this

 

   public EnemyCollision enemyCollision;

  public CompositeCharacter playerCollision;

public void LoadContent(string spriteSet)
        {
            // Load animations.
            enemyCollision = new EnemyCollision(Farseer.Physics, position,25, 53, 10, Game1.SprSinglePixel);

           enemyCollision.geom.OnCollision += OnCollision;

       }

In this my playerCollision is never used hence why when i use it in my Oncollision its comes back as a Null Reference. So does anyone know how to pass the geomtry from PlayerCollision into my Enemy class so it can detect its collision

 

Thank you for you response Genbox

JB

Coordinator
Nov 30, 2010 at 5:27 PM

The OnCollision event is fired when a collision happens. That means you don't have to check for it. Do something like this instead:

public bool OnCollision(Geom geom1, Geom geom2, ContactList contactList)
{
//We check if it is the player and enemy that collided
if (geom1 == enemyCollision.geom && geom2 == playerCollision)
{
   //If they collided, we kill the enemy or player
   OnKilled();
}
 
   //We return false because the collision should not produce any collision response.
   return false;
}

In your project you need to have PlayerCollision and EnemyCollision instantiated. That means you should have done something like this:
PlayerCollision myPlayer = new PlayerCollision(Farseer.Physics, playerPosition,25, 53, 10, Game1.SprSinglePixel);
EnemyCollision myEnemy = new EnemyCollision(Farseer.Physics, enemyPosition, 25, 53, 10, Game1.SprSinglePixel);

if you don't instantiate your classes to objects, you will get a NullReferenceException.

Nov 30, 2010 at 6:28 PM

Thank you for your response. I got it working by using this;

 

            if (geom2.CollisionCategories == CollisionCategory.Cat2
                 && geom1.CollisionCategories == CollisionCategory.Cat3)
            {

                  OnKilled();
             }

This way i can do my collision detection based upon what CollisionCategory i have assigned them. Seems to be working pretty nice too.

 

Thank you for your help, ill keep you noted on how this method goes.

 

Cheers JB