So you are used to work with Box2D and know everything about body types, such as static bodies and dynamic bodies… why nobody talks about kinematic bodies?
I think kinematic bodies are great to do some tasks, but first let me briefly explain the difference among body types.
A dynamic body is a body which is affected by world forces and react to collisions. And you already met a million of them.
A static body is a body which isn’t affected by world forces it does not react to collisions. It can’t be moved. Fullstop.
A kinematic body is an hybrid body which is not affected by forces and collisions like a static body but can moved with a linear velocity like a dynamic body.
So I made this little, commented script where dynamic spheres fall down at every second in a world full of moving kinematic bodies. The effect is unique and can be used in some games.
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
public class Main extends Sprite {
private var world:b2World=new b2World(new b2Vec2(0,5),true);
private var worldScale:Number=30;
private var timer:Timer=new Timer(1000);
public function Main() {
debugDraw();
for (var i:int=0; i<10; i++) {
// building 10 kinematic spheres
// five on the left side of the stage moving right
// five on the right side of the stage moving left
kinematicSphere(640*(i%2),50+40*i,10,(1-2*(i%2))*(Math.random()*10+5));
}
addEventListener(Event.ENTER_FRAME,updateWorld);
// I will make a dynamic sphere fall from the top of the stage
// at every second
timer.start();
timer.addEventListener(TimerEvent.TIMER,addSphere);
}
private function addSphere(e:TimerEvent):void {
dynamicSphere(320,-10,10);
}
private function dynamicSphere(pX:int,pY:int,r:Number):void {
var bodyDef:b2BodyDef=new b2BodyDef();
bodyDef.position.Set(pX/worldScale,pY/worldScale);
bodyDef.type=b2Body.b2_dynamicBody;
var circleShape:b2CircleShape=new b2CircleShape(r/worldScale);
var fixtureDef:b2FixtureDef=new b2FixtureDef();
fixtureDef.shape=circleShape;
var theDynamic:b2Body=world.CreateBody(bodyDef);
theDynamic.CreateFixture(fixtureDef);
}
private function kinematicSphere(pX:int,pY:int,r:Number,hV):void {
var bodyDef:b2BodyDef=new b2BodyDef();
bodyDef.position.Set(pX/worldScale,pY/worldScale);
// ************************** HERE IS THE MAGIC LINE ************************** \\
bodyDef.type=b2Body.b2_kinematicBody;
var circleShape:b2CircleShape=new b2CircleShape(r/worldScale);
var fixtureDef:b2FixtureDef=new b2FixtureDef();
fixtureDef.shape=circleShape;
var theKinematic:b2Body=world.CreateBody(bodyDef);
theKinematic.CreateFixture(fixtureDef);
// look, I can set a linear velocity
theKinematic.SetLinearVelocity(new b2Vec2(hV,0));
}
private function debugDraw():void {
var debugDraw:b2DebugDraw=new b2DebugDraw();
var debugSprite:Sprite=new Sprite();
addChild(debugSprite);
debugDraw.SetSprite(debugSprite);
debugDraw.SetDrawScale(worldScale);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
debugDraw.SetFillAlpha(0.5);
world.SetDebugDraw(debugDraw);
}
private function updateWorld(e:Event):void {
world.Step(1/30,10,10);
world.ClearForces();
for (var b:b2Body = world.GetBodyList(); b; b = b.GetNext()) {
// changing kinematic sphere linear velocity if it touches stage edges
if (b.GetType()==b2Body.b2_kinematicBody) {
var xSpeed:Number=b.GetLinearVelocity().x;
var xPos:Number=b.GetWorldCenter().x*worldScale;
if ((xPos<10&&xSpeed<0) || (xPos>630&&xSpeed>0)) {
xSpeed*=-1;
b.SetLinearVelocity(new b2Vec2(xSpeed,0));
}
}
else {
if (b.GetWorldCenter().y*worldScale>480) {
world.DestroyBody(b);
}
}
}
world.DrawDebugData();
}
}
}
This is the result:
Also look how debug draw shows kinematic bodies.