UNPKG

planck-js

Version:

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

158 lines (131 loc) 5.15 kB
planck.testbed('8 Ball', function(testbed) { var pl = planck, Vec2 = pl.Vec2, Math = pl.Math; var SPI4 = Math.sin(Math.PI / 4), SPI3 = Math.sin(Math.PI / 3); var COLORED = true; var BLACK = {fill: 'black', stroke: 'white'}; var WHITE = {fill: 'white', stroke: 'black'}; var COLORS = [ {fill: '#ffdd00', stroke: '#000000'}, {fill: '#ffdd00', stroke: '#ffffff'}, {fill: '#ff3300', stroke: '#000000'}, {fill: '#ff3300', stroke: '#ffffff'}, {fill: '#662200', stroke: '#000000'}, {fill: '#662200', stroke: '#ffffff'}, {fill: '#ff8800', stroke: '#000000'}, {fill: '#ff8800', stroke: '#ffffff'}, {fill: '#00bb11', stroke: '#000000'}, {fill: '#00bb11', stroke: '#ffffff'}, {fill: '#9900ff', stroke: '#000000'}, {fill: '#9900ff', stroke: '#ffffff'}, {fill: '#0077ff', stroke: '#000000'}, {fill: '#0077ff', stroke: '#ffffff'} ]; var width = 8.00, height = 4.00; var BALL_R = 0.12; var POCKET_R = 0.2; testbed.x = 0; testbed.y = 0; testbed.width = width * 1.2; testbed.height = height * 1.2; testbed.ratio = 100; testbed.mouseForce = -30; pl.Settings.velocityThreshold = 0; var world = pl.World({}); var railH = [ Vec2(POCKET_R, height * .5), Vec2(POCKET_R, height * .5 + POCKET_R), Vec2(width * .5 - POCKET_R / SPI4 + POCKET_R, height * .5 + POCKET_R), Vec2(width * .5 - POCKET_R / SPI4, height * .5) ]; var railV = [ Vec2(width * .5, -(height * .5 - POCKET_R / SPI4)), Vec2(width * .5 + POCKET_R, -(height * .5 - POCKET_R / SPI4 + POCKET_R)), Vec2(width * .5 + POCKET_R, height * .5 - POCKET_R / SPI4 + POCKET_R), Vec2(width * .5, height * .5 - POCKET_R / SPI4) ]; var railFixDef = { friction: 0.1, restitution: 0.9, userData: 'rail' }; var pocketFixDef = { userData: 'pocket' }; var ballFixDef = { friction: 0.1, restitution: 0.99, density: 1, userData: 'ball' }; var ballBodyDef = { linearDamping: 1.5, angularDamping: 1 }; world.createBody().createFixture(pl.Polygon(railV.map(Vec2.scaleFn(+1, +1))), railFixDef); world.createBody().createFixture(pl.Polygon(railV.map(Vec2.scaleFn(-1, +1))), railFixDef); world.createBody().createFixture(pl.Polygon(railH.map(Vec2.scaleFn(+1, +1))), railFixDef); world.createBody().createFixture(pl.Polygon(railH.map(Vec2.scaleFn(-1, +1))), railFixDef); world.createBody().createFixture(pl.Polygon(railH.map(Vec2.scaleFn(+1, -1))), railFixDef); world.createBody().createFixture(pl.Polygon(railH.map(Vec2.scaleFn(-1, -1))), railFixDef); world.createBody().createFixture(pl.Circle(Vec2(0, -height * .5 - POCKET_R * 1.5), POCKET_R), pocketFixDef); world.createBody().createFixture(pl.Circle(Vec2(0, +height * .5 + POCKET_R * 1.5), POCKET_R), pocketFixDef); world.createBody().createFixture(pl.Circle(Vec2(+width * .5 + POCKET_R * .7, +height * .5 + POCKET_R * .7), POCKET_R), pocketFixDef); world.createBody().createFixture(pl.Circle(Vec2(-width * .5 - POCKET_R * .7, +height * .5 + POCKET_R * .7), POCKET_R), pocketFixDef); world.createBody().createFixture(pl.Circle(Vec2(+width * .5 + POCKET_R * .7, -height * .5 - POCKET_R * .7), POCKET_R), pocketFixDef); world.createBody().createFixture(pl.Circle(Vec2(-width * .5 - POCKET_R * .7, -height * .5 - POCKET_R * .7), POCKET_R), pocketFixDef); var balls = rack(BALL_R).map(Vec2.translateFn(width / 4, 0)); balls.push({x: -width / 4, y: 0}); if (COLORED) { shuffleArray(COLORS); for (var i = 0; i < COLORS.length; i++) { balls[i].render = COLORS[i]; } balls[14].render = balls[4].render; balls[4].render = BLACK; balls[balls.length - 1].render = WHITE; } for (i = 0; i < balls.length; i++) { var ball = world.createDynamicBody(ballBodyDef); ball.setBullet(true); ball.setPosition(balls[i]); ball.createFixture(pl.Circle(BALL_R), ballFixDef); ball.render = balls[i].render; } world.on('post-solve', function(contact) { var fA = contact.getFixtureA(), bA = fA.getBody(); var fB = contact.getFixtureB(), bB = fB.getBody(); var pocket = fA.getUserData() === pocketFixDef.userData && bA || fB.getUserData() === pocketFixDef.userData && bB; var ball = fA.getUserData() === ballFixDef.userData && bA || fB.getUserData() === ballFixDef.userData && bB; // do not change world immediately setTimeout(function() { if (ball && pocket) { world.destroyBody(ball); } }, 1); }); return world; function rack(r) { var n = 5; var balls = []; var d = r * 2, l = SPI3 * d; for (var i = 0; i < n; i++) { for (var j = 0; j <= i; j++) { balls.push({ x: i * l /*- (n - 1) * 0.5 * l*/ + Math.random(r * 0.02), y: (j - i * 0.5 ) * d + Math.random(r * 0.02), }); } } return balls; } function shuffleArray(array) { // http://stackoverflow.com/a/12646864/483728 for (var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = array[i]; array[i] = array[j]; array[j] = temp; } return array; } });