Talking about Tiny Wings game, Actionscript 3, Box2D, Flash and Game development.
When I introduced the scrolling in my Tiny Wings-like terrain I told you it would have been interesting to add a car to the game.
That’s what I made in this prototype:
You can control the cart with ARROW keys this way: UP: accelerate; DOWN: brake; LEFT: balance the cart on the left side; RIGHT: balance the cart on the right side.
And there’s not that much to say, apart from the cart creation which will be covered in a standalone post, I just scroll the game field and create new hills according to cart position rather than automatically like I did in the previous example.
And this is the commented source code:
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 {
private var world:b2World=new b2World(new b2Vec2(0,10),true);
private var worldScale:int=30;
// variables which will be used to determine key pressed
private var left:Boolean=false;
private var right:Boolean=false;
private var up:Boolean=false;
private var down:Boolean=false;
// the body of the cart
private var cart:b2Body;
// wheels motor speed
private var motorSpeed:Number=0;
// front and rear wheels revolute joints
private var rearWheelRevoluteJoint:b2RevoluteJoint;
private var frontWheelRevoluteJoint:b2RevoluteJoint;
// random hill's height
private var nextHill:Number=140+Math.random()*200;
// build another hill when stage's x position is lower than this value
private var buildNextHillAt:Number=0;
public function Main():void {
debugDraw();
// we start with two hills
nextHill=drawHill(10,0,nextHill);
nextHill=drawHill(10,640,nextHill);
addEventListener(Event.ENTER_FRAME,updateWorld);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP,keyReleased);
// add the cart
var carBodyDef:b2BodyDef = new b2BodyDef();
carBodyDef.type=b2Body.b2_dynamicBody;
carBodyDef.position.Set(320/worldScale,50/worldScale);
carBodyDef.userData=new Object();
var box:b2PolygonShape = new b2PolygonShape();
box.SetAsBox(30/worldScale,10/worldScale);
var boxDef:b2FixtureDef = new b2FixtureDef();
boxDef.density=0.5;
boxDef.friction=3;
boxDef.restitution=0.3;
boxDef.filter.groupIndex=-1;
boxDef.shape=box;
cart=world.CreateBody(carBodyDef);
cart.CreateFixture(boxDef);
// wheel shape
var wheelShape:b2CircleShape=new b2CircleShape(12/worldScale);
// wheel fixture
var wheelFixture:b2FixtureDef = new b2FixtureDef();
wheelFixture.density=1;
wheelFixture.friction=3;
wheelFixture.restitution=0.1;
wheelFixture.filter.groupIndex=-1;
wheelFixture.shape=wheelShape;
// wheel body definition
var wheelBodyDef:b2BodyDef = new b2BodyDef();
wheelBodyDef.type=b2Body.b2_dynamicBody;
// real wheel
wheelBodyDef.position.Set(cart.GetWorldCenter().x-(16/worldScale),cart.GetWorldCenter().y+(15/worldScale));
var rearWheel:b2Body=world.CreateBody(wheelBodyDef);
rearWheel.CreateFixture(wheelFixture);
// front wheel
wheelBodyDef.position.Set(cart.GetWorldCenter().x+(16/worldScale),cart.GetWorldCenter().y+(15/worldScale));
var frontWheel:b2Body=world.CreateBody(wheelBodyDef);
frontWheel.CreateFixture(wheelFixture);
// rear joint
var rearWheelRevoluteJointDef:b2RevoluteJointDef=new b2RevoluteJointDef();
rearWheelRevoluteJointDef.Initialize(rearWheel,cart,rearWheel.GetWorldCenter());
rearWheelRevoluteJointDef.enableMotor=true;
rearWheelRevoluteJointDef.maxMotorTorque=10000;
rearWheelRevoluteJoint=world.CreateJoint(rearWheelRevoluteJointDef) as b2RevoluteJoint;
// front joint
var frontWheelRevoluteJointDef:b2RevoluteJointDef=new b2RevoluteJointDef();
frontWheelRevoluteJointDef.Initialize(frontWheel,cart,frontWheel.GetWorldCenter());
frontWheelRevoluteJointDef.enableMotor=true;
frontWheelRevoluteJointDef.maxMotorTorque=10000;
frontWheelRevoluteJoint=world.CreateJoint(frontWheelRevoluteJointDef) as b2RevoluteJoint;
}
private function drawHill(pixelStep:int,xOffset:Number,yOffset:Number):Number {
var hillStartY:Number=yOffset;
var hillWidth:Number=640;
var hillSliceWidth=hillWidth/pixelStep;
var hillVector:Vector.;
var randomHeight:Number=Math.random()*100;
if (xOffset!=0) {
hillStartY-=randomHeight;
}
for (var j:int=0; j();
hillVector.push(new b2Vec2((j*pixelStep+xOffset)/worldScale,480/worldScale));
hillVector.push(new b2Vec2((j*pixelStep+xOffset)/worldScale,(hillStartY+randomHeight*Math.cos(2*Math.PI/hillSliceWidth*j))/worldScale));
hillVector.push(new b2Vec2(((j+1)*pixelStep+xOffset)/worldScale,(hillStartY+randomHeight*Math.cos(2*Math.PI/hillSliceWidth*(j+1)))/worldScale));
hillVector.push(new b2Vec2(((j+1)*pixelStep+xOffset)/worldScale,480/worldScale));
var sliceBody:b2BodyDef=new b2BodyDef ;
var centre:b2Vec2=findCentroid(hillVector,hillVector.length);
sliceBody.position.Set(centre.x,centre.y);
for (var z:int=0; z, count:uint):b2Vec2 {
var c:b2Vec2 = new b2Vec2();
var area:Number=0.0;
var p1X:Number=0.0;
var p1Y:Number=0.0;
var inv3:Number=1.0/3.0;
for (var i:int = 0; i < count; ++i) {
var p2:b2Vec2=vs[i];
var p3:b2Vec2=i+1100) {
motorSpeed=100;
}
// setting wheels motor speed
rearWheelRevoluteJoint.SetMotorSpeed(motorSpeed);
frontWheelRevoluteJoint.SetMotorSpeed(motorSpeed);
world.Step(1/30,10,10);
world.ClearForces();
for (var currentBody:b2Body=world.GetBodyList(); currentBody; currentBody=currentBody.GetNext()) {
// getting cart x position
if (currentBody.GetUserData()!=null) {
// adjusting stage position to keep cart in the vertical middle of the stage
x=320-currentBody.GetPosition().x*worldScale;
// checking if it's time to add a new hill
if (x<=buildNextHillAt) {
buildNextHillAt-=640;
nextHill=drawHill(10,- buildNextHillAt+640,nextHill);
}
}
if (currentBody.GetPosition().x*worldScale<(x*-1)-640) {
world.DestroyBody(currentBody);
}
}
world.DrawDebugData();
}
}
}
No need to download anything, just copy and paste it on the class you can find in the first post.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.