How to add 2D Physics to CreateJs
October 25th 2019 1:55pm
Updated: November 8th 2019 4:23pm
Web Dev
Game Dev
Intro
Adding the Box2D physics library to your create js game can open up the possibilities for exciting gameplay. Using a physics system creates a consistent simulation experience and as a result players can more easily and intuitively predict movement and interactions.
We will be using box2Dweb. If you are interested in implementing this project in typescript see below for details on that. There is a package available online that includes types for box2dweb for quick and easy programming.
https://github.com/hecht-software/box2dweb
Steps
Once the box2dweb library has been included there are just a few steps you need to do.
- create a physics world
Think of the physics world just like the createjs stage. The phyics world unlike the createjs stage doesn't work with pixel units and we must introduce a scaling variable to link the different scales. Also the y axis in box2d increases when you go upwards unlike createjs but this difference can be mitigated by using a positive gravity value. - Create our physics objects
createjs graphics
createRigidBody
createRigidbodyFixture - Add physics objects to physics world
- Perform game update
update() physics world
update graphics to match physics object
Example Javascript Code
index.html
<head>
<script>
var module = {};
</script>
<script src="https://cdn.jsdelivr.net/npm/box2dweb@2.1.0-b/box2d.min.js"></script>
<script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>
</head>
<body onload="">
<canvas id="demoCanvas" width="400" height="400"></canvas>
<script src="main.js"></script>
</body>
main.js
var Box2D = module.exports;
var physicsScale = 30
var fps = 60;
let canvas = document.getElementById("demoCanvas");
let stage = new createjs.Stage(canvas);
stage.enableMouseOver(20);
createjs.Ticker.framerate = fps;
var scene = new createjs.Container();
stage.addChild(scene);
var graphic = new createjs.Shape();
graphic.graphics.beginFill("red").drawRect(0, 0, 32,32);
graphic.regX = 32 * 0.5;
graphic.regY = 32 * 0.5;
graphic.x = 50;
graphic.y = 16;
scene.addChild(graphic);
var graphic2 = new createjs.Shape();
graphic2.graphics.beginFill("green").drawRect(0, 0, 400,50);
graphic2.regX = 400 * 0.5;
graphic2.regY = 50 * 0.5;
graphic2.x = 100;
graphic2.y = 162;
scene.addChild(graphic2);
stage.update();
var gravity = new Box2D.Common.Math.b2Vec2(0,9);
var doSleep = false;
var physicsWorld = new Box2D.Dynamics.b2World( gravity, doSleep);
function createBodyDefinition(type, fixedRotation, linearDamping, x, y){
let rbDefinition = new Box2D.Dynamics.b2BodyDef();
rbDefinition.type = type;
rbDefinition.fixedRotation = fixedRotation;
rbDefinition.linearDamping = linearDamping;
rbDefinition.position = new Box2D.Common.Math.b2Vec2(x / physicsScale, y / physicsScale)
return rbDefinition;
}
function createPlatformFixtureDef(shape, friction, restitution, density, isSensor, userData){
let pFDefinition = new Box2D.Dynamics.b2FixtureDef();
pFDefinition.shape = shape;
pFDefinition.friction = friction;
pFDefinition.restitution = restitution;
pFDefinition.density = density;
pFDefinition.isSensor = isSensor;
pFDefinition.userData = userData;
return pFDefinition;
}
var rigidbody;
var rigidbodyDefinition = createBodyDefinition(Box2D.Dynamics.b2Body.b2_dynamicBody, false, 0 , graphic.x,graphic.y);
var platformFixtureDef = createPlatformFixtureDef(Box2D.Collision.Shapes.b2PolygonShape.AsBox( 16 / physicsScale, 16 / physicsScale), 1, 0 ,10, false, {'name':'box'});
//creates rigidbody in our physics world
rigidbody = physicsWorld.CreateBody(rigidbodyDefinition);
rigidbody.CreateFixture(platformFixtureDef);
var rbGround;
var rigidbodyDefinition2 = createBodyDefinition(Box2D.Dynamics.b2Body.b2_staticBody, false, 0 , graphic2.x,graphic2.y);
//creates rigidbody in our physics world
rbGround = physicsWorld.CreateBody(rigidbodyDefinition2);
var platformFixtureDef2 = createPlatformFixtureDef(Box2D.Collision.Shapes.b2PolygonShape.AsBox( 200 / physicsScale, 25 / physicsScale), 10, 0 ,10, false, {'name':'ground'});
rbGround.CreateFixture(platformFixtureDef2);
rbGround.SetAngle( 0.5 );
function Update(){
//update physics world -- box2dweb does all the magic for us here
if(physicsWorld != undefined){
physicsWorld.Step(1/ fps , 10, 10);
//update the graphic to match the physics body
var position = rigidbody.GetPosition();
graphic.rotation = rigidbody.GetAngle() * (180 / Math.PI)
graphic.x = position.x * physicsScale ;
graphic.y = position.y * physicsScale ;
position = rbGround.GetPosition();
graphic2.rotation = rbGround.GetAngle() * (180 / Math.PI)
graphic2.x = position.x * physicsScale ;
graphic2.y = position.y * physicsScale ;
}
stage.update();
}
createjs.Ticker.on("tick", Update);
If you are using typescript in your project then you can install a types definition for box2dweb
there used to be a types definition here: https://github.com/jbaldwin/box2dweb.d.ts but that looks to be removed so try out this: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/box2d instead.
If you make any projects with create js and or box2d please share them with me on twitter!
Comments
☕ Buy me a coffee