diff --git a/.DS_Store b/.DS_Store index 21bb93d..4cb7f5b 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/js/bullet.js b/js/bullet.js index e8631be..bd80b96 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -3381,7 +3381,7 @@ const b = { // makeNeedle(m.angle - spread) }, fireRivets() { - m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 23 : 15) * b.fireCD); // cool down + m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 25 : 17) * b.fireCD); // cool down const me = bullet.length; const size = tech.rivetSize * 7.5 @@ -4176,7 +4176,7 @@ const b = { name: "foam", description: "spray bubbly foam that sticks to mobs
slows mobs and does damage over time", ammo: 0, - ammoPack: 27, + ammoPack: 22, have: false, charge: 0, isDischarge: false, diff --git a/js/level.js b/js/level.js index e4b025d..1e16ceb 100644 --- a/js/level.js +++ b/js/level.js @@ -13,8 +13,9 @@ const level = { start() { if (level.levelsCleared === 0) { //this code only runs on the first level // simulation.enableConstructMode() //used to build maps in testing mode + // simulation.difficulty = 20 // simulation.isHorizontalFlipped = true - // level.difficultyIncrease(30) + // level.difficultyIncrease(99) // m.setField("standing wave harmonics") // tech.giveTech("spherical harmonics") // for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics") @@ -29,7 +30,6 @@ const level = { // for (let i = 0; i < 3; i++) tech.giveTech("bound state") // for (let i = 0; i < 9; i++) tech.giveTech("WIMPs") - level.intro(); //starting level // level.labs(); // level.testing(); //not in rotation, used for testing @@ -96,7 +96,7 @@ const level = { powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "tech", false); } if (tech.isHealLowHealth) { - const len = Math.floor((m.maxHealth - m.health) / 0.33) + const len = Math.ceil((m.maxHealth - m.health) / 0.33) for (let i = 0; i < len; i++) powerUps.spawn(player.position.x + 90 * (Math.random() - 0.5), player.position.y + 90 * (Math.random() - 0.5), "heal", false); } if (tech.isMACHO) spawn.MACHO() @@ -276,8 +276,8 @@ const level = { } }, spinner(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0) { - x = x + width / 2 - y = y + height / 2 + x += width / 2 + y += height / 2 const who = body[body.length] = Bodies.rectangle(x, y, width, height, { collisionFilter: { category: cat.body, @@ -296,8 +296,8 @@ const level = { Matter.Body.setDensity(who, density) const constraint = Constraint.create({ //fix rotor in place, but allow rotation pointA: { - x: x, - y: y + x: who.position.x, + y: who.position.y }, bodyB: who, stiffness: 1, @@ -553,17 +553,15 @@ const level = { return rotor }, toggle(x, y, isOn = false, isLockOn = false) { - spawn.mapVertex(x + 65, y + 2, "70 10 -70 10 -40 -10 40 -10"); + spawn.mapVertex(x + 65, y + 2, "70 10 -70 10 -40 -10 40 -10"); //toggle platform map[map.length - 1].restitution = 0; map[map.length - 1].friction = 1; map[map.length - 1].frictionStatic = 1; - - spawn.bodyRect(x, y - 5, 120, 15) //Portal platform + spawn.bodyRect(x, y - 5, 120, 15) //toggle body called flip let flip = body[body.length - 1]; - flip.isNoSetCollision = true //prevents collision form being rewritten in level.addToWorld + flip.isNoSetCollision = true //prevents collision from being rewritten in level.addToWorld flip.collisionFilter.category = cat.body flip.collisionFilter.mask = cat.player | cat.body - flip.isNotHoldable = true flip.frictionAir = 0.01 flip.restitution = 0 @@ -573,11 +571,6 @@ const level = { } else { Matter.Body.setAngle(flip, (-0.25 - 0.5) * Math.PI) } - - // setTimeout(function() { - - // }, 100); - cons[cons.length] = Constraint.create({ pointA: { x: x + 65, @@ -589,7 +582,6 @@ const level = { }); World.add(engine.world, [cons[cons.length - 1]]); - return { flip: flip, isOn: isOn, @@ -607,7 +599,6 @@ const level = { Matter.Body.setAngularVelocity(flip, 0); this.isOn = true } - if (this.isOn) { ctx.beginPath(); ctx.moveTo(flip.vertices[0].x, flip.vertices[0].y); @@ -734,9 +725,6 @@ const level = { Matter.Body.setStatic(doorBlock, true); //make static return doorBlock }, - - - portal(centerA, angleA, centerB, angleB) { const width = 50 const height = 150 @@ -1089,57 +1077,46 @@ const level = { //****************************************************************************************************************** //****************************************************************************************************************** labs() { - // level.difficultyIncrease(30) - level.defaultZoom = 1800 + level.isProcedural = true //used in generating text itn he level builder + level.defaultZoom = 1700 simulation.zoomTransition(level.defaultZoom) document.body.style.backgroundColor = "#dcdcdf"; - // document.body.style.backgroundColor = "#d5d5d5"; let isDoorLeft, isDoorRight, x, y doCustom = [] doCustomTopLayer = [] offset = { x: 0, y: 0 } enterOptions = [ (x = offset.x, y = offset.y) => { //lasers - level.setPosToSpawn(x + 2300, y - 800); + level.setPosToSpawn(x + 1750, y - 800); spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); - spawn.mapRect(x + 1850, y - 1350, 50, 450); //entrance left wall - spawn.bodyRect(x + 1860, y - 900, 30, 150); //entrance door - - spawn.mapRect(x + 2000, y - 350, 750, 150); //toggle shelf - const toggle = level.toggle(x + 2050, y - 350, true) //(x,y,isOn,isLockOn = true/false) - + spawn.mapRect(x + 1450, y - 1350, 50, 450); //entrance left wall + spawn.bodyRect(x + 1460, y - 900, 30, 150); //entrance door + spawn.mapRect(x + 1600, y - 350, 500, 100); //toggle shelf + const toggle = level.toggle(x + 1650, y - 350, true) //(x,y,isOn,isLockOn = true/false) let hazard if (Math.random() > 0.5) { - spawn.mapRect(x + 550, y - 750, 2200, 50); //entrance shelf - hazard = level.hazard(x + 850, y - 920, 1000, 10, 0.4) //laser + spawn.mapRect(x + 550, y - 750, 1500, 50); //entrance shelf + hazard = level.hazard(x + 850, y - 920, 600, 10, 0.4) //laser spawn.mapRect(x + 860, y - 925, 10, 20); //laser nose spawn.mapRect(x + 660, y - 975, 200, 120); //laser body } else { - spawn.mapRect(x + 1450, y - 750, 1300, 50); //entrance shelf - hazard = level.hazard(x + 1040, y - 660, 1700, 10, 0.4) //laser + spawn.mapRect(x + 1350, y - 750, 700, 50); //entrance shelf + hazard = level.hazard(x + 1040, y - 660, 1000, 10, 0.4) //laser spawn.mapRect(x + 1050, y - 665, 10, 20); //laser nose spawn.mapRect(x + 650, y - 705, 400, 100); //laser body } - - const hazard2 = level.hazard(x - 150, y - 330, 600, 10, 0.4) //laser + const hazard2 = level.hazard(x, y - 330, 450, 10, 0.4) //laser spawn.mapRect(x + 440, y - 335, 10, 20); //laser nose spawn.mapRect(x + 450, y - 375, 400, 100); //laser body //exit hazards const Xoffset = Math.floor(400 * Math.random()) const hazard3 = level.hazard(x + Xoffset, y - 1300, 10, 1300, 0.4) //laser spawn.mapRect(x + Xoffset - 5, y - 1310, 20, 20); //laser nose + const Xoffset2 = 1650 + Math.floor(300 * Math.random()) + const hazard4 = level.hazard(x + Xoffset2, y - 240, 10, 250, 0.4) //laser + spawn.mapRect(x + Xoffset2 - 5, y - 250, 20, 20); //laser nose - const Xoffset2 = 2050 + Math.floor(550 * Math.random()) - const hazard4 = level.hazard(x + Xoffset2, y - 200, 10, 200, 0.4) //laser - spawn.mapRect(x + Xoffset2 - 5, y - 210, 20, 20); //laser nose - - spawn.randomSmallMob(x + 2225, y - 100); - spawn.randomMob(x + 0, y - 125, 0); - spawn.randomMob(x + 650, y - 100, 0.5); - spawn.randomGroup(x + 1300, y - 250, 0.1); - // spawn.randomSmallMob(1300, -70); - // spawn.randomMob(2650, -975, 0.8); - // spawn.randomGroup(1700, -900, 0.4); + let isSpawnedMobs = false doCustomTopLayer.push( () => { toggle.query(); @@ -1151,66 +1128,57 @@ const level = { hazard2.opticalQuery(); hazard3.opticalQuery(); hazard4.opticalQuery(); + if (!isSpawnedMobs && !toggle.isOn) { + isSpawnedMobs = true + spawn.randomMob(x + 150, y + -1100, Infinity); + spawn.randomMob(x + 175, y + -775, Infinity); + spawn.randomMob(x + 150, y + -350, Infinity); + spawn.randomMob(x + 150, y + -75, Infinity); + spawn.randomMob(x + 650, y + -125, Infinity); + spawn.randomMob(x + 1200, y + -75, Infinity); + } } ) - }, - // () => { - // level.setPosToSpawn(x + 1250, y - 50); - // spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); - // } ] exitOptions = [ - (x = offset.x, y = offset.y) => { //8 spinners - level.exit.x = x + 1250; + (x = offset.x, y = offset.y) => { + level.exit.x = x + 1725; level.exit.y = y - 980; spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); - spawn.mapRect(x + 1050, y - 950, 500, 25); //exit platform - spawn.mapRect(x + 1100, y - 1300, 25, 175); //exit side wall - spawn.mapRect(x + 1475, y - 1300, 25, 175); //exit side wall - if (0.33 < Math.random()) { //center large stage - spawn.mapRect(x + 1050, y - 350, 500, 400); - } else if (0.5 < Math.random()) { - spawn.mapVertex(x + 1300, y - 310, "-300 0 -250 -425 250 -425 300 0"); - } else { - spawn.mapVertex(x + 1300, y - 125, "-400 0 -250 -400 250 -400 400 0"); - } + spawn.mapRect(x + 1500, y - 950, 500, 25); //exit platform + spawn.mapRect(x + 1550, y - 1300, 25, 175); //exit side wall + spawn.mapVertex(x + 1300, y - 125, "-400 0 -250 -400 250 -400 400 0"); - spawn.bodyRect(x + 1275, y - 475, 125, 125, 0.25); - spawn.bodyRect(x + 1825, y - 125, 125, 125, 0.25); + spawn.bodyRect(x + 1075, y - 475, 125, 125, 0.25); spawn.bodyRect(x + 500, y - 100, 125, 100, 0.25); - spawn.bodyRect(x + 0, y - 150, 100, 150, 0.25); - spawn.bodyRect(x + 2375, y - 150, 125, 150, 0.25); + spawn.bodyRect(x + 200, y - 150, 100, 150, 0.25); spawn.bodyRect(x + 1075, y - 1075, 100, 125, 0.25); - spawn.bodyRect(x + 1450, y - 1050, 100, 100, 0.25); - const density = 0.0015 + (simulation.difficultyMode < 3 ? 0.003 : 0) const angle = 0 const variance = Math.PI const frictionAir = 0 const angularVelocity = 0.01 const spinVariance = 0.02 - - balance1 = level.spinner(x + 150, y - 600, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) // spinner(x, y, width, height, density = 0.001, angle=0,frictionAir=0.001,angularVelocity=0) { + balance1 = level.spinner(x + 225, y - 565, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) // spinner(x, y, width, height, density = 0.001, angle=0,frictionAir=0.001,angularVelocity=0) { balance2 = level.spinner(x + 300, y - 1000, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) balance3 = level.spinner(x + 650, y - 750, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) balance4 = level.spinner(x + 800, y - 1150, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) + balance5 = level.spinner(x + 1250, y - 1150, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - balance5 = level.spinner(x + 1770, y - 1150, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - balance6 = level.spinner(x + 1930, y - 750, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - balance7 = level.spinner(x + 2270, y - 1000, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - balance8 = level.spinner(x + 2410, y - 600, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - - spawn.randomMob(x + 1175, y - 725, 0.1); - spawn.randomMob(x + 1450, y - 725, 0.2); - spawn.randomMob(x + 425, y - 100, 0.3); - spawn.randomMob(x + 2300, y - 125, 0.4); - spawn.randomMob(x + 1300, y - 375, 0.5); - + let isInRoom = false doCustom.push( () => { + if (!isInRoom && m.pos.x > x - 100 && m.pos.x < x + 2700 && m.pos.y > y - 1300 && m.pos.y < y) { //check if player is in this room and run code once + isInRoom = true + spawn.randomMob(x + 1175, y - 725, Infinity); + spawn.randomMob(x + 1450, y - 725, Infinity); + spawn.randomMob(x + 425, y - 100, Infinity); + spawn.randomMob(x + 1200, y - 125, Infinity); + spawn.randomMob(x + 1300, y - 375, Infinity); + } ctx.fillStyle = "#d4f4f4" - ctx.fillRect(x + 1100, y - 1300, 400, 350) + ctx.fillRect(x + 1550, y - 1300, 450, 350) } ) doCustomTopLayer.push( @@ -1226,28 +1194,21 @@ const level = { ctx.arc(balance4.pointA.x, balance4.pointA.y, 9, 0, 2 * Math.PI); ctx.moveTo(balance5.pointA.x, balance5.pointA.y) ctx.arc(balance5.pointA.x, balance5.pointA.y, 9, 0, 2 * Math.PI); - ctx.moveTo(balance6.pointA.x, balance6.pointA.y) - ctx.arc(balance6.pointA.x, balance6.pointA.y, 9, 0, 2 * Math.PI); - ctx.moveTo(balance7.pointA.x, balance7.pointA.y) - ctx.arc(balance7.pointA.x, balance7.pointA.y, 9, 0, 2 * Math.PI); - ctx.moveTo(balance8.pointA.x, balance8.pointA.y) - ctx.arc(balance8.pointA.x, balance8.pointA.y, 9, 0, 2 * Math.PI); ctx.fill(); } ) }, - (x = offset.x, y = offset.y) => { //7 spinners - level.exit.x = x + 2450; + (x = offset.x, y = offset.y) => { + level.exit.x = x + 1750; level.exit.y = y - 980; spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); - spawn.mapRect(x + 2250, y - 950, 500, 25); //exit platform - spawn.mapRect(x + 2300, y - 1300, 25, 175); //exit side wall - + spawn.mapRect(x + 1550, y - 950, 500, 25); //exit platform + spawn.mapRect(x + 1600, y - 1300, 25, 175); //exit side wall spawn.bodyRect(x + 1275, y - 475, 125, 125, 0.25); - spawn.bodyRect(x + 1825, y - 125, 125, 125, 0.25); spawn.bodyRect(x + 500, y - 100, 125, 100, 0.25); spawn.bodyRect(x + 800, y - 150, 100, 150, 0.25); - spawn.bodyRect(x + 2375, y - 150, 125, 150, 0.25); + spawn.bodyRect(x + 875, y + -50, 50, 50); + spawn.bodyRect(x + 1025, y + -50, 50, 50); if (Math.random() > 0.5) { const density = 0.0012 + (simulation.difficultyMode < 3 ? 0.002 : 0) @@ -1255,13 +1216,11 @@ const level = { const variance = 0.2 //Math.PI const frictionAir = 0.012 const height = 35 - balance1 = level.spinner(x + 1150, y - 500, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) // spinner(x, y, width, height, density = 0.001, angle=0,frictionAir=0.001,angularVelocity=0) { - balance3 = level.spinner(x + 600, y - 600, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) - balance2 = level.spinner(x + 125, y - 850, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) - balance4 = level.spinner(x + 650, y - 1145, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) - balance5 = level.spinner(x + 1100, y - 1145, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) - balance6 = level.spinner(x + 1550, y - 1145, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) - balance7 = level.spinner(x + 2000, y - 1145, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) + balance1 = level.spinner(x + 1300, y - 450, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) // spinner(x, y, width, height, density = 0.001, angle=0,frictionAir=0.001,angularVelocity=0) { + balance3 = level.spinner(x + 750, y - 600, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) + balance2 = level.spinner(x + 300, y - 850, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) + balance4 = level.spinner(x + 850, y - 1100, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) + balance5 = level.spinner(x + 1300, y - 1145, height, 410, density, angle + variance * (Math.random() - 0.5), frictionAir) } else { const density = 0.001 + (simulation.difficultyMode < 3 ? 0.002 : 0) const angle = Math.PI / 2 @@ -1269,26 +1228,26 @@ const level = { const frictionAir = 0 const width = 200 const height = 200 - const angularVelocity = 0.01 - const spinVariance = 0.02 - - balance1 = level.spinner(x + 50, y - 350, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) // spinner(x, y, width, height, density = 0.001, angle=0,frictionAir=0.001,angularVelocity=0) { - balance4 = level.spinner(x + 350, y - 550, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - balance3 = level.spinner(x + 650, y - 700, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - balance5 = level.spinner(x + 950, y - 850, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - balance2 = level.spinner(x + 1250, y - 650, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - balance6 = level.spinner(x + 1600, y - 850, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - balance7 = level.spinner(x + 2000, y - 800, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) + const spinVariance = 0.05 + balance1 = level.spinner(x + 150, y - 300, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, spinVariance * (Math.random() - 0.5)) // spinner(x, y, width, height, density = 0.001, angle=0,frictionAir=0.001,angularVelocity=0) { + balance4 = level.spinner(x + 435, y - 525, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, spinVariance * (Math.random() - 0.5)) + balance3 = level.spinner(x + 735, y - 700, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, spinVariance * (Math.random() - 0.5)) + balance5 = level.spinner(x + 1040, y - 850, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, spinVariance * (Math.random() - 0.5)) + balance2 = level.spinner(x + 1380, y - 750, height, width, density, angle + variance * (Math.random() - 0.5), frictionAir, spinVariance * (Math.random() - 0.5)) } - spawn.randomMob(x + 1175, y - 725, 0.1); - spawn.randomMob(x + 1450, y - 725, 0.2); - spawn.randomMob(x + 425, y - 100, 0.3); - spawn.randomMob(x + 2300, y - 125, 0.4); - spawn.randomMob(x + 1300, y - 375, 0.5); + let isInRoom = false doCustom.push( () => { + if (!isInRoom && m.pos.x > x - 100 && m.pos.x < x + 2700 && m.pos.y > y - 1300 && m.pos.y < y) { //check if player is in this room and run code once + isInRoom = true + spawn.randomMob(x + 1175, y - 725, Infinity); + spawn.randomMob(x + 1450, y - 725, Infinity); + spawn.randomMob(x + 425, y - 100, Infinity); + spawn.randomMob(x + 1200, y - 125, Infinity); + spawn.randomMob(x + 1300, y - 375, Infinity); + } ctx.fillStyle = "#d4f4f4" - ctx.fillRect(x + 2300, y - 1300, 400, 350) + ctx.fillRect(x + 1600, y - 1300, 400, 350) } ) doCustomTopLayer.push( @@ -1304,100 +1263,624 @@ const level = { ctx.arc(balance4.pointA.x, balance4.pointA.y, 9, 0, 2 * Math.PI); ctx.moveTo(balance5.pointA.x, balance5.pointA.y) ctx.arc(balance5.pointA.x, balance5.pointA.y, 9, 0, 2 * Math.PI); - ctx.moveTo(balance6.pointA.x, balance6.pointA.y) - ctx.arc(balance6.pointA.x, balance6.pointA.y, 9, 0, 2 * Math.PI); - ctx.moveTo(balance7.pointA.x, balance7.pointA.y) - ctx.arc(balance7.pointA.x, balance7.pointA.y, 9, 0, 2 * Math.PI); ctx.fill(); } ) } ] - emptyOptions = [ //nothing good here - (x = offset.x, y = offset.y) => { - if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 1250, y - 600); + emptyOptions = [ //nothing good here except the starting power up, and duplicated bosses + (x = offset.x, y = offset.y) => { //pulse + if (!isDoorLeft && isDoorRight) { //flipped, entering from the right + powerUps.spawnStartingPowerUps(x + 2000 - 1650, y + -400); + spawn.mapRect(x + 2000 - 1575 - 25, y + -625, 25, 375); //wall on top of wall + spawn.mapRect(x + 2000 - 1575 - 25, y + -1325, 25, 525); //wall on top of wall + spawn.mapRect(x + 2000 - 1525 - 250, y + -350, 250, 450); //wall + spawn.mapRect(x + 2000 - 245 - 300, y + -200, 300, 100); //gun + spawn.mapRect(x + 2000 - 530 - 25, y + -190, 25, 80); //gun nose + const button = level.button(x + 2000 - 290 - 140, y - 200) + button.isReadyToFire = true + doCustom.push( + () => { + ctx.fillStyle = "rgba(0,0,0,0.05)"; //"rgba(0,0,0,0.1)"; + ctx.fillRect(x + 2000 - 255 - 280, y + -100, 280, 100); + button.query(); + button.draw(); + if (!button.isReadyToFire && button.isUp) { + button.isReadyToFire = true + } else if (button.isReadyToFire && !button.isUp) { + button.isReadyToFire = false + b.pulse(100, Math.PI, { x: x + 2000 - 560, y: y - 150 }) + } + } + ) + if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 2000 - 650, y + -875); + spawn.randomMob(x + 2000 - 1600, y + -425, Infinity); + spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity); + spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity); + spawn.randomMob(x + 2000 - 300, y + -1200, Infinity); + spawn.randomMob(x + 2000 - 800, y + -125, Infinity); + let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; + spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob + } else { + powerUps.spawnStartingPowerUps(x + 1650, y + -400); + spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall + spawn.mapRect(x + 1575, y + -1325, 25, 525); //wall on top of wall + spawn.mapRect(x + 1525, y + -350, 250, 450); //wall + spawn.mapRect(x + 245, y + -200, 300, 100); //gun + spawn.mapRect(x + 530, y + -190, 25, 80); //gun nose + const button = level.button(x + 290, y - 200) + button.isReadyToFire = true + + doCustom.push( + () => { + ctx.fillStyle = "rgba(0,0,0,0.05)"; //"rgba(0,0,0,0.1)"; + ctx.fillRect(x + 255, y + -100, 280, 100); + button.query(); + button.draw(); + if (!button.isReadyToFire && button.isUp) { + button.isReadyToFire = true + } else if (button.isReadyToFire && !button.isUp) { + button.isReadyToFire = false + b.pulse(100, 0, { x: x + 560, y: y - 150 }) + } + } + ) + if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875); + spawn.randomMob(x + 1600, y + -425, Infinity); + spawn.randomMob(x + 1725, y + -1250, Infinity); + spawn.randomMob(x + 1250, y + -1200, Infinity); + spawn.randomMob(x + 300, y + -1200, Infinity); + spawn.randomMob(x + 800, y + -125, Infinity); + let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; + spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob + } + }, + (x = offset.x, y = offset.y) => { //spawn block and fire it + if (!isDoorLeft && isDoorRight) { + powerUps.spawnStartingPowerUps(x + 1650, y + -400); + spawn.mapRect(x + 2000 - 1575 - 25, y + -625, 25, 375); //wall on top of wall + spawn.mapRect(x + 2000 - 1575 - 25, y + -1325, 25, 525); //wall on top of wall + spawn.mapRect(x + 2000 - 1525 - 250, y + -350, 250, 450); //wall + spawn.mapRect(x + 2000 - 245 - 300, y + -200, 300, 100); //gun + spawn.mapRect(x + 2000 - 530 - 25, y + -190, 25, 80); + const button = level.button(x + 2000 - 290 - 140, y - 200) + button.isReadyToFire = true + doCustom.push( + () => { + ctx.fillStyle = "rgba(0,0,0,0.05)"; //"rgba(0,0,0,0.1)"; + ctx.fillRect(x + 2000 - 255 - 280, y + -100, 280, 100); + button.query(); + button.draw(); + if (!button.isReadyToFire && button.isUp) { + button.isReadyToFire = true + } else if (button.isReadyToFire && !button.isUp) { + button.isReadyToFire = false + fireBlock = function(xPos, yPos) { + const index = body.length + spawn.bodyRect(xPos, yPos, 35 + 50 * Math.random(), 35 + 50 * Math.random()); + const bodyBullet = body[body.length - 1] + Matter.Body.setVelocity(body[index], { + x: -120, + y: -5 + }); + body[index].collisionFilter.category = cat.body; + body[index].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + body[index].classType = "body"; + World.add(engine.world, body[index]); //add to world + setTimeout(() => { //remove block + for (let i = 0; i < body.length; i++) { + if (body[i] === bodyBullet) { + Matter.World.remove(engine.world, body[i]); + body.splice(i, 1); + } + } + }, 1000); + } + fireBlock(x + 2000 - 90 - 560 + 30 * Math.random(), y - 140); + fireBlock(x + 2000 - 90 - 560 + 30 * Math.random(), y - 160); + fireBlock(x + 2000 - 90 - 560 + 30 * Math.random(), y - 180); + fireBlock(x + 2000 - 90 - 560 + 30 * Math.random(), y - 200); + fireBlock(x + 2000 - 90 - 560 + 30 * Math.random(), y - 220); + fireBlock(x + 2000 - 90 - 560 + 30 * Math.random(), y - 240); + } + } + ) + if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875); + spawn.randomMob(x + 2000 - 1600, y + -425, Infinity); + spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity); + spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity); + spawn.randomMob(x + 2000 - 300, y + -1200, Infinity); + spawn.randomMob(x + 2000 - 800, y + -125, Infinity); + let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; + spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob + } else { + powerUps.spawnStartingPowerUps(x + 1650, y + -400); + spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall + spawn.mapRect(x + 1575, y + -1325, 25, 525); //wall on top of wall + spawn.mapRect(x + 1525, y + -350, 250, 450); //wall + spawn.mapRect(x + 245, y + -200, 300, 100); //gun + spawn.mapRect(x + 530, y + -190, 25, 80); + const button = level.button(x + 290, y - 200) + button.isReadyToFire = true + doCustom.push( + () => { + ctx.fillStyle = "rgba(0,0,0,0.05)"; //"rgba(0,0,0,0.1)"; + ctx.fillRect(x + 255, y + -100, 280, 100); + button.query(); + button.draw(); + if (!button.isReadyToFire && button.isUp) { + button.isReadyToFire = true + } else if (button.isReadyToFire && !button.isUp) { + button.isReadyToFire = false + fireBlock = function(xPos, yPos) { + const index = body.length + spawn.bodyRect(xPos, yPos, 35 + 50 * Math.random(), 35 + 50 * Math.random()); + const bodyBullet = body[body.length - 1] + Matter.Body.setVelocity(body[index], { + x: 120, + y: -5 + }); + body[index].collisionFilter.category = cat.body; + body[index].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + body[index].classType = "body"; + World.add(engine.world, body[index]); //add to world + setTimeout(() => { //remove block + for (let i = 0; i < body.length; i++) { + if (body[i] === bodyBullet) { + Matter.World.remove(engine.world, body[i]); + body.splice(i, 1); + } + } + }, 1000); + } + fireBlock(x + 560 + 30 * Math.random(), y - 140); + fireBlock(x + 560 + 30 * Math.random(), y - 160); + fireBlock(x + 560 + 30 * Math.random(), y - 180); + fireBlock(x + 560 + 30 * Math.random(), y - 200); + fireBlock(x + 560 + 30 * Math.random(), y - 220); + fireBlock(x + 560 + 30 * Math.random(), y - 240); + } + } + ) + if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875); + spawn.randomMob(x + 1600, y + -425, Infinity); + spawn.randomMob(x + 1725, y + -1250, Infinity); + spawn.randomMob(x + 1250, y + -1200, Infinity); + spawn.randomMob(x + 300, y + -1200, Infinity); + spawn.randomMob(x + 800, y + -125, Infinity); + let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; + spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob + } + }, + (x = offset.x, y = offset.y) => { //fire an "ammo clip" of blocks + if (!isDoorLeft && isDoorRight) { //flipped, entering from the right + powerUps.spawnStartingPowerUps(x + 2000 - 1650, y + -400); + spawn.mapRect(x + 2000 - 1575 - 25, y + -625, 25, 375); //wall on top of wall + spawn.mapRect(x + 2000 - 1575 - 25, y + -1325, 25, 525); //wall on top of wall + spawn.mapRect(x + 2000 - 1525 - 250, y + -350, 250, 450); //wall + spawn.mapRect(x + 2000 - 175 - 370, y + -200, 370, 100); //gun + spawn.mapRect(x + 2000 - 530 - 25, y + -190, 25, 80); + spawn.mapRect(x + 2000 - 545 - 10, y + -770, 10, 325); //block loader for gun //walls + spawn.mapRect(x + 2000 - 620 - 10, y + -770, 10, 325); //walls + spawn.mapRect(x + 2000 + 50 - 150, y + -425, 150, 50); + spawn.mapRect(x + 2000 - 175 - 370, y + -650, 370, 50); + spawn.mapRect(x + 2000 - 540 - 95, y + -460, 95, 15); //bottom that opens and closes + const bulletDoor = map[map.length - 1] //keep track of this body so it can be make non-collide later + for (let i = 0; i < 6; i++) spawn.bodyRect(x + 2000 - 60 - 555 + Math.floor(Math.random() * 10), y + -520 - 50 * i, 50, 50); //bullets for gun + spawn.bodyRect(x + 2000 - 250 - 40, y + -700, 40, 50); //extra bullets + spawn.bodyRect(x + 2000 - 350 - 30, y + -700, 30, 35); + spawn.bodyRect(x + 2000 - 425 - 40, y + -700, 40, 70); + const button = level.button(x + 2000 - 280 - 140, y - 200) //trigger for gun + button.isReadyToFire = true + doCustom.push( + () => { + ctx.fillStyle = "rgba(0,0,0,0.05)"; //"rgba(0,0,0,0.1)"; + ctx.fillRect(x + 2000 - 200 - 325, y + -625, 325, 650); + button.query(); + button.draw(); + if (!button.isReadyToFire && button.isUp) { + button.isReadyToFire = true + bulletDoor.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + } else if (button.isReadyToFire && !button.isUp) { + button.isReadyToFire = false + bulletDoor.collisionFilter.mask = 0 //cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + } else if (!button.isUp) { + const bounds = { + min: { + x: x + 2000 - 580, + y: y - 125 + }, + max: { + x: x + 2000 - 530, + y: y - 110 + } + } + const list = Matter.Query.region(body, bounds) + for (let i = 0, len = list.length; i < len; i++) { + Matter.Body.setVelocity(list[i], { + x: -120, + y: -5 + }); + } + if (Matter.Query.region([player], bounds).length) { + Matter.Body.setVelocity(player, { + x: -100, + y: -5 + }); + } + ctx.fillStyle = `rgba(255,0,255,${0.2+0.7*Math.random()})` + ctx.fillRect(bounds.min.x, y - 185, 38, 70); + } + } + ) + if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875); + spawn.randomMob(x + 2000 - 1600, y + -425, Infinity); + spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity); + spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity); + spawn.randomMob(x + 2000 - 300, y + -1200, Infinity); + spawn.randomMob(x + 2000 - 800, y + -125, Infinity); + let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; + spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob + } else { + powerUps.spawnStartingPowerUps(x + 1650, y + -400); + spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall + spawn.mapRect(x + 1575, y + -1325, 25, 525); //wall on top of wall + spawn.mapRect(x + 1525, y + -350, 250, 450); //wall + spawn.mapRect(x + 175, y + -200, 370, 100); //gun + spawn.mapRect(x + 530, y + -190, 25, 80); + spawn.mapRect(x + 545, y + -770, 10, 325); //block loader for gun //walls + spawn.mapRect(x + 620, y + -770, 10, 325); //walls + spawn.mapRect(x - 50, y + -425, 150, 50); + spawn.mapRect(x + 175, y + -650, 370, 50); + spawn.mapRect(x + 540, y + -460, 95, 15); //bottom that opens and closes + const bulletDoor = map[map.length - 1] //keep track of this body so it can be make non-collide later + for (let i = 0; i < 6; i++) spawn.bodyRect(x + 555 + Math.floor(Math.random() * 10), y + -520 - 50 * i, 50, 50); //bullets for gun + spawn.bodyRect(x + 250, y + -700, 40, 50); //extra bullets + spawn.bodyRect(x + 350, y + -700, 30, 35); + spawn.bodyRect(x + 425, y + -700, 40, 70); + const button = level.button(x + 280, y - 200) //trigger for gun + button.isReadyToFire = true + doCustom.push( + () => { + ctx.fillStyle = "rgba(0,0,0,0.05)"; //"rgba(0,0,0,0.1)"; + ctx.fillRect(x + 200, y + -625, 325, 650); + button.query(); + button.draw(); + if (!button.isReadyToFire && button.isUp) { + button.isReadyToFire = true + bulletDoor.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + } else if (button.isReadyToFire && !button.isUp) { + button.isReadyToFire = false + bulletDoor.collisionFilter.mask = 0 //cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + } else if (!button.isUp) { + const bounds = { + min: { + x: x + 530, + y: y - 125 + }, + max: { + x: x + 580, + y: y - 110 + } + } + const list = Matter.Query.region(body, bounds) + for (let i = 0, len = list.length; i < len; i++) { + Matter.Body.setVelocity(list[i], { + x: 120, + y: -5 + }); + } + if (Matter.Query.region([player], bounds).length) { + Matter.Body.setVelocity(player, { + x: 100, + y: -5 + }); + } + ctx.fillStyle = `rgba(255,0,255,${0.2+0.7*Math.random()})` + ctx.fillRect(bounds.min.x, y - 185, 38, 70); + } + } + ) + if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875); + spawn.randomMob(x + 1600, y + -425, Infinity); + spawn.randomMob(x + 1725, y + -1250, Infinity); + spawn.randomMob(x + 1250, y + -1200, Infinity); + spawn.randomMob(x + 300, y + -1200, Infinity); + spawn.randomMob(x + 800, y + -125, Infinity); + let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; + spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob + } } ] lootOptions = [ //has some power up reward //field, ammo, research, gun (x = offset.x, y = offset.y) => { - powerUps.spawnStartingPowerUps(x + 1250, y - 100); + spawn.mapRect(x + 1925, y + -325, 125, 150); //4 wall ledges + spawn.mapRect(x + 1925, y + -865, 125, 150); //4 wall ledges + spawn.mapRect(x + -50, y + -325, 125, 150); //4 wall ledges + spawn.mapRect(x + -50, y + -865, 125, 150); //4 wall ledges + spawn.mapRect(x + 1700, y + -500, 200, 25); + spawn.mapRect(x + 75, y + -500, 200, 25); + + let chamberY = -650 + if (Math.random() > 0.5) { //upper chamber + chamberY = -650 - 640 + spawn.mapRect(x + 550, y + -10 - 640, 900, 25); //raised floor + spawn.mapRect(x + 450, y + -20 - 640, 1100, 25); + spawn.mapRect(x + 450, y + -675 - 640, 1100, 25); //chamber ceiling + powerUps.spawn(x + 998, y - 333 - 640, "tech", false); + spawn.mapVertex(x + 1000, y + -0, "575 0 -575 0 -450 -100 450 -100"); //base + } else { //lower chamber + spawn.mapRect(x + 400, y + -10, 1200, 50); //raised floor + spawn.mapRect(x + 450, y + -20, 1100, 50); + spawn.mapRect(x + 450, y + -675, 1100, 25); //chamber ceiling + spawn.mapRect(x + 550, y + -685, 900, 25); + powerUps.spawn(x + 998, y - 333, "tech", false); + } + const powerUp1 = powerUp[powerUp.length - 1] + powerUp1.holdPosition = { x: powerUp1.position.x, y: powerUp1.position.y } + let isSpawnedMobs = false + doCustom.push( + () => { + ctx.fillStyle = "#e4e4e9" //"rgba(255,255,255,1)"; + ctx.fillRect(x + 450, y + chamberY, 1100, 650); //chamber background + // if (!isInRoom && m.pos.x > x - 100 && m.pos.x < x + 2000 && m.pos.y > y - 1300 && m.pos.y < y) { //is player inside this room? + // isInRoom = true + // } else + if (powerUp1.velocity.y !== 0) { //don't run this code if power up is gone //hack: powerUp1.velocity.y !== 0 seems to only be true if the power up up doesn't exist and is no longer being affected by gravity + ctx.strokeStyle = "#f0f" + ctx.lineWidth = 2; + if (Vector.magnitudeSquared(Vector.sub(m.pos, powerUp1.position)) < 90000) { //zone radius is 300 + //damage player and drain energy + if (m.immuneCycle < m.cycle) m.damage(0.01); + if (m.energy > 0.1) m.energy -= 0.02 + //draw electricity going towards player + const unit = Vector.normalise(Vector.sub(m.pos, powerUp1.position)) + let xElec = powerUp1.position.x + 40 * unit.x; + let yElec = powerUp1.position.y + 40 * unit.y; + ctx.beginPath(); + ctx.moveTo(xElec, yElec); + const step = 40 + for (let i = 0; i < 6; i++) { + xElec += step * (unit.x + 1.5 * (Math.random() - 0.5)) + yElec += step * (unit.y + 1.5 * (Math.random() - 0.5)) + ctx.lineTo(xElec, yElec); + } + } else { + //draw electricity going in random directions + const angle = Math.random() * 2 * Math.PI + const Dx = Math.cos(angle); + const Dy = Math.sin(angle); + let xElec = powerUp1.position.x + 40 * Dx; + let yElec = powerUp1.position.y + 40 * Dy; + ctx.beginPath(); + ctx.moveTo(xElec, yElec); + const step = 40 + for (let i = 0; i < 6; i++) { + xElec += step * (Dx + 1.5 * (Math.random() - 0.5)) + yElec += step * (Dy + 1.5 * (Math.random() - 0.5)) + ctx.lineTo(xElec, yElec); + } + } + ctx.lineWidth = 2 * Math.random(); + ctx.stroke(); //draw electricity + + ctx.beginPath(); //outline damage zone + ctx.arc(powerUp1.position.x, powerUp1.position.y, 300, 0, 2 * Math.PI); + ctx.stroke(); + //float power up in the air + Matter.Body.setPosition(powerUp1, { + x: powerUp1.holdPosition.x + 4 * Math.random(), //1300 -2 + y: powerUp1.holdPosition.y + 4 * Math.random() //335 -2 + }); + Matter.Body.setVelocity(powerUp1, { + x: 0, + y: 0 + }); + } else if (!isSpawnedMobs) { + isSpawnedMobs = true + if (chamberY === -650) { //lower chamber + spawn.randomGroup(x + 275, y + -1050, Infinity); + spawn.randomGroup(x + 675, y + -975, Infinity); + spawn.randomGroup(x + 1225, y + -975, Infinity); + spawn.randomMob(x + 250, y + -650, Infinity); + spawn.randomMob(x + 1825, y + -600, Infinity); + } else { //upper chamber + spawn.randomGroup(x + 300, y + -300, Infinity); + spawn.randomGroup(x + 650, y + -275, Infinity); + spawn.randomGroup(x + 1125, y + -300, Infinity); + spawn.randomMob(x + 250, y + -650, Infinity); + spawn.randomMob(x + 1800, y + -625, Infinity); + } + } + } + ) } ] upDownOptions = [ //extra tall vertical section 3000x3000 //this is where the level boss is (x = offset.x, y = offset.y) => { - const elevator1 = level.elevator(x + 1100, y - 200, 250, 30, -2100, 0.0015) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }, isTeleport = false) { - const toggle = level.toggle(650, 0, false, true) // toggle(x, y, isOn = false, isLockOn = false) { + const toggle = level.toggle(x + 950, y + 0, false, true) // toggle(x, y, isOn = false, isLockOn = false) { toggle.isAddedElements = false - + spawn.mapVertex(x + 5, y + -1318, "0 0 0 -250 125 -250"); //left ledges + spawn.mapVertex(x + 1995, y + -1318, "0 0 0 -250 -125 -250"); // right ledges doCustomTopLayer.push( () => { - elevator1.move() toggle.query(); - if (toggle.isOn && !toggle.isAddedElements) { + if (toggle.isOn && !toggle.isAddedElements) { //this code runs once after the toggle is triggered toggle.isAddedElements = true //only do this once + addMapToLevelInProgress = (who) => { //adds new map elements to the level while the level is already running //don't forget to run simulation.draw.setPaths() after you all the the elements so they show up visually + who.collisionFilter.category = cat.map; + who.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet; + Matter.Body.setStatic(who, true); //make static + World.add(engine.world, who); //add to world + } + let r = 150 + let hexagon = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 ${r*Math.cos(2.0944)} ${r*Math.sin(2.0944)} ${r*Math.cos(1.0472)} ${r*Math.sin(1.0472)} ` + //450 horizontal spread // -130-130-130 = 390 vertical + if (Math.random() < 0.5) { + spawn.mapVertex(x + 775, y + -260, hexagon); + spawn.mapVertex(x + 1225, y + -260, hexagon); - // if (simulation.difficulty > 3) - spawn.randomLevelBoss(x + 1250, y - 1400); + spawn.mapVertex(x + 550, y + -650, hexagon); + spawn.mapVertex(x + 1000, y + -650, hexagon); + spawn.mapVertex(x + 1450, y + -650, hexagon); - spawn.mapRect(1375, -1400, 1375, 1225); - len = map.length - 1 - map[len].collisionFilter.category = cat.map; - map[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet; - Matter.Body.setStatic(map[len], true); //make static - World.add(engine.world, map[len]); //add to world + spawn.mapVertex(x + 325, y + -1040, hexagon); + spawn.mapVertex(x + 775, y + -1040, hexagon); + spawn.mapVertex(x + 1225, y + -1040, hexagon); + spawn.mapVertex(x + 1675, y + -1040, hexagon); - // spawn.mapRect(1800, -1825, 725, 1550); - spawn.mapRect(-175, -1400, 1250, 1225); - len = map.length - 1 - map[len].collisionFilter.category = cat.map; - map[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet; - Matter.Body.setStatic(map[len], true); //make static - World.add(engine.world, map[len]); //add to world + spawn.mapVertex(x + 550, y + -1430, hexagon); + spawn.mapVertex(x + 1000, y + -1430, hexagon); + spawn.mapVertex(x + 1450, y + -1430, hexagon); - //see map in world + const numberOfMapElementsAdded = 12 + for (let i = 0; i < numberOfMapElementsAdded; i++) addMapToLevelInProgress(map[map.length - 1 - i]) + spawn.randomMob(x + 225, y + -1775, Infinity); + spawn.randomMob(x + 700, y + -1750, Infinity); + spawn.randomMob(x + 1175, y + -1725, Infinity); + spawn.randomMob(x + 1700, y + -1700, Infinity); + spawn.randomMob(x + 1750, y + -250, Infinity); + spawn.randomMob(x + 125, y + -250, Infinity); + } else { + spawn.mapVertex(x + 775, y + -260, hexagon); + spawn.mapVertex(x + 1225, y + -260, hexagon); + + spawn.mapVertex(x + 550, y + -650, hexagon); + spawn.mapVertex(x + 1000, y + -650, hexagon); + spawn.mapVertex(x + 1450, y + -650, hexagon); + + spawn.mapVertex(x + 775, y + -1040, hexagon); + spawn.mapVertex(x + 1225, y + -1040, hexagon); + + spawn.mapVertex(x + 550, y + -1430, hexagon); + spawn.mapVertex(x + 1000, y + -1430, hexagon); + spawn.mapVertex(x + 1450, y + -1430, hexagon); + + spawn.mapVertex(x + 775, y + -1820, hexagon); + spawn.mapVertex(x + 1225, y + -1820, hexagon); + const numberOfMapElementsAdded = 12 + for (let i = 0; i < numberOfMapElementsAdded; i++) addMapToLevelInProgress(map[map.length - 1 - i]) + + spawn.randomMob(x + 225, y + -1025, Infinity); + spawn.randomMob(x + 200, y + -675, Infinity); + spawn.randomMob(x + 225, y + -200, Infinity); + spawn.randomMob(x + 1750, y + -1075, Infinity); + spawn.randomMob(x + 1700, y + -650, Infinity); + spawn.randomMob(x + 1675, y + -175, Infinity); + } simulation.draw.setPaths() //update map graphics + spawn.randomGroup(x + 300, y + -2200); + spawn.randomGroup(x + 1625, y + -2200); + spawn.randomLevelBoss(x + 950, y + -2200); } } ) }, (x = offset.x, y = offset.y) => { - const elevator1 = level.elevator(x + 1100, y - 200, 250, 30, -2100, 0.0015) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }, isTeleport = false) { - // const elevator1 = level.elevator(x + 175, y - 200, 250, 30, -1400, 0.001) - // const elevator2 = level.elevator(x + 2175, y - 200, 250, 30, -1400, 0.001) + const toggle = level.toggle(x + 950, y + 0, false, true) // toggle(x, y, isOn = false, isLockOn = false) { + toggle.isAddedElements = false - spawn.mapRect(-200, -1400, 350, 50); //up left door ledge - spawn.mapRect(2450, -1400, 350, 50); //up right door ledge + //left ledges + spawn.mapVertex(x + 5, y + -1868, "0 0 0 -250 125 -250"); + spawn.mapVertex(x + 5, y + -1318, "0 0 0 -250 125 -250"); //door + spawn.mapVertex(x + 5, y + -768, "0 0 0 -250 125 -250"); + // right ledges + spawn.mapVertex(x + 2000, y + -1868, "0 0 0 -250 -125 -250"); + spawn.mapVertex(x + 2000, y + -1318, "0 0 0 -250 -125 -250"); //door + spawn.mapVertex(x + 2000, y + -768, "0 0 0 -250 -125 -250"); - spawn.mapRect(225, -450, 350, 350); //left crawl zone - // spawn.mapRect(725, -175, 275, 75); - spawn.mapRect(725, -225, 350, 100); - spawn.mapRect(275, -750, 200, 200); - spawn.mapRect(1375, -700, 500, 750); //right side big elevator wall - spawn.mapRect(2375, -325, 350, 50); - spawn.mapRect(1800, -500, 250, 50); - - //up high elevator - spawn.mapRect(1375, -2100, 500, 175); - spawn.mapRect(600, -2100, 475, 175); - - if (simulation.difficulty > 3) spawn.randomLevelBoss(x + 1250, y - 1400); doCustomTopLayer.push( () => { - elevator1.move() + toggle.query(); + if (toggle.isOn && !toggle.isAddedElements) { //this code runs once after the toggle is triggered + toggle.isAddedElements = true //only do this once + addMapToLevelInProgress = (who) => { //adds new map elements to the level while the level is already running //don't forget to run simulation.draw.setPaths() after you all the the elements so they show up visually + who.collisionFilter.category = cat.map; + who.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet; + Matter.Body.setStatic(who, true); //make static + World.add(engine.world, who); //add to world + } + //right side hexagons + let r = 300 + let hexagon = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 ${r*Math.cos(2.0944)} ${r*Math.sin(2.0944)} ${r*Math.cos(1.0472)} ${r*Math.sin(1.0472)} ` + spawn.mapVertex(x + 1640, y + -365, hexagon); + // r = 275 + // let hexagonHalf = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 ` + // spawn.mapVertex(x + 2300, y + -75, hexagonHalf); + r = 150 + const hexagon150 = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 ${r*Math.cos(2.0944)} ${r*Math.sin(2.0944)} ${r*Math.cos(1.0472)} ${r*Math.sin(1.0472)} ` + // spawn.mapVertex(x + 1750, y + -550, hexagon150); + spawn.mapVertex(x + 1750, y + -1100, hexagon150); + spawn.mapVertex(x + 1750, y + -1650, hexagon150); + spawn.mapVertex(x + 1750, y + -2200, hexagon150); + + //left side + r = 350 + let hexagonHalf = `${r} 0 ${r*Math.cos(5.236)} ${r*Math.sin(5.236)} ${r*Math.cos(4.189)} ${r*Math.sin(4.189)} ${-r} 0 ` + spawn.mapVertex(x + 425, y + -90, hexagonHalf); + + spawn.mapVertex(x + 850, y + -500, hexagon150); + spawn.mapVertex(x + 550, y + -850, hexagon150); + spawn.mapVertex(x + 250, y + -1200, hexagon150); + spawn.mapVertex(x + 250, y + -1700, hexagon150); + spawn.mapVertex(x + 725, y + -1950, hexagon150); + spawn.mapVertex(x + 1200, y + -2200, hexagon150); + const numberOfMapElementsAdded = 13 + for (let i = 0; i < numberOfMapElementsAdded; i++) addMapToLevelInProgress(map[map.length - 1 - i]) + + spawn.randomMob(x + 1075, y + -1500, Infinity); + spawn.randomMob(x + 325, y + -550, Infinity); + spawn.randomMob(x + 800, y + -925, Infinity); + spawn.randomMob(x + 1400, y + -1250, Infinity); + spawn.randomMob(x + 1350, y + -1725, Infinity); + spawn.randomMob(x + 575, y + -1375, Infinity); + spawn.randomMob(x + 225, y + -2275, Infinity); + spawn.randomMob(x + 875, y + -2450, Infinity); + spawn.randomMob(x + 1550, y + -2525, Infinity); + if (simulation.difficulty > 3) spawn.randomLevelBoss(x + 1075, y + -1500); + simulation.draw.setPaths() //update map graphics + } } ) - } + }, + // (x = offset.x, y = offset.y) => { + // const elevator1 = level.elevator(x + 1100, y - 200, 250, 30, -2100, 0.0015) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }, isTeleport = false) { + // // const elevator1 = level.elevator(x + 175, y - 200, 250, 30, -1400, 0.001) + // // const elevator2 = level.elevator(x + 2175, y - 200, 250, 30, -1400, 0.001) + + // spawn.mapRect(-200, -1400, 350, 50); //up left door ledge + // spawn.mapRect(2450, -1400, 350, 50); //up right door ledge + + // spawn.mapRect(225, -450, 350, 350); //left crawl zone + // // spawn.mapRect(725, -175, 275, 75); + // spawn.mapRect(725, -225, 350, 100); + // spawn.mapRect(275, -750, 200, 200); + // spawn.mapRect(1375, -700, 500, 750); //right side big elevator wall + // spawn.mapRect(2375, -325, 350, 50); + // spawn.mapRect(1800, -500, 250, 50); + + // //up high elevator + // spawn.mapRect(1375, -2100, 500, 175); + // spawn.mapRect(600, -2100, 475, 175); + + // if (simulation.difficulty > 3) spawn.randomLevelBoss(x + 1250, y - 1400); + // doCustomTopLayer.push( + // () => { + // elevator1.move() + // } + // ) + // } ] //pick which type of room spawns enter = enterOptions[Math.floor(Math.random() * enterOptions.length)]; exit = exitOptions[Math.floor(Math.random() * exitOptions.length)]; empty = emptyOptions[Math.floor(Math.random() * emptyOptions.length)]; loot = lootOptions[Math.floor(Math.random() * lootOptions.length)]; - // upDown = upDownOptions[Math.floor(Math.random() * upDownOptions.length)]; - upDown = upDownOptions[0] //********************************* DO !NOT! RUN THIS LINE IN THE FINAL VERSION *************************************** + upDown = upDownOptions[Math.floor(Math.random() * upDownOptions.length)]; + // empty = emptyOptions[2] //controls what level spawns for map designing building //********************************* DO !NOT! RUN THIS LINE IN THE FINAL VERSION *************************************** //3x2: 4 short rooms (3000x1500), 1 double tall room (3000x3000) //rooms - let rooms = ["enter", "empty", "loot", "exit"] + let rooms = ["loot", "enter", "empty", "exit"] rooms = shuffle(rooms); //shuffles array order //look... you and I both know there is a better way to do this, but it works so I'm gonna focus on other things while ( //makes sure that the exit and entrance aren't both on the same floor @@ -1412,38 +1895,38 @@ const level = { if (rooms[i] === "empty") rooms[i] = empty if (rooms[i] === "loot") rooms[i] = loot } - rooms = [empty, loot, exit, enter, ] //controls what level spawns for map designing building //********************************* DO !NOT! RUN THIS LINE IN THE FINAL VERSION *************************************** + // rooms = [enter, exit, loot, empty, ] //controls what level spawns for map designing building //********************************* DO !NOT! RUN THIS LINE IN THE FINAL VERSION *************************************** - outlineDoors = () => { - spawn.mapRect(offset.x - 200, offset.y, 3000, 100); //floor - spawn.mapRect(offset.x - 200, offset.y - 1400, 3000, 100); //ceiling - if (!isDoorLeft) spawn.mapRect(offset.x - 200, offset.y - 1400, 100, 1500); //left wall + outline = (isLower = true) => { + spawn.mapRect(offset.x - 100, offset.y - 1400, 2100, 100); //ceiling + if (isLower) spawn.mapRect(offset.x - 100, offset.y, 2200, 100); //only draw floor if on the lower level + if (!isDoorLeft) spawn.mapRect(offset.x - 100, offset.y - 1400, 100, 1500); //left wall if (isDoorRight) { //if door only add wall on right side - spawn.mapRect(offset.x + 2700, offset.y - 1400, 100, 1225); //right wall - spawn.mapRect(offset.x + 2700, offset.y - 10, 100, 20); //right doorstep + spawn.mapRect(offset.x + 2000, offset.y - 1400, 100, 1225); //right wall + spawn.mapRect(offset.x + 2000, offset.y - 10, 100, 20); //right doorstep const doorWidth = 15 + Math.floor(100 * Math.random() * Math.random()) - spawn.bodyRect(offset.x + 2750 - doorWidth / 2, offset.y - 175, doorWidth, 165); //block door + spawn.bodyRect(offset.x + 2050 - doorWidth / 2, offset.y - 175, doorWidth, 165); //block door } else { - spawn.mapRect(offset.x + 2700, offset.y - 1400, 100, 1500); //right wall + spawn.mapRect(offset.x + 2000, offset.y - 1400, 100, 1500); //right wall } } outlineUpDown = () => { - spawn.mapRect(offset.x - 200, offset.y + 0, 3000, 100); //floor - spawn.mapRect(offset.x - 200, offset.y - 2800, 3000, 100); //ceiling - if (!isDoorLeft) spawn.mapRect(offset.x - 200, offset.y - 2800, 100, 2800); //left wall + spawn.mapRect(offset.x - 100, offset.y + 0, 2100, 100); //floor + spawn.mapRect(offset.x - 100, offset.y - 2800, 2100, 100); //ceiling + if (!isDoorLeft) spawn.mapRect(offset.x - 100, offset.y - 2800, 100, 2900); //left wall if (isDoorRight) { //if door only add wall on right side //upper door - spawn.mapRect(offset.x + 2700, offset.y - 2800, 100, 1225); //right wall - spawn.mapRect(offset.x + 2700, offset.y - 1410, 100, 20); //right doorstep + spawn.mapRect(offset.x + 2000, offset.y - 2800, 100, 1225); //right wall + spawn.mapRect(offset.x + 2000, offset.y - 1410, 100, 20); //right doorstep const doorWidth = 15 + Math.floor(100 * Math.random() * Math.random()) - spawn.bodyRect(offset.x + 2750 - doorWidth / 2, offset.y - 1225, doorWidth, 165); //block door + spawn.bodyRect(offset.x + 2050 - doorWidth / 2, offset.y - 1575, doorWidth, 165); //block door //lower door - spawn.mapRect(offset.x + 2700, offset.y - 1400, 100, 1225); //right wall - spawn.mapRect(offset.x + 2700, offset.y - 10, 100, 20); //right doorstep + spawn.mapRect(offset.x + 2000, offset.y - 1400, 100, 1225); //right wall + spawn.mapRect(offset.x + 2000, offset.y - 10, 100, 20); //right doorstep const doorWidth2 = 15 + Math.floor(100 * Math.random() * Math.random()) - spawn.bodyRect(offset.x + 2750 - doorWidth2 / 2, offset.y - 175, doorWidth2, 165); //block door + spawn.bodyRect(offset.x + 2050 - doorWidth2 / 2, offset.y - 175, doorWidth2, 165); //block door } else { - spawn.mapRect(offset.x + 2700, offset.y - 2800, 100, 2800); //right wall + spawn.mapRect(offset.x + 2000, offset.y - 2800, 100, 2800); //right wall } } @@ -1455,26 +1938,24 @@ const level = { }, () => { offset.y = 0 - outlineDoors() + outline() rooms[0]() offset.y = -1400 - outlineDoors() + outline(false) rooms[1]() }, () => { offset.y = 0 - outlineDoors() + outline() rooms[2]() offset.y = -1400 - outlineDoors() + outline(false) rooms[3]() - } + }, ] - - // rows = shuffle(rows) //********************************* RUN THIS LINE IN THE FINAL VERSION *************************************** - + rows = shuffle(rows) //********************************* RUN THIS LINE IN THE FINAL VERSION *************************************** for (let i = 0; i < 3; i++) { if (i === 0) { isDoorLeft = false @@ -1486,7 +1967,7 @@ const level = { isDoorLeft = true isDoorRight = false } - offset.x = i * 2900 + offset.x = i * 2100 rows[i]() } level.custom = () => { @@ -1500,7 +1981,7 @@ const level = { }; powerUps.addResearchToLevel() //needs to run after mobs are spawned - level.setPosToSpawn(200, -100); //********************************* DO !NOT! RUN THIS LINE IN THE FINAL VERSION *************************************** + // level.setPosToSpawn(850, -40); //********************************* DO !NOT! RUN THIS LINE IN THE FINAL VERSION *************************************** }, null() { level.levels.pop(); //remove lore level from rotation diff --git a/js/mob.js b/js/mob.js index b7d6eb6..7d4d598 100644 --- a/js/mob.js +++ b/js/mob.js @@ -1172,7 +1172,7 @@ const mobs = { //replace dead mob with a regular body replace(i) { //if there are too many bodies don't turn into blocks to help performance - if (this.leaveBody && body.length < 60 && this.mass < 200 && this.radius > 18) { + if (this.leaveBody && body.length < 40 && this.mass < 200 && this.radius > 18) { const len = body.length; const v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure body[len] = Matter.Bodies.fromVertices(this.position.x, this.position.y, v); diff --git a/js/simulation.js b/js/simulation.js index 522c074..247c044 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -526,6 +526,7 @@ const simulation = { level.levels = shuffle(level.levels); //shuffles order of maps } level.levels.unshift("intro"); //add level to the start of the randomized levels list + level.levels.push("labs"); //add level to the end of the randomized levels list level.levels.push("gauntlet"); //add level to the end of the randomized levels list level.levels.push("final"); //add level to the end of the randomized levels list @@ -595,6 +596,7 @@ const simulation = { m.holdingTarget = null //set to default field + tech.healMaxEnergyBonus = 0 m.setMaxEnergy(); m.fieldMode = 0; // simulation.makeTextLog(`${simulation.SVGrightMouse} ${m.fieldUpgrades[m.fieldMode].name}

${m.fieldUpgrades[m.fieldMode].description}`, 600); @@ -1125,6 +1127,7 @@ const simulation = { } }, enableConstructMode() { + level.isProcedural = false //this is set to be true in levels like labs that need x+ and y+ in front of positions simulation.isConstructionMode = true; simulation.isHorizontalFlipped = false; simulation.isAutoZoom = false; @@ -1143,11 +1146,20 @@ const simulation = { const dy = Math.max(25, round(simulation.mouseInGame.y) - y) if (e.which === 2) { - simulation.outputMapString(`spawn.randomMob(${x}, ${y},0.5);`); + if (level.isProcedural) { + simulation.outputMapString(`spawn.randomMob(x+${x}, y+${y},0.5);`); + } else { + simulation.outputMapString(`spawn.randomMob(${x}, ${y},0.5);`); + } + } else if (simulation.mouseInGame.x > simulation.constructMouseDownPosition.x && simulation.mouseInGame.y > simulation.constructMouseDownPosition.y) { //make sure that the width and height are positive if (e.which === 1) { //add map - simulation.outputMapString(`spawn.mapRect(${x}, ${y}, ${dx}, ${dy});`); + if (level.isProcedural) { + simulation.outputMapString(`spawn.mapRect(x+${x}, y+${y}, ${dx}, ${dy});`); + } else { + simulation.outputMapString(`spawn.mapRect(${x}, ${y}, ${dx}, ${dy});`); + } //see map in world spawn.mapRect(x, y, dx, dy); len = map.length - 1 @@ -1158,7 +1170,11 @@ const simulation = { simulation.draw.setPaths() //update map graphics } else if (e.which === 3) { //add body - simulation.outputMapString(`spawn.bodyRect(${x}, ${y}, ${dx}, ${dy});`); + if (level.isProcedural) { + simulation.outputMapString(`spawn.bodyRect(x+${x}, y+${y}, ${dx}, ${dy});`); + } else { + simulation.outputMapString(`spawn.bodyRect(${x}, ${y}, ${dx}, ${dy});`); + } //see map in world spawn.bodyRect(x, y, dx, dy); diff --git a/js/tech.js b/js/tech.js index 6fc84c3..d8caa4d 100644 --- a/js/tech.js +++ b/js/tech.js @@ -110,7 +110,7 @@ if (tech.isMetaAnalysis && tech.tech[index].isJunk) { simulation.makeTextLog(`//tech: meta-analysis replaced junk tech with random tech`); tech.giveTech('random') - for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "research"); + for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 40 * Math.random(), m.pos.y + 40 * Math.random(), "research"); return } @@ -404,7 +404,7 @@ }, { name: "catabolism", - description: "when you fire while out of ammo
gain 4 ammo, but lose 1 max health", + description: "firing while out of ammo spawns 4 ammo
and reduces your maximum health by 1", maxCount: 1, count: 0, frequency: 1, @@ -2119,12 +2119,12 @@ description: "each unused power up at the end of a level
adds 3 max energy", // (up to 51 health per level)", maxCount: 1, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, allowed() { - return tech.isEnergyHealth && !tech.isDroneGrab + return !tech.isDroneGrab }, - requires: "mass-energy equivalence, not drone harvester", + requires: "not drone harvester", effect() { tech.isExtraMaxEnergy = true; //tracked by tech.extraMaxHealth }, @@ -2615,7 +2615,7 @@ }, { name: "quantum immortality", - description: "after dying, continue in an alternate reality
reduce harm by 33%", //spawn 4 research + description: "reduce harm by 33%
after dying, continue in an alternate reality", maxCount: 1, count: 0, frequency: 4, @@ -2626,7 +2626,6 @@ requires: "anthropic principle, not many-worlds, Ψ(t) collapse, non-unitary", effect() { tech.isImmortal = true; - // for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false); }, remove() { tech.isImmortal = false; @@ -2840,7 +2839,7 @@ }, { name: "meta-analysis", - description: "if you choose a JUNK tech you instead get a
random normal tech and 2 research", + description: "if you choose a JUNK tech you instead get a
random normal tech and 5 research", maxCount: 1, count: 0, frequency: 1, @@ -4511,7 +4510,7 @@ }, { name: "laser diodes", - description: "all lasers drain 30% less energy
effects laser-gun, laser-bot, and laser-mines", + description: "all lasers drain 30% less energy
affects laser-gun, laser-bot, and laser-mines", isGunTech: true, maxCount: 1, count: 0, @@ -4530,7 +4529,7 @@ }, { name: "relativistic momentum", - description: "all lasers push mobs away
effects laser-gun, laser-bot, and laser-mines", + description: "all lasers push mobs away
affects laser-gun, laser-bot, and laser-mines", isGunTech: true, maxCount: 1, count: 0, @@ -5667,6 +5666,102 @@ // }, // remove() {} // }, + { + name: "emergency broadcasting", + description: "emit 2 sound sine waveforms at 853 Hz and 960 Hz
lower your volume", + maxCount: 1, + count: 0, + frequency: 0, + isExperimentHide: true, + isJunk: true, + isNonRefundable: true, + allowed() { + return true + }, + requires: "", + effect: () => { + //setup audio context + function tone(frequency) { + const audioCtx = new(window.AudioContext || window.webkitAudioContext)(); + const oscillator1 = audioCtx.createOscillator(); + const gainNode1 = audioCtx.createGain(); + gainNode1.gain.value = 0.5; //controls volume + oscillator1.connect(gainNode1); + gainNode1.connect(audioCtx.destination); + oscillator1.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom' + oscillator1.frequency.value = frequency; // value in hertz + oscillator1.start(); + return audioCtx + } + // let sound = tone(1050) + + function EBS() { + const audioCtx = new(window.AudioContext || window.webkitAudioContext)(); + + const oscillator1 = audioCtx.createOscillator(); + const gainNode1 = audioCtx.createGain(); + gainNode1.gain.value = 0.3; //controls volume + oscillator1.connect(gainNode1); + gainNode1.connect(audioCtx.destination); + oscillator1.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom' + oscillator1.frequency.value = 853; // value in hertz + oscillator1.start(); + + const oscillator2 = audioCtx.createOscillator(); + const gainNode2 = audioCtx.createGain(); + gainNode2.gain.value = 0.3; //controls volume + oscillator2.connect(gainNode2); + gainNode2.connect(audioCtx.destination); + oscillator2.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom' + oscillator2.frequency.value = 960; // value in hertz + oscillator2.start(); + return audioCtx + } + let sound = EBS() + + delay = 1000 + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + setTimeout(() => { + sound.resume() + setTimeout(() => { + sound.suspend() + powerUps.spawn(m.pos.x + 160 * (Math.random() - 0.5), m.pos.y + 160 * (Math.random() - 0.5), "heal"); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, delay); + }, + remove() {} + }, { name: "automatic", description: "you can't fire when moving
always fire when at rest", diff --git a/lib/OLD_matter.min.js b/lib/OLD_matter.min.js new file mode 100644 index 0000000..8255c59 --- /dev/null +++ b/lib/OLD_matter.min.js @@ -0,0 +1,96 @@ +/** +* matter-js 0.14.2 by @liabru 2018-06-11 +* http://brm.io/matter-js/ +* License MIT +*/ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.Matter=e()}}(function(){return function(){function e(t,n,o){function i(s,a){if(!n[s]){if(!t[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(r)return r(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var d=n[s]={exports:{}};t[s][0].call(d.exports,function(e){return i(t[s][1][e]||e)},d,d.exports,e,t,n,o)}return n[s].exports}for(var r="function"==typeof require&&require,s=0;s0&&r.rotateAbout(s.position,n,e.position,s.position)}},o.setVelocity=function(e,t){e.positionPrev.x=e.position.x-t.x,e.positionPrev.y=e.position.y-t.y, +e.velocity.x=t.x,e.velocity.y=t.y,e.speed=r.magnitude(e.velocity)},o.setAngularVelocity=function(e,t){e.anglePrev=e.angle-t,e.angularVelocity=t,e.angularSpeed=Math.abs(e.angularVelocity)},o.translate=function(e,t){o.setPosition(e,r.add(e.position,t))},o.rotate=function(e,t,n){if(n){var i=Math.cos(t),r=Math.sin(t),s=e.position.x-n.x,a=e.position.y-n.y;o.setPosition(e,{x:n.x+(s*i-a*r),y:n.y+(s*r+a*i)}),o.setAngle(e,e.angle+t)}else o.setAngle(e,e.angle+t)},o.scale=function(e,t,n,r){var s=0,a=0;r=r||e.position;for(var d=0;d0&&(s+=u.area,a+=u.inertia),u.position.x=r.x+(u.position.x-r.x)*t,u.position.y=r.y+(u.position.y-r.y)*n,l.update(u.bounds,u.vertices,e.velocity) +}e.parts.length>1&&(e.area=s,e.isStatic||(o.setMass(e,e.density*s),o.setInertia(e,a))),e.circleRadius&&(t===n?e.circleRadius*=t:e.circleRadius=null)},o.update=function(e,t,n,o){var s=Math.pow(t*n*e.timeScale,2),a=1-e.frictionAir*n*e.timeScale,d=e.position.x-e.positionPrev.x,u=e.position.y-e.positionPrev.y;e.velocity.x=d*a*o+e.force.x/e.mass*s,e.velocity.y=u*a*o+e.force.y/e.mass*s,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.angularVelocity=(e.angle-e.anglePrev)*a*o+e.torque/e.inertia*s,e.anglePrev=e.angle,e.angle+=e.angularVelocity,e.speed=r.magnitude(e.velocity),e.angularSpeed=Math.abs(e.angularVelocity);for(var p=0;p0&&(f.position.x+=e.velocity.x,f.position.y+=e.velocity.y),0!==e.angularVelocity&&(i.rotate(f.vertices,e.angularVelocity,e.position),c.rotate(f.axes,e.angularVelocity), +p>0&&r.rotateAbout(f.position,e.angularVelocity,e.position,f.position)),l.update(f.bounds,f.vertices,e.velocity)}},o.applyForce=function(e,t,n){e.force.x+=n.x,e.force.y+=n.y;var o={x:t.x-e.position.x,y:t.y-e.position.y};e.torque+=o.x*n.y-o.y*n.x},o._totalProperties=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n1?1:0;u1?1:0;f0:0!=(e.mask&t.category)&&0!=(t.mask&e.category)}}()},{"../geometry/Bounds":26,"./Pair":7,"./SAT":11}],6:[function(e,t,n){var o={};t.exports=o;var i=e("./Pair"),r=e("./Detector"),s=e("../core/Common");!function(){o.create=function(e){var t={controller:o,detector:r.collisions,buckets:{},pairs:{},pairsList:[],bucketWidth:48,bucketHeight:48};return s.extend(t,e)},o.update=function(e,t,n,i){ +var r,s,a,l,c,d=n.world,u=e.buckets,p=!1;for(r=0;rd.bounds.max.x||f.bounds.max.yd.bounds.max.y)){var m=o._getRegion(e,f);if(!f.region||m.id!==f.region.id||i){f.region&&!i||(f.region=m);var v=o._regionUnion(m,f.region);for(s=v.startCol;s<=v.endCol;s++)for(a=v.startRow;a<=v.endRow;a++){c=o._getBucketId(s,a),l=u[c];var y=s>=m.startCol&&s<=m.endCol&&a>=m.startRow&&a<=m.endRow,g=s>=f.region.startCol&&s<=f.region.endCol&&a>=f.region.startRow&&a<=f.region.endRow;!y&&g&&g&&l&&o._bucketRemoveBody(e,l,f),(f.region===m||y&&!g||i)&&(l||(l=o._createBucket(u,c)),o._bucketAddBody(e,l,f))}f.region=m,p=!0}}}p&&(e.pairsList=o._createActivePairsList(e))},o.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]},o._regionUnion=function(e,t){var n=Math.min(e.startCol,t.startCol),i=Math.max(e.endCol,t.endCol),r=Math.min(e.startRow,t.startRow),s=Math.max(e.endRow,t.endRow) +;return o._createRegion(n,i,r,s)},o._getRegion=function(e,t){var n=t.bounds,i=Math.floor(n.min.x/e.bucketWidth),r=Math.floor(n.max.x/e.bucketWidth),s=Math.floor(n.min.y/e.bucketHeight),a=Math.floor(n.max.y/e.bucketHeight);return o._createRegion(i,r,s,a)},o._createRegion=function(e,t,n,o){return{id:e+","+t+","+n+","+o,startCol:e,endCol:t,startRow:n,endRow:o}},o._getBucketId=function(e,t){return"C"+e+"R"+t},o._createBucket=function(e,t){return e[t]=[]},o._bucketAddBody=function(e,t,n){for(var o=0;o0?o.push(n):delete e.pairs[t[i]];return o}}()},{"../core/Common":14,"./Detector":5,"./Pair":7}], +7:[function(e,t,n){var o={};t.exports=o;var i=e("./Contact");!function(){o.create=function(e,t){var n=e.bodyA,i=e.bodyB,r=e.parentA,s=e.parentB,a={id:o.id(n,i),bodyA:n,bodyB:i,contacts:{},activeContacts:[],separation:0,isActive:!0,isSensor:n.isSensor||i.isSensor,timeCreated:t,timeUpdated:t,inverseMass:r.inverseMass+s.inverseMass,friction:Math.min(r.friction,s.friction),frictionStatic:Math.max(r.frictionStatic,s.frictionStatic),restitution:Math.max(r.restitution,s.restitution),slop:Math.max(r.slop,s.slop)};return o.update(a,e,t),a},o.update=function(e,t,n){var r=e.contacts,s=t.supports,a=e.activeContacts,l=t.parentA,c=t.parentB;if(e.collision=t,e.inverseMass=l.inverseMass+c.inverseMass,e.friction=Math.min(l.friction,c.friction),e.frictionStatic=Math.max(l.frictionStatic,c.frictionStatic),e.restitution=Math.max(l.restitution,c.restitution),e.slop=Math.max(l.slop,c.slop),a.length=0,t.collided){for(var d=0;do._pairMaxIdleLife&&c.push(s);for(s=0;sf.friction*f.frictionStatic*E*n&&(F=T,L=s.clamp(f.friction*R*n,-F,F));var O=r.cross(A,g),q=r.cross(P,g),W=b/(v.inverseMass+y.inverseMass+v.inverseInertia*O*O+y.inverseInertia*q*q);if(V*=W,L*=W,I<0&&I*I>o._restingThresh*n)S.normalImpulse=0;else{var D=S.normalImpulse;S.normalImpulse=Math.min(S.normalImpulse+V,0),V=S.normalImpulse-D}if(_*_>o._restingThreshTangent*n)S.tangentImpulse=0;else{var N=S.tangentImpulse;S.tangentImpulse=s.clamp(S.tangentImpulse+L,-F,F),L=S.tangentImpulse-N}i.x=g.x*V+x.x*L,i.y=g.y*V+x.y*L,v.isStatic||v.isSleeping||(v.positionPrev.x+=i.x*v.inverseMass,v.positionPrev.y+=i.y*v.inverseMass, +v.anglePrev+=r.cross(A,i)*v.inverseInertia),y.isStatic||y.isSleeping||(y.positionPrev.x-=i.x*y.inverseMass,y.positionPrev.y-=i.y*y.inverseMass,y.anglePrev-=r.cross(P,i)*y.inverseInertia)}}}}}()},{"../core/Common":14,"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29}],11:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../geometry/Vector");!function(){o.collides=function(e,t,n){var s,a,l,c,d=!1;if(n){var u=e.parent,p=t.parent,f=u.speed*u.speed+u.angularSpeed*u.angularSpeed+p.speed*p.speed+p.angularSpeed*p.angularSpeed;d=n&&n.collided&&f<.2,c=n}else c={collided:!1,bodyA:e,bodyB:t};if(n&&d){var m=c.axisBody,v=m===e?t:e,y=[m.axes[n.axisNumber]];if(l=o._overlapAxes(m.vertices,v.vertices,y),c.reused=!0,l.overlap<=0)return c.collided=!1,c}else{if(s=o._overlapAxes(e.vertices,t.vertices,e.axes),s.overlap<=0)return c.collided=!1,c;if(a=o._overlapAxes(t.vertices,e.vertices,t.axes),a.overlap<=0)return c.collided=!1,c;s.overlapi?i=a:a=0?s.index-1:d.length-1],c.x=i.x-u.x,c.y=i.y-u.y,l=-r.dot(n,c),a=i,i=d[(s.index+1)%d.length],c.x=i.x-u.x,c.y=i.y-u.y,o=-r.dot(n,c),o0?1:.7),t.damping=t.damping||0,t.angularStiffness=t.angularStiffness||0,t.angleA=t.bodyA?t.bodyA.angle:t.angleA,t.angleB=t.bodyB?t.bodyB.angle:t.angleB,t.plugin={};var s={visible:!0,lineWidth:2,strokeStyle:"#ffffff",type:"line",anchors:!0};return 0===t.length&&t.stiffness>.1?(s.type="pin",s.anchors=!1):t.stiffness<.9&&(s.type="spring"),t.render=c.extend(s,t.render),t},o.preSolveAll=function(e){for(var t=0;t0&&(u.position.x+=c.x,u.position.y+=c.y),0!==c.angle&&(i.rotate(u.vertices,c.angle,n.position),l.rotate(u.axes,c.angle), +d>0&&r.rotateAbout(u.position,c.angle,n.position,u.position)),a.update(u.bounds,u.vertices,n.velocity)}c.angle*=o._warming,c.x*=o._warming,c.y*=o._warming}}}}()},{"../core/Common":14,"../core/Sleeping":22,"../geometry/Axes":25,"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29}],13:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../core/Sleeping"),s=e("../core/Mouse"),a=e("../core/Events"),l=e("../collision/Detector"),c=e("./Constraint"),d=e("../body/Composite"),u=e("../core/Common"),p=e("../geometry/Bounds");!function(){o.create=function(e,t){var n=(e?e.mouse:null)||(t?t.mouse:null);n||(e&&e.render&&e.render.canvas?n=s.create(e.render.canvas):t&&t.element?n=s.create(t.element):(n=s.create(),u.warn("MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected")));var i=c.create({label:"Mouse Constraint",pointA:n.position,pointB:{x:0,y:0},length:.01,stiffness:.1,angularStiffness:1, +render:{strokeStyle:"#90EE90",lineWidth:3}}),r={type:"mouseConstraint",mouse:n,element:null,body:null,constraint:i,collisionFilter:{category:1,mask:4294967295,group:0}},l=u.extend(r,t);return a.on(e,"beforeUpdate",function(){var t=d.allBodies(e.world);o.update(l,t),o._triggerEvents(l)}),l},o.update=function(e,t){var n=e.mouse,o=e.constraint,s=e.body;if(0===n.button){if(o.bodyB)r.set(o.bodyB,!1),o.pointA=n.position;else for(var c=0;c1?1:0;d0;t--){var n=Math.floor(o.random()*(t+1)),i=e[t];e[t]=e[n],e[n]=i}return e},o.choose=function(e){return e[Math.floor(o.random()*e.length)]},o.isElement=function(e){return"undefined"!=typeof HTMLElement?e instanceof HTMLElement:!!(e&&e.nodeType&&e.nodeName)},o.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},o.isFunction=function(e){return"function"==typeof e},o.isPlainObject=function(e){return"object"==typeof e&&e.constructor===Object},o.isString=function(e){return"[object String]"===toString.call(e)},o.clamp=function(e,t,n){return en?n:e},o.sign=function(e){return e<0?-1:1},o.now=function(){ +if(window.performance){if(window.performance.now)return window.performance.now();if(window.performance.webkitNow)return window.performance.webkitNow()}return new Date-o._nowStartTime},o.random=function(e,n){return e=void 0!==e?e:0,n=void 0!==n?n:1,e+t()*(n-e)};var t=function(){return o._seed=(9301*o._seed+49297)%233280,o._seed/233280};o.colorToNumber=function(e){return e=e.replace("#",""),3==e.length&&(e=e.charAt(0)+e.charAt(0)+e.charAt(1)+e.charAt(1)+e.charAt(2)+e.charAt(2)),parseInt(e,16)},o.logLevel=1,o.log=function(){console&&o.logLevel>0&&o.logLevel<=3&&console.log.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},o.info=function(){console&&o.logLevel>0&&o.logLevel<=2&&console.info.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},o.warn=function(){console&&o.logLevel>0&&o.logLevel<=3&&console.warn.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},o.nextId=function(){return o._nextId++}, +o.indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;n0&&d.trigger(e,"collisionStart",{pairs:h.collisionStart}),s.preSolvePosition(h.list),i=0;i0&&d.trigger(e,"collisionActive",{pairs:h.collisionActive}),h.collisionEnd.length>0&&d.trigger(e,"collisionEnd",{pairs:h.collisionEnd}),o._bodiesClearForces(y),d.trigger(e,"afterUpdate",v),e},o.merge=function(e,t){if(f.extend(e,t),t.world){e.world=t.world,o.clear(e);for(var n=u.allBodies(e.world),i=0;ir?(i.warn("Plugin.register:",o.toString(t),"was upgraded to",o.toString(e)),o._registry[e.name]=e):n-1},o.isFor=function(e,t){var n=e.for&&o.dependencyParse(e.for) +;return!e.for||t.name===n.name&&o.versionSatisfies(t.version,n.range)},o.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0===e.uses.length)return void i.warn("Plugin.use:",o.toString(e),"does not specify any dependencies to install.");for(var n=o.dependencies(e),r=i.topologicalSort(n),s=[],a=0;a0&&i.info(s.join(" "))},o.dependencies=function(e,t){var n=o.dependencyParse(e),r=n.name;if(t=t||{},!(r in t)){e=o.resolve(e)||e,t[r]=i.map(e.uses||[],function(t){o.isPlugin(t)&&o.register(t);var r=o.dependencyParse(t),s=o.resolve(t) +;return s&&!o.versionSatisfies(s.version,r.range)?(i.warn("Plugin.dependencies:",o.toString(s),"does not satisfy",o.toString(r),"used by",o.toString(n)+"."),s._warned=!0,e._warned=!0):s||(i.warn("Plugin.dependencies:",o.toString(t),"used by",o.toString(n),"could not be resolved."),e._warned=!0),r.name});for(var s=0;s=i[2];if("^"===n.operator)return i[0]>0?s[0]===i[0]&&r.number>=n.number:i[1]>0?s[1]===i[1]&&s[2]>=i[2]:s[2]===i[2]}return e===t||"*"===e}}()},{"./Common":14}],21:[function(e,t,n){var o={};t.exports=o;var i=e("./Events"),r=e("./Engine"),s=e("./Common");!function(){var e,t;if("undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame,t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),!e){var n;e=function(e){n=setTimeout(function(){e(s.now())},1e3/60)},t=function(){clearTimeout(n)}}o.create=function(e){var t={fps:60,correction:1,deltaSampleSize:60, +counterTimestamp:0,frameCounter:0,deltaHistory:[],timePrev:null,timeScalePrev:1,frameRequestId:null,isFixed:!1,enabled:!0},n=s.extend(t,e);return n.delta=n.delta||1e3/n.fps,n.deltaMin=n.deltaMin||1e3/n.fps,n.deltaMax=n.deltaMax||1e3/(.5*n.fps),n.fps=1e3/n.delta,n},o.run=function(t,n){return void 0!==t.positionIterations&&(n=t,t=o.create()),function i(r){t.frameRequestId=e(i),r&&t.enabled&&o.tick(t,n,r)}(),t},o.tick=function(e,t,n){var o,s=t.timing,a=1,l={timestamp:s.timestamp};i.trigger(e,"beforeTick",l),i.trigger(t,"beforeTick",l),e.isFixed?o=e.delta:(o=n-e.timePrev||e.delta,e.timePrev=n,e.deltaHistory.push(o),e.deltaHistory=e.deltaHistory.slice(-e.deltaSampleSize),o=Math.min.apply(null,e.deltaHistory),o=oe.deltaMax?e.deltaMax:o,a=o/e.delta,e.delta=o),0!==e.timeScalePrev&&(a*=s.timeScale/e.timeScalePrev),0===s.timeScale&&(a=0),e.timeScalePrev=s.timeScale,e.correction=a,e.frameCounter+=1, +n-e.counterTimestamp>=1e3&&(e.fps=e.frameCounter*((n-e.counterTimestamp)/1e3),e.counterTimestamp=n,e.frameCounter=0),i.trigger(e,"tick",l),i.trigger(t,"tick",l),t.world.isModified&&t.render&&t.render.controller&&t.render.controller.clear&&t.render.controller.clear(t.render),i.trigger(e,"beforeUpdate",l),r.update(t,o,a),i.trigger(e,"afterUpdate",l),t.render&&t.render.controller&&(i.trigger(e,"beforeRender",l),i.trigger(t,"beforeRender",l),t.render.controller.world(t.render),i.trigger(e,"afterRender",l),i.trigger(t,"afterRender",l)),i.trigger(e,"afterTick",l),i.trigger(t,"afterTick",l)},o.stop=function(e){t(e.frameRequestId)},o.start=function(e,t){o.run(e,t)}}()},{"./Common":14,"./Engine":15,"./Events":16}],22:[function(e,t,n){var o={};t.exports=o;var i=e("./Events");!function(){o._motionWakeThreshold=.18,o._motionSleepThreshold=.08,o._minBias=.9,o.update=function(e,t){for(var n=t*t*t,i=0;i0&&r.motion=r.sleepThreshold&&o.set(r,!0)):r.sleepCounter>0&&(r.sleepCounter-=1)}else o.set(r,!1)}},o.afterCollisions=function(e,t){for(var n=t*t*t,i=0;io._motionWakeThreshold*n&&o.set(c,!1)}}}},o.set=function(e,t){var n=e.isSleeping;t?(e.isSleeping=!0,e.sleepCounter=e.sleepThreshold,e.positionImpulse.x=0,e.positionImpulse.y=0,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.anglePrev=e.angle,e.speed=0,e.angularSpeed=0,e.motion=0,n||i.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&i.trigger(e,"sleepEnd"))}}()},{ +"./Events":16}],23:[function(e,t,n){var o={};t.exports=o;var i,r=e("../geometry/Vertices"),s=e("../core/Common"),a=e("../body/Body"),l=e("../geometry/Bounds"),c=e("../geometry/Vector");!function(){o.rectangle=function(e,t,n,o,i){i=i||{};var l={label:"Rectangle Body",position:{x:e,y:t},vertices:r.fromPath("L 0 0 L "+n+" 0 L "+n+" "+o+" L 0 "+o)};if(i.chamfer){var c=i.chamfer;l.vertices=r.chamfer(l.vertices,c.radius,c.quality,c.qualityMin,c.qualityMax),delete i.chamfer}return a.create(s.extend({},l,i))},o.trapezoid=function(e,t,n,o,i,l){l=l||{},i*=.5;var c,d=(1-2*i)*n,u=n*i,p=u+d,f=p+u;c=i<.5?"L 0 0 L "+u+" "+-o+" L "+p+" "+-o+" L "+f+" 0":"L 0 0 L "+p+" "+-o+" L "+f+" 0";var m={label:"Trapezoid Body",position:{x:e,y:t},vertices:r.fromPath(c)};if(l.chamfer){var v=l.chamfer;m.vertices=r.chamfer(m.vertices,v.radius,v.quality,v.qualityMin,v.qualityMax),delete l.chamfer}return a.create(s.extend({},m,l))},o.circle=function(e,t,n,i,r){i=i||{};var a={label:"Circle Body",circleRadius:n};r=r||25 +;var l=Math.ceil(Math.max(10,Math.min(r,n)));return l%2==1&&(l+=1),o.polygon(e,t,l,n,s.extend({},a,i))},o.polygon=function(e,t,n,i,l){if(l=l||{},n<3)return o.circle(e,t,i,l);for(var c=2*Math.PI/n,d="",u=.5*c,p=0;p0&&r.area(P)1?(f=a.create(s.extend({parts:m.slice(0)},o)),a.setPosition(f,{x:e,y:t}),f):m[0]}}()},{"../body/Body":1,"../core/Common":14,"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29}],24:[function(e,t,n){var o={};t.exports=o +;var i=e("../body/Composite"),r=e("../constraint/Constraint"),s=e("../core/Common"),a=e("../body/Body"),l=e("./Bodies");!function(){o.stack=function(e,t,n,o,r,s,l){for(var c,d=i.create({label:"Stack"}),u=e,p=t,f=0,m=0;mv&&(v=x),a.translate(g,{x:.5*h,y:.5*x}),u=g.bounds.max.x+r,i.addBody(d,g),c=g,f+=1}else u+=r}p+=v+s,u=e}return d},o.chain=function(e,t,n,o,a,l){for(var c=e.bodies,d=1;d0)for(c=0;c0&&(p=f[c-1+(l-1)*t],i.addConstraint(e,r.create(s.extend({bodyA:p,bodyB:u},a)))),o&&cp)){c=p-c;var m=c,v=n-1-c;if(!(sv)){1===u&&a.translate(d,{x:(s+(n%2==1?1:-1))*f,y:0});return l(e+(d?s*f:0)+s*r,o,s,c,d,u)}}})},o.newtonsCradle=function(e,t,n,o,s){for(var a=i.create({label:"Newtons Cradle"}),c=0;ce.max.x&&(e.max.x=i.x),i.xe.max.y&&(e.max.y=i.y),i.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},o.contains=function(e,t){return t.x>=e.min.x&&t.x<=e.max.x&&t.y>=e.min.y&&t.y<=e.max.y},o.overlaps=function(e,t){return e.min.x<=t.max.x&&e.max.x>=t.min.x&&e.max.y>=t.min.y&&e.min.y<=t.max.y},o.translate=function(e,t){e.min.x+=t.x, +e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},o.shift=function(e,t){var n=e.max.x-e.min.x,o=e.max.y-e.min.y;e.min.x=t.x,e.max.x=t.x+n,e.min.y=t.y,e.max.y=t.y+o}}()},{}],27:[function(e,t,n){var o={};t.exports=o;var i=(e("../geometry/Bounds"),e("../core/Common"));!function(){o.pathToVertices=function(e,t){"undefined"==typeof window||"SVGPathSeg"in window||i.warn("Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.");var n,r,s,a,l,c,d,u,p,f,m,v,y=[],g=0,x=0,h=0;t=t||15;var b=function(e,t,n){var o=n%2==1&&n>1;if(!p||e!=p.x||t!=p.y){p&&o?(m=p.x,v=p.y):(m=0,v=0);var i={x:m+e,y:v+t};!o&&p||(p=i),y.push(i),x=m+e,h=v+t}},w=function(e){var t=e.pathSegTypeAsLetter.toUpperCase();if("Z"!==t){switch(t){case"M":case"L":case"T":case"C":case"S":case"Q":x=e.x,h=e.y;break;case"H":x=e.x;break;case"V":h=e.y}b(x,h,e.pathSegType)}};for(o._svgPathToAbsolute(e),s=e.getTotalLength(),c=[],n=0;n0)return!1}return!0},o.scale=function(e,t,n,r){if(1===t&&1===n)return e;r=r||o.centre(e);for(var s,a,l=0;l=0?l-1:e.length-1],d=e[l],u=e[(l+1)%e.length],p=t[l0&&(r|=2),3===r)return!1;return 0!==r||null},o.hull=function(e){var t,n,o=[],r=[];for(e=e.slice(0),e.sort(function(e,t){var n=e.x-t.x;return 0!==n?n:e.y-t.y}),n=0;n=2&&i.cross3(r[r.length-2],r[r.length-1],t)<=0;)r.pop();r.push(t)}for(n=e.length-1;n>=0;n-=1){for(t=e[n];o.length>=2&&i.cross3(o[o.length-2],o[o.length-1],t)<=0;)o.pop();o.push(t)}return o.pop(),r.pop(),o.concat(r)}}()},{"../core/Common":14,"../geometry/Vector":28}],30:[function(e,t,n){var o=t.exports=e("../core/Matter");o.Body=e("../body/Body"),o.Composite=e("../body/Composite"), +o.World=e("../body/World"),o.Contact=e("../collision/Contact"),o.Detector=e("../collision/Detector"),o.Grid=e("../collision/Grid"),o.Pairs=e("../collision/Pairs"),o.Pair=e("../collision/Pair"),o.Query=e("../collision/Query"),o.Resolver=e("../collision/Resolver"),o.SAT=e("../collision/SAT"),o.Constraint=e("../constraint/Constraint"),o.MouseConstraint=e("../constraint/MouseConstraint"),o.Common=e("../core/Common"),o.Engine=e("../core/Engine"),o.Events=e("../core/Events"),o.Mouse=e("../core/Mouse"),o.Runner=e("../core/Runner"),o.Sleeping=e("../core/Sleeping"),o.Plugin=e("../core/Plugin"),o.Bodies=e("../factory/Bodies"),o.Composites=e("../factory/Composites"),o.Axes=e("../geometry/Axes"),o.Bounds=e("../geometry/Bounds"),o.Svg=e("../geometry/Svg"),o.Vector=e("../geometry/Vector"),o.Vertices=e("../geometry/Vertices"),o.Render=e("../render/Render"),o.RenderPixi=e("../render/RenderPixi"),o.World.add=o.Composite.add,o.World.remove=o.Composite.remove, +o.World.addComposite=o.Composite.addComposite,o.World.addBody=o.Composite.addBody,o.World.addConstraint=o.Composite.addConstraint,o.World.clear=o.Composite.clear,o.Engine.run=o.Runner.run},{"../body/Body":1,"../body/Composite":2,"../body/World":3,"../collision/Contact":4,"../collision/Detector":5,"../collision/Grid":6,"../collision/Pair":7,"../collision/Pairs":8,"../collision/Query":9,"../collision/Resolver":10,"../collision/SAT":11,"../constraint/Constraint":12,"../constraint/MouseConstraint":13,"../core/Common":14,"../core/Engine":15,"../core/Events":16,"../core/Matter":17,"../core/Metrics":18,"../core/Mouse":19,"../core/Plugin":20,"../core/Runner":21,"../core/Sleeping":22,"../factory/Bodies":23,"../factory/Composites":24,"../geometry/Axes":25,"../geometry/Bounds":26,"../geometry/Svg":27,"../geometry/Vector":28,"../geometry/Vertices":29,"../render/Render":31,"../render/RenderPixi":32}],31:[function(e,t,n){var o={};t.exports=o +;var i=e("../core/Common"),r=e("../body/Composite"),s=e("../geometry/Bounds"),a=e("../core/Events"),l=e("../collision/Grid"),c=e("../geometry/Vector"),d=e("../core/Mouse");!function(){var e,t;"undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(function(){e(i.now())},1e3/60)},t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),o.create=function(e){var t={controller:o,engine:null,element:null,canvas:null,mouse:null,frameRequestId:null,options:{width:800,height:600,pixelRatio:1,background:"#18181d",wireframeBackground:"#0f0f13",hasBounds:!!e.bounds,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showBroadphase:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showSeparations:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showShadows:!1, +showVertexNumbers:!1,showConvexHulls:!1,showInternalEdges:!1,showMousePosition:!1}},r=i.extend(t,e);return r.canvas&&(r.canvas.width=r.options.width||r.canvas.width,r.canvas.height=r.options.height||r.canvas.height),r.mouse=e.mouse,r.engine=e.engine,r.canvas=r.canvas||n(r.options.width,r.options.height),r.context=r.canvas.getContext("2d"),r.textures={},r.bounds=r.bounds||{min:{x:0,y:0},max:{x:r.canvas.width,y:r.canvas.height}},1!==r.options.pixelRatio&&o.setPixelRatio(r,r.options.pixelRatio),i.isElement(r.element)?r.element.appendChild(r.canvas):r.canvas.parentNode||i.log("Render.create: options.element was undefined, render.canvas was created but not appended","warn"),r},o.run=function(t){!function n(i){t.frameRequestId=e(n),o.world(t)}()},o.stop=function(e){t(e.frameRequestId)},o.setPixelRatio=function(e,t){var n=e.options,o=e.canvas;"auto"===t&&(t=u(o)),n.pixelRatio=t,o.setAttribute("data-pixel-ratio",t),o.width=n.width*t,o.height=n.height*t,o.style.width=n.width+"px", +o.style.height=n.height+"px",e.context.scale(t,t)},o.lookAt=function(e,t,n,o){o=void 0===o||o,t=i.isArray(t)?t:[t],n=n||{x:0,y:0};for(var r={min:{x:1/0,y:1/0},max:{x:-1/0,y:-1/0}},s=0;sr.max.x&&(r.max.x=c.x),l.yr.max.y&&(r.max.y=c.y))}var u=r.max.x-r.min.x+2*n.x,p=r.max.y-r.min.y+2*n.y,f=e.canvas.height,m=e.canvas.width,v=m/f,y=u/p,g=1,x=1;y>v?x=y/v:g=v/y,e.options.hasBounds=!0,e.bounds.min.x=r.min.x,e.bounds.max.x=r.min.x+u*g,e.bounds.min.y=r.min.y,e.bounds.max.y=r.min.y+p*x,o&&(e.bounds.min.x+=.5*u-u*g*.5,e.bounds.max.x+=.5*u-u*g*.5,e.bounds.min.y+=.5*p-p*x*.5,e.bounds.max.y+=.5*p-p*x*.5),e.bounds.min.x-=n.x,e.bounds.max.x-=n.x,e.bounds.min.y-=n.y,e.bounds.max.y-=n.y,e.mouse&&(d.setScale(e.mouse,{x:(e.bounds.max.x-e.bounds.min.x)/e.canvas.width,y:(e.bounds.max.y-e.bounds.min.y)/e.canvas.height}), +d.setOffset(e.mouse,e.bounds.min))},o.startViewTransform=function(e){var t=e.bounds.max.x-e.bounds.min.x,n=e.bounds.max.y-e.bounds.min.y,o=t/e.options.width,i=n/e.options.height;e.context.scale(1/o,1/i),e.context.translate(-e.bounds.min.x,-e.bounds.min.y)},o.endViewTransform=function(e){e.context.setTransform(e.options.pixelRatio,0,0,e.options.pixelRatio,0,0)},o.world=function(e){var t,n=e.engine,i=n.world,u=e.canvas,p=e.context,m=e.options,v=r.allBodies(i),y=r.allConstraints(i),g=m.wireframes?m.wireframeBackground:m.background,x=[],h=[],b={timestamp:n.timing.timestamp};if(a.trigger(e,"beforeRender",b),e.currentBackground!==g&&f(e,g),p.globalCompositeOperation="source-in",p.fillStyle="transparent",p.fillRect(0,0,u.width,u.height),p.globalCompositeOperation="source-over",m.hasBounds){for(t=0;t=500){var l="";s.timing&&(l+="fps: "+Math.round(s.timing.fps)+" "),e.debugString=l,e.debugTimestamp=o.timing.timestamp}if(e.debugString){n.font="12px Arial",a.wireframes?n.fillStyle="rgba(255,255,255,0.5)":n.fillStyle="rgba(0,0,0,0.5)";for(var c=e.debugString.split("\n"),d=0;d1?1:0;s1?1:0;a1?1:0;r1?1:0;a1?1:0;r1?1:0;r1?1:0;i0)){var u=o.activeContacts[0].vertex.x,p=o.activeContacts[0].vertex.y;2===o.activeContacts.length&&(u=(o.activeContacts[0].vertex.x+o.activeContacts[1].vertex.x)/2,p=(o.activeContacts[0].vertex.y+o.activeContacts[1].vertex.y)/2),i.bodyB===i.supports[0].body||!0===i.bodyA.isStatic?a.moveTo(u-8*i.normal.x,p-8*i.normal.y):a.moveTo(u+8*i.normal.x,p+8*i.normal.y),a.lineTo(u,p)} +l.wireframes?a.strokeStyle="rgba(255,165,0,0.7)":a.strokeStyle="orange",a.lineWidth=1,a.stroke()},o.separations=function(e,t,n){var o,i,r,s,a,l=n,c=e.options;for(l.beginPath(),a=0;a1?1:0;p0&&r.rotateAbout(s.position,n,e.position,s.position)}},o.setVelocity=function(e,t){e.positionPrev.x=e.position.x-t.x,e.positionPrev.y=e.position.y-t.y, -e.velocity.x=t.x,e.velocity.y=t.y,e.speed=r.magnitude(e.velocity)},o.setAngularVelocity=function(e,t){e.anglePrev=e.angle-t,e.angularVelocity=t,e.angularSpeed=Math.abs(e.angularVelocity)},o.translate=function(e,t){o.setPosition(e,r.add(e.position,t))},o.rotate=function(e,t,n){if(n){var i=Math.cos(t),r=Math.sin(t),s=e.position.x-n.x,a=e.position.y-n.y;o.setPosition(e,{x:n.x+(s*i-a*r),y:n.y+(s*r+a*i)}),o.setAngle(e,e.angle+t)}else o.setAngle(e,e.angle+t)},o.scale=function(e,t,n,r){var s=0,a=0;r=r||e.position;for(var d=0;d0&&(s+=u.area,a+=u.inertia),u.position.x=r.x+(u.position.x-r.x)*t,u.position.y=r.y+(u.position.y-r.y)*n,l.update(u.bounds,u.vertices,e.velocity) -}e.parts.length>1&&(e.area=s,e.isStatic||(o.setMass(e,e.density*s),o.setInertia(e,a))),e.circleRadius&&(t===n?e.circleRadius*=t:e.circleRadius=null)},o.update=function(e,t,n,o){var s=Math.pow(t*n*e.timeScale,2),a=1-e.frictionAir*n*e.timeScale,d=e.position.x-e.positionPrev.x,u=e.position.y-e.positionPrev.y;e.velocity.x=d*a*o+e.force.x/e.mass*s,e.velocity.y=u*a*o+e.force.y/e.mass*s,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.angularVelocity=(e.angle-e.anglePrev)*a*o+e.torque/e.inertia*s,e.anglePrev=e.angle,e.angle+=e.angularVelocity,e.speed=r.magnitude(e.velocity),e.angularSpeed=Math.abs(e.angularVelocity);for(var p=0;p0&&(f.position.x+=e.velocity.x,f.position.y+=e.velocity.y),0!==e.angularVelocity&&(i.rotate(f.vertices,e.angularVelocity,e.position),c.rotate(f.axes,e.angularVelocity), -p>0&&r.rotateAbout(f.position,e.angularVelocity,e.position,f.position)),l.update(f.bounds,f.vertices,e.velocity)}},o.applyForce=function(e,t,n){e.force.x+=n.x,e.force.y+=n.y;var o={x:t.x-e.position.x,y:t.y-e.position.y};e.torque+=o.x*n.y-o.y*n.x},o._totalProperties=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n1?1:0;u1?1:0;f0:0!=(e.mask&t.category)&&0!=(t.mask&e.category)}}()},{"../geometry/Bounds":26,"./Pair":7,"./SAT":11}],6:[function(e,t,n){var o={};t.exports=o;var i=e("./Pair"),r=e("./Detector"),s=e("../core/Common");!function(){o.create=function(e){var t={controller:o,detector:r.collisions,buckets:{},pairs:{},pairsList:[],bucketWidth:48,bucketHeight:48};return s.extend(t,e)},o.update=function(e,t,n,i){ -var r,s,a,l,c,d=n.world,u=e.buckets,p=!1;for(r=0;rd.bounds.max.x||f.bounds.max.yd.bounds.max.y)){var m=o._getRegion(e,f);if(!f.region||m.id!==f.region.id||i){f.region&&!i||(f.region=m);var v=o._regionUnion(m,f.region);for(s=v.startCol;s<=v.endCol;s++)for(a=v.startRow;a<=v.endRow;a++){c=o._getBucketId(s,a),l=u[c];var y=s>=m.startCol&&s<=m.endCol&&a>=m.startRow&&a<=m.endRow,g=s>=f.region.startCol&&s<=f.region.endCol&&a>=f.region.startRow&&a<=f.region.endRow;!y&&g&&g&&l&&o._bucketRemoveBody(e,l,f),(f.region===m||y&&!g||i)&&(l||(l=o._createBucket(u,c)),o._bucketAddBody(e,l,f))}f.region=m,p=!0}}}p&&(e.pairsList=o._createActivePairsList(e))},o.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]},o._regionUnion=function(e,t){var n=Math.min(e.startCol,t.startCol),i=Math.max(e.endCol,t.endCol),r=Math.min(e.startRow,t.startRow),s=Math.max(e.endRow,t.endRow) -;return o._createRegion(n,i,r,s)},o._getRegion=function(e,t){var n=t.bounds,i=Math.floor(n.min.x/e.bucketWidth),r=Math.floor(n.max.x/e.bucketWidth),s=Math.floor(n.min.y/e.bucketHeight),a=Math.floor(n.max.y/e.bucketHeight);return o._createRegion(i,r,s,a)},o._createRegion=function(e,t,n,o){return{id:e+","+t+","+n+","+o,startCol:e,endCol:t,startRow:n,endRow:o}},o._getBucketId=function(e,t){return"C"+e+"R"+t},o._createBucket=function(e,t){return e[t]=[]},o._bucketAddBody=function(e,t,n){for(var o=0;o0?o.push(n):delete e.pairs[t[i]];return o}}()},{"../core/Common":14,"./Detector":5,"./Pair":7}], -7:[function(e,t,n){var o={};t.exports=o;var i=e("./Contact");!function(){o.create=function(e,t){var n=e.bodyA,i=e.bodyB,r=e.parentA,s=e.parentB,a={id:o.id(n,i),bodyA:n,bodyB:i,contacts:{},activeContacts:[],separation:0,isActive:!0,isSensor:n.isSensor||i.isSensor,timeCreated:t,timeUpdated:t,inverseMass:r.inverseMass+s.inverseMass,friction:Math.min(r.friction,s.friction),frictionStatic:Math.max(r.frictionStatic,s.frictionStatic),restitution:Math.max(r.restitution,s.restitution),slop:Math.max(r.slop,s.slop)};return o.update(a,e,t),a},o.update=function(e,t,n){var r=e.contacts,s=t.supports,a=e.activeContacts,l=t.parentA,c=t.parentB;if(e.collision=t,e.inverseMass=l.inverseMass+c.inverseMass,e.friction=Math.min(l.friction,c.friction),e.frictionStatic=Math.max(l.frictionStatic,c.frictionStatic),e.restitution=Math.max(l.restitution,c.restitution),e.slop=Math.max(l.slop,c.slop),a.length=0,t.collided){for(var d=0;do._pairMaxIdleLife&&c.push(s);for(s=0;sf.friction*f.frictionStatic*E*n&&(F=T,L=s.clamp(f.friction*R*n,-F,F));var O=r.cross(A,g),q=r.cross(P,g),W=b/(v.inverseMass+y.inverseMass+v.inverseInertia*O*O+y.inverseInertia*q*q);if(V*=W,L*=W,I<0&&I*I>o._restingThresh*n)S.normalImpulse=0;else{var D=S.normalImpulse;S.normalImpulse=Math.min(S.normalImpulse+V,0),V=S.normalImpulse-D}if(_*_>o._restingThreshTangent*n)S.tangentImpulse=0;else{var N=S.tangentImpulse;S.tangentImpulse=s.clamp(S.tangentImpulse+L,-F,F),L=S.tangentImpulse-N}i.x=g.x*V+x.x*L,i.y=g.y*V+x.y*L,v.isStatic||v.isSleeping||(v.positionPrev.x+=i.x*v.inverseMass,v.positionPrev.y+=i.y*v.inverseMass, -v.anglePrev+=r.cross(A,i)*v.inverseInertia),y.isStatic||y.isSleeping||(y.positionPrev.x-=i.x*y.inverseMass,y.positionPrev.y-=i.y*y.inverseMass,y.anglePrev-=r.cross(P,i)*y.inverseInertia)}}}}}()},{"../core/Common":14,"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29}],11:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../geometry/Vector");!function(){o.collides=function(e,t,n){var s,a,l,c,d=!1;if(n){var u=e.parent,p=t.parent,f=u.speed*u.speed+u.angularSpeed*u.angularSpeed+p.speed*p.speed+p.angularSpeed*p.angularSpeed;d=n&&n.collided&&f<.2,c=n}else c={collided:!1,bodyA:e,bodyB:t};if(n&&d){var m=c.axisBody,v=m===e?t:e,y=[m.axes[n.axisNumber]];if(l=o._overlapAxes(m.vertices,v.vertices,y),c.reused=!0,l.overlap<=0)return c.collided=!1,c}else{if(s=o._overlapAxes(e.vertices,t.vertices,e.axes),s.overlap<=0)return c.collided=!1,c;if(a=o._overlapAxes(t.vertices,e.vertices,t.axes),a.overlap<=0)return c.collided=!1,c;s.overlapi?i=a:a=0?s.index-1:d.length-1],c.x=i.x-u.x,c.y=i.y-u.y,l=-r.dot(n,c),a=i,i=d[(s.index+1)%d.length],c.x=i.x-u.x,c.y=i.y-u.y,o=-r.dot(n,c),o0?1:.7),t.damping=t.damping||0,t.angularStiffness=t.angularStiffness||0,t.angleA=t.bodyA?t.bodyA.angle:t.angleA,t.angleB=t.bodyB?t.bodyB.angle:t.angleB,t.plugin={};var s={visible:!0,lineWidth:2,strokeStyle:"#ffffff",type:"line",anchors:!0};return 0===t.length&&t.stiffness>.1?(s.type="pin",s.anchors=!1):t.stiffness<.9&&(s.type="spring"),t.render=c.extend(s,t.render),t},o.preSolveAll=function(e){for(var t=0;t0&&(u.position.x+=c.x,u.position.y+=c.y),0!==c.angle&&(i.rotate(u.vertices,c.angle,n.position),l.rotate(u.axes,c.angle), -d>0&&r.rotateAbout(u.position,c.angle,n.position,u.position)),a.update(u.bounds,u.vertices,n.velocity)}c.angle*=o._warming,c.x*=o._warming,c.y*=o._warming}}}}()},{"../core/Common":14,"../core/Sleeping":22,"../geometry/Axes":25,"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29}],13:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../core/Sleeping"),s=e("../core/Mouse"),a=e("../core/Events"),l=e("../collision/Detector"),c=e("./Constraint"),d=e("../body/Composite"),u=e("../core/Common"),p=e("../geometry/Bounds");!function(){o.create=function(e,t){var n=(e?e.mouse:null)||(t?t.mouse:null);n||(e&&e.render&&e.render.canvas?n=s.create(e.render.canvas):t&&t.element?n=s.create(t.element):(n=s.create(),u.warn("MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected")));var i=c.create({label:"Mouse Constraint",pointA:n.position,pointB:{x:0,y:0},length:.01,stiffness:.1,angularStiffness:1, -render:{strokeStyle:"#90EE90",lineWidth:3}}),r={type:"mouseConstraint",mouse:n,element:null,body:null,constraint:i,collisionFilter:{category:1,mask:4294967295,group:0}},l=u.extend(r,t);return a.on(e,"beforeUpdate",function(){var t=d.allBodies(e.world);o.update(l,t),o._triggerEvents(l)}),l},o.update=function(e,t){var n=e.mouse,o=e.constraint,s=e.body;if(0===n.button){if(o.bodyB)r.set(o.bodyB,!1),o.pointA=n.position;else for(var c=0;c1?1:0;d0;t--){var n=Math.floor(o.random()*(t+1)),i=e[t];e[t]=e[n],e[n]=i}return e},o.choose=function(e){return e[Math.floor(o.random()*e.length)]},o.isElement=function(e){return"undefined"!=typeof HTMLElement?e instanceof HTMLElement:!!(e&&e.nodeType&&e.nodeName)},o.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},o.isFunction=function(e){return"function"==typeof e},o.isPlainObject=function(e){return"object"==typeof e&&e.constructor===Object},o.isString=function(e){return"[object String]"===toString.call(e)},o.clamp=function(e,t,n){return en?n:e},o.sign=function(e){return e<0?-1:1},o.now=function(){ -if(window.performance){if(window.performance.now)return window.performance.now();if(window.performance.webkitNow)return window.performance.webkitNow()}return new Date-o._nowStartTime},o.random=function(e,n){return e=void 0!==e?e:0,n=void 0!==n?n:1,e+t()*(n-e)};var t=function(){return o._seed=(9301*o._seed+49297)%233280,o._seed/233280};o.colorToNumber=function(e){return e=e.replace("#",""),3==e.length&&(e=e.charAt(0)+e.charAt(0)+e.charAt(1)+e.charAt(1)+e.charAt(2)+e.charAt(2)),parseInt(e,16)},o.logLevel=1,o.log=function(){console&&o.logLevel>0&&o.logLevel<=3&&console.log.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},o.info=function(){console&&o.logLevel>0&&o.logLevel<=2&&console.info.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},o.warn=function(){console&&o.logLevel>0&&o.logLevel<=3&&console.warn.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},o.nextId=function(){return o._nextId++}, -o.indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;n0&&d.trigger(e,"collisionStart",{pairs:h.collisionStart}),s.preSolvePosition(h.list),i=0;i0&&d.trigger(e,"collisionActive",{pairs:h.collisionActive}),h.collisionEnd.length>0&&d.trigger(e,"collisionEnd",{pairs:h.collisionEnd}),o._bodiesClearForces(y),d.trigger(e,"afterUpdate",v),e},o.merge=function(e,t){if(f.extend(e,t),t.world){e.world=t.world,o.clear(e);for(var n=u.allBodies(e.world),i=0;ir?(i.warn("Plugin.register:",o.toString(t),"was upgraded to",o.toString(e)),o._registry[e.name]=e):n-1},o.isFor=function(e,t){var n=e.for&&o.dependencyParse(e.for) -;return!e.for||t.name===n.name&&o.versionSatisfies(t.version,n.range)},o.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0===e.uses.length)return void i.warn("Plugin.use:",o.toString(e),"does not specify any dependencies to install.");for(var n=o.dependencies(e),r=i.topologicalSort(n),s=[],a=0;a0&&i.info(s.join(" "))},o.dependencies=function(e,t){var n=o.dependencyParse(e),r=n.name;if(t=t||{},!(r in t)){e=o.resolve(e)||e,t[r]=i.map(e.uses||[],function(t){o.isPlugin(t)&&o.register(t);var r=o.dependencyParse(t),s=o.resolve(t) -;return s&&!o.versionSatisfies(s.version,r.range)?(i.warn("Plugin.dependencies:",o.toString(s),"does not satisfy",o.toString(r),"used by",o.toString(n)+"."),s._warned=!0,e._warned=!0):s||(i.warn("Plugin.dependencies:",o.toString(t),"used by",o.toString(n),"could not be resolved."),e._warned=!0),r.name});for(var s=0;s=i[2];if("^"===n.operator)return i[0]>0?s[0]===i[0]&&r.number>=n.number:i[1]>0?s[1]===i[1]&&s[2]>=i[2]:s[2]===i[2]}return e===t||"*"===e}}()},{"./Common":14}],21:[function(e,t,n){var o={};t.exports=o;var i=e("./Events"),r=e("./Engine"),s=e("./Common");!function(){var e,t;if("undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame,t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),!e){var n;e=function(e){n=setTimeout(function(){e(s.now())},1e3/60)},t=function(){clearTimeout(n)}}o.create=function(e){var t={fps:60,correction:1,deltaSampleSize:60, -counterTimestamp:0,frameCounter:0,deltaHistory:[],timePrev:null,timeScalePrev:1,frameRequestId:null,isFixed:!1,enabled:!0},n=s.extend(t,e);return n.delta=n.delta||1e3/n.fps,n.deltaMin=n.deltaMin||1e3/n.fps,n.deltaMax=n.deltaMax||1e3/(.5*n.fps),n.fps=1e3/n.delta,n},o.run=function(t,n){return void 0!==t.positionIterations&&(n=t,t=o.create()),function i(r){t.frameRequestId=e(i),r&&t.enabled&&o.tick(t,n,r)}(),t},o.tick=function(e,t,n){var o,s=t.timing,a=1,l={timestamp:s.timestamp};i.trigger(e,"beforeTick",l),i.trigger(t,"beforeTick",l),e.isFixed?o=e.delta:(o=n-e.timePrev||e.delta,e.timePrev=n,e.deltaHistory.push(o),e.deltaHistory=e.deltaHistory.slice(-e.deltaSampleSize),o=Math.min.apply(null,e.deltaHistory),o=oe.deltaMax?e.deltaMax:o,a=o/e.delta,e.delta=o),0!==e.timeScalePrev&&(a*=s.timeScale/e.timeScalePrev),0===s.timeScale&&(a=0),e.timeScalePrev=s.timeScale,e.correction=a,e.frameCounter+=1, -n-e.counterTimestamp>=1e3&&(e.fps=e.frameCounter*((n-e.counterTimestamp)/1e3),e.counterTimestamp=n,e.frameCounter=0),i.trigger(e,"tick",l),i.trigger(t,"tick",l),t.world.isModified&&t.render&&t.render.controller&&t.render.controller.clear&&t.render.controller.clear(t.render),i.trigger(e,"beforeUpdate",l),r.update(t,o,a),i.trigger(e,"afterUpdate",l),t.render&&t.render.controller&&(i.trigger(e,"beforeRender",l),i.trigger(t,"beforeRender",l),t.render.controller.world(t.render),i.trigger(e,"afterRender",l),i.trigger(t,"afterRender",l)),i.trigger(e,"afterTick",l),i.trigger(t,"afterTick",l)},o.stop=function(e){t(e.frameRequestId)},o.start=function(e,t){o.run(e,t)}}()},{"./Common":14,"./Engine":15,"./Events":16}],22:[function(e,t,n){var o={};t.exports=o;var i=e("./Events");!function(){o._motionWakeThreshold=.18,o._motionSleepThreshold=.08,o._minBias=.9,o.update=function(e,t){for(var n=t*t*t,i=0;i0&&r.motion=r.sleepThreshold&&o.set(r,!0)):r.sleepCounter>0&&(r.sleepCounter-=1)}else o.set(r,!1)}},o.afterCollisions=function(e,t){for(var n=t*t*t,i=0;io._motionWakeThreshold*n&&o.set(c,!1)}}}},o.set=function(e,t){var n=e.isSleeping;t?(e.isSleeping=!0,e.sleepCounter=e.sleepThreshold,e.positionImpulse.x=0,e.positionImpulse.y=0,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.anglePrev=e.angle,e.speed=0,e.angularSpeed=0,e.motion=0,n||i.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&i.trigger(e,"sleepEnd"))}}()},{ -"./Events":16}],23:[function(e,t,n){var o={};t.exports=o;var i,r=e("../geometry/Vertices"),s=e("../core/Common"),a=e("../body/Body"),l=e("../geometry/Bounds"),c=e("../geometry/Vector");!function(){o.rectangle=function(e,t,n,o,i){i=i||{};var l={label:"Rectangle Body",position:{x:e,y:t},vertices:r.fromPath("L 0 0 L "+n+" 0 L "+n+" "+o+" L 0 "+o)};if(i.chamfer){var c=i.chamfer;l.vertices=r.chamfer(l.vertices,c.radius,c.quality,c.qualityMin,c.qualityMax),delete i.chamfer}return a.create(s.extend({},l,i))},o.trapezoid=function(e,t,n,o,i,l){l=l||{},i*=.5;var c,d=(1-2*i)*n,u=n*i,p=u+d,f=p+u;c=i<.5?"L 0 0 L "+u+" "+-o+" L "+p+" "+-o+" L "+f+" 0":"L 0 0 L "+p+" "+-o+" L "+f+" 0";var m={label:"Trapezoid Body",position:{x:e,y:t},vertices:r.fromPath(c)};if(l.chamfer){var v=l.chamfer;m.vertices=r.chamfer(m.vertices,v.radius,v.quality,v.qualityMin,v.qualityMax),delete l.chamfer}return a.create(s.extend({},m,l))},o.circle=function(e,t,n,i,r){i=i||{};var a={label:"Circle Body",circleRadius:n};r=r||25 -;var l=Math.ceil(Math.max(10,Math.min(r,n)));return l%2==1&&(l+=1),o.polygon(e,t,l,n,s.extend({},a,i))},o.polygon=function(e,t,n,i,l){if(l=l||{},n<3)return o.circle(e,t,i,l);for(var c=2*Math.PI/n,d="",u=.5*c,p=0;p0&&r.area(P)1?(f=a.create(s.extend({parts:m.slice(0)},o)),a.setPosition(f,{x:e,y:t}),f):m[0]}}()},{"../body/Body":1,"../core/Common":14,"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29}],24:[function(e,t,n){var o={};t.exports=o -;var i=e("../body/Composite"),r=e("../constraint/Constraint"),s=e("../core/Common"),a=e("../body/Body"),l=e("./Bodies");!function(){o.stack=function(e,t,n,o,r,s,l){for(var c,d=i.create({label:"Stack"}),u=e,p=t,f=0,m=0;mv&&(v=x),a.translate(g,{x:.5*h,y:.5*x}),u=g.bounds.max.x+r,i.addBody(d,g),c=g,f+=1}else u+=r}p+=v+s,u=e}return d},o.chain=function(e,t,n,o,a,l){for(var c=e.bodies,d=1;d0)for(c=0;c0&&(p=f[c-1+(l-1)*t],i.addConstraint(e,r.create(s.extend({bodyA:p,bodyB:u},a)))),o&&cp)){c=p-c;var m=c,v=n-1-c;if(!(sv)){1===u&&a.translate(d,{x:(s+(n%2==1?1:-1))*f,y:0});return l(e+(d?s*f:0)+s*r,o,s,c,d,u)}}})},o.newtonsCradle=function(e,t,n,o,s){for(var a=i.create({label:"Newtons Cradle"}),c=0;ce.max.x&&(e.max.x=i.x),i.xe.max.y&&(e.max.y=i.y),i.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},o.contains=function(e,t){return t.x>=e.min.x&&t.x<=e.max.x&&t.y>=e.min.y&&t.y<=e.max.y},o.overlaps=function(e,t){return e.min.x<=t.max.x&&e.max.x>=t.min.x&&e.max.y>=t.min.y&&e.min.y<=t.max.y},o.translate=function(e,t){e.min.x+=t.x, -e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},o.shift=function(e,t){var n=e.max.x-e.min.x,o=e.max.y-e.min.y;e.min.x=t.x,e.max.x=t.x+n,e.min.y=t.y,e.max.y=t.y+o}}()},{}],27:[function(e,t,n){var o={};t.exports=o;var i=(e("../geometry/Bounds"),e("../core/Common"));!function(){o.pathToVertices=function(e,t){"undefined"==typeof window||"SVGPathSeg"in window||i.warn("Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.");var n,r,s,a,l,c,d,u,p,f,m,v,y=[],g=0,x=0,h=0;t=t||15;var b=function(e,t,n){var o=n%2==1&&n>1;if(!p||e!=p.x||t!=p.y){p&&o?(m=p.x,v=p.y):(m=0,v=0);var i={x:m+e,y:v+t};!o&&p||(p=i),y.push(i),x=m+e,h=v+t}},w=function(e){var t=e.pathSegTypeAsLetter.toUpperCase();if("Z"!==t){switch(t){case"M":case"L":case"T":case"C":case"S":case"Q":x=e.x,h=e.y;break;case"H":x=e.x;break;case"V":h=e.y}b(x,h,e.pathSegType)}};for(o._svgPathToAbsolute(e),s=e.getTotalLength(),c=[],n=0;n0)return!1}return!0},o.scale=function(e,t,n,r){if(1===t&&1===n)return e;r=r||o.centre(e);for(var s,a,l=0;l=0?l-1:e.length-1],d=e[l],u=e[(l+1)%e.length],p=t[l0&&(r|=2),3===r)return!1;return 0!==r||null},o.hull=function(e){var t,n,o=[],r=[];for(e=e.slice(0),e.sort(function(e,t){var n=e.x-t.x;return 0!==n?n:e.y-t.y}),n=0;n=2&&i.cross3(r[r.length-2],r[r.length-1],t)<=0;)r.pop();r.push(t)}for(n=e.length-1;n>=0;n-=1){for(t=e[n];o.length>=2&&i.cross3(o[o.length-2],o[o.length-1],t)<=0;)o.pop();o.push(t)}return o.pop(),r.pop(),o.concat(r)}}()},{"../core/Common":14,"../geometry/Vector":28}],30:[function(e,t,n){var o=t.exports=e("../core/Matter");o.Body=e("../body/Body"),o.Composite=e("../body/Composite"), -o.World=e("../body/World"),o.Contact=e("../collision/Contact"),o.Detector=e("../collision/Detector"),o.Grid=e("../collision/Grid"),o.Pairs=e("../collision/Pairs"),o.Pair=e("../collision/Pair"),o.Query=e("../collision/Query"),o.Resolver=e("../collision/Resolver"),o.SAT=e("../collision/SAT"),o.Constraint=e("../constraint/Constraint"),o.MouseConstraint=e("../constraint/MouseConstraint"),o.Common=e("../core/Common"),o.Engine=e("../core/Engine"),o.Events=e("../core/Events"),o.Mouse=e("../core/Mouse"),o.Runner=e("../core/Runner"),o.Sleeping=e("../core/Sleeping"),o.Plugin=e("../core/Plugin"),o.Bodies=e("../factory/Bodies"),o.Composites=e("../factory/Composites"),o.Axes=e("../geometry/Axes"),o.Bounds=e("../geometry/Bounds"),o.Svg=e("../geometry/Svg"),o.Vector=e("../geometry/Vector"),o.Vertices=e("../geometry/Vertices"),o.Render=e("../render/Render"),o.RenderPixi=e("../render/RenderPixi"),o.World.add=o.Composite.add,o.World.remove=o.Composite.remove, -o.World.addComposite=o.Composite.addComposite,o.World.addBody=o.Composite.addBody,o.World.addConstraint=o.Composite.addConstraint,o.World.clear=o.Composite.clear,o.Engine.run=o.Runner.run},{"../body/Body":1,"../body/Composite":2,"../body/World":3,"../collision/Contact":4,"../collision/Detector":5,"../collision/Grid":6,"../collision/Pair":7,"../collision/Pairs":8,"../collision/Query":9,"../collision/Resolver":10,"../collision/SAT":11,"../constraint/Constraint":12,"../constraint/MouseConstraint":13,"../core/Common":14,"../core/Engine":15,"../core/Events":16,"../core/Matter":17,"../core/Metrics":18,"../core/Mouse":19,"../core/Plugin":20,"../core/Runner":21,"../core/Sleeping":22,"../factory/Bodies":23,"../factory/Composites":24,"../geometry/Axes":25,"../geometry/Bounds":26,"../geometry/Svg":27,"../geometry/Vector":28,"../geometry/Vertices":29,"../render/Render":31,"../render/RenderPixi":32}],31:[function(e,t,n){var o={};t.exports=o -;var i=e("../core/Common"),r=e("../body/Composite"),s=e("../geometry/Bounds"),a=e("../core/Events"),l=e("../collision/Grid"),c=e("../geometry/Vector"),d=e("../core/Mouse");!function(){var e,t;"undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(function(){e(i.now())},1e3/60)},t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),o.create=function(e){var t={controller:o,engine:null,element:null,canvas:null,mouse:null,frameRequestId:null,options:{width:800,height:600,pixelRatio:1,background:"#18181d",wireframeBackground:"#0f0f13",hasBounds:!!e.bounds,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showBroadphase:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showSeparations:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showShadows:!1, -showVertexNumbers:!1,showConvexHulls:!1,showInternalEdges:!1,showMousePosition:!1}},r=i.extend(t,e);return r.canvas&&(r.canvas.width=r.options.width||r.canvas.width,r.canvas.height=r.options.height||r.canvas.height),r.mouse=e.mouse,r.engine=e.engine,r.canvas=r.canvas||n(r.options.width,r.options.height),r.context=r.canvas.getContext("2d"),r.textures={},r.bounds=r.bounds||{min:{x:0,y:0},max:{x:r.canvas.width,y:r.canvas.height}},1!==r.options.pixelRatio&&o.setPixelRatio(r,r.options.pixelRatio),i.isElement(r.element)?r.element.appendChild(r.canvas):r.canvas.parentNode||i.log("Render.create: options.element was undefined, render.canvas was created but not appended","warn"),r},o.run=function(t){!function n(i){t.frameRequestId=e(n),o.world(t)}()},o.stop=function(e){t(e.frameRequestId)},o.setPixelRatio=function(e,t){var n=e.options,o=e.canvas;"auto"===t&&(t=u(o)),n.pixelRatio=t,o.setAttribute("data-pixel-ratio",t),o.width=n.width*t,o.height=n.height*t,o.style.width=n.width+"px", -o.style.height=n.height+"px",e.context.scale(t,t)},o.lookAt=function(e,t,n,o){o=void 0===o||o,t=i.isArray(t)?t:[t],n=n||{x:0,y:0};for(var r={min:{x:1/0,y:1/0},max:{x:-1/0,y:-1/0}},s=0;sr.max.x&&(r.max.x=c.x),l.yr.max.y&&(r.max.y=c.y))}var u=r.max.x-r.min.x+2*n.x,p=r.max.y-r.min.y+2*n.y,f=e.canvas.height,m=e.canvas.width,v=m/f,y=u/p,g=1,x=1;y>v?x=y/v:g=v/y,e.options.hasBounds=!0,e.bounds.min.x=r.min.x,e.bounds.max.x=r.min.x+u*g,e.bounds.min.y=r.min.y,e.bounds.max.y=r.min.y+p*x,o&&(e.bounds.min.x+=.5*u-u*g*.5,e.bounds.max.x+=.5*u-u*g*.5,e.bounds.min.y+=.5*p-p*x*.5,e.bounds.max.y+=.5*p-p*x*.5),e.bounds.min.x-=n.x,e.bounds.max.x-=n.x,e.bounds.min.y-=n.y,e.bounds.max.y-=n.y,e.mouse&&(d.setScale(e.mouse,{x:(e.bounds.max.x-e.bounds.min.x)/e.canvas.width,y:(e.bounds.max.y-e.bounds.min.y)/e.canvas.height}), -d.setOffset(e.mouse,e.bounds.min))},o.startViewTransform=function(e){var t=e.bounds.max.x-e.bounds.min.x,n=e.bounds.max.y-e.bounds.min.y,o=t/e.options.width,i=n/e.options.height;e.context.scale(1/o,1/i),e.context.translate(-e.bounds.min.x,-e.bounds.min.y)},o.endViewTransform=function(e){e.context.setTransform(e.options.pixelRatio,0,0,e.options.pixelRatio,0,0)},o.world=function(e){var t,n=e.engine,i=n.world,u=e.canvas,p=e.context,m=e.options,v=r.allBodies(i),y=r.allConstraints(i),g=m.wireframes?m.wireframeBackground:m.background,x=[],h=[],b={timestamp:n.timing.timestamp};if(a.trigger(e,"beforeRender",b),e.currentBackground!==g&&f(e,g),p.globalCompositeOperation="source-in",p.fillStyle="transparent",p.fillRect(0,0,u.width,u.height),p.globalCompositeOperation="source-over",m.hasBounds){for(t=0;t=500){var l="";s.timing&&(l+="fps: "+Math.round(s.timing.fps)+" "),e.debugString=l,e.debugTimestamp=o.timing.timestamp}if(e.debugString){n.font="12px Arial",a.wireframes?n.fillStyle="rgba(255,255,255,0.5)":n.fillStyle="rgba(0,0,0,0.5)";for(var c=e.debugString.split("\n"),d=0;d1?1:0;s1?1:0;a1?1:0;r1?1:0;a1?1:0;r1?1:0;r1?1:0;i0)){var u=o.activeContacts[0].vertex.x,p=o.activeContacts[0].vertex.y;2===o.activeContacts.length&&(u=(o.activeContacts[0].vertex.x+o.activeContacts[1].vertex.x)/2,p=(o.activeContacts[0].vertex.y+o.activeContacts[1].vertex.y)/2),i.bodyB===i.supports[0].body||!0===i.bodyA.isStatic?a.moveTo(u-8*i.normal.x,p-8*i.normal.y):a.moveTo(u+8*i.normal.x,p+8*i.normal.y),a.lineTo(u,p)} -l.wireframes?a.strokeStyle="rgba(255,165,0,0.7)":a.strokeStyle="orange",a.lineWidth=1,a.stroke()},o.separations=function(e,t,n){var o,i,r,s,a,l=n,c=e.options;for(l.beginPath(),a=0;a1?1:0;p0;t--){var i=Math.floor(n.random()*(t+1)),o=e[t];e[t]=e[i],e[i]=o}return e},n.choose=function(e){return e[Math.floor(n.random()*e.length)]},n.isElement=function(e){return"undefined"!=typeof HTMLElement?e instanceof HTMLElement:!!(e&&e.nodeType&&e.nodeName)},n.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},n.isFunction=function(e){return"function"==typeof e},n.isPlainObject=function(e){return"object"==typeof e&&e.constructor===Object},n.isString=function(e){return"[object String]"===toString.call(e)},n.clamp=function(e,t,n){return en?n:e},n.sign=function(e){return e<0?-1:1},n.now=function(){if("undefined"!=typeof window&&window.performance){if(window.performance.now)return window.performance.now();if(window.performance.webkitNow)return window.performance.webkitNow()}return Date.now?Date.now():new Date-n._nowStartTime},n.random=function(t,n){return n=void 0!==n?n:1,(t=void 0!==t?t:0)+e()*(n-t)};var e=function(){return n._seed=(9301*n._seed+49297)%233280,n._seed/233280};n.colorToNumber=function(e){return 3==(e=e.replace("#","")).length&&(e=e.charAt(0)+e.charAt(0)+e.charAt(1)+e.charAt(1)+e.charAt(2)+e.charAt(2)),parseInt(e,16)},n.logLevel=1,n.log=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.log.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.info=function(){console&&n.logLevel>0&&n.logLevel<=2&&console.info.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warn=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.warn.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warnOnce=function(){var e=Array.prototype.slice.call(arguments).join(" ");n._warnedOnce[e]||(n.warn(e),n._warnedOnce[e]=!0)},n.deprecated=function(e,t,i){e[t]=n.chain((function(){n.warnOnce("🔅 deprecated 🔅",i)}),e[t])},n.nextId=function(){return n._nextId++},n.indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;ne.max.x&&(e.max.x=o.x),o.xe.max.y&&(e.max.y=o.y),o.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},n.contains=function(e,t){return t.x>=e.min.x&&t.x<=e.max.x&&t.y>=e.min.y&&t.y<=e.max.y},n.overlaps=function(e,t){return e.min.x<=t.max.x&&e.max.x>=t.min.x&&e.max.y>=t.min.y&&e.min.y<=t.max.y},n.translate=function(e,t){e.min.x+=t.x,e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},n.shift=function(e,t){var n=e.max.x-e.min.x,i=e.max.y-e.min.y;e.min.x=t.x,e.max.x=t.x+n,e.min.y=t.y,e.max.y=t.y+i}},function(e,t){var n={};e.exports=n,n.create=function(e,t){return{x:e||0,y:t||0}},n.clone=function(e){return{x:e.x,y:e.y}},n.magnitude=function(e){return Math.sqrt(e.x*e.x+e.y*e.y)},n.magnitudeSquared=function(e){return e.x*e.x+e.y*e.y},n.rotate=function(e,t,n){var i=Math.cos(t),o=Math.sin(t);n||(n={});var r=e.x*i-e.y*o;return n.y=e.x*o+e.y*i,n.x=r,n},n.rotateAbout=function(e,t,n,i){var o=Math.cos(t),r=Math.sin(t);i||(i={});var a=n.x+((e.x-n.x)*o-(e.y-n.y)*r);return i.y=n.y+((e.x-n.x)*r+(e.y-n.y)*o),i.x=a,i},n.normalise=function(e){var t=n.magnitude(e);return 0===t?{x:0,y:0}:{x:e.x/t,y:e.y/t}},n.dot=function(e,t){return e.x*t.x+e.y*t.y},n.cross=function(e,t){return e.x*t.y-e.y*t.x},n.cross3=function(e,t,n){return(t.x-e.x)*(n.y-e.y)-(t.y-e.y)*(n.x-e.x)},n.add=function(e,t,n){return n||(n={}),n.x=e.x+t.x,n.y=e.y+t.y,n},n.sub=function(e,t,n){return n||(n={}),n.x=e.x-t.x,n.y=e.y-t.y,n},n.mult=function(e,t){return{x:e.x*t,y:e.y*t}},n.div=function(e,t){return{x:e.x/t,y:e.y/t}},n.perp=function(e,t){return{x:(t=!0===t?-1:1)*-e.y,y:t*e.x}},n.neg=function(e){return{x:-e.x,y:-e.y}},n.angle=function(e,t){return Math.atan2(t.y-e.y,t.x-e.x)},n._temp=[n.create(),n.create(),n.create(),n.create(),n.create(),n.create()]},function(e,t,n){var i={};e.exports=i;var o=n(2),r=n(0);i.create=function(e,t){for(var n=[],i=0;i0)return!1}return!0},i.scale=function(e,t,n,r){if(1===t&&1===n)return e;var a,s;r=r||i.centre(e);for(var l=0;l=0?l-1:e.length-1],u=e[l],d=e[(l+1)%e.length],p=t[l0&&(r|=2),3===r)return!1;return 0!==r||null},i.hull=function(e){var t,n,i=[],r=[];for((e=e.slice(0)).sort((function(e,t){var n=e.x-t.x;return 0!==n?n:e.y-t.y})),n=0;n=2&&o.cross3(r[r.length-2],r[r.length-1],t)<=0;)r.pop();r.push(t)}for(n=e.length-1;n>=0;n-=1){for(t=e[n];i.length>=2&&o.cross3(i[i.length-2],i[i.length-1],t)<=0;)i.pop();i.push(t)}return i.pop(),r.pop(),i.concat(r)}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.on=function(e,t,n){for(var i,o=t.split(" "),r=0;r0){n||(n={}),i=t.split(" ");for(var c=0;c0&&r.rotateAbout(a.position,n,e.position,a.position)}},i.setVelocity=function(e,t){e.positionPrev.x=e.position.x-t.x,e.positionPrev.y=e.position.y-t.y,e.velocity.x=t.x,e.velocity.y=t.y,e.speed=r.magnitude(e.velocity)},i.setAngularVelocity=function(e,t){e.anglePrev=e.angle-t,e.angularVelocity=t,e.angularSpeed=Math.abs(e.angularVelocity)},i.translate=function(e,t){i.setPosition(e,r.add(e.position,t))},i.rotate=function(e,t,n){if(n){var o=Math.cos(t),r=Math.sin(t),a=e.position.x-n.x,s=e.position.y-n.y;i.setPosition(e,{x:n.x+(a*o-s*r),y:n.y+(a*r+s*o)}),i.setAngle(e,e.angle+t)}else i.setAngle(e,e.angle+t)},i.scale=function(e,t,n,r){var a=0,s=0;r=r||e.position;for(var u=0;u0&&(a+=d.area,s+=d.inertia),d.position.x=r.x+(d.position.x-r.x)*t,d.position.y=r.y+(d.position.y-r.y)*n,l.update(d.bounds,d.vertices,e.velocity)}e.parts.length>1&&(e.area=a,e.isStatic||(i.setMass(e,e.density*a),i.setInertia(e,s))),e.circleRadius&&(t===n?e.circleRadius*=t:e.circleRadius=null)},i.update=function(e,t,n,i){var a=Math.pow(t*n*e.timeScale,2),s=1-e.frictionAir*n*e.timeScale,u=e.position.x-e.positionPrev.x,d=e.position.y-e.positionPrev.y;e.velocity.x=u*s*i+e.force.x/e.mass*a,e.velocity.y=d*s*i+e.force.y/e.mass*a,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.angularVelocity=(e.angle-e.anglePrev)*s*i+e.torque/e.inertia*a,e.anglePrev=e.angle,e.angle+=e.angularVelocity,e.speed=r.magnitude(e.velocity),e.angularSpeed=Math.abs(e.angularVelocity);for(var p=0;p0&&(f.position.x+=e.velocity.x,f.position.y+=e.velocity.y),0!==e.angularVelocity&&(o.rotate(f.vertices,e.angularVelocity,e.position),c.rotate(f.axes,e.angularVelocity),p>0&&r.rotateAbout(f.position,e.angularVelocity,e.position,f.position)),l.update(f.bounds,f.vertices,e.velocity)}},i.applyForce=function(e,t,n){e.force.x+=n.x,e.force.y+=n.y;var i=t.x-e.position.x,o=t.y-e.position.y;e.torque+=i*n.y-o*n.x},i._totalProperties=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n0&&r.motion=r.sleepThreshold&&i.set(r,!0)):r.sleepCounter>0&&(r.sleepCounter-=1)}else i.set(r,!1)}},i.afterCollisions=function(e,t){for(var n=t*t*t,o=0;oi._motionWakeThreshold*n&&i.set(c,!1)}}}},i.set=function(e,t){var n=e.isSleeping;t?(e.isSleeping=!0,e.sleepCounter=e.sleepThreshold,e.positionImpulse.x=0,e.positionImpulse.y=0,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.anglePrev=e.angle,e.speed=0,e.angularSpeed=0,e.motion=0,n||o.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&o.trigger(e,"sleepEnd"))}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(2),a=n(7),s=n(1),l=n(10),c=n(0);i._warming=.4,i._torqueDampen=1,i._minLength=1e-6,i.create=function(e){var t=e;t.bodyA&&!t.pointA&&(t.pointA={x:0,y:0}),t.bodyB&&!t.pointB&&(t.pointB={x:0,y:0});var n=t.bodyA?r.add(t.bodyA.position,t.pointA):t.pointA,i=t.bodyB?r.add(t.bodyB.position,t.pointB):t.pointB,o=r.magnitude(r.sub(n,i));t.length=void 0!==t.length?t.length:o,t.id=t.id||c.nextId(),t.label=t.label||"Constraint",t.type="constraint",t.stiffness=t.stiffness||(t.length>0?1:.7),t.damping=t.damping||0,t.angularStiffness=t.angularStiffness||0,t.angleA=t.bodyA?t.bodyA.angle:t.angleA,t.angleB=t.bodyB?t.bodyB.angle:t.angleB,t.plugin={};var a={visible:!0,lineWidth:2,strokeStyle:"#ffffff",type:"line",anchors:!0};return 0===t.length&&t.stiffness>.1?(a.type="pin",a.anchors=!1):t.stiffness<.9&&(a.type="spring"),t.render=c.extend(a,t.render),t},i.preSolveAll=function(e){for(var t=0;t0&&(d.position.x+=c.x,d.position.y+=c.y),0!==c.angle&&(o.rotate(d.vertices,c.angle,n.position),l.rotate(d.axes,c.angle),u>0&&r.rotateAbout(d.position,c.angle,n.position,d.position)),s.update(d.bounds,d.vertices,n.velocity)}c.angle*=i._warming,c.x*=i._warming,c.y*=i._warming}}},i.pointAWorld=function(e){return{x:(e.bodyA?e.bodyA.position.x:0)+e.pointA.x,y:(e.bodyA?e.bodyA.position.y:0)+e.pointA.y}},i.pointBWorld=function(e){return{x:(e.bodyB?e.bodyB.position.x:0)+e.pointB.x,y:(e.bodyB?e.bodyB.position.y:0)+e.pointB.y}}},function(e,t,n){var i={};e.exports=i;var o=n(17);i.create=function(e,t){var n=e.bodyA,o=e.bodyB,r=e.parentA,a=e.parentB,s={id:i.id(n,o),bodyA:n,bodyB:o,contacts:{},activeContacts:[],separation:0,isActive:!0,confirmedActive:!0,isSensor:n.isSensor||o.isSensor,timeCreated:t,timeUpdated:t,inverseMass:r.inverseMass+a.inverseMass,friction:Math.min(r.friction,a.friction),frictionStatic:Math.max(r.frictionStatic,a.frictionStatic),restitution:Math.max(r.restitution,a.restitution),slop:Math.max(r.slop,a.slop)};return i.update(s,e,t),s},i.update=function(e,t,n){var r=e.contacts,a=t.supports,s=e.activeContacts,l=t.parentA,c=t.parentB;if(e.collision=t,e.inverseMass=l.inverseMass+c.inverseMass,e.friction=Math.min(l.friction,c.friction),e.frictionStatic=Math.max(l.frictionStatic,c.frictionStatic),e.restitution=Math.max(l.restitution,c.restitution),e.slop=Math.max(l.slop,c.slop),s.length=0,t.collided){for(var u=0;u0&&o.area(C)1?(v=a.create(r.extend({parts:m.slice(0)},i)),a.setPosition(v,{x:e,y:t}),v):m[0]}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.create=function(e){var t={};return e||o.log("Mouse.create: element was undefined, defaulting to document.body","warn"),t.element=e||document.body,t.absolute={x:0,y:0},t.position={x:0,y:0},t.mousedownPosition={x:0,y:0},t.mouseupPosition={x:0,y:0},t.offset={x:0,y:0},t.scale={x:1,y:1},t.wheelDelta=0,t.button=-1,t.pixelRatio=parseInt(t.element.getAttribute("data-pixel-ratio"),10)||1,t.sourceEvents={mousemove:null,mousedown:null,mouseup:null,mousewheel:null},t.mousemove=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&(t.button=0,e.preventDefault()),t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.sourceEvents.mousemove=e},t.mousedown=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches?(t.button=0,e.preventDefault()):t.button=e.button,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mousedownPosition.x=t.position.x,t.mousedownPosition.y=t.position.y,t.sourceEvents.mousedown=e},t.mouseup=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&e.preventDefault(),t.button=-1,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mouseupPosition.x=t.position.x,t.mouseupPosition.y=t.position.y,t.sourceEvents.mouseup=e},t.mousewheel=function(e){t.wheelDelta=Math.max(-1,Math.min(1,e.wheelDelta||-e.detail)),e.preventDefault()},i.setElement(t,t.element),t},i.setElement=function(e,t){e.element=t,t.addEventListener("mousemove",e.mousemove),t.addEventListener("mousedown",e.mousedown),t.addEventListener("mouseup",e.mouseup),t.addEventListener("mousewheel",e.mousewheel),t.addEventListener("DOMMouseScroll",e.mousewheel),t.addEventListener("touchmove",e.mousemove),t.addEventListener("touchstart",e.mousedown),t.addEventListener("touchend",e.mouseup)},i.clearSourceEvents=function(e){e.sourceEvents.mousemove=null,e.sourceEvents.mousedown=null,e.sourceEvents.mouseup=null,e.sourceEvents.mousewheel=null,e.wheelDelta=0},i.setOffset=function(e,t){e.offset.x=t.x,e.offset.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i.setScale=function(e,t){e.scale.x=t.x,e.scale.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i._getRelativeMousePosition=function(e,t,n){var i,o,r=t.getBoundingClientRect(),a=document.documentElement||document.body.parentNode||document.body,s=void 0!==window.pageXOffset?window.pageXOffset:a.scrollLeft,l=void 0!==window.pageYOffset?window.pageYOffset:a.scrollTop,c=e.changedTouches;return c?(i=c[0].pageX-r.left-s,o=c[0].pageY-r.top-l):(i=e.pageX-r.left-s,o=e.pageY-r.top-l),{x:i/(t.clientWidth/(t.width||t.clientWidth)*n),y:o/(t.clientHeight/(t.height||t.clientHeight)*n)}}},function(e,t,n){var i={};e.exports=i;var o=n(14),r=n(9),a=n(1);i.collisions=function(e,t){for(var n=[],s=t.pairs.table,l=0;l1?1:0;d1?1:0;f0:0!=(e.mask&t.category)&&0!=(t.mask&e.category)}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(2);i.collides=function(e,t,n){var a,s,l,c,u=!1;if(n){var d=e.parent,p=t.parent,f=d.speed*d.speed+d.angularSpeed*d.angularSpeed+p.speed*p.speed+p.angularSpeed*p.angularSpeed;u=n&&n.collided&&f<.2,c=n}else c={collided:!1,bodyA:e,bodyB:t};if(n&&u){var v=c.axisBody,m=v===e?t:e,y=[v.axes[n.axisNumber]];if(l=i._overlapAxes(v.vertices,m.vertices,y),c.reused=!0,l.overlap<=0)return c.collided=!1,c}else{if((a=i._overlapAxes(e.vertices,t.vertices,e.axes)).overlap<=0)return c.collided=!1,c;if((s=i._overlapAxes(t.vertices,e.vertices,t.axes)).overlap<=0)return c.collided=!1,c;a.overlapo?o=s:s=0?a.index-1:u.length-1],c.x=o.x-d.x,c.y=o.y-d.y,l=-r.dot(n,c),s=o,o=u[(a.index+1)%u.length],c.x=o.x-d.x,c.y=o.y-d.y,(i=-r.dot(n,c))r?(o.warn("Plugin.register:",i.toString(t),"was upgraded to",i.toString(e)),i._registry[e.name]=e):n-1},i.isFor=function(e,t){var n=e.for&&i.dependencyParse(e.for);return!e.for||t.name===n.name&&i.versionSatisfies(t.version,n.range)},i.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0!==e.uses.length){for(var n=i.dependencies(e),r=o.topologicalSort(n),a=[],s=0;s0&&o.info(a.join(" "))}else o.warn("Plugin.use:",i.toString(e),"does not specify any dependencies to install.")},i.dependencies=function(e,t){var n=i.dependencyParse(e),r=n.name;if(!(r in(t=t||{}))){e=i.resolve(e)||e,t[r]=o.map(e.uses||[],(function(t){i.isPlugin(t)&&i.register(t);var r=i.dependencyParse(t),a=i.resolve(t);return a&&!i.versionSatisfies(a.version,r.range)?(o.warn("Plugin.dependencies:",i.toString(a),"does not satisfy",i.toString(r),"used by",i.toString(n)+"."),a._warned=!0,e._warned=!0):a||(o.warn("Plugin.dependencies:",i.toString(t),"used by",i.toString(n),"could not be resolved."),e._warned=!0),r.name}));for(var a=0;a=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-]+)?$/;t.test(e)||o.warn("Plugin.versionParse:",e,"is not a valid version or range.");var n=t.exec(e),i=Number(n[4]),r=Number(n[5]),a=Number(n[6]);return{isRange:Boolean(n[1]||n[2]),version:n[3],range:e,operator:n[1]||n[2]||"",major:i,minor:r,patch:a,parts:[i,r,a],prerelease:n[7],number:1e8*i+1e4*r+a}},i.versionSatisfies=function(e,t){t=t||"*";var n=i.versionParse(t),o=i.versionParse(e);if(n.isRange){if("*"===n.operator||"*"===e)return!0;if(">"===n.operator)return o.number>n.number;if(">="===n.operator)return o.number>=n.number;if("~"===n.operator)return o.major===n.major&&o.minor===n.minor&&o.patch>=n.patch;if("^"===n.operator)return n.major>0?o.major===n.major&&o.number>=n.number:n.minor>0?o.minor===n.minor&&o.patch>=n.patch:o.patch===n.patch}return e===t||"*"===e}},function(e,t,n){var i={};e.exports=i;var o=n(0),r=n(5),a=n(1),s=n(4),l=n(2),c=n(12);!function(){var e,t;"undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout((function(){e(o.now())}),1e3/60)},t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),i._goodFps=30,i._goodDelta=1e3/60,i.create=function(e){var t={controller:i,engine:null,element:null,canvas:null,mouse:null,frameRequestId:null,timing:{historySize:60,delta:0,deltaHistory:[],lastTime:0,lastTimestamp:0,lastElapsed:0,timestampElapsed:0,timestampElapsedHistory:[],engineDeltaHistory:[],engineElapsedHistory:[],elapsedHistory:[]},options:{width:800,height:600,pixelRatio:1,background:"#14151f",wireframeBackground:"#14151f",hasBounds:!!e.bounds,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showStats:!1,showPerformance:!1,showBroadphase:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showSeparations:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showVertexNumbers:!1,showConvexHulls:!1,showInternalEdges:!1,showMousePosition:!1}},n=o.extend(t,e);return n.canvas&&(n.canvas.width=n.options.width||n.canvas.width,n.canvas.height=n.options.height||n.canvas.height),n.mouse=e.mouse,n.engine=e.engine,n.canvas=n.canvas||d(n.options.width,n.options.height),n.context=n.canvas.getContext("2d"),n.textures={},n.bounds=n.bounds||{min:{x:0,y:0},max:{x:n.canvas.width,y:n.canvas.height}},1!==n.options.pixelRatio&&i.setPixelRatio(n,n.options.pixelRatio),o.isElement(n.element)?n.element.appendChild(n.canvas):n.canvas.parentNode||o.log("Render.create: options.element was undefined, render.canvas was created but not appended","warn"),n},i.run=function(t){!function o(r){t.frameRequestId=e(o),n(t,r),i.world(t,r),(t.options.showStats||t.options.showDebug)&&i.stats(t,t.context,r),(t.options.showPerformance||t.options.showDebug)&&i.performance(t,t.context,r)}()},i.stop=function(e){t(e.frameRequestId)},i.setPixelRatio=function(e,t){var n=e.options,i=e.canvas;"auto"===t&&(t=p(i)),n.pixelRatio=t,i.setAttribute("data-pixel-ratio",t),i.width=n.width*t,i.height=n.height*t,i.style.width=n.width+"px",i.style.height=n.height+"px"},i.lookAt=function(e,t,n,i){i=void 0===i||i,t=o.isArray(t)?t:[t],n=n||{x:0,y:0};for(var r={min:{x:1/0,y:1/0},max:{x:-1/0,y:-1/0}},a=0;ar.max.x&&(r.max.x=u.x),l.yr.max.y&&(r.max.y=u.y))}var d=r.max.x-r.min.x+2*n.x,p=r.max.y-r.min.y+2*n.y,f=e.canvas.height,v=e.canvas.width/f,m=d/p,y=1,g=1;m>v?g=m/v:y=v/m,e.options.hasBounds=!0,e.bounds.min.x=r.min.x,e.bounds.max.x=r.min.x+d*y,e.bounds.min.y=r.min.y,e.bounds.max.y=r.min.y+p*g,i&&(e.bounds.min.x+=.5*d-d*y*.5,e.bounds.max.x+=.5*d-d*y*.5,e.bounds.min.y+=.5*p-p*g*.5,e.bounds.max.y+=.5*p-p*g*.5),e.bounds.min.x-=n.x,e.bounds.max.x-=n.x,e.bounds.min.y-=n.y,e.bounds.max.y-=n.y,e.mouse&&(c.setScale(e.mouse,{x:(e.bounds.max.x-e.bounds.min.x)/e.canvas.width,y:(e.bounds.max.y-e.bounds.min.y)/e.canvas.height}),c.setOffset(e.mouse,e.bounds.min))},i.startViewTransform=function(e){var t=e.bounds.max.x-e.bounds.min.x,n=e.bounds.max.y-e.bounds.min.y,i=t/e.options.width,o=n/e.options.height;e.context.setTransform(e.options.pixelRatio/i,0,0,e.options.pixelRatio/o,0,0),e.context.translate(-e.bounds.min.x,-e.bounds.min.y)},i.endViewTransform=function(e){e.context.setTransform(e.options.pixelRatio,0,0,e.options.pixelRatio,0,0)},i.world=function(e,t){var n,u=o.now(),d=e.engine,p=d.world,f=e.canvas,m=e.context,y=e.options,g=e.timing,x=r.allBodies(p),h=r.allConstraints(p),b=y.wireframes?y.wireframeBackground:y.background,S=[],w=[],A={timestamp:d.timing.timestamp};if(s.trigger(e,"beforeRender",A),e.currentBackground!==b&&v(e,b),m.globalCompositeOperation="source-in",m.fillStyle="transparent",m.fillRect(0,0,f.width,f.height),m.globalCompositeOperation="source-over",y.hasBounds){for(n=0;n1?1:0;a1?1:0;s1?1:0;r1?1:0;s1?1:0;r1?1:0;r1?1:0;o0)){var u=i.activeContacts[0].vertex.x,d=i.activeContacts[0].vertex.y;2===i.activeContacts.length&&(u=(i.activeContacts[0].vertex.x+i.activeContacts[1].vertex.x)/2,d=(i.activeContacts[0].vertex.y+i.activeContacts[1].vertex.y)/2),o.bodyB===o.supports[0].body||!0===o.bodyA.isStatic?s.moveTo(u-8*o.normal.x,d-8*o.normal.y):s.moveTo(u+8*o.normal.x,d+8*o.normal.y),s.lineTo(u,d)}l.wireframes?s.strokeStyle="rgba(255,165,0,0.7)":s.strokeStyle="orange",s.lineWidth=1,s.stroke()},i.separations=function(e,t,n){var i,o,r,a,s,l=n,c=e.options;for(l.beginPath(),s=0;s0&&c.trigger(e,"collisionStart",{pairs:A.collisionStart}),r.preSolvePosition(A.list),m=0;m0&&c.trigger(e,"collisionActive",{pairs:A.collisionActive}),A.collisionEnd.length>0&&c.trigger(e,"collisionEnd",{pairs:A.collisionEnd}),i._bodiesClearForces(b),c.trigger(e,"afterUpdate",h),e.timing.lastElapsed=p.now()-f,e},i.merge=function(e,t){if(p.extend(e,t),t.world){e.world=t.world,i.clear(e);for(var n=u.allBodies(e.world),r=0;rf.friction*f.frictionStatic*L*n&&(O=T,V=a.clamp(f.friction*R*n,-O,O));var F=r.cross(P,g),D=r.cross(M,g),H=b/(m.inverseMass+y.inverseMass+m.inverseInertia*F*F+y.inverseInertia*D*D);if(E*=H,V*=H,k<0&&k*k>i._restingThresh*n)w.normalImpulse=0;else{var j=w.normalImpulse;w.normalImpulse=Math.min(w.normalImpulse+E,0),E=w.normalImpulse-j}if(I*I>i._restingThreshTangent*n)w.tangentImpulse=0;else{var W=w.tangentImpulse;w.tangentImpulse=a.clamp(w.tangentImpulse+V,-O,O),V=w.tangentImpulse-W}o.x=g.x*E+x.x*V,o.y=g.y*E+x.y*V,m.isStatic||m.isSleeping||(m.positionPrev.x+=o.x*m.inverseMass,m.positionPrev.y+=o.y*m.inverseMass,m.anglePrev+=r.cross(P,o)*m.inverseInertia),y.isStatic||y.isSleeping||(y.positionPrev.x-=o.x*y.inverseMass,y.positionPrev.y-=o.y*y.inverseMass,y.anglePrev-=r.cross(M,o)*y.inverseInertia)}}}}},function(e,t,n){var i={};e.exports=i;var o=n(9),r=n(0);i._pairMaxIdleLife=1e3,i.create=function(e){return r.extend({table:{},list:[],collisionStart:[],collisionActive:[],collisionEnd:[]},e)},i.update=function(e,t,n){var i,r,a,s,l=e.list,c=e.table,u=e.collisionStart,d=e.collisionEnd,p=e.collisionActive;for(u.length=0,d.length=0,p.length=0,s=0;si._pairMaxIdleLife&&c.push(a);for(a=0;au.bounds.max.x||f.bounds.max.yu.bounds.max.y))){var v=i._getRegion(e,f);if(!f.region||v.id!==f.region.id||o){f.region&&!o||(f.region=v);var m=i._regionUnion(v,f.region);for(a=m.startCol;a<=m.endCol;a++)for(s=m.startRow;s<=m.endRow;s++){l=d[c=i._getBucketId(a,s)];var y=a>=v.startCol&&a<=v.endCol&&s>=v.startRow&&s<=v.endRow,g=a>=f.region.startCol&&a<=f.region.endCol&&s>=f.region.startRow&&s<=f.region.endRow;!y&&g&&g&&l&&i._bucketRemoveBody(e,l,f),(f.region===v||y&&!g||o)&&(l||(l=i._createBucket(d,c)),i._bucketAddBody(e,l,f))}f.region=v,p=!0}}}p&&(e.pairsList=i._createActivePairsList(e))},i.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]},i._regionUnion=function(e,t){var n=Math.min(e.startCol,t.startCol),o=Math.max(e.endCol,t.endCol),r=Math.min(e.startRow,t.startRow),a=Math.max(e.endRow,t.endRow);return i._createRegion(n,o,r,a)},i._getRegion=function(e,t){var n=t.bounds,o=Math.floor(n.min.x/e.bucketWidth),r=Math.floor(n.max.x/e.bucketWidth),a=Math.floor(n.min.y/e.bucketHeight),s=Math.floor(n.max.y/e.bucketHeight);return i._createRegion(o,r,a,s)},i._createRegion=function(e,t,n,i){return{id:e+","+t+","+n+","+i,startCol:e,endCol:t,startRow:n,endRow:i}},i._getBucketId=function(e,t){return"C"+e+"R"+t},i._createBucket=function(e,t){return e[t]=[]},i._bucketAddBody=function(e,t,n){for(var i=0;i0?i.push(n):delete e.pairs[t[o]];return i}},function(e,t,n){var i=e.exports=n(23);i.Axes=n(10),i.Bodies=n(11),i.Body=n(6),i.Bounds=n(1),i.Common=n(0),i.Composite=n(5),i.Composites=n(24),i.Constraint=n(8),i.Contact=n(17),i.Detector=n(13),i.Engine=n(18),i.Events=n(4),i.Grid=n(21),i.Mouse=n(12),i.MouseConstraint=n(25),i.Pair=n(9),i.Pairs=n(20),i.Plugin=n(15),i.Query=n(26),i.Render=n(16),i.Resolver=n(19),i.Runner=n(27),i.SAT=n(14),i.Sleeping=n(7),i.Svg=n(28),i.Vector=n(2),i.Vertices=n(3),i.World=n(29),i.Engine.run=i.Runner.run,i.Common.deprecated(i.Engine,"run","Engine.run ➤ use Matter.Runner.run(engine) instead")},function(e,t,n){var i={};e.exports=i;var o=n(15),r=n(0);i.name="matter-js",i.version="0.17.1",i.uses=[],i.used=[],i.use=function(){o.use(i,Array.prototype.slice.call(arguments))},i.before=function(e,t){return e=e.replace(/^Matter./,""),r.chainPathBefore(i,e,t)},i.after=function(e,t){return e=e.replace(/^Matter./,""),r.chainPathAfter(i,e,t)}},function(e,t,n){var i={};e.exports=i;var o=n(5),r=n(8),a=n(0),s=n(6),l=n(11),c=a.deprecated;i.stack=function(e,t,n,i,r,a,l){for(var c,u=o.create({label:"Stack"}),d=e,p=t,f=0,v=0;vm&&(m=x),s.translate(g,{x:.5*h,y:.5*x}),d=g.bounds.max.x+r,o.addBody(u,g),c=g,f+=1}else d+=r}p+=m+a,d=e}return u},i.chain=function(e,t,n,i,s,l){for(var c=e.bodies,u=1;u0)for(c=0;c0&&(p=f[c-1+(l-1)*t],o.addConstraint(e,r.create(a.extend({bodyA:p,bodyB:d},s)))),i&&cp||a<(c=p-c)||a>n-1-c))return 1===d&&s.translate(u,{x:(a+(n%2==1?1:-1))*f,y:0}),l(e+(u?a*f:0)+a*r,i,a,c,u,d)}))},i.newtonsCradle=function(e,t,n,i,a){for(var s=o.create({label:"Newtons Cradle"}),c=0;c1?1:0;ue.deltaMax?e.deltaMax:i)/e.delta,e.delta=i),0!==e.timeScalePrev&&(s*=a.timeScale/e.timeScalePrev),0===a.timeScale&&(s=0),e.timeScalePrev=a.timeScale,e.correction=s,e.frameCounter+=1,n-e.counterTimestamp>=1e3&&(e.fps=e.frameCounter*((n-e.counterTimestamp)/1e3),e.counterTimestamp=n,e.frameCounter=0),o.trigger(e,"tick",l),o.trigger(e,"beforeUpdate",l),r.update(t,i,s),o.trigger(e,"afterUpdate",l),o.trigger(e,"afterTick",l)},i.stop=function(e){t(e.frameRequestId)},i.start=function(e,t){i.run(e,t)}}()},function(e,t,n){var i={};e.exports=i;n(1);var o=n(0);i.pathToVertices=function(e,t){"undefined"==typeof window||"SVGPathSeg"in window||o.warn("Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.");var n,r,a,s,l,c,u,d,p,f,v,m=[],y=0,g=0,x=0;t=t||15;var h=function(e,t,n){var i=n%2==1&&n>1;if(!p||e!=p.x||t!=p.y){p&&i?(f=p.x,v=p.y):(f=0,v=0);var o={x:f+e,y:v+t};!i&&p||(p=o),m.push(o),g=f+e,x=v+t}},b=function(e){var t=e.pathSegTypeAsLetter.toUpperCase();if("Z"!==t){switch(t){case"M":case"L":case"T":case"C":case"S":case"Q":g=e.x,x=e.y;break;case"H":g=e.x;break;case"V":x=e.y}h(g,x,e.pathSegType)}};for(i._svgPathToAbsolute(e),a=e.getTotalLength(),c=[],n=0;n