Creation of a Box2D car with 10 customizable parameters

This post is virtually a mix of step by step creation of a Box2D car/truck with motors and shocks and the second example of two ways to make Box2D cars, and will allow you to create the same truck you can see in the second example, just using the latest Box2D version, without inverting y axis and making the truck fully configurable.

Look at the amount of values you can set:

and let’s explain them in detail:

carPosX: the horizontal center of the car body, in pixels

carPosY: the vertical center of the car body, in pixels

carWidth: the half width of the car, in pixels

carHeight: the half height of the car, in pixels

axleContainerDistance: horizontal distance of the axle containers from the center of the car

axleContainerWidth: half width of the axle container

axleContainerHeight: half height of the axle container

axleContainerDepth: vertical distance of the axle containers from the center of the car

axleAngle: angle of the axles, in degrees

wheelRadius: radius of the wheels, in pixels

This is the script:

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 const degreesToRadians:Number=0.0174532925;
		//
		private var world:b2World=new b2World(new b2Vec2(0,10),true);
		private var worldScale:int=30;
		private var car:b2Body;
		private var leftWheelRevoluteJoint:b2RevoluteJoint;
		private var rightWheelRevoluteJoint:b2RevoluteJoint;
		private var left:Boolean=false;
		private var right:Boolean=false;
		private var motorSpeed:Number=0;
		private var leftAxlePrismaticJoint:b2PrismaticJoint;
		private var rightAxlePrismaticJoint:b2PrismaticJoint;
		//
		private var carPosX:Number=320;
		private var carPosY:Number=250;
		private var carWidth:Number=45;
		private var carHeight:Number=10;
		private var axleContainerDistance:Number=30;
		private var axleContainerWidth:Number=5;
		private var axleContainerHeight:Number=20;
		private var axleContainerDepth:Number=10;
		private var axleAngle:Number=20;
		private var wheelRadius:Number=25;
		public function Main():void {
			debugDraw();
			// ************************ THE FLOOR ************************ //
			var floorShape:b2PolygonShape = new b2PolygonShape();
			floorShape.SetAsBox(640/worldScale,10/worldScale);
			var floorFixture:b2FixtureDef = new b2FixtureDef();
			floorFixture.density=0;
			floorFixture.friction=10;
			floorFixture.restitution=0;
			floorFixture.shape=floorShape;
			var floorBodyDef:b2BodyDef = new b2BodyDef();
			floorBodyDef.position.Set(320/worldScale,480/worldScale);
			var floor:b2Body=world.CreateBody(floorBodyDef);
			floor.CreateFixture(floorFixture);
			// ************************ THE CAR ************************ //
			var carShape:b2PolygonShape = new b2PolygonShape();
			carShape.SetAsBox(carWidth/worldScale,carHeight/worldScale);
			var carFixture:b2FixtureDef = new b2FixtureDef();
			carFixture.density=5;
			carFixture.friction=3;
			carFixture.restitution=0.3;
			carFixture.filter.groupIndex=-1;
			carFixture.shape=carShape;
			var carBodyDef:b2BodyDef = new b2BodyDef();
			carBodyDef.position.Set(carPosX/worldScale,carPosY/worldScale);
			carBodyDef.type=b2Body.b2_dynamicBody;
			// ************************ LEFT AXLE CONTAINER ************************ //
			var leftAxleContainerShape:b2PolygonShape = new b2PolygonShape();
			leftAxleContainerShape.SetAsOrientedBox(axleContainerWidth/worldScale,axleContainerHeight/worldScale,new b2Vec2(-axleContainerDistance/worldScale,axleContainerDepth/worldScale),axleAngle*degreesToRadians);
			var leftAxleContainerFixture:b2FixtureDef = new b2FixtureDef();
			leftAxleContainerFixture.density=3;
			leftAxleContainerFixture.friction=3;
			leftAxleContainerFixture.restitution=0.3;
			leftAxleContainerFixture.filter.groupIndex=-1;
			leftAxleContainerFixture.shape=leftAxleContainerShape;
			// ************************ RIGHT AXLE CONTAINER ************************ //
			var rightAxleContainerShape:b2PolygonShape = new 
			b2PolygonShape();
			rightAxleContainerShape.SetAsOrientedBox(axleContainerWidth/worldScale,axleContainerHeight/worldScale,new b2Vec2(axleContainerDistance/worldScale,axleContainerDepth/worldScale),-axleAngle*degreesToRadians);
			var rightAxleContainerFixture:b2FixtureDef = new 
			b2FixtureDef();
			rightAxleContainerFixture.density=3;
			rightAxleContainerFixture.friction=3;
			rightAxleContainerFixture.restitution=0.3;
			rightAxleContainerFixture.filter.groupIndex=-1;
			rightAxleContainerFixture.shape=rightAxleContainerShape;
			// ************************ MERGING ALL TOGETHER ************************ //
			car=world.CreateBody(carBodyDef);
			car.CreateFixture(carFixture);
			car.CreateFixture(leftAxleContainerFixture);
			car.CreateFixture(rightAxleContainerFixture);
			// ************************ THE AXLES ************************ //
			var leftAxleShape:b2PolygonShape = new b2PolygonShape();
			leftAxleShape.SetAsOrientedBox(axleContainerWidth/worldScale/2,axleContainerHeight/worldScale,new b2Vec2(0,0),axleAngle*degreesToRadians);
			var leftAxleFixture:b2FixtureDef = new b2FixtureDef();
			leftAxleFixture.density=0.5;
			leftAxleFixture.friction=3;
			leftAxleFixture.restitution=0;
			leftAxleFixture.shape=leftAxleShape;
			leftAxleFixture.filter.groupIndex=-1;
			var leftAxleBodyDef:b2BodyDef = new b2BodyDef();
			leftAxleBodyDef.type=b2Body.b2_dynamicBody;
			var leftAxle:b2Body=world.CreateBody(leftAxleBodyDef);
			leftAxle.CreateFixture(leftAxleFixture);
			leftAxle.SetPosition(new b2Vec2(carPosX/worldScale-axleContainerDistance/worldScale-axleContainerHeight/worldScale*Math.cos((90-axleAngle)*degreesToRadians),carPosY/worldScale+axleContainerDepth/worldScale+axleContainerHeight/worldScale*Math.sin((90-axleAngle)*degreesToRadians)));
			var rightAxleShape:b2PolygonShape = new b2PolygonShape();
			rightAxleShape.SetAsOrientedBox(axleContainerWidth/worldScale/2,axleContainerHeight/worldScale,new b2Vec2(0,0),-axleAngle*degreesToRadians);
			var rightAxleFixture:b2FixtureDef = new b2FixtureDef();
			rightAxleFixture.density=0.5;
			rightAxleFixture.friction=3;
			rightAxleFixture.restitution=0;
			rightAxleFixture.shape=rightAxleShape;
			rightAxleFixture.filter.groupIndex=-1;
			var rightAxleBodyDef:b2BodyDef = new b2BodyDef();
			rightAxleBodyDef.type=b2Body.b2_dynamicBody;
			var rightAxle:b2Body=world.CreateBody(rightAxleBodyDef);
			rightAxle.CreateFixture(rightAxleFixture);
			rightAxle.SetPosition(new b2Vec2(carPosX/worldScale+axleContainerDistance/worldScale+axleContainerHeight/worldScale*Math.cos((90-axleAngle)*degreesToRadians),carPosY/worldScale+axleContainerDepth/worldScale+axleContainerHeight/worldScale*Math.sin((90-axleAngle)*degreesToRadians)));
			// ************************ THE WHEELS ************************ //;
			var wheelShape:b2CircleShape=new 
			b2CircleShape(wheelRadius/worldScale);
			var wheelFixture:b2FixtureDef = new b2FixtureDef();
			wheelFixture.density=1;
			wheelFixture.friction=15;
			wheelFixture.restitution=0.2;
			wheelFixture.filter.groupIndex=-1;
			wheelFixture.shape=wheelShape;
			var wheelBodyDef:b2BodyDef = new b2BodyDef();
			wheelBodyDef.type=b2Body.b2_dynamicBody;
			wheelBodyDef.position.Set(carPosX/worldScale-axleContainerDistance/worldScale-2*axleContainerHeight/worldScale*Math.cos((90-axleAngle)*degreesToRadians),carPosY/worldScale+axleContainerDepth/worldScale+2*axleContainerHeight/worldScale*Math.sin((90-axleAngle)*degreesToRadians));
			var leftWheel:b2Body=world.CreateBody(wheelBodyDef);
			leftWheel.CreateFixture(wheelFixture);
			wheelBodyDef.position.Set(carPosX/worldScale+axleContainerDistance/worldScale+2*axleContainerHeight/worldScale*Math.cos((90-axleAngle)*degreesToRadians),carPosY/worldScale+axleContainerDepth/worldScale+2*axleContainerHeight/worldScale*Math.sin((90-axleAngle)*degreesToRadians));
			var rightWheel:b2Body=world.CreateBody(wheelBodyDef);
			rightWheel.CreateFixture(wheelFixture);
			// ************************ REVOLUTE JOINTS ************************ //
			var leftWheelRevoluteJointDef:b2RevoluteJointDef=new b2RevoluteJointDef();
			leftWheelRevoluteJointDef.Initialize(leftWheel,leftAxle,leftWheel.GetWorldCenter());
			leftWheelRevoluteJointDef.enableMotor=true;
			leftWheelRevoluteJoint=world.CreateJoint(leftWheelRevoluteJointDef) as b2RevoluteJoint;
			leftWheelRevoluteJoint.SetMaxMotorTorque(10);
			var rightWheelRevoluteJointDef:b2RevoluteJointDef=new b2RevoluteJointDef();
			rightWheelRevoluteJointDef.Initialize(rightWheel,rightAxle,rightWheel.GetWorldCenter());
			rightWheelRevoluteJointDef.enableMotor=true;
			rightWheelRevoluteJoint=world.CreateJoint(rightWheelRevoluteJointDef) as b2RevoluteJoint;
			rightWheelRevoluteJoint.SetMaxMotorTorque(10);
			// ************************ PRISMATIC JOINTS ************************ //
			var leftAxlePrismaticJointDef:b2PrismaticJointDef=new b2PrismaticJointDef();
			leftAxlePrismaticJointDef.lowerTranslation=0;
			leftAxlePrismaticJointDef.upperTranslation=axleContainerDepth/worldScale;
			leftAxlePrismaticJointDef.enableLimit=true;
			leftAxlePrismaticJointDef.enableMotor=true;
			leftAxlePrismaticJointDef.Initialize(car,leftAxle,leftAxle.GetWorldCenter(), new b2Vec2(-Math.cos((90-axleAngle)*degreesToRadians),Math.sin((90-axleAngle)*degreesToRadians)));
			leftAxlePrismaticJoint=world.CreateJoint(leftAxlePrismaticJointDef) as b2PrismaticJoint;
			leftAxlePrismaticJoint.SetMaxMotorForce(10);                         
			leftAxlePrismaticJoint.SetMotorSpeed(10);                         			
			var rightAxlePrismaticJointDef:b2PrismaticJointDef=new b2PrismaticJointDef();
			rightAxlePrismaticJointDef.lowerTranslation=0;
			rightAxlePrismaticJointDef.upperTranslation=axleContainerDepth/worldScale;
			rightAxlePrismaticJointDef.enableLimit=true;
			rightAxlePrismaticJointDef.enableMotor=true;
			rightAxlePrismaticJointDef.Initialize(car,rightAxle,rightAxle.GetWorldCenter(), new b2Vec2(Math.cos((90-axleAngle)*degreesToRadians),Math.sin((90-axleAngle)*degreesToRadians)));
			rightAxlePrismaticJoint=world.CreateJoint(rightAxlePrismaticJointDef) as b2PrismaticJoint;
			rightAxlePrismaticJoint.SetMaxMotorForce(10);                         
			rightAxlePrismaticJoint.SetMotorSpeed(10);      
			addEventListener(Event.ENTER_FRAME,updateWorld);
			stage.addEventListener(KeyboardEvent.KEY_DOWN,keyPressed);
			stage.addEventListener(KeyboardEvent.KEY_UP,keyReleased);
		}
		private function debugDraw():void {
			var worldDebugDraw:b2DebugDraw=new b2DebugDraw();
			var debugSprite:Sprite = new Sprite();
			addChild(debugSprite);
			worldDebugDraw.SetSprite(debugSprite);
			worldDebugDraw.SetDrawScale(worldScale);
			worldDebugDraw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit);
			worldDebugDraw.SetFillAlpha(0.5);
			world.SetDebugDraw(worldDebugDraw);
		}
		private function keyPressed(e:KeyboardEvent):void {
			switch (e.keyCode) {
				case 37 :
					left=true;
					break;
				case 39 :
					right=true;
					break;
			}
		}
		private function keyReleased(e:KeyboardEvent):void {
			switch (e.keyCode) {
				case 37 :
					left=false;
					break;
				case 39 :
					right=false;
					break;
			}
		}
		private function updateWorld(e:Event):void {
			if (left) {
				motorSpeed+=0.1;
			}
			if (right) {
				motorSpeed-=0.1;
			}
			motorSpeed*=0.99;
			if (motorSpeed>10) {
				motorSpeed=10;
			}
			leftWheelRevoluteJoint.SetMotorSpeed(motorSpeed);
			rightWheelRevoluteJoint.SetMotorSpeed(motorSpeed);
			world.Step(1/30,10,10);
			world.ClearForces();
			world.DrawDebugData();
		}
	}
}

and this is the result:

no need to download anything, just overwrite Main class in the step by step creation of a Box2D car.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers