An one-button way to control the player coming from the past – Box2D version (introducing friction joints)
This is a quick attempt to port the engine of the one-button way to control the player coming from the past using Box2D, introducing for the first time the friction joint, a type of joint which is poorly explained in the tutorial you can see around the web, and it’s a pity because it’s very useful when you have to handle with top down simulations.
Basically I created a world with no gravity, then I created a friction joint between the ball controlled by the player and the “ground”, in this case the world body.
The final result is a lot more realistic than any other result you can achieve using linear damping or other tricks.
This is the source 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 |
package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.text.TextField; import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import Box2D.Dynamics.Joints.*; public class Main extends Sprite { private var world:b2World=new b2World(new b2Vec2(0,0),true); private var worldScale:Number=30; private var theBall:b2Body; private var ball:Ball=new Ball(); private var directionArrow:DirectionArrow=new DirectionArrow(); private var powerText:TextField = new TextField(); private var rotate:Boolean=true; private var power:Number=0; private var rotationSpeed:Number=5; public function Main() { debugDraw(); createBall(); addChild(ball); ball.x=320; ball.y=240; ball.addChild(directionArrow); powerText.textColor=0xffffff; powerText.y=-10; powerText.x=-5; powerText.visible=false; ball.addChild(powerText); addEventListener(Event.ENTER_FRAME,update); stage.addEventListener(MouseEvent.MOUSE_DOWN,prepareLaunch); stage.addEventListener(MouseEvent.MOUSE_UP,launch); } private function createBall():void { var fixtureDef:b2FixtureDef = new b2FixtureDef(); fixtureDef.restitution=0; fixtureDef.density=1; var circleShape:b2CircleShape=new b2CircleShape(10/worldScale); fixtureDef.shape=circleShape; var bodyDef:b2BodyDef=new b2BodyDef(); bodyDef.userData=new Sprite(); bodyDef.position.Set(320/worldScale,240/worldScale); bodyDef.type=b2Body.b2_dynamicBody; bodyDef.userData=ball; theBall=world.CreateBody(bodyDef); theBall.CreateFixture(fixtureDef); var frictionJointDef:b2FrictionJointDef = new b2FrictionJointDef(); var anchorA:b2Vec2=new b2Vec2(0,0); var anchorB:b2Vec2=new b2Vec2(320/worldScale,240/worldScale); frictionJointDef.localAnchorA=anchorA; frictionJointDef.localAnchorB=anchorB; frictionJointDef.bodyA=theBall; frictionJointDef.bodyB=world.GetGroundBody(); frictionJointDef.maxForce=0.5; frictionJointDef.maxTorque=5; world.CreateJoint(frictionJointDef as b2JointDef); } 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|b2DebugDraw.e_jointBit); debugDraw.SetFillAlpha(0.5); world.SetDebugDraw(debugDraw); } private function prepareLaunch(e:MouseEvent):void { powerText.visible=true; rotate=false; } private function launch(e:MouseEvent):void { if (! rotate) { powerText.visible=false; rotate=true; theBall.ApplyImpulse(new b2Vec2(power*Math.cos((directionArrow.rotation-90)*0.0174532925)/10,power*Math.sin((directionArrow.rotation-90)*0.0174532925)/10),theBall.GetWorldCenter()); power=0; rotationSpeed*=-1; } } private function update(e:Event):void { world.Step(1/30, 10, 10); if (rotate) { directionArrow.rotation+=rotationSpeed; } else { power++; power=Math.min(power,50); powerText.text=power.toString(); } for (var b:b2Body = world.GetBodyList(); b; b = b.GetNext()) { if (b.GetUserData()!=null) { b.GetUserData().x=b.GetPosition().x*worldScale; b.GetUserData().y=b.GetPosition().y*worldScale; } } world.ClearForces(); world.DrawDebugData(); } } } |
and this is the result:
You know how to “play”: press and keep the mouse pressed to move the ball with a given direction and speed. Also look at the friction joint in the debug draw.
They can be easily customized to meet the unique requirements of your project.












This post has one comment
Dex
I love where this is going! Please, continue with the series :)