Real world catapult prototype using Box2D – Cleaner code
We got it.
After the first catapult prototype and the “slippery wheels” sequel, this is a version with realistic movement and a lot cleaner code.
To add realistic movement I defined friction and restitution, making useless the CreateFixture2 function and widely using the more appropriate CreateFixture one.
This way I have full control on fixtures, while in the old way I could only define their masses.
This is the result:
Left and right to move, spacebar to fire
And this is the code:
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | package { import flash.display.Sprite; import flash.events.Event; import flash.events.KeyboardEvent; import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import Box2D.Dynamics.Joints.*; public class main extends Sprite { public var world:b2World=new b2World(new b2Vec2(0,10.0),true); public var world_scale:int=30; var catapult_chassis_body:b2Body; var catapult_arm_body:b2Body; var rear_wheel_body:b2Body; var front_wheel_body:b2Body; var arm_revolute_joint:b2RevoluteJoint; var front_wheel_revolute_joint:b2RevoluteJoint; var rear_wheel_revolute_joint:b2RevoluteJoint; var left_key_pressed:Boolean=false; var right_key_pressed:Boolean=false; public function main():void { debug_draw(); the_ground(); the_catapult_body(); the_catapult_arm(); the_catapult_motor(); the_wheels(); the_wheel_motors(); the_cannonball(); addEventListener(Event.ENTER_FRAME, update); stage.addEventListener(KeyboardEvent.KEY_DOWN, key_down); stage.addEventListener(KeyboardEvent.KEY_UP, key_up); } public function the_cannonball():void { var cannonball:b2BodyDef= new b2BodyDef(); cannonball.position.Set(90/world_scale, 90/world_scale); cannonball.type=b2Body.b2_dynamicBody; var ball:b2CircleShape=new b2CircleShape(10/world_scale); var cannonball_fixture:b2FixtureDef = new b2FixtureDef(); cannonball_fixture.shape=ball; cannonball_fixture.friction=0.9; cannonball_fixture.density=20; cannonball_fixture.restitution=0.5; var the_cannonball_itself:b2Body=world.CreateBody(cannonball); the_cannonball_itself.CreateFixture(cannonball_fixture); } public function the_wheel_motors():void { var front_wheel_joint:b2RevoluteJointDef = new b2RevoluteJointDef(); front_wheel_joint.enableMotor=true; front_wheel_joint.Initialize(catapult_chassis_body, front_wheel_body,new b2Vec2(0,0)); front_wheel_joint.localAnchorA=new b2Vec2(80/world_scale,0); front_wheel_joint.localAnchorB=new b2Vec2(0,0); front_wheel_revolute_joint=world.CreateJoint(front_wheel_joint) as b2RevoluteJoint; front_wheel_revolute_joint.SetMaxMotorTorque(1000000); // var rear_wheel_joint:b2RevoluteJointDef = new b2RevoluteJointDef(); rear_wheel_joint.enableMotor=true; rear_wheel_joint.Initialize(catapult_chassis_body, rear_wheel_body,new b2Vec2(0,0)); rear_wheel_joint.localAnchorA=new b2Vec2(-80/world_scale,0); rear_wheel_joint.localAnchorB=new b2Vec2(0,0); rear_wheel_revolute_joint=world.CreateJoint(rear_wheel_joint) as b2RevoluteJoint; rear_wheel_revolute_joint.SetMaxMotorTorque(1000000); } public function the_wheels():void { var rear_wheel:b2BodyDef= new b2BodyDef(); rear_wheel.position.Set(250/world_scale, 200/world_scale); rear_wheel.type=b2Body.b2_dynamicBody; var rear_wheel_shape:b2CircleShape=new b2CircleShape(40/world_scale); var rear_wheel_fixture:b2FixtureDef = new b2FixtureDef(); rear_wheel_fixture.shape=rear_wheel_shape; rear_wheel_fixture.friction=0.9; rear_wheel_fixture.density=30; rear_wheel_fixture.restitution=0.1; rear_wheel_body=world.CreateBody(rear_wheel); rear_wheel_body.CreateFixture(rear_wheel_fixture); // var front_wheel:b2BodyDef= new b2BodyDef(); front_wheel.position.Set(450/world_scale, 200/world_scale); front_wheel.type=b2Body.b2_dynamicBody; var front_wheel_shape:b2CircleShape=new b2CircleShape(40/world_scale); var front_wheel_fixture:b2FixtureDef = new b2FixtureDef(); front_wheel_fixture.shape=front_wheel_shape; front_wheel_fixture.friction=0.9; front_wheel_fixture.density=30; front_wheel_fixture.restitution=0.1; front_wheel_body=world.CreateBody(front_wheel); front_wheel_body.CreateFixture(front_wheel_fixture); } public function the_catapult_motor():void { var arm_joint:b2RevoluteJointDef = new b2RevoluteJointDef(); arm_joint.enableMotor=true; arm_joint.enableLimit=true; arm_joint.Initialize(catapult_chassis_body, catapult_arm_body,new b2Vec2(0,0)); arm_joint.localAnchorA=new b2Vec2(-80/world_scale,-90/world_scale); arm_joint.localAnchorB=new b2Vec2(60/world_scale,0); arm_revolute_joint=world.CreateJoint(arm_joint) as b2RevoluteJoint; arm_revolute_joint.SetMotorSpeed(1000); arm_revolute_joint.SetLimits(-Math.PI,Math.PI/3); arm_revolute_joint.SetMaxMotorTorque(1); } public function the_catapult_arm():void { var catapult_arm:b2BodyDef = new b2BodyDef(); catapult_arm.allowSleep=false; catapult_arm.position.Set(210/world_scale,110/world_scale); catapult_arm.type=b2Body.b2_dynamicBody; var arm_part:b2PolygonShape = new b2PolygonShape(); arm_part.SetAsOrientedBox(150/world_scale, 10/world_scale, new b2Vec2(0,0),0); var arm_part_fixture:b2FixtureDef = new b2FixtureDef(); arm_part_fixture.shape=arm_part; arm_part_fixture.friction=0.9; arm_part_fixture.density=5; arm_part_fixture.restitution=0.1; var stopper:b2PolygonShape = new b2PolygonShape(); stopper.SetAsOrientedBox(10/world_scale, 20/world_scale, new b2Vec2(-140/world_scale,-30/world_scale),0); var stopper_fixture:b2FixtureDef = new b2FixtureDef(); stopper_fixture.shape=stopper; stopper_fixture.friction=0.9; stopper_fixture.density=10; stopper_fixture.restitution=0.1; catapult_arm_body=world.CreateBody(catapult_arm); catapult_arm_body.CreateFixture(arm_part_fixture); catapult_arm_body.CreateFixture(stopper_fixture); } public function the_catapult_body():void { var catapult_body:b2BodyDef = new b2BodyDef(); catapult_body.position.Set(350/world_scale,200/world_scale); catapult_body.type=b2Body.b2_dynamicBody; var main_part:b2PolygonShape = new b2PolygonShape(); main_part.SetAsOrientedBox(125/world_scale, 20/world_scale, new b2Vec2(0,0),0); var chassis_fixture:b2FixtureDef = new b2FixtureDef(); chassis_fixture.shape=main_part; chassis_fixture.friction=0.9; chassis_fixture.density=50; chassis_fixture.restitution=0.1; var fixed_arm:b2PolygonShape = new b2PolygonShape(); fixed_arm.SetAsOrientedBox(20/world_scale, 60/world_scale, new b2Vec2(-80/world_scale,-40/world_scale),0); var fixed_arm_fixture:b2FixtureDef = new b2FixtureDef(); fixed_arm_fixture.shape=fixed_arm; fixed_arm_fixture.friction=0.9; fixed_arm_fixture.density=1; fixed_arm_fixture.restitution=0.1; catapult_chassis_body=world.CreateBody(catapult_body); catapult_chassis_body.CreateFixture(chassis_fixture); catapult_chassis_body.CreateFixture(fixed_arm_fixture); } public function the_ground():void { var ground:b2BodyDef= new b2BodyDef(); ground.position.Set(250/world_scale, 400/world_scale); var my_box:b2PolygonShape = new b2PolygonShape(); my_box.SetAsBox(1000/world_scale, 15/world_scale); var ground_fixture:b2FixtureDef = new b2FixtureDef(); ground_fixture.shape=my_box; ground_fixture.friction=0.9; ground_fixture.restitution=0.1; var the_ground_itself:b2Body=world.CreateBody(ground); the_ground_itself.CreateFixture(ground_fixture); } public function key_up(event:KeyboardEvent):void { switch (event.keyCode) { case 39 : right_key_pressed=false; break; case 37 : left_key_pressed=false; break; } } public function key_down(event:KeyboardEvent):void { switch (event.keyCode) { case 39 : right_key_pressed=true; left_key_pressed=false; break; case 37 : left_key_pressed=true; right_key_pressed=false; break; case 32 : arm_revolute_joint.SetMaxMotorTorque(10000); break; } } public function debug_draw():void { var debug_draw:b2DebugDraw = new b2DebugDraw(); var debug_sprite:Sprite = new Sprite(); addChild(debug_sprite); debug_draw.SetSprite(debug_sprite); debug_draw.SetDrawScale(world_scale); debug_draw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit); debug_draw.SetFillAlpha(0.5); world.SetDebugDraw(debug_draw); } public function set_motor_speed():void { var current_speed:Number; if (right_key_pressed) { current_speed=1; } if (left_key_pressed) { current_speed=-1; } if (! right_key_pressed&&! left_key_pressed) { current_speed=rear_wheel_revolute_joint.GetMotorSpeed()*0.9; if (Math.abs(current_speed)<0.1) { current_speed=0; } } rear_wheel_revolute_joint.SetMotorSpeed(current_speed); front_wheel_revolute_joint.SetMotorSpeed(current_speed); } public function update(e:Event):void { set_motor_speed(); world.Step(1/30,10,10); world.ClearForces(); world.DrawDebugData(); } } } |
No need to download, just cut and paste on the first catapult prototype.
Next time, full comments and some other interesting features…
They can be easily customized to meet the unique requirements of your project.















(9 votes, average: 4.11 out of 5)









This post has 6 comments
César Jr.
muito legal…
já tomo esse site como base..
parabéns..
pelo seu otimo trabalho…
Zero Xue
Thanks a lot,this is really helpful!
Devon
SOO much better! Thanks for making this update Emanuele!
dario111cro
Nice and clean. Really helped me :)
Now, you should add/edit:
Smaller size of catapult.
Boxes in what will hit catapult
Ball should go more away and lower from ground.
(sry for bad English)
Porter
Woot for clean code, I’ll never be able to adjust to underscores in function names though, especially with the lower casing of the second word in a function. Good stuff though, very organized.
diego
Perfect! that’s an Excellent example!!
i try do a slingshot…
can you help me? how can i do it this?