Box2d 2.1 b2world.QueryPoint() and iterating over a b2fixture list
In version 2.1 (and earlier I believe) of box2d objects are stored in linked lists. A common task will be iterate over one of these linked lists. For instance if you want to iterate over a body’s b2fixture linked list. In my case, I had the following problem: I was making a kids math game on how to combine like terms called Rj The Robot , and I only wanted the robot to jump if it was standing on a ‘floor’ shape. Now all ‘foors’ in the game had a string attached to their b2fixture called ‘is_floor’. Below is some code that demonstrates how floor bodies, shapes and fixtures are creating. Note: if you don’t know what a b2fixture is read this.
//bottom wall
var bottom_wallShape:b2PolygonShape = new b2PolygonShape();
var bottom_wallBd:b2BodyDef = new b2BodyDef();
bottom_wallBd.type = b2Body.b2_staticBody;
var bottom_wallBody:b2Body;
bottom_wallBd.position.Set(halfOfStageWidth /PIXELS_PER_METER , halfOfStage*2/ PIXELS_PER_METER- .5 );
bottom_wallShape.SetAsBox(ground_width, ground_height);
bottom_wallBody = myB2World.CreateBody(bottom_wallBd);
var fd:b2FixtureDef = new b2FixtureDef();
fd.friction = 1 ;
fd.shape = bottom_wallShape;
fd.userData = 'is_floor';
bottom_wallBody.CreateFixture(fd);

Now, I wanted the hero to be able to tell if it was standing on a shape whose b2fixture had the string ‘is_floor’ as its userdata. The solution is to use the b2World.QueryPoint() function . This function takes the form of myb2World.QueryPoint(callbackFunction, someB2Vec) where the someB2Vec is the point to check. In the picture below I was sending the red dot, called heroFootPoint in my code, to the function. Below is the full code explained in the comments
//get hero's center point
var currentCenter:b2Vec2 = _body.GetWorldCenter();
heroFootPoint.x = currentCenter.x
heroFootPoint.y = currentCenter.y + 1.43 //add 1.43 so point is below Robot foot;
var bIsOnFloor:Boolean = false; //assume not standing on floor
function bOnFloorFixture(fixture:b2Fixture):Boolean //call back function
{ //this call back function
var body:b2Body = b2Fixture(fixture).GetBody(); //get body of current fixture
var bsFixture:b2Fixture = body.GetFixtureList();
while (bsFixture != null ) //it
{
if (bsFixture.GetUserData() == ‘is_floor’) //found a fixture whose userdata is ‘is_floor’…ie are standing on the floor
{
bIsOnFloor = true;
return false; //return false so that we don’t continue iterating over the list
}
bsFixture = bsFixture.GetNext(); //if we got here we didn’t yet find a fixture with ‘is_floor’ userdat..
} //so see if body has another b2fixture attached for checking
return true; //callback returns true means that the queryWorld() function will check next b2Fixture at heroFootPoint
}
myB2World.QueryPoint(bOnFloorFixture, heroFootPoint); //start queryPoint()…check all fixtures overlapping heroFootPoint
leave a comment