UNPKG

planck-js

Version:

2D JavaScript physics engine for cross-platform HTML5 game development

188 lines (148 loc) 4.8 kB
/* * 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('EdgeShapes', function(testbed) { var pl = planck, Vec2 = pl.Vec2; var world = new pl.World(Vec2(0, -10)); var pause = false; var MAX_BODIES = 256; var bodies = []; var shapes = []; { var ground = world.createBody(); var x1 = -20.0; var y1 = 2.0 * Math.cos(x1 / 10.0 * Math.PI); for (var i = 0; i < 80; ++i) { var x2 = x1 + 0.5; var y2 = 2.0 * Math.cos(x2 / 10.0 * Math.PI); ground.createFixture(pl.Edge(Vec2(x1, y1), Vec2(x2, y2)), 0.0); x1 = x2; y1 = y2; } } 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; var vertices = []; vertices[0] = Vec2(0.5 * s, 0.0); vertices[1] = Vec2(0.5 * w, b); vertices[2] = Vec2(0.5 * w, b + s); vertices[3] = Vec2(0.5 * s, w); vertices[4] = Vec2(-0.5 * s, w); vertices[5] = Vec2(-0.5 * w, b + s); vertices[6] = Vec2(-0.5 * w, b); vertices[7] = Vec2(-0.5 * s, 0.0); shapes[2] = pl.Polygon(vertices); } shapes[3] = pl.Box(0.5, 0.5); shapes[4] = pl.Circle(0.5); var angle = 0.0; function createItem(index) { if (bodies.length > MAX_BODIES) { world.destroyBody(bodies.shift()); } var bd = {}; var x = pl.Math.random(-10.0, 10.0); var y = pl.Math.random(10.0, 20.0); bd.position = Vec2(x, y); bd.angle = pl.Math.random(-Math.PI, Math.PI); bd.type = 'dynamic'; if (index === 4) { bd.angularDamping = 0.02; } var body = world.createBody(bd); var fd = {}; fd.shape = shapes[index]; fd.friction = 0.3; fd.density = 20.0; body.createFixture(fd); bodies.push(body); } function destroyBody() { world.destroyBody(bodies.shift()); } testbed.keydown = function(code, char) { switch (char) { case '1': createItem(0); break; case '2': createItem(1); break; case '3': createItem(2); break; case '4': createItem(3); break; case '5': createItem(4); break; case 'X': destroyBody(); break; case 'Z': pause = !pause; break; } }; testbed.info('1-5: Drop new object, X: Destroy an object'); var RayCastListener = (function() { var def = {}; def.callback = function(fixture, point, normal, fraction) { def.fixture = fixture; def.point = point; def.normal = normal; return fraction; }; def.reset = function() { def.fixture = null; def.point = null; def.normal = null; }; return def; })(); testbed.step = function() { var advanceRay = !pause; // settings.pause == 0 || settings.singleStep; var L = 25.0; var point1 = Vec2(0.0, 10.0); var d = Vec2(L * Math.cos(angle), -L * Math.abs(Math.sin(angle))); var point2 = Vec2.add(point1, d); RayCastListener.reset(); world.rayCast(point1, point2, RayCastListener.callback); if (RayCastListener.fixture) { testbed.drawPoint(RayCastListener.point, 5.0, testbed.color(0.4, 0.9, 0.4)); testbed.drawSegment(point1, RayCastListener.point, testbed.color(0.8, 0.8, 0.8)); var head = Vec2.combine(1, RayCastListener.point, 0.5, RayCastListener.normal); testbed.drawSegment(RayCastListener.point, head, testbed.color(0.9, 0.9, 0.4)); } else { testbed.drawSegment(point1, point2, testbed.color(0.8, 0.8, 0.8)); } if (advanceRay) { angle += 0.25 * Math.PI / 180.0; } }; return world; });