planck-js
Version:
2D JavaScript physics engine for cross-platform HTML5 game development
218 lines (171 loc) • 5.47 kB
JavaScript
/*
* MIT License
* Copyright (c) 2019 Erin Catto
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
planck.testbed('PolyShapes', function(testbed) {
var pl = planck, Vec2 = pl.Vec2;
var world = new pl.World(Vec2(0, -10));
var MAX_BODIES = 256;
var bodies = [];
var shapes = [];
var ground = world.createBody();
ground.createFixture(pl.Edge(Vec2(-40.0, 0.0), Vec2(40.0, 0.0)), 0.0);
shapes[0] = pl.Polygon([
Vec2(-0.5, 0.0),
Vec2(0.5, 0.0),
Vec2(0.0, 1.5)
]);
shapes[1] = pl.Polygon([
Vec2(-0.1, 0.0),
Vec2(0.1, 0.0),
Vec2(0.0, 1.5)
]);
{
var w = 1.0;
var b = w / (2.0 + Math.sqrt(2.0));
var s = Math.sqrt(2.0) * b;
shapes[2] = pl.Polygon([
Vec2(0.5 * s, 0.0),
Vec2(0.5 * w, b),
Vec2(0.5 * w, b + s),
Vec2(0.5 * s, w),
Vec2(-0.5 * s, w),
Vec2(-0.5 * w, b + s),
Vec2(-0.5 * w, b),
Vec2(-0.5 * s, 0.0),
]);
}
shapes[3] = pl.Box(0.5, 0.5);
shapes[4] = pl.Circle(0.5);
function createBody(index) {
if (bodies.length > MAX_BODIES) {
world.destroyBody(bodies.shift());
}
var bd = {};
bd.type = 'dynamic';
var x = Math.random() * 0.4 - 2.0;
bd.position = Vec2(x, 10.0);
bd.angle = Math.random() * 2 * Math.PI - Math.PI;
if (index === 4) {
bd.angularDamping = 0.02;
}
var body = world.createBody(bd);
body.createFixture(shapes[index % shapes.length], {
density: 1.0,
friction: 0.3,
});
bodies.push(body);
}
function destroyBody() {
world.destroyBody(bodies.shift());
}
testbed.keydown = function(code, char) {
switch (char) {
case '1':
createBody(1);
break;
case '2':
createBody(2);
break;
case '3':
createBody(3);
break;
case '4':
createBody(4);
break;
case '5':
createBody(5);
break;
case 'Z':
for (var i = 0; i < bodies.length; i += 2) {
var body = bodies[i];
body.setActive(!body.isActive());
}
break;
case 'X':
destroyBody();
break;
}
};
testbed.info("1-5: Drop new objects, Z: Activate/deactivate some bodies, X: Destroy an object");
testbed.step = function() {
AABBQueryListener.reset();
var aabb = pl.AABB();
AABBQueryListener.circle.computeAABB(aabb, AABBQueryListener.transform, 0);
world.queryAABB(aabb, AABBQueryListener.callback);
testbed.drawCircle(AABBQueryListener.circle.m_p, AABBQueryListener.circle.m_radius, testbed.color(0.4, 0.7, 0.8));
};
function drawFixture(fixture) {
var color = testbed.color(0.95, 0.95, 0.6);
var xf = fixture.getBody().getTransform();
switch (fixture.getType()) {
case 'circle': {
var circle = fixture.getShape();
var center = pl.Transform.mul(xf, circle.getCenter());
var radius = circle.getRadius();
testbed.drawCircle(center, radius, color);
}
break;
case 'polygon': {
var poly = fixture.getShape();
var vertexCount = poly.m_count;
// assert(vertexCount <= b2_maxPolygonVertices);
var vertices = poly.m_vertices.map(pl.Transform.mulFn(xf));
testbed.drawPolygon(vertices, color);
}
break;
default:
break;
}
}
// This tests stacking. It also shows how to use World.query and TestOverlap.
// This callback is called by World.queryAABB. We find all the fixtures
// that overlap an AABB. Of those, we use TestOverlap to determine which fixtures
// overlap a circle. Up to 4 overlapped fixtures will be highlighted with a
// yellow border.
var AABBQueryListener = (function() {
var def = {};
def.circle = pl.Circle(Vec2(0.0, 1.1), 2.0);
def.transform = pl.Transform();
var count = 0;
var MAX_COUNT = 40;
def.reset = function() {
count = 0;
};
// Called for each fixture found in the query AABB.
// return false to terminate the query.
def.callback = function(fixture) {
if (count === MAX_COUNT) {
return false;
}
var body = fixture.getBody();
var shape = fixture.getShape();
var overlap = pl.internal.Distance.testOverlap(shape, 0, def.circle, 0, body.getTransform(), def.transform);
if (overlap) {
drawFixture(fixture);
++count;
}
return true;
};
return def;
})();
return world;
});