Understanding Box2D kinematic bodies

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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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();
  }
 }
}
 
 
Also look how debug draw shows kinematic bodies.
Download the source code.

0 comments:

Post a Comment

 

ACTION SCRIPT 3.0 Copyright © 2011-2012 | Powered by Blogger