planck-js
Version:
2D JavaScript physics engine for cross-platform HTML5 game development
154 lines (136 loc) • 4.77 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.
*/
// This is a test of typical character collision scenarios. This does not
// show how you should implement a character in your application.
// Instead this is used to test smooth collision on edge chains.
planck.testbed('CharacterCollision', function(testbed) {
var pl = planck, Vec2 = pl.Vec2;
var world = new pl.World(Vec2(0, -10));
// Ground body
var ground = world.createBody();
ground.createFixture(pl.Edge(Vec2(-20.0, 0.0), Vec2(20.0, 0.0)), 0.0);
// Collinear edges with no adjacency information.
// This shows the problematic case where a box shape can hit
// an internal vertex.
var edge = world.createBody();
edge.createFixture(pl.Edge(Vec2(-8.0, 1.0), Vec2(-6.0, 1.0)), 0.0);
edge.createFixture(pl.Edge(Vec2(-6.0, 1.0), Vec2(-4.0, 1.0)), 0.0);
edge.createFixture(pl.Edge(Vec2(-4.0, 1.0), Vec2(-2.0, 1.0)), 0.0);
// Chain shape
var chain = world.createBody(Vec2(), 0.25 * Math.PI);
chain.createFixture(pl.Chain([
Vec2(5.0, 7.0),
Vec2(6.0, 8.0),
Vec2(7.0, 8.0),
Vec2(8.0, 7.0)
]), 0.0);
// Square tiles. This shows that adjacency shapes may
// have non-smooth collision. There is no solution
// to this problem.
var tiles = world.createBody();
tiles.createFixture(pl.Box(1.0, 1.0, Vec2(4.0, 3.0), 0.0), 0.0);
tiles.createFixture(pl.Box(1.0, 1.0, Vec2(6.0, 3.0), 0.0), 0.0);
tiles.createFixture(pl.Box(1.0, 1.0, Vec2(8.0, 3.0), 0.0), 0.0);
// Square made from an edge loop. Collision should be smooth.
var square = world.createBody();
square.createFixture(pl.Chain([
Vec2(-1.0, 3.0),
Vec2(1.0, 3.0),
Vec2(1.0, 5.0),
Vec2(-1.0, 5.0)
], true), 0.0);
// Edge loop. Collision should be smooth.
var loop = world.createBody(Vec2(-10.0, 4.0));
loop.createFixture(pl.Chain([
Vec2(0.0, 0.0),
Vec2(6.0, 0.0),
Vec2(6.0, 2.0),
Vec2(4.0, 1.0),
Vec2(2.0, 2.0),
Vec2(0.0, 2.0),
Vec2(-2.0, 2.0),
Vec2(-4.0, 3.0),
Vec2(-6.0, 2.0),
Vec2(-6.0, 0.0)
], true), 0.0);
// Square character 1
var char1 = world.createBody({
position : Vec2(-3.0, 8.0),
type : 'dynamic',
fixedRotation : true,
allowSleep : false
});
char1.createFixture(pl.Box(0.5, 0.5), 20.0);
// Square character 2
var char2 = world.createBody({
position : Vec2(-5.0, 5.0),
type : 'dynamic',
fixedRotation : true,
allowSleep : false
});
char2.createFixture(pl.Box(0.25, 0.25), 20.0);
// Hexagon character
var hex = world.createBody({
position : Vec2(-5.0, 8.0),
type : 'dynamic',
fixedRotation : true,
allowSleep : false
});
var angle = 0.0;
var delta = Math.PI / 3.0;
var vertices = [];
for (var i = 0; i < 6; ++i) {
vertices[i] = Vec2(0.5 * Math.cos(angle), 0.5 * Math.sin(angle));
angle += delta;
}
hex.createFixture(pl.Polygon(vertices), 20.0);
// Circle character
var circle = world.createBody({
position : Vec2(3.0, 5.0),
type : 'dynamic',
fixedRotation : true,
allowSleep : false
});
circle.createFixture(pl.Circle(0.5), 20.0);
// Circle character
var character = world.createBody({
position : Vec2(-7.0, 6.0),
type : 'dynamic',
allowSleep : false
});
character.createFixture(pl.Circle(0.25), {
density : 20.0,
friction : 1.0
});
testbed.step = function() {
var v = character.getLinearVelocity();
v.x = -5.0;
character.setLinearVelocity(v);
};
testbed.info(
'This tests various character collision shapes.' +
'\nLimitation: square and hexagon can snag on aligned boxes.' +
'\nFeature: edge chains have smooth collision inside and out.'
);
return world;
});