Yesterday, I realized that my initial difficulties with Three.js and Box2dWeb integration were caused by my failure to account for rotation. Specifically, objects in Box2dWeb were rotating / falling down after a collision, but I was only representing the position change in Three.js.
The solution was to copy the rotation from the Box2dWeb world into the Three.js scene:
function gameStep() { world.Step( 1 / 60, //frame-rate 10, //velocity iterations 10 //position iterations ); world.ClearForces(); var pdef = player_fixture.GetBody().GetDefinition(); player.position.x = pdef.position.x; player.position.y = pdef.position.y; player.rotation.z = pdef.angle; var fdef = fruit_fixture.GetBody().GetDefinition(); fruit.position.x = fdef.position.x; fruit.position.y = fdef.position.y; setTimeout(gameStep, 1000 / 60); // process the game logic // at a target 60 FPS. }That works, but I do not really want my player to rotate or fall down in this jumping game. Happily, Box2dWeb provides a
fixedRotation
property to accomplish this: // ...
// player
bodyDef.type = b2Body.b2_dynamicBody;
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(10, 25);
bodyDef.position.x = -75;
bodyDef.position.y = 10;
bodyDef.fixedRotation = true;
player_fixture = world.CreateBody(bodyDef).CreateFixture(fixDef);
// ...
With that, I can collide without rotating:Next, I would like to detect the collision. This turns out to be fairly straight forward in Box2dWeb. Straight-forward, but a little different than typical JavaScript events.
Normally, I would add an event listener to the player or the game tokens. But in Box2dWeb, I need to create a
b2ContactListener
object and, on that object, I need to set a BeginContact
property. Lastly, I have to add the listener to the Box2dWeb world object as a contact listener: // ...
var myListener = new Box2D.Dynamics.b2ContactListener;
myListener.BeginContact = function(contact) {
if (contact.m_fixtureA === ground) return;
if (contact.m_fixtureB === ground) return;
console.log(contact);
score += 10;
writeScoreBoard("Score: " + score);
};
world.SetContactListener(myListener);
// ...
In any collision, there are two objects. In Box2dWeb, these are properties of a contact object supplied to the listener's callback. The properties are named m_fixtureA
and m_fixtureB
. In my callback, I need guard clauses to ignore collisions with the ground. If it is a real collision, I update the game score.And it works:
Nice. This listener object, call back property, set-on-world process feels a bit awkward, but it works. And for something compiled from ActionScript, I'll take it.
Day #500
No comments:
Post a Comment