Using Tweens with Box2D 2.0.1
Juten tach,
i am currently involved in a fun project, where i am told to build a classical jump ‘n run game. Very nice. I am using the flash port of Box2d in its version 2.0.1. I know, that there is version 2.1, but it’s still alpha and i generally do not feel so comfortable using alpha software.
Like in most jump ‘n run games, we have moving obstacles, like little bricks, that move from left to right and back again and you have to jump on them to get over a giant abyss.
Now these moving bricks should move autonomously and indefinitely. Being a flash developer, first thing, that comes to mind is tweening them. But as we learn from many sources in the box2d community, this is actually a no-go, because we should rather use velocities and the real physics of Box2d to make things move. Makes sense to me.
So my first attempt was to reuse some of the smart scripts from Todd. And that worked quite well. Here is an excerpt of the script (actually with slight changes from my side), that will run in the usual world update method (box2d specific):
if(currentPosition.x >= initialPosition.x + movementDistance) { _direction = -1; }else if(currentPosition.x <= initialPosition.x) { _direction = 1; } var idealLocation:b2Vec2 = new b2Vec2(currentPosition.x + (_direction * (TRAVEL_SPEED / PhysiVals.RATIO)), initialPosition.y); var directionToTravel:b2Vec2 = idealLocation.Copy(); directionToTravel.Subtract(currentPosition); directionToTravel.Multiply(30); _body.SetLinearVelocity(directionToTravel); |
So looking at this, after a while i thought, idealLocation is a point, that changes on every box2d world step and reflects the position, where the body should be. Isn’t that the same thing, that a tweener does? Of course, it is.
So changing this script to use a tweener like TweenLite or something is pretty easy. In my case, i am using TimelineMax, because i want to let my body to move back and forth infinitely (code simplified):
private var positionTracker:b2Vec2; private function initialize():void { positionTracker = initialPosition.Copy(); timeline = new TimelineMax({repeat:-1}); timeline.append(new TweenLite(positionTracker, 1, {x:initialPosition.x + movementDistance})); timeline.append(new TweenLite(positionTracker, 1, {x:initialPosition.x})); } private function onWorldUpdate():void { var currentPosition:b2Vec2 = myBody.GetXForm().position; var directionToTravel:b2Vec2 = positionTracker.Copy(); directionToTravel.Subtract(currentPosition); directionToTravel.Multiply(Environment.TIME_STEP); myBody.SetLinearVelocity(directionToTravel); } |
So, what is happening here? Well, we keep a helper object, the positionTracker. This is our object, that gets modified by our tweener. It is a b2Vec2 instance, which has x and y attributes. We give the positionTracker our initialPosition of our box2d body. Then we create our tween, just the normal way we always use tweens. But we use our positionTracker with it.
Now, somewhere in our program we usually have a world update method, because that’s how Box2D works. And here we simply use the approach Todd uses in his tutorial, we take the current position of our body, calculate the difference from our desired location (which now is the location our tweener has calculated) and the current location and build a velocity vector from it, which we then set to our body.
The result is a crystal clear animation just the way we have defined it in our tween. But since we are setting a velocity, our body is still open for other forces, that have an impact on it. So in my case, when my character jumps on the brick, the brick eases off a bit, but quickly goes back on its path, which is a rather nice behavior, i think.

Very nice article, i wanted to try Box2D Flash port before but example were too “Flash Pro” based for me (used to dev in Flash Builder Flex App instead).
Keep posting code snippet, that’s the interesting part
Fabien
Please show us something with Box2D and tweening =)
Hi
I solved it like this – not the “real” way to do – but the it works, for simple things.
b2 = new b2Vec2()
b2.x = myb2Body.GetPosition().x;
b2.y = myb2Body.GetPosition().y;
TweenLite.killTweensOf(b2)
TweenLite.to (b2 , 2, { x: ( ( Math.random() *300 )+200 )/worldScale, ease:Expo.easeOut, onUpdate:setpos } );
}
private function setpos():void {
myb2Body.SetPosition(b2)
}