2
\$\begingroup\$

I'm trying to make a game that uses Farseer physics engine as its main collision detection engine. I have a 2d circle body object that has a matching fixture (I used the CreatCircle method. I did not create the fixtures and bodies separate). When IsSensor is set to false, objects collide with this circle and bounce off. My goal was to have events triggered when other physics enabled bodies move through this field and just use the engine to detect the collisions (or rather intersections) so I set it to IsSensor = true, and now all the other bodies pass right through but I do not get collision events. The be specific, sometimes I do get events but not continuously as I would expect. My intention was to have this collision code fired each time the world re evaluated collisions.

Does anyone know a way to do this. My googling has led me nowhere and I'll be fudging with the limited farseer documentation I can find this weekend to try and get this right.

Thanks ahead of time.

\$\endgroup\$
0
\$\begingroup\$

Get the Body.ContactList which is populated by all contact resulting from BB collisions. If you want contacts that actually have fixtures touching check to see if Contact.IsTouching() is true.

Edit: There are performance issues with this approach so I suggest setting a flag when the sensor collision event fires and setting the flag to false when none of the items in the ContactList are touching. Only iterate though the contact while this flag it set to true. This would prevent you from iterating every every time a BB intersects with your sensor.

\$\endgroup\$
  • \$\begingroup\$ So this would be a home rolled collision check, probably in the update method of the game component and not an event I can register a delegate for? \$\endgroup\$ – Flostation Feb 16 '12 at 21:14
  • \$\begingroup\$ Yes. However, you can use the collision event to kick of the collision checking and stopping as soon as no objects are touching reducing the workload if you are worried about performance issues. See my edit. \$\endgroup\$ – ClassicThunder Feb 16 '12 at 21:28
  • \$\begingroup\$ I like this approach but I'm running into a problem with the initial OnCollision and the following OnSeperation events. The don't get fired right away when the initial contact with the fixtures is made and the separation event is never fired. It seems to almost randomly choose when to flag collision. Would timing with a sensor type body be an issue when looking for collisions? \$\endgroup\$ – Flostation Feb 16 '12 at 21:37
  • \$\begingroup\$ I believe with sensors you are supposed to use BeginContact and EndContact in the ContactListener. Don't have the API in front of my so I may be remembering incorrectly. \$\endgroup\$ – ClassicThunder Feb 16 '12 at 21:43
  • \$\begingroup\$ This pretty much worked. I'm still having issues with the timing of the BeginContact and EndContact events. They sometimes don't fire till in the middle of my sensor circle, but at least they are firing. I can post some example code if someone is having this same problem. I had to fumble around the codebase of farseer a little to figure out what delegates to add my methods to. Its not really spelled out in any documentation. Coming from using Java all day every day at work, this really makes me longingly pine for Javadocs... Sigh. Some day. Some where. \$\endgroup\$ – Flostation Feb 20 '12 at 20:43
0
\$\begingroup\$
//declare variables 
private List<Dynamics.Contacts.Contact> contacts;

public int SensorData;
//you need your fixture
//my fixture create by Bayazit
TactSensorTexture = Content.Load<Texture2D>("test_1");
uint[] data1 = new uint[TactSensorTexture.Width * TactSensorTexture.Height];
TactSensorTexture.GetData(data1);
Vertices verts1 = PolygonTools.CreatePolygon(data1, TactSensorTexture.Width);
Vector2 scale = new Vector2(0.07f, 0.07f);
List<Vertices> _list = FarseerPhysics.Common.Decomposition.Triangulate.ConvexPartition(verts1, TriangulationAlgorithm.Bayazit);
foreach (Vertices vertices in _list)
        {
            vertices.Scale(ref scale);
        }
//attach to create body (already have a circle shape)
compaund = FixtureFactory.AttachCompoundPolygon(_list, 0.000f, _circleBody);
//FixtureFactory create two fixture
compaund[1].IsSensor = true;
compaund[0].IsSensor = true;

//in function update i white next construction (insert on right place)
SensorData = 0; //always set zero because you in update funciton
contacts = _world.ContactList; //get list of contacts
foreach(Dynamics.Contacts.Contact contact in contacts)
            {   

                if ((contact.FixtureA == compaund[0] && contact.IsTouching) || (contact.FixtureB == compaund[0] && contact.IsTouching)) //check only for one fixture because it's just example
                {
                    SensorData = 1;
                }
                else
                {
                   //dont need do anything
                }

            }
//also you can drow on screen (insert on right place)
_batch.DrawString(_font, System.Convert.ToString(SensorData), new Vector2(14f, 20f), Color.Red);
\$\endgroup\$
  • \$\begingroup\$ This answer would be even better with a brief introductory text, so a user doesn't need to read through all of your code to get the basic idea of what you're suggesting. The easier you make it for someone to understand the answer, the more likely you are to attract upvotes from casual readers. :) \$\endgroup\$ – DMGregory Mar 29 '17 at 12:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.