Help converting code from FP2.x to FP3

Topics: Developer Forum, User Forum
Aug 5, 2010 at 6:06 AM

Okay, so I've tried and tried on this, so now I'm asking for input.  Maybe I don't understand yet the new OnCollision and PostSolve events well enough.  When I used FP2.x a year ago, I was able to use a pinjoint with my blocks to cause a block to stick to surfaces (as seen here: http://vimeo.com/3952954)

The code looked something like this:

       private bool MyOnCollisionMethod(Geom geom1, Geom geom2, ContactList list)
        {
            float distance;
            distance = Vector2.Distance(collisionIndex, list[0].Position);

            if (collisionJoint != null)
            {
                if (distance > 63f)
                {
                    //This part is crucial to the movement.  (HAS TO HAPPEN)
                    collisionJoint.Dispose();

                    Vector2 index = list[0].Position;
                    collisionJoint = JointFactory.Instance.CreateRevoluteJoint(PhysicsSimulator, geom1.Body, geom2.Body, index);
                    collisionJoint.Enabled = true;
                    collisionJoint.Breakpoint = 2f;
                    index = collisionIndex;
                }
            }
            else if (collisionJoint == null)
            {
                Vector2 index = list[0].Position;
                collisionJoint = JointFactory.Instance.CreateRevoluteJoint(PhysicsSimulator, geom1.Body, geom2.Body, index);
                collisionJoint.Enabled = true;
                collisionJoint.Breakpoint = 2f;

                index = collisionIndex;
            }
            return true; 
        }

Now, using FP3, I've tried many different ways to replicate a similar function.  I wanted to limit the joint creation to the corner of the moving block (which was 128f wide before, so >63f would force the joint to only create right at or near the exact corner).  This time around, I've had a hard time.  I figure out that I can't create joints while it is solving, so I created a bool which then is checked during the game's update, and then create's a joint then.  My problem now is that I can't seem to get the coordinates right and nothing I seem to try gets me anywhere close.  Does anyone have any ideas to help me.  I am applying torque to the blocks, but it ends up being so much that they bounce without a joint holding them down.  I also want them to be able to climb on each other, so the way I had things before worked great.

Thanks.

Aug 5, 2010 at 7:53 AM

Are you having trouble creating the joint anchors?

Please post your FP3 code, it'll be easier to see what you're doing wrong. The code looks easy to convert, but there are a few differences between the engines.

Aug 5, 2010 at 8:10 AM
Edited Aug 5, 2010 at 8:13 AM

I've tried many different variations.  I'm even playing with the World's contact manager right now, but still am in need of assistance.  Here is the current iteration:

public virtual bool BlonkOnCollision(Fixture a, Fixture b, Manifold manifold)
{
   //if (_world.JointList.Contains(_blonkJoint) == true)
   //    _removeJoint = true;
                        
   return true;
}

public virtual void BlonkPostSolve(ContactConstraint contactConstraint)
{
    if (_world.JointList.Contains(_blonkJoint) == true)
         _removeJoint = true;

    if ((!_world.JointList.Contains(_blonkJoint)) && (_blonkBody.ContactList != null))
    {
         _CBodyA = contactConstraint.BodyA;
         _CBodyB = contactConstraint.BodyB;
         _jointPoint = contactConstraint.Points[0].LocalPoint;
         _createJoint = true;
    }
}

Now, in my engine's Update(), I have this:

if (_selectedBlonk.RemoveJoint == true)
{
    _world.Remove(_selectedBlonk.BlonkJoint);
    _selectedBlonk.RemoveJoint = false;
}

if (_selectedBlonk.CreateJoint == true)
{
    _selectedBlonk.BlonkJoint = JointFactory.CreateRevoluteJoint(_world, _selectedBlonk.CBodyA, _selectedBlonk.CBodyB, _selectedBlonk.JointPoint);
    _selectedBlonk.BlonkJoint.CollideConnected = true;
    _selectedBlonk.CreateJoint = false;
}

Thanks.

Aug 8, 2010 at 7:27 PM
Ok, so here is my problem: I can't seem to figure out what coordinates to send to the createRevoluteJoint. Or rather, I can't seem to figure out what coordinates are being given to me by the ContactConstraint. I simply want the coordinates of the contact, nothing more. With those coordinates I need to make a RevoluteJoint at that point containing the two bodies in contact. What am I missing? I am sure it has to do with whther I am using local or world points, but I can't seem to figure out what it is giving me and what is needed by the RevoluteJoint. Thanks.
Aug 15, 2010 at 6:18 AM
So here is all the detail I can give. I am still having a heck of a hard time trying to replicate the functionality that was so simple to do in FP2.x. It seems that I should be using the OnCollision delegate, like I was doing in the past, which I am doing. The problem is that it is no longer simple (and definitely not intuitive) to get the local points of a single collision between two bodies. The only way I can see to do this is like this:
        public virtual bool BlonkOnCollision(Fixture a, Fixture b, Contact contact)
        {
            if (_engine.JointList.Contains(_blonkJoint))
                _removeJoint = true;

            if (!_engine.JointList.Contains(_blonkJoint) && _blonkBody.ContactList != null)
            {
                _CBodyA = a.Body;
                _CBodyB = b.Body;
                _jointPointA = contact.Manifold.Points[0].LocalPoint;
                //_jointPointB = b.Body.GetWorldPoint(contact.Manifold.Points[1].LocalPoint); <- this doesn't work at all.  The b fixture doesn't return values of the 2nd body in the collision (maybe a bug?)
                WorldManifold worldManifold;
                contact.GetWorldManifold(out worldManifold);
                Manifold manifold;
                contact.GetManifold(out manifold);
                //_jointPointA = worldManifold.Points[0];  //This is a world point
                _jointPointB = b.Body.GetLocalPoint(worldManifold.Points[0]); //This is a world point
                _createJoint = true;
            }
            
            return true;
        }
Since I am trying to create a RevoluteJoint, I need to get two local points. This finally creates a revolute joint at one of the corners of my blocks, but it never breaks the joint, because the OnCollision is not getting called again ever once this RevoluteJoint is being created. In FP2.x (with the code and video I posted above), the block is able to break the joint and create a new one, so it can roll over and over again. This time around the Joint is only able to break if I put something in the PostSolve, but this doesn't do me any good since the PostSolve gets called much more frequently than the collision, so the Joint only lasts for a few milliseconds. I've read the Box2D manual multiple times, but am still not able to see a way to do this the way I need it to happen. I need for the joint to create upon impact, and then stay until the block as rotated either 90 degrees (on a flat surface) or impacted another object, at which point the joint breaks and recreates at the new collision point. Any suggestions would be greatly appreciated. I'm starting to lose hope with getting FP3 to work the way I need it to.
Coordinator
Aug 15, 2010 at 8:33 PM

I will take a look at the OnCollision and OnSeparation delegates and see if I can simplify the output they give.