zphy
Version:
Physics Zimjs
623 lines (572 loc) • 25.1 kB
JavaScript
module.exports = function Physics() {
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 b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef;
var b2DistanceJointDef = Box2D.Dynamics.Joints.b2DistanceJointDef;
var b2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef;
var b2WeldJointDef = Box2D.Dynamics.Joints.b2WeldJointDef;
var b2AABB = Box2D.Collision.b2AABB;
var b2DebugDraw = Box2D.Dynamics.b2DebugDraw;
var b2BuoyancyController = Box2D.Dynamics.Controllers.b2BuoyancyController;
var b2ContactListener = Box2D.Dynamics.b2ContactListener;
var zimPhysics = true;
var zimDefaultPhysics;
var zim = function(zim) {
zim.Physics = function(gravity, borders, scroll, frame) {
var sig = "gravity, borders, scroll, frame";
var duo; if (duo = zob(zim.Physics, arguments, sig, this)) return duo;
var that = this;
if (zon) zog("ZIM PHYSICS");
if (zot(frame) && (typeof zimDefaultFrame == "undefined" || zot(zimDefaultFrame))) {console.log("zim.Physics() - please provide a zim Frame object"); return;}
frame = frame || zimDefaultFrame;
that.frame = frame;
if (zot(borders)) borders = {x:0, y:0, width:that.frame.width, height:that.frame.height};
borders = {x:borders.x, y:borders.y, width:borders.width, height:borders.height};
if (zot(gravity)) gravity = 10;
if (zot(scroll)) scroll = false;
if (zot(zimDefaultPhysics)) zimDefaultPhysics = this;
this.gravity = gravity;
var scale = this.scale = 30;
var step = this.step = 20;
var timeStep = 1/step;
var world = this.world = new b2World(new b2Vec2(0, gravity), true); // gravity, allow sleep
// each of these return a b2Body with x, y, and rotation properties added
this.makeRectangle = function(width, height, dynamic, friction, angular, density, restitution, maskBits, categoryBits, linear) {
var duo; if (duo = zob(that.makeRectangle, arguments)) return duo;
return makeShape(["rectangle", width, height], dynamic, friction, angular, density, restitution, maskBits, categoryBits, linear);
}
this.makeCircle = function(radius, dynamic, friction, angular, density, restitution, maskBits, categoryBits, linear) {
var duo; if (duo = zob(that.makeCircle, arguments)) return duo;
return makeShape(["circle", radius], dynamic, friction, angular, density, restitution, maskBits, categoryBits, linear);
}
this.makeTriangle = function(a, b, c, dynamic, friction, angular, density, restitution, maskBits, categoryBits, linear) {
var duo; if (duo = zob(that.makeTriangle, arguments)) return duo;
return makeShape(["triangle", a, b, c], dynamic, friction, angular, density, restitution, maskBits, categoryBits, linear);
}
function makeShape(shape, dynamic, friction, angular, density, restitution, maskBits, categoryBits, linear) {
var type = shape[0];
if (zot(dynamic)) dynamic = true;
if (zot(friction)) friction = .8;
if (zot(angular)) angular = .5; // rotational damping
if (zot(linear)) linear = .5; // linear damping
if (zot(density)) density = 1;
if (zot(restitution)) restitution = 0;
var definition = new b2BodyDef();
if (dynamic == "kinematic") {
definition.type = b2Body.b2_kinematicBody;
} else if (dynamic) {
definition.type = b2Body.b2_dynamicBody;
} else {
definition.type = b2Body.b2_staticBody;
}
definition.angularDamping = angular;
definition.linearDamping = linear;
var body = world.CreateBody(definition);
var s;
if (type=="rectangle") {
s = new b2PolygonShape();
if (zot(shape[1])) shape[1] = 100;
if (zot(shape[2])) shape[2] = 100;
s.width = shape[1];
s.height = shape[2];
s.SetAsBox(s.width/scale/2, s.height/scale/2);
} else if (type=="triangle") {
if (!zim) return;
s = new b2PolygonShape();
if (zot(shape[1])) shape[1] = 100;
if (zot(shape[2])) shape[2] = 100;
if (zot(shape[3])) shape[3] = 100;
// uses zim Triangle to match Box2D shape
var tri = new zim.Triangle(shape[1], shape[2], shape[3]);
s.width = tri.width;
s.height = tri.height;
var points = [];
// outside is right of line - so needed to reverse order
points[2] = new b2Vec2((tri.one.x-tri.regX)/scale, (tri.one.y+tri.regY)/scale);
points[1] = new b2Vec2((tri.two.x-tri.regX)/scale, (tri.two.y+tri.regY)/scale);
points[0] = new b2Vec2((tri.three.x-tri.regX)/scale, (tri.three.y+tri.regY)/scale);
s.SetAsArray(points, points.length);
} else { // circle
if (zot(shape[1])) shape[1] = 50;
s = new b2CircleShape(shape[1]/scale);
s.width = s.height = shape[1]*2;
}
var fixture = new b2FixtureDef();
if (!zot(categoryBits)) fixture.filter.categoryBits = categoryBits;
if (!zot(maskBits)) fixture.filter.maskBits = maskBits;
fixture.shape = s;
fixture.density = density;
fixture.friction = friction;
fixture.restitution = restitution;
body.CreateFixture(fixture);
body.width = s.width;
body.height = s.height;
// these hold x, y and rotation local values
body.zimX = 0;
body.zimY = 0;
body.zimR = 0;
setBasicProperties(body);
return body;
}
function setBasicProperties(body) {
Object.defineProperty(body, 'x', {
get: function() {
return body.GetWorldCenter().x*that.scale;
},
set: function(x) {
body.zimX = x;
body.SetPosition(new b2Vec2(body.zimX/scale, body.zimY/scale));
}
});
Object.defineProperty(body, 'y', {
get: function() {
return body.GetWorldCenter().y*that.scale;
},
set: function(y) {
body.zimY = y;
body.SetPosition(new b2Vec2(body.zimX/scale, body.zimY/scale));
}
});
Object.defineProperty(body, 'rotation', {
get: function() {
return body.GetAngle()*180/Math.PI;
},
set: function(rotation) {
body.zimR = rotation;
body.SetAngle(rotation*Math.PI/180);
}
});
}
this.join = function(body1, body2, point1, point2, minAngle, maxAngle, type) {
if (zot(body1) || zot(body2)) return;
if (body1.body) body1 = body1.body;
if (body2.body) body2 = body2.body;
if (zot(point1)) point1 = new zim.Point(body1.GetWorldCenter().x*that.scale, body1.GetWorldCenter().y*that.scale);
if (zot(point2)) point2 = new zim.Point(body2.GetWorldCenter().x*that.scale, body2.GetWorldCenter().y*that.scale);
if (zot(type)) type = "weld";
var def;
if (type=="distance") def = new b2DistanceJointDef();
if (type=="revolute") def = new b2RevoluteJointDef();
if (type=="weld") def = new b2WeldJointDef();
def.Initialize(body1, body2, new b2Vec2(point1.x/that.scale, point1.y/that.scale), new b2Vec2(point2.x/that.scale, point2.y/that.scale));
if (!zot(minAngle) || !zot(maxAngle)) {
def.enableLimit = true;
def.lowerAngle = minAngle*Math.PI/180;
def.upperAngle = maxAngle*Math.PI/180;
}
return that.world.CreateJoint(def);
}
this.break = function(joint) {
that.world.DestroyJoint(joint);
}
// for backwards compatibility - use join() now...
this.makeJoint = function(body1, body2, pointX, pointY, minAngle, maxAngle, type) {
var def = (!zot(type) && type=="distance") ? new b2DistanceJointDef() : new b2RevoluteJointDef();
def.Initialize(body1, body2, body1.GetWorldPoint(new b2Vec2(pointX/that.scale, pointY/that.scale)));
if (!zot(minAngle) || !zot(maxAngle)) {
def.enableLimit = true;
def.lowerAngle = minAngle*Math.PI/180;
def.upperAngle = maxAngle*Math.PI/180;
}
return that.world.CreateJoint(def);
}
var debug;
this.debug = function() {
if (debug) {
debug.debugCanvas.style.display = "block";
} else {
// make the Debug object with its canvas only once
debug = new this.Debug();
}
debug.active = true;
that.updateDebug();
}
this.Debug = function() {
var debugCanvas = this.debugCanvas = document.createElement("canvas");
debugCanvas.setAttribute("id", "debugCanvas");
if (that.frame.scale != 1) {
debugCanvas.setAttribute("width", that.frame.width);
debugCanvas.setAttribute("height", that.frame.height);
} else {
var largest = Math.max(window.innerWidth, screen.width, window.innerHeight, screen.height);
debugCanvas.setAttribute("width", largest);
debugCanvas.setAttribute("height", largest);
}
that.frame.canvas.parentElement.appendChild(debugCanvas);
debugCanvas.style.pointerEvents = "none";
var debugDraw = new b2DebugDraw();
debugDraw.SetSprite(debugCanvas.getContext('2d'));
debugDraw.SetDrawScale(scale);
debugDraw.SetFillAlpha(0.7);
debugDraw.SetLineThickness(1.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
world.SetDebugDraw(debugDraw);
this.update = function() {
world.m_debugDraw.m_sprite.graphics.clear();
world.DrawDebugData();
}
}
this.updateDebug = function() {
if (zot(debug)) return;
var canvasPosition = getElementPosition(that.frame.canvas);
var c = debug.debugCanvas;
c.style.position = "absolute";
c.style.zIndex = 2;
c.style.left = that.frame.canvas.style.left;
c.style.top = that.frame.canvas.style.top;
c.style.width = that.frame.canvas.style.width;
c.style.height = that.frame.canvas.style.height;
}
this.removeDebug = function() {
if (!debug) return;
debug.active = false;
debug.debugCanvas.style.display = "none";
}
// keep a remove list and remove in update function
// at the correct time so world does not get confused
var removeList = [];
this.remove = function(body) {
removeList.push(body);
}
function doRemove() {
var len = removeList.length;
if (len==0) return;
var body;
for (var i=len-1; i>=0; i--) {
body = removeList[i];
mappings.remove(body);
world.DestroyBody(body);
body = null;
removeList.pop();
}
}
this.follow = function(obj, damp, dampY, leftOffset, rightOffset, upOffset, downOffset, offsetDamp, offsetDampY, horizontal, vertical, borderLock, borderOriginal) {
var duo; if (duo = zob(that.follow, arguments)) return duo;
that.followObj = null;
if (zot(obj)) return;
if (obj.zimObj) obj = obj.zimObj; // passed in a box2DBody instead
// Ticker uses these if controls are used so just set them to 0 here
obj.controlX = obj.controlDirX = obj.controlY = obj.controlDirY = 0;
that.followObj = obj;
obj.followDampX = null;
obj.followDampY = null;
if (zot(damp)) damp = .05;
if (zot(dampY)) dampY = damp;
if (zot(leftOffset)) leftOffset = 0;
if (zot(rightOffset)) rightOffset = that.frame.stage.width;
if (zot(upOffset)) upOffset = 0;
if (zot(downOffset)) downOffset = that.frame.stage.height;
if (zot(offsetDamp)) offsetDamp = .02;
if (zot(offsetDampY)) offsetDampY = offsetDamp;
if (zot(horizontal)) horizontal = true;
if (zot(vertical)) vertical = true;
if (zot(borderLock)) borderLock = borders.constructor === {}.constructor;
if (zot(borderOriginal)) borderOriginal = false;
obj.frameBorderLock = borderLock;
obj.frameBorderOriginal = borderOriginal;
if (horizontal) {
obj.followDampX = new Damp(0,damp);
obj.offsetDampX = new Damp((leftOffset+rightOffset)/2,offsetDamp);
obj.followOffsetX = [(leftOffset+rightOffset)/2, leftOffset, rightOffset];
}
if (vertical) {
obj.followDampY = new Damp(0,dampY);
obj.offsetDampY = new Damp((upOffset+downOffset)/2,offsetDampY);
obj.followOffsetY = [(upOffset+downOffset)/2, upOffset, downOffset];
}
}
this.control = function(obj, type, speed, speedY, horizontal, vertical) {
var duo; if (duo = zob(that.control, arguments)) return duo;
if (zot(obj)) return;
if (obj.zimObj) zimObj = obj.zimObj; // passed in a box2DBody instead
that.controlObj = obj;
obj.controlX = 0;
obj.controlY = 0;
if (zot(type)) type = "both";
if (zot(speed)) speed = 200;
if (zot(speedY)) speedY = speed;
if (zot(horizontal)) horizontal = true;
if (zot(vertical)) vertical = true;
var k = [0,0,0,0,0,0,0,0]; // keep track of wasd 87, 65, 83, 68 and arrows down
obj.controlKeydown = that.frame.on("keydown", function(e) {checkKeys(e.keyCode, speed, speedY);});
obj.controlKeyup = that.frame.on("keyup", function(e) {checkKeys(e.keyCode, 0, 0);});
function checkKeys(code, speed, speedY) {
if (code == 37 && horizontal && (type == "both" || type == "arrows")) k[0] = -speed;
if (code == 38 && vertical && (type == "both" || type == "arrows")) k[1] = -speedY;
if (code == 39 && horizontal && (type == "both" || type == "arrows")) k[2] = speed;
if (code == 40 && vertical && (type == "both" || type == "arrows")) k[3] = speedY;
if (code == 65 && horizontal && (type == "both" || type == "wasd")) k[4] = -speed;
if (code == 87 && vertical && (type == "both" || type == "wasd")) k[5] = -speedY;
if (code == 68 && horizontal && (type == "both" || type == "wasd")) k[6] = speed;
if (code == 83 && vertical && (type == "both" || type == "wasd")) k[7] = speedY;
obj.controlDirX = k[0]+k[2]+k[4]+k[6]==0?0:(k[0]+k[2]+k[4]+k[6]>0?1:-1); // 0,-1,1
obj.controlDirY = k[1]+k[3]+k[5]+k[7]==0?0:(k[1]+k[3]+k[5]+k[7]>0?1:-1);
obj.controlX = k[0]+k[2]+k[4]+k[6]==0?0:(k[0]+k[2]+k[4]+k[6]>0?1:2); // 0,1,2
obj.controlY = k[1]+k[3]+k[5]+k[7]==0?0:(k[1]+k[3]+k[5]+k[7]>0?1:2);
}
var body = obj.body;
obj.controlTicker = that.Ticker.add(function() {
// k[0]+k[2] is the total x speed, for instance
if (Math.abs(k[0]+k[2]+k[4]+k[6]) + Math.abs(k[1]+k[3]+k[5]+k[7]) == 0) return;
body.ApplyForce(new b2Vec2(
k[0]+k[2]+k[4]+k[6]>0?speed:(k[0]+k[2]+k[4]+k[6]<0?-speed:0),
k[1]+k[3]+k[5]+k[7]>0?speedY:(k[1]+k[3]+k[5]+k[7]<0?-speedY:0)
), body.GetWorldCenter());
});
}
this.noControl = function(obj) {
if (!zot(obj) && obj.controlTicker) {
that.controlObj = null;
that.Ticker.remove(obj.controlTicker);
that.frame.off("keydown", obj.controlKeydown);
that.frame.off("keyup", obj.controlKeyup);
obj.controlX = obj.controlDirX = obj.controlY = obj.controlDirY = 0;
}
}
// Drag wraps the demo example mouse code
var drag;
this.drag = function(list) {
drag = new that.Drag(list);
}
this.noDrag = function() {
drag.removeListeners();
drag = null;
}
this.Drag = function(list) {
if (zot(frame)) frame = {scale:1};
if (zot(list)) list = [];
for (var i=0; i<list.length; i++) {
if (list[i].body) list[i] = list[i].body;
}
this.list = list;
var that2 = this;
this.removeListeners = function() {
isMouseDown = false;
if (that2.mousedownEvent) stage.off("stagemousedown", that2.mousedownEvent);
if (that2.mousemoveEvent) stage.off("stagemousemove", that2.mousemoveEvent);
if (that2.mouseupEvent) stage.off("stagemouseup", that2.mouseupEvent);
if (mouseJoint) world.DestroyJoint(mouseJoint);
mouseJoint = null;
};
this.removeListeners();
// modified demo.html code at https://code.google.com/p/box2dweb/
var canvasPosition, mouseX, mouseY, mousePVec, isMouseDown, selectedBody, mouseJoint;
var stage = that.frame.stage;
that2.mousedownEvent = stage.on("stagemousedown", function(e) {
isMouseDown = true;
mouseX = (e.stageX/stage.scaleX-(scroll?stage.x:0))/scale;
mouseY = (e.stageY/stage.scaleY-(scroll?stage.y:0))/scale;
that2.mousemoveEvent = stage.on("stagemousemove", function(e) {
mouseX = (e.stageX/stage.scaleX-(scroll?stage.x:0))/scale;
mouseY = (e.stageY/stage.scaleY-(scroll?stage.y:0))/scale;
});
});
that2.mouseupEvent = stage.on("stagemouseup", function(e) {
isMouseDown = false;
stage.off("stagemousemove", that2.mousemoveEvent);
mouseX = (e.stageX/stage.scaleX-(scroll?stage.x:0))/scale;
mouseY = (e.stageY/stage.scaleY-(scroll?stage.y:0))/scale;
});
function getBodyAtMouse() {
mousePVec = new b2Vec2(mouseX, mouseY);
var aabb = new b2AABB();
aabb.lowerBound.Set(mouseX - 0.001, mouseY - 0.001);
aabb.upperBound.Set(mouseX + 0.001, mouseY + 0.001);
// Query the world for overlapping shapes.
selectedBody = null;
world.QueryAABB(getBodyCB, aabb);
return selectedBody;
}
function getBodyCB(fixture) {
if(fixture.GetBody().GetType() != b2Body.b2_staticBody) {
if(fixture.GetShape().TestPoint(fixture.GetBody().GetTransform(), mousePVec)) {
selectedBody = fixture.GetBody();
return false;
}
}
return true;
}
this.update = function() {
if(isMouseDown && (!mouseJoint)) {
var body = getBodyAtMouse();
if(body) {
if (that2.list.length > 0 && that2.list.indexOf(body) < 0) return;
var md = new b2MouseJointDef();
md.bodyA = world.GetGroundBody();
md.bodyB = body;
md.target.Set(mouseX, mouseY);
md.collideConnected = true;
md.maxForce = 300.0 * body.GetMass();
mouseJoint = world.CreateJoint(md);
body.SetAwake(true);
}
}
if (mouseJoint) {
if (isMouseDown) {
mouseJoint.SetTarget(new b2Vec2(mouseX, mouseY));
} else {
world.DestroyJoint(mouseJoint);
mouseJoint = null;
}
}
}
}
//http://js-tut.aardon.de/js-tut/tutorial/position.html
function getElementPosition(element) {
var elem=element, tagname="", x=0, y=0;
while((typeof(elem) == "object") && (typeof(elem.tagName) != "undefined")) {
y += elem.offsetTop;
x += elem.offsetLeft;
tagname = elem.tagName.toUpperCase();
if(tagname == "BODY") elem=0;
if(typeof(elem) == "object") {
if(typeof(elem.offsetParent) == "object") elem = elem.offsetParent;
}
}
return {x:x-zim.scrollX(), y:y-zim.scrollY()};
}
// mappings put zim assets to the x, y and rotation of Box2D bodies
// a dictionary is used for easy adding and removing
var mappings = new zim.Dictionary(true);
function updateMap() {
for (var i=0; i<mappings.length; i++) {
var zimObj = mappings.values[i];
var box2DBody = mappings.objects[i];
var p = box2DBody.GetWorldPoint(new b2Vec2(0, 0));
if (!scroll) {
var point = zimObj.parent.globalToLocal(p.x * scale, p.y * scale);
zimObj.x = point.x;
zimObj.y = point.y;
} else {
zimObj.x = p.x * scale;
zimObj.y = p.y * scale;
//if (that.followObj && that.followObj==zimObj && zimObj.followDampX) that.frame.stage.x = zimObj.followDampX.convert(zimObj.offsetDampX.convert(zimObj.followOffsetX[zimObj.controlX])-zimObj.x);
//if (that.followObj && that.followObj==zimObj && zimObj.followDampY) that.frame.stage.y = zimObj.followDampY.convert(zimObj.offsetDampY.convert(zimObj.followOffsetY[zimObj.controlY])-zimObj.y);
if (that.followObj && that.followObj==zimObj && zimObj.followDampX) that.frame.stage.x = that.frame.stage.scaleX*zimObj.followDampX.convert(zimObj.offsetDampX.convert(zimObj.followOffsetX[zimObj.controlX])-zimObj.x);
if (that.followObj && that.followObj==zimObj && zimObj.followDampY) that.frame.stage.y = that.frame.stage.scaleY*zimObj.followDampY.convert(zimObj.offsetDampY.convert(zimObj.followOffsetY[zimObj.controlY])-zimObj.y);
if (zimObj.frameBorderLock) {
if (that.frame.stage.x < that.frame.stage.scaleX*borders.x && ((zimObj.frameBorderOriginal && that.borderRight.m_fixtureCount == 0) || that.borderRight.m_fixtureCount == 1)) that.frame.stage.x = that.frame.stage.scaleX*borders.x;
if (that.frame.stage.y < that.frame.stage.scaleY*borders.y && ((zimObj.frameBorderOriginal && that.borderBottom.m_fixtureCount == 0) || that.borderBottom.m_fixtureCount == 1)) that.frame.stage.y = that.frame.stage.scaleY*borders.y;
if (that.frame.stage.x > that.frame.stage.scaleX*(borders.x + borders.width - that.frame.stage.width) && ((zimObj.frameBorderOriginal && that.borderLeft.m_fixtureCount == 0) || that.borderLeft.m_fixtureCount == 1)) that.frame.stage.x = that.frame.stage.scaleX*(borders.x + borders.width - that.frame.stage.width);
if (that.frame.stage.y > that.frame.stage.scaleY*(borders.y + borders.height - that.frame.stage.height) && ((zimObj.frameBorderOriginal && that.borderTop.m_fixtureCount == 0) || that.borderTop.m_fixtureCount == 1)) that.frame.stage.y = that.frame.stage.scaleY*(borders.y + borders.height - that.frame.stage.height);
}
}
zimObj.rotation = box2DBody.GetAngle() * (180 / Math.PI);
}
that.frame.stage.update();
}
this.addMap = function(box2DBody, zimObj) {
if (zot(box2DBody) || zot(zimObj)) {
console.log("physics.Map() - please provide a box2DBody and zimObj");
return;
}
zimObj.body = box2DBody;
box2DBody.zimObj = zimObj;
mappings.add(box2DBody, zimObj);
}
this.removeMap = function(box2DBody) {
mappings.remove(box2DBody);
}
this.borders = function(rect) {
if (zot(rect.x) || zot(rect.y) || zot(rect.width) || zot(rect.height)) return;
if (that.borderTop) that.remove(that.borderTop);
if (that.borderBottom) that.remove(that.borderBottom);
if (that.borderLeft) that.remove(that.borderLeft);
if (that.borderRight) that.remove(that.borderRight);
var w = 2000; // width of wall
// Create border of boxes
var wall = new b2PolygonShape();
var wallBd = new b2BodyDef();
var wallB;
// Left
// wallBd.position.Set((rect.x-w)/scale, (rect.y+rect.height/2)/scale);
// wall.SetAsBox(w/scale, rect.height/2/scale);
// wallB = that.borderLeft = world.CreateBody(wallBd);
// wallB.CreateFixture2(wall);
that.borderLeft = that.makeRectangle(w*2, rect.height, false);
that.borderLeft.x = rect.x-w;
that.borderLeft.y = rect.y+rect.height/2;
// Right
// wallBd.position.Set((rect.x+rect.width+w)/scale, (rect.y+rect.height/2)/scale);
// wallB = that.borderRight = world.CreateBody(wallBd);
// wallB.CreateFixture2(wall);
that.borderRight = that.makeRectangle(w*2, rect.height, false);
that.borderRight.x = rect.x+rect.width+w;
that.borderRight.y = rect.y+rect.height/2;
// Top
// wallBd.position.Set((rect.x + rect.width/2)/scale, (rect.y-w)/scale);
// wall.SetAsBox(rect.width/2/scale, w/scale);
// wallB = that.borderTop = world.CreateBody(wallBd);
// wallB.CreateFixture2(wall);
that.borderTop = that.makeRectangle(rect.width, w*2, false);
that.borderTop.x = rect.x + rect.width/2;
that.borderTop.y = rect.y-w;
// Bottom
// wallBd.position.Set((rect.x + rect.width/2)/scale, (rect.y+rect.height+w)/scale);
// wallB = that.borderBottom = world.CreateBody(wallBd);
// wallB.CreateFixture2(wall);
that.borderBottom = that.makeRectangle(rect.width, w*2, false);
that.borderBottom.x = rect.x + rect.width/2;
that.borderBottom.y = rect.y+rect.height+w;
}
this.borders(borders);
// the Ticker keeps add and remove methods
// to add and remove functions to the update function
// either before the world step or after the word step
// these can be used for adding forces
var beforeList = new zim.Dictionary();
var afterList = new zim.Dictionary();
this.Ticker = {
add:function(f, after) {
if (zot(after)) after = true;
if (after) afterList.add(f, 1);
else beforeList.add(f, 1);
return f;
},
remove:function(f) {
afterList.remove(f);
beforeList.remove(f);
}
};
// update world
var request;
function update() {
request = requestAnimationFrame(update);
if (drag) drag.update();
for (var i=0; i<beforeList.objects.length; i++) beforeList.objects[i]();
world.Step(timeStep, 10, 10); // last two are velocity iterations, position iterations
doRemove();
world.ClearForces();
for (i=0; i<afterList.objects.length; i++) afterList.objects[i]();
if (debug && debug.active) debug.update();
updateMap();
}
update();
this.dispose = function() {
// this does not seem to let us make a world again properly?
if (drag) drag.removeListeners();
if (this == zimDefaultPhysics) zimDefaultPhysics = null;
zimContactListener = null
var node = that.world.GetBodyList();
while(node) {
var b = node;
node = node.GetNext();
that.world.DestroyBody(b);
b = null;
}
that.removeDebug();
cancelAnimationFrame(request);
that.world = null;
}
};
return zim;
}(zim || {});
if (!window.zns) Physics = zim.Physics;
return Physics;
}