Checking when a collision happens and sticking objects together.

Topics: Developer Forum, User Forum
Jul 31, 2009 at 11:21 PM

I need to check when two circles collide and then stick them together so that they move like 1 object. I can't seem to figure out how to check if two specific objects are colliding. And I assume I can use a weld joint inside an if statement so that if they collide they weld together, but I'm not sure if thats possible. I'm relatively new to Farseer but not new to programming or XNA. I'm currently using Farseer on an XNA project.

Coordinator
Aug 1, 2009 at 12:38 AM

All geometries are polygons, so there is no way in Farseer to check if you collide with a circle geometry. You will have to use the Tag property on the geometries. You can store some kind of "circleid" in it and then check it in the OnCollision event. (CircleGeom.OnCollision)

You have a lot of choices for sticking them together. One is the weld joint, another is a couple of pin joints (or just one, depending on what kind of behavior you want). You could also create a single body with the two geometries, that would make them move as one geometry.

The manual is a good place to start and so are the simple samples provided in the download section.

Aug 1, 2009 at 1:30 AM

would it be possible to have one ball enter another if they collide only about 20% then stick in place after reaching that point? The way this is set up it seems that might be very difficult to pull off.

Coordinator
Aug 1, 2009 at 1:33 AM

You can make both circles ignore collision responses (CollisionResponseEnabled = false). This would permit the circles to enter each other while they still detect collisions as normal. You can then create a inner circle where you have set Geom.IsSensor = true. Once you registered a collision with the sensor geometry (the inner one), you can attach the geometries using a joint.

Aug 4, 2009 at 5:20 AM

I've gotten balls to stick to each other. However the only way I managed to get it to work was by disposing of both geoms old bodys and giving them a new singular body. This works to an extent. However the object immediatly stops and also will no longer collide with other objects.

Coordinator
Aug 4, 2009 at 7:34 PM

If you create a whole new body with the two geometries, it will not retain the velocity from the old geometries. You could save the velocity and apply it to the new one.

Do you use collision groups or collision categories?

Aug 5, 2009 at 4:01 AM

I don't use groups or categories. What value for the gemos is velocity? And how would I apply this afterwards?

Coordinator
Aug 5, 2009 at 1:54 PM

Have you added the new body to the physics simulator?

All bodies have a LinearVelocity property that contains the direction and magnitude of movement. When you dispose the body, you remove its movement, so you will have to save the value before you remove it and then add it to the new body when you create it.

Aug 5, 2009 at 9:00 PM
Edited Aug 5, 2009 at 9:00 PM

This is the current code in my oncollision function where I'm checking for two circles colliding

Vector2 velocity = geom1.Body.LinearVelocity;
Vector2 velocity2 = geom2.Body.LinearVelocity;
geom1.Body.Dispose();
geom2.Body.Dispose();
 Body Temp = geom1.Body;

 Temp.LinearVelocity = velocity + velocity2;
geom1.SetBody(Temp);
geom2.SetBody(Temp);
phySim.Add(Temp);
phySim.Add(geom1);
phySim.Add(geom2);

I am adding the new body as you an see. After doing this they stop in place and can no longer be collided with. Maybe its something to do with the order I'm doing everything in?

Aug 6, 2009 at 7:37 AM

This is what I would do:

  1. At creation of a circle geometry, add geom to a List called circleGeoms
  2. Everytime the collision handler is called, check if both geoms are in this list
  3. *Check if these geoms are in a dictionary<Geom, int> called tempCollidedGeoms, and if they both have the same value, exit function*
  4. If yes, retrieve Geom.Body & joint the two bodies together @ the first point in the ContactPoints array
  5. Register joint in the Physics simulator
  6. Set ignore collision with this geom, so function wont be called every frame
  7. *Add both Geoms to the tempCollidedGeoms dictionary, with a unique ID*
  8. *At the end of frame, clear the tempCollidedGeoms & prepare for next frame*

I think this way is more flexible then simply having a single body for both. However, the problem is that the collision function will be called for both Geoms in the same frame, so steps 3,7,8 are to prevent two joints from being created and causing problems.

 

Hope this helps

Aug 10, 2009 at 8:15 PM
Edited Aug 10, 2009 at 8:16 PM

I've done the following but the Joint never seems to exist when they collide.

 

Key++;
            if ((BallGeoms.Contains(geom1)) && (BallGeoms.Contains(geom2)))
            {
                int value1;
                int value2;
                bool temp1 = tempCollidedGeoms.ContainsKey(geom1);
                bool temp2 = tempCollidedGeoms.ContainsKey(geom2);
                if (temp1 && temp2)
                {
                tempCollidedGeoms.TryGetValue(geom1,out value1);
                tempCollidedGeoms.TryGetValue(geom2,out value2);

                    if (value1 == value2)
                    {
                        return false;
                    }
                    else
                    {
                        tempCollidedGeoms.Add(geom1, Key);
                        tempCollidedGeoms.Add(geom2, Key);

                        Joint Connector = JointFactory.Instance.CreatePinJoint(geom1.Body, contactList[0].Position, geom2.Body, contactList[0].Position);
                        phySim.Add(Connector);
                    }
                }
            }
            return true;

Aug 17, 2009 at 8:58 PM

Alright I've almost got this. The only problem now is I can't figure out how to turn off collision detection between two geoms. Is there any way to do this without using collision groups?

Aug 18, 2009 at 12:00 AM

Alright I have a REALLY weird bug. I have 7 balls on screen 6 of these are one size and another is twice as big with twice the mass. Now I run my program when the balls collide they stick together. However when the bigger ball gets 2 stuck to it freaks out and ends up blowing up and crashing the program. I have no clue why since all the smaller balls can collide and attach properly infinite amounts of times.