Skip to content

Instantly share code, notes, and snippets.

@pindamonhangaba
Created October 28, 2012 17:48
Show Gist options
  • Select an option

  • Save pindamonhangaba/3969259 to your computer and use it in GitHub Desktop.

Select an option

Save pindamonhangaba/3969259 to your computer and use it in GitHub Desktop.
Luxurious Animals "Combining Easel.js and Box2d in Canvas" using Typescript -> http://www.luxanimals.com/blog/article/combining_easel_box2d
declare var $: any;
declare var Box2D: any;
declare var Stage: any;
var stage: any;
declare var Ticker: any;
declare var addDebug: any;
declare var Bitmap: any;
// Box2d vars
var b2Vec2 = Box2D.Common.Math.b2Vec2;
var b2BodyDef = Box2D.Dynamics.b2BodyDef;
var b2Body = Box2D.Dynamics.b2Body;
var b2FixtureDef = Box2D.Dynamics.b2FixtureDef;
var b2Fixture = Box2D.Dynamics.b2Fixture;
var b2World = Box2D.Dynamics.b2World;
var b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape;
var b2CircleShape = Box2D.Collision.Shapes.b2CircleShape;
var b2DebugDraw = Box2D.Dynamics.b2DebugDraw;
class Ticaroo {
tick(dt, paused) {
if(focused) {
box2d.update();
stage.update();
birdDelayCounter++;
if(birdDelayCounter % 10 === 0) { // delay so it doesn't spawn a bird on every frame
birdDelayCounter = 0;
var birds = new Birds();
birds.spawn();
}
}
}
}
class Setup {
canvas() {
canvas = document.getElementById('demoCanvas');
debugCanvas = document.getElementById('debugCanvas');
context = canvas.getContext('2d');
debugContext = debugCanvas.getContext('2d');
stage = new Stage(canvas);
stage.snapPixelsEnabled = true;
}
ticker() {
Ticker.setFPS(30);
Ticker.useRAF = true;
Ticker.addListener(Tic); // looks for "tick" function within the luxanimals.demo object
}
}
class Box2d {
// important box2d scale and speed vars
private SCALE = 30;
private STEP = 20;
private TIMESTEP = 1/20;
private world;
private lastTimestamp: number;
private fixedTimestepAccumulator: number;
private bodiesToRemove = [];
private actors: any[] = [];
private bodies: any[] = [];
constructor () {
this.lastTimestamp = Date.now();
this.fixedTimestepAccumulator = 0;
}
// box2d world setup and boundaries
setup(){
this.world = new b2World(new b2Vec2(0,10), true);
this.addDebug();
// boundaries - floor
var floorFixture = new b2FixtureDef;
floorFixture.density = 1;
floorFixture.restitution = 1;
floorFixture.shape = new b2PolygonShape;
floorFixture.shape.SetAsBox(550 / this.SCALE, 10 / this.SCALE);
var floorBodyDef = new b2BodyDef;
floorBodyDef.type = b2Body.b2_staticBody;
floorBodyDef.position.x = -25 / this.SCALE;
floorBodyDef.position.y = 509 / this.SCALE;
var floor = this.world.CreateBody(floorBodyDef);
floor.CreateFixture(floorFixture);
// boundaries - left
var leftFixture = new b2FixtureDef;
leftFixture.shape = new b2PolygonShape;
leftFixture.shape.SetAsBox(10 / this.SCALE, 550 / this.SCALE);
var leftBodyDef = new b2BodyDef;
leftBodyDef.type = b2Body.b2_staticBody;
leftBodyDef.position.x = -9 / this.SCALE;
leftBodyDef.position.y = -25 / this.SCALE;
var left = this.world.CreateBody(leftBodyDef);
left.CreateFixture(leftFixture);
// boundaries - right
var rightFixture = new b2FixtureDef;
rightFixture.shape = new b2PolygonShape;
rightFixture.shape.SetAsBox(10 / this.SCALE, 550 / this.SCALE);
var rightBodyDef = new b2BodyDef;
rightBodyDef.type = b2Body.b2_staticBody;
rightBodyDef.position.x = 509 / this.SCALE;
rightBodyDef.position.y = -25 / this.SCALE;
var right = this.world.CreateBody(rightBodyDef);
right.CreateFixture(rightFixture);
}
// box2d debugger
addDebug() {
var debugDraw = new b2DebugDraw();
debugDraw.SetSprite(debugContext);
debugDraw.SetDrawScale(this.SCALE);
debugDraw.SetFillAlpha(0.7);
debugDraw.SetLineThickness(1.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
this.world.SetDebugDraw(debugDraw);
}
callmethis() {
console.log(this);
}
// create bird body shape and assign actor object
createBird(skin) {
var birdFixture = new b2FixtureDef;
birdFixture.density = 1;
birdFixture.restitution = 0.6;
birdFixture.shape = new b2CircleShape(24 / this.SCALE);
var birdBodyDef = new b2BodyDef;
birdBodyDef.type = b2Body.b2_dynamicBody;
birdBodyDef.position.x = skin.x / this.SCALE;
birdBodyDef.position.y = skin.y / this.SCALE;
var bird = this.world.CreateBody(birdBodyDef);
bird.CreateFixture(birdFixture);
// assign actor
var actor = new ActorObject(bird, skin, this);
bird.SetUserData(actor); // set the actor as user data of the body so we can use it later: body.GetUserData()
this.bodies.push(bird);
}
// remove actor and it's skin object
removeActor(actor) {
stage.removeChild(actor.skin);
this.actors.splice(this.actors.indexOf(actor),1);
}
// box2d update function. delta time is used to avoid differences in simulation if frame rate drops
update() {
var now = Date.now();
var dt = now - this.lastTimestamp;
this.fixedTimestepAccumulator += dt;
this.lastTimestamp = now;
while(this.fixedTimestepAccumulator >= this.STEP) {
// remove bodies before world timestep
for(var i=0, l=this.bodiesToRemove.length; i<l; i++) {
this.removeActor(this.bodiesToRemove[i].GetUserData());
this.bodiesToRemove[i].SetUserData(null);
this.world.DestroyBody(this.bodiesToRemove[i]);
}
this.bodiesToRemove = [];
// update active actors
for(var i=0, l=this.actors.length; i<l; i++) {
this.actors[i].update();
}
this.world.Step(this.TIMESTEP, 10, 10);
this.fixedTimestepAccumulator -= this.STEP;
this.world.ClearForces();
this.world.m_debugDraw.m_sprite.graphics.clear();
this.world.DrawDebugData();
if(this.bodies.length > 30) {
this.bodiesToRemove.push(this.bodies[0]);
this.bodies.splice(0,1);
}
}
}
pauseResume(p) {
if(p) { this.TIMESTEP = 0;
} else { this.TIMESTEP = 1/this.STEP; }
this.lastTimestamp = Date.now();
}
pushActors(actor) {
this.actors.push(actor);
}
get scale() {
return this.SCALE;
}
}
class ActorObject {
// actor object - this is responsible for taking the body's position and translating it to your easel display object
private body: any;
private skin: any;
private box2d: Box2d;
constructor(body: any, skin:any, box2d: Box2d) {
this.body = body;
this.box2d = box2d;
this.skin = skin;
this.box2d.pushActors(this);
}
update() { // translate box2d positions to pixels
console.log(this);
console.log(this.skin);
this.skin.rotation = this.body.GetAngle() * (180 / Math.PI);
this.skin.x = this.body.GetWorldCenter().x * this.box2d.scale;
this.skin.y = this.body.GetWorldCenter().y * this.box2d.scale;
}
}
class Birds {
spawn() {
var birdBMP = new Bitmap("images/bird.png");
birdBMP.x = Math.round(Math.random()*500);
birdBMP.y = -30;
birdBMP.regX = 25; // important to set origin point to center of your bitmap
birdBMP.regY = 25;
birdBMP.snapToPixel = true;
birdBMP.mouseEnabled = false;
stage.addChild(birdBMP);
box2d.createBird(birdBMP);
}
}
// demo vars
var canvas, context, debugCanvas, debugContext;
var birdDelayCounter = 0; // counter for delaying creation of birds
var focused = true;
$('#debug').on('click', function() { $('#debugCanvas').toggle(); }); // toggle debug view
var setup = new Setup();
var box2d = new Box2d();
var Tic = new Ticaroo();
$(document).ready(function() {
// setup functions to run once page is loaded
setup.canvas();
setup.ticker();
var a = new box2d.callmethis();
box2d.setup();
window.onfocus = onFocus;
window.onblur = onBlur;
});
function onFocus() { focused = true; box2d.pauseResume(false); $('#paused').css({'display':'none'}); }
function onBlur() { focused = false; box2d.pauseResume(true); $('#paused').css({'display':'block'}); }
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Luxurious Animals TS port</title>
</head>
<body>
<canvas width="500" height="500" id="demoCanvas"></canvas>
<canvas width="500" height="500" id="debugCanvas"></canvas>
<div id="paused">Paused. Click to resume.</div><br/>
<div id="debug" class="button">Show/Hide Debug</div>
<script type="text/javascript" src="libs/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="libs/easel.js"></script>
<script type="text/javascript" src="libs/Box2dWeb-2.1.a.3.min.js"></script>
<script src="app.js"></script>
<!-- <script type="text/javascript" src="js/demo.js"></script> -->
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment