OnCollison not being called?

Topics: Developer Forum, User Forum
Dec 21, 2009 at 8:55 PM

Hi all,

I've been working on creating a path finding system using FarSeer, with the goal being to have a list of PathNode objects (vector based structs, essentially) that describe all of the valid locations where a particular entity might move to on a 2D tilemap world. One of the challenges I have been struggling with is identifying where not to place these nodes. My thinking was that after I loaded the static geometry into the world (i.e., the walls, buildings, and the like), I could find every PathNode that was within close proximity to those geometry's bodies, add those nodes to the phsicsSimulator, call physicsSimulator.Update(), and override the OnCollision event such that I would remove that node from the master navigationNode List, with the end result being a List that only contained non-colliding PathNodes.

In other words, I start by identifying the nodes that are close to the bodies of the static objects in the world:

foreach (PathNode p in navNodes)
{
IEnumerable<int> nodeXRange = Enumerable.Range((int)(e.currentBodyGeom.Position.X - ZSGameManager.tileMapEngine.currentLevelMap.tileSize / 2), ZSGameManager.tileMapEngine.currentLevelMap.tileSize);
IEnumerable<int> nodeYRange = Enumerable.Range((int)(e.currentBodyGeom.Position.Y - ZSGameManager.tileMapEngine.currentLevelMap.tileSize / 2), ZSGameManager.tileMapEngine.currentLevelMap.tileSize);

foreach (int intX in nodeXRange)
{
if (p.position.X == intX)
{
foreach (int intY in nodeYRange)
if (p.position.Y == intY)
{
tempNode = p;
tempNode.wasChecked = true;
nodesToCheck.Add(tempNode);
}
}
}
}

Then I iterate through that list, adding each of the nodesToCheck to the physicsSimulator:

foreach (PathNode p in nodesToCheck)
    ZSGameManager.tileMapEngine.physicsHandler.physicsSimulator.Add(p.geom);  
             
ZSGameManager.tileMapEngine.physicsHandler.Update(ZSGameManager.elapsedTime);

Each PathNode is set up as follows:

tempNode.body = BodyFactory.Instance.CreateCircleBody((float)(ZSGameManager.tileMapEngine.currentLevelMap.tileSize / gridGranularity), 1.0f);
tempNode.geom = GeomFactory.Instance.CreateCircleGeom(tempNode.body, (float)(ZSGameManager.tileMapEngine.currentLevelMap.tileSize / gridGranularity), 16);
tempNode.geom.CollisionEnabled = true;
tempNode.geom.CollisionResponseEnabled = false;
tempNode.geom.OnCollision += OnCollision;
tempNode.geom.Tag = tempNode;

And I have an OnCollision function that should get called:

 private bool OnCollision(Geom geometry1, Geom geometry2, ContactList contactList)
{
ZSGameManager.engineLogger.AddToLog("\t\tCollison: " + geometry1.Position.ToString() + " and " + geometry2.Position.ToString());
PathNode pathNode = (PathNode)geometry1.Tag;

geometry1.OnCollision -= OnCollision;
geometry1.Body.Enabled = false;

geometry1.Tag = null;
ZSGameManager.tileMapEngine.physicsHandler.physicsSimulator.Remove(geometry1.Body);
ZSGameManager.tileMapEngine.physicsHandler.physicsSimulator.Remove(geometry1);
navNodes.Remove(pathNode);

return false;
}

However, that OnCollision code never gets called. I've debugged far enough to see that the PathNodes I expect in nodesToCheck do get added to the geomList during ProcessAddedItems(), and that the rest of the world geometry is in that list at that time, as well. Is there anything obvious that I'm missing?

 

Dec 28, 2009 at 8:43 PM

No need to reply here; it turned out that the problem was mine, in that I was effectively removing the PathNodes from the physics simulator before checking for collisions.

For what it's worth, until FarSeer supports a Query method, it's not a terribly effective system for handling this type of thing. Instead, I ended up culling nodes that intersected objects as reported via a color comparison, which was (a) pixel perfect, and (b) much faster.

Coordinator
Dec 28, 2009 at 9:31 PM

Querying the broadphase will be supported in Farseer Physics Engine 3.0.

Dec 28, 2009 at 9:32 PM

And you guys rock for it. Let me know if there is anything I can do to help!