general balance (also removed some unused files)

This commit is contained in:
landgreen
2019-09-22 18:55:52 -07:00
parent 8aa9189049
commit 47feed19e5
35 changed files with 172 additions and 3865 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -543,8 +543,12 @@ const b = {
fire() {
const me = bullet.length;
const dir = mech.angle;
bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle), 31, 2, b.fireAttributes(dir));
b.fireProps(mech.crouch ? 40 : 20, mech.crouch ? 45 : 37, dir, me); //cd , speed
if (mech.crouch) {
bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle), 40, 3, b.fireAttributes(dir));
} else {
bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle), 31, 2, b.fireAttributes(dir));
}
b.fireProps(mech.crouch ? 50 : 20, mech.crouch ? 45 : 37, dir, me); //cd , speed
bullet[me].endCycle = game.cycle + 180;
bullet[me].dmg = mech.crouch ? 1.35 : 1;
b.drawOneBullet(bullet[me].vertices);
@@ -870,7 +874,7 @@ const b = {
{
name: "drones",
ammo: 0,
ammoPack: 27,
ammoPack: 23,
have: false,
fire() {
const THRUST = 0.0015
@@ -884,7 +888,7 @@ const b = {
restitution: 1,
dmg: 0.15, //damage done in addition to the damage from momentum
lookFrequency: 79 + Math.floor(32 * Math.random()),
endCycle: game.cycle + 720 + 300 * Math.random(),
endCycle: game.cycle + 780 + 360 * Math.random(),
classType: "bullet",
collisionFilter: {
category: 0x000100,
@@ -937,7 +941,7 @@ const b = {
}
}
})
b.fireProps(mech.crouch ? 15 : 10, mech.crouch ? 26 : 2, dir, me); //cd , speed
b.fireProps(mech.crouch ? 22 : 15, mech.crouch ? 26 : 1, dir, me); //cd , speed
b.drawOneBullet(bullet[me].vertices);
// Matter.Body.setDensity(bullet[me], 0.000001);
// bullet[me].onDmg = function () {
@@ -954,7 +958,8 @@ const b = {
game.updateGunHUD();
} else {
mech.fireCDcycle = game.cycle + 30; //cooldown
game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div><span class = 'box'>E</span> / <span class = 'box'>Q</span>", 200);
// game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div><span class = 'box'>E</span> / <span class = 'box'>Q</span>", 200);
game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div> <p style='font-size:90%;'><strong>Q</strong>, <strong>E</strong>, and <strong>mouse wheel</strong> change weapons</p>", 200);
}
}
},
@@ -966,7 +971,7 @@ const b = {
game.updateGunHUD();
} else {
mech.fireCDcycle = game.cycle + 30; //cooldown
game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div><span class = 'box'>E</span> / <span class = 'box'>Q</span>", 200);
game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div><p style='font-size:90%;'><strong>Q</strong>, <strong>E</strong>, and <strong>mouse wheel</strong> change weapons</p>", 200);
}
}
},

View File

@@ -448,9 +448,17 @@ const game = {
//only in testing mode
if (keys[70]) {
// f for power ups
for (let i = 0; i < 16; ++i) {
powerUps.spawnRandomPowerUp(game.mouseInGame.x, game.mouseInGame.y, 0, 0);
}
powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "gun");
powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "gun");
powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "gun");
powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "gun");
powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "field");
powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "heal");
powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "heal");
// for (let i = 0; i < 16; ++i) {
// powerUps.spawnRandomPowerUp(game.mouseInGame.x, game.mouseInGame.y, 0, 0);
// }
}
if (keys[82]) {
// r to teleport to mouse
@@ -555,15 +563,10 @@ const game = {
player.force.y += player.mass * mech.gravity;
},
reset() {
//removes guns and ammo
b.inventory = [];
b.inventory = []; //removes guns and ammo
for (let i = 0, len = b.guns.length; i < len; ++i) {
if (b.guns[i].ammo != Infinity) {
b.guns[i].ammo = 0;
b.guns[i].have = false;
} else {
b.inventory.push(i);
}
b.guns[i].have = false;
if (b.guns[i].ammo != Infinity) b.guns[i].ammo = 0;
}
game.paused = false;
engine.timing.timeScale = 1;
@@ -573,14 +576,14 @@ const game = {
game.makeGunHUD();
mech.drop();
mech.addHealth(1);
mech.fieldUpgrades[0](); //reset to starting field? or let them keep the field
mech.alive = true;
level.onLevel = 0;
game.levelsCleared = 0;
// level.onLevel = Math.floor(Math.random() * level.levels.length); //picks a random starting level
game.clearNow = true;
document.getElementById("text-log").style.opacity = 0;
document.getElementById("fade-out").style.opacity = 0;
// mech.fieldUpgrades[0](); //reset to starting field? or let them keep the field
if (!mech.fieldMode) mech.fieldUpgrades[0](); //reset to starting field? or let them keep the field
},
firstRun: true,
splashReturn() {

View File

@@ -2,6 +2,18 @@
/* TODO: *******************************************
*****************************************************
field power up effects
field produces a whirlpool effect of force around player
field allows player to hold and throw living mobs
field puts a circle of "something" each time right click is pressed
null gravity
damage
high friction
other power up ideas
killing a mob triggers: a spore bullet
maybe you could replace the power method with a new one to get this to work
have mob acceleration and look frequency scale with difficulty level
this will speed up the responses of later mobs
this should provide a feeling of difficulty without inflating the life of mobs

View File

@@ -13,17 +13,18 @@ const level = {
// game.zoomScale = 1400 //1400
if (game.levelsCleared === 0) {
document.title = "n-gon";
this.intro(); //starting level
// b.giveGuns(0) // set a starting gun for testing
mech.fieldUpgrades[6]() //give a field power up for testing
// game.levelsCleared = 3; //for testing to simulate possible mobs spawns
// this.bosses();
// this.intro(); //starting level\
// this.testingMap();
// this.bosses();
// this.skyscrapers();
// this.rooftops();
// this.warehouse();
this.warehouse();
// this.highrise();
// this.towers();
// game.levelsCleared = 3; //for testing to simulate possible mobs spawns
// b.giveGuns(0) // set a starting gun for testing
// mech.fieldUpgrades[1]() //give a field power up for testing
} else {
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
this[this.levels[this.onLevel]](); //picks the current map from the the levels array
@@ -117,9 +118,9 @@ const level = {
// spawn.starter(800, -1150);
// spawn.groupBoss(-600, -550);
// for (let i = 0; i < 1; ++i) {
spawn.shooter(800, -1150);
// spawn.shooter(800, -1150);
// }
// spawn.groupBoss(900, -1070);
spawn.groupBoss(900, -1070);
// for (let i = 0; i < 20; i++) {
// spawn.randomBoss(-100, -1470);
// }
@@ -222,12 +223,6 @@ const level = {
// "<br><br><div class='wrapper'> <div class = 'grid-box'> <span class = 'box'>W</span><br> <span class = 'box'>A</span> <span class = 'box'>S</span> <span class = 'box'>D</span></div> <div class = 'grid-box'> <span class = 'mouse'><span class='mouse-line'></span></span> </div></div>",
// Infinity
// );
game.makeTextLog(
// "<br><br><br><br><div class='wrapper'> <div class = 'grid-box'><strong>right mouse / space bar:</strong><br>pick up things</div> <div class = 'grid-box'> <span class = 'mouse'><span class='mouse-line'></span></span> </div></div>",
"Use <strong>right mouse</strong> or <strong>space bar</strong> to pick up things.",
Infinity
);
level.fill.push({
x: -150,
y: -1150,
@@ -875,7 +870,7 @@ const level = {
},
warehouse() {
game.zoomTransition(1300)
document.body.style.backgroundColor = "#bbb";
document.body.style.backgroundColor = "#f2f5f3";
mech.setPosToSpawn(25, -60); //normal spawn
//mech.setPosToSpawn(-2000, -1700); // left ledge spawn
level.enter.x = mech.spawnPos.x - 50;
@@ -895,33 +890,33 @@ const level = {
// level.fill.push({ x: -1800, y: -500, width: 1975, height: 550, color: "rgba(0,0,0,0.05)"});
// level.fill.push({ x: -2600, y: -150, width: 700, height: 200, color: "rgba(0,0,0,0.05)"});
//background
const BGColor = "#f3f3ea";
level.fillBG.push({
const BGColor = "rgba(0,0,0,0.1)";
level.fill.push({
x: -3025,
y: 50,
width: 4125,
height: 1350,
color: BGColor
});
level.fillBG.push({
level.fill.push({
x: -1800,
y: -500,
width: 1625,
height: 555,
height: 550,
color: BGColor
});
level.fillBG.push({
x: -177,
level.fill.push({
x: -175,
y: -250,
width: 350,
height: 300,
color: "#e3e3da"
color: BGColor
});
level.fillBG.push({
level.fill.push({
x: -2600,
y: -150,
width: 700,
height: 205,
height: 200,
color: BGColor
});
level.fillBG.push({
@@ -986,8 +981,9 @@ const level = {
length: 1
});
spawn.bodyRect(-2775, 1150, 190, 150, 1, spawn.propsSlide); //weight
spawn.bodyRect(-2575, 1150, 200, 150, 1, spawn.propsSlide); //weight
spawn.bodyRect(-2775, 1150, 180, 160, 1, spawn.propsSlide); //weight
spawn.bodyRect(-2550, 1150, 200, 150, 1, spawn.propsSlide); //weight
spawn.bodyRect(-2775, 1300, 400, 100, 1, spawn.propsHoist); //hoist
cons[cons.length] = Constraint.create({
pointA: {
@@ -995,8 +991,8 @@ const level = {
y: 150
},
bodyB: body[body.length - 1],
stiffness: 0.000076,
length: 220
stiffness: 0.0002,
length: 566
});
//blocks

View File

@@ -1,998 +0,0 @@
//global game variables
let body = []; //non static bodies
let map = []; //all static bodies
let cons = []; //all constaints between a point and a body
let consBB = []; //all constaints between two bodies
//main object for spawning levels
const level = {
onLevel: undefined,
start: function() {
// game.levelsCleared = 3; //for testing to simulate all possible mobs spawns
// game.draw.setMapColors();
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
// this.procedural();
this.testingMap();
//this.warehouse(); //this.highrise(); //this.towers(); // this.skyscrapers(); //this.rooftops();
this.addToWorld(); //add map to world
game.draw.setPaths();
this.levelAnnounce();
},
//******************************************************************************************************************
//******************************************************************************************************************
//empty map for testing mobs
testingMap: function() {
// game.levelsCleared = 5; //for testing to simulate all possible mobs spawns
// for (let i = 0; i < 5; i++) {
// game.dmgScale += 0.4; //damage done by mobs increases each level
// b.dmgScale *= 0.9; //damage done by player decreases each level
// }
mech.setPosToSpawn(-75, -60); //normal spawn
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y + 20;
level.exit.x = 3500;
level.exit.y = -870;
this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
// this.addZone(250, -1000, 500, 1500, "laser");
//spawn.debris(0, -900, 4500, 10); //15 debris per level
// setTimeout(function() {
// document.body.style.backgroundColor = "#eee";
// }, 1);
document.body.style.backgroundColor = "#fff";
// document.body.style.backgroundColor = "#fafcff";
// document.body.style.backgroundColor = "#bbb";
// document.body.style.backgroundColor = "#eee4e4";
// document.body.style.backgroundColor = "#dcdcde";
// document.body.style.backgroundColor = "#e0e5e0";
// this.addQueryRegion(550, -25, 100, 50, "bounce", { Vx: 0, Vy: -25 });
// level.fillBG.push({ x: 550, y: -25, width: 100, height: 50, color: "#ff0" });
spawn.mapRect(-1200, 0, 2200, 300); //left ground
spawn.mapRect(3500, -860, 100, 50); //ground bump wall
spawn.mapVertex(1250, 0, "0 0 0 300 -500 600 -500 300");
spawn.mapRect(1500, -300, 2000, 300); //upper ground
spawn.mapVertex(3750, 0, "0 600 0 300 -500 0 -500 300");
spawn.mapRect(4000, 0, 1000, 300); //right lower ground
spawn.mapRect(2200, -600, 600, 50); //center platform
spawn.mapRect(1300, -850, 700, 50); //center platform
spawn.mapRect(3000, -850, 700, 50); //center platform
// spawn.mapRect(0, -2000, 3000, 50); //center platform
spawn.spawnBuilding(-200, -250, 275, 240, false, true, "left"); //far left; player spawns in side
// spawn.boost(350, 0, -1000);
for (let i = 0; i < 17; i++) {
powerUps.spawn(450, -125, "gun", false);
}
for (let i = 0; i < 5; i++) {
powerUps.spawn(2500 + i * 20, -1300, "gun", false);
powerUps.spawn(2500 + i * 20, -1100, "ammo", false);
}
spawn.bodyRect(700, -50, 50, 50);
spawn.bodyRect(700, -100, 50, 50);
spawn.bodyRect(700, -150, 50, 50);
spawn.bodyRect(700, -200, 50, 50);
spawn.bodyRect(-100, -260, 250, 10);
// spawn.springer(100, -550);
// spawn.grower(100, -550);
// spawn.chaser(100, -550);
// spawn.striker(100, -550);
// spawn.spinner(100, -550);
// spawn.hopper(100, -550);
// spawn.grower(100, -550);
// spawn.springer(100, -550);
// spawn.zoomer(100, -550);
// spawn.shooter(100, -550);
// spawn.beamer(100, -550);
// spawn.focuser(100, -550);
// spawn.laser(100, -550);
// spawn.blinker(100, -550);
// spawn.drifter(100, -550);
// spawn.sucker(100, -550);
// spawn.exploder(100, -550);
// spawn.spawner(100, -550);
// spawn.ghoster(100, -550);
// spawn.sneaker(100, -550);
// spawn.bomber(100, -550);
// spawn.flocker(-600, -650);
// spawn.flocker(-600, -550);
// spawn.flocker(-600, -750);
// spawn.starter(-600, -550);
// spawn.flocker(-900, -850);
// spawn.flocker(-600, -550);
// spawn.flocker(-600, -750);
spawn.starter(-600, -550);
// for (let i = 0; i < 4; ++i) {
// spawn.shooter(800, -1150);
// }
// spawn.nodeBoss(900, -1070, "shooter", 9);
// spawn.randomBoss(-100, -1470);
// spawn.randomBoss(500, -1470);
// spawn.randomBoss(900, -1470);
// spawn.randomBoss(900, -1000);
},
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
procedural: function() {
const mobChance = 0.3;
const maxJump = 390;
const boostScale = 0.000023;
//
mech.setPosToSpawn(0, -10); //normal spawn
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y - 15;
//starting zone
spawn.mapRect(-250, -320, 50, 400); //far left starting left wall
spawn.mapRect(-250, -0, 500, 110); //far left starting ground
spawn.mapRect(-250, -340, 500, 50); //far left starting ceiling
spawn.mapRect(200, -320, 50, 180); //far left starting right part of wall
spawn.bodyRect(220, -120, 14, 140, 1, spawn.propsFriction); //door to starting room
spawn.mapRect(-50, -10, 100, 50);
spawn.mapRect(0, 10, 400, 100); //***********ground
if (b.inventory.length < 3) {
powerUps.spawn(550, -50, "gun", false); //starting gun
} else {
powerUps.spawnRandomPowerUp(550, -50);
}
level.fill.push({
x: -250,
y: -300,
width: 500,
height: 300,
color: "rgba(0,0,0,0.15)"
});
let o = { x: 400, y: 10 }; //keeps track of where the next mapNode should be added
mapNode = [
function() {
//one or two shelves
let nodeRange = { x: 650 + Math.round(Math.random() * 900), y: 0 };
spawn.mapRect(o.x, o.y, nodeRange.x, 100);
spawn.randomMob(o.x + 200 + 600 * Math.random(), o.y - 50, mobChance);
spawn.debris(o.x + 50, o.y, nodeRange.x - 100, 2);
//shelf(s)
const shelfElevation = 230 + 200 * Math.random();
const shelfWidth = nodeRange.x - 200 - 300 * Math.random();
if (Math.random() < 0.85 && shelfWidth > 650) {
const len = 1 + Math.ceil(Math.random() * Math.random() * Math.random() * 5);
const sep = 50 + 100 * Math.random();
const x1 = o.x + nodeRange.x / 2 - shelfWidth / 2;
const x2 = o.x + nodeRange.x / 2 + sep;
for (let i = 1; i < len; ++i) {
//two shelves
spawn.mapRect(x1, o.y - shelfElevation * i, shelfWidth / 2 - sep, 50);
spawn.mapRect(x2, o.y - shelfElevation * i, shelfWidth / 2 - sep, 50);
//plank connecting shelves
spawn.bodyRect(
o.x + (nodeRange.x - shelfWidth) / 2 + shelfWidth / 2 - sep - 75,
o.y - shelfElevation * i - 30,
sep + 250,
10,
0.6,
spawn.propsFrictionMedium
);
}
level.fillBG.push({
x: x1,
y: o.y - shelfElevation * (len - 1),
width: shelfWidth / 2 - sep,
height: shelfElevation * (len - 1),
color: "#f0f0f3"
});
level.fillBG.push({
x: x2,
y: o.y - shelfElevation * (len - 1),
width: shelfWidth / 2 - sep,
height: shelfElevation * (len - 1),
color: "#f0f0f3"
});
} else {
const len = 1 + Math.ceil(Math.random() * Math.random() * Math.random() * 5);
for (let i = 1; i < len; ++i) {
//one shelf
spawn.mapRect(o.x + (nodeRange.x - shelfWidth) / 2, o.y - shelfElevation * i, shelfWidth, 50);
level.fillBG.push({
x: o.x + (nodeRange.x - shelfWidth) / 2,
y: o.y - shelfElevation * (len - 1),
width: shelfWidth,
height: shelfElevation * (len - 1),
color: "#f0f0f3"
});
}
}
//square block
const blockSize = 60 + Math.random() * 120;
if (shelfElevation > blockSize + 100) {
spawn.bodyRect(o.x + 100 + Math.random() * (nodeRange.x - 200), o.y - blockSize, blockSize, blockSize, 0.3);
} else {
spawn.bodyRect(o.x + 50 + (nodeRange.x - shelfWidth) / 2, o.y - shelfElevation - blockSize, blockSize, blockSize, 0.3);
}
spawn.randomMob(o.x + (nodeRange.x - shelfWidth) / 2, o.y - shelfElevation - 100, mobChance); //mob above shelf
spawn.debris(o.x + 50 + (nodeRange.x - shelfWidth) / 2, o.y - shelfElevation - 50, shelfWidth - 100, 1);
// set starting position for new mapNode
o.x += nodeRange.x;
o.y += nodeRange.y;
},
function() {
//several platforms that rise up
const wide = 120 + Math.floor(Math.random() * Math.random() * 450);
let nodeRange = { x: 100, y: -Math.floor(200 + Math.random() * 150) };
for (let i = 0, len = 1 + Math.ceil(Math.random() * 4); i < len; i++) {
spawn.platform(o.x + nodeRange.x, o.y, wide, nodeRange.y);
spawn.debris(o.x + nodeRange.x - 120, o.y - 50, wide + 250, Math.floor(Math.random() * 0.8 + 0.5));
if (Math.random() < 0.3) {
spawn.randomBoss(o.x + nodeRange.x + 20 + (wide - 40) * Math.random(), o.y + nodeRange.y - 450, mobChance);
} else {
spawn.randomMob(o.x + nodeRange.x + 20 + (wide - 40) * Math.random(), o.y + nodeRange.y - 50, mobChance); //mob above shelf
}
nodeRange.x += Math.floor(wide + 155 + Math.random() * 200);
nodeRange.y -= Math.floor(115 + Math.random() * 200);
}
spawn.mapRect(o.x, o.y, nodeRange.x, 100); //ground
spawn.mapRect(o.x + nodeRange.x, o.y + nodeRange.y + 15, 100, -nodeRange.y + 85); //right wall
// set starting position for new mapNode
o.x += nodeRange.x;
o.y += nodeRange.y;
},
function() {
//s-shaped building goes up 2 levels
const floorHeight = maxJump - Math.floor(Math.random() * 150); //maxJump = 390
let nodeRange = { x: 700 + Math.floor(Math.random() * 800), y: -floorHeight * 2 };
const wallWidth = 20 + Math.floor(Math.random() * 40);
const numberOfFloors = 2 + Math.floor(Math.random() * 2);
const frontYardWidth = 250;
o.x += frontYardWidth;
spawn.mapRect(o.x - frontYardWidth, o.y, nodeRange.x + frontYardWidth, 100); //first floor ground
let floorWidth = nodeRange.x - wallWidth - 250 - Math.random() * Math.random() * nodeRange.x * 0.4; //possible open area with only half long 2nd floor
spawn.mapRect(o.x + wallWidth, o.y - floorHeight, floorWidth, wallWidth); //second floor
spawn.mapRect(o.x + 300, o.y - floorHeight * 2, nodeRange.x - 300, wallWidth); //third floor
if (numberOfFloors > 2) spawn.mapRect(o.x, o.y - floorHeight * 3, nodeRange.x, wallWidth); //optional roof
spawn.mapRect(o.x, o.y - floorHeight * numberOfFloors, wallWidth, floorHeight * numberOfFloors - 175); //left building wall
if (Math.random() < 0.8) {
spawn.mapRect(o.x + nodeRange.x - wallWidth, o.y - floorHeight * 2 + wallWidth, wallWidth, floorHeight * 2); //right building wall
} else {
spawn.mapRect(o.x + nodeRange.x - wallWidth, o.y - floorHeight * 2 + wallWidth, wallWidth, floorHeight * 2 - 175 - wallWidth); //right building wall with right door
}
level.fill.push({
x: o.x,
y: o.y - floorHeight * numberOfFloors,
width: nodeRange.x,
height: floorHeight * numberOfFloors,
color: "rgba(0,0,0,0.1)"
});
//random extras
const debrisRange = nodeRange.x - wallWidth * 4;
spawn.debris(o.x + wallWidth, o.y - 50, debrisRange, 1);
spawn.debris(o.x + wallWidth, o.y - 50 - floorHeight, debrisRange - 250, 1);
spawn.debris(o.x + wallWidth + 250, o.y - 50 - floorHeight * 2, debrisRange - 250, 1);
spawn.randomSmallMob(o.x + wallWidth + Math.random() * debrisRange, o.y - 80, 3);
spawn.randomSmallMob(o.x + wallWidth + Math.random() * (debrisRange - 250), o.y - 80 - floorHeight);
spawn.randomSmallMob(o.x + wallWidth + 250 + Math.random() * (debrisRange - 250), o.y - 80 - floorHeight * 2);
let blockSize = 70 + Math.random() * 70;
spawn.bodyRect(o.x - blockSize + nodeRange.x - wallWidth - Math.random() * 30, o.y - blockSize, blockSize, blockSize, 0.4);
blockSize = 70 + Math.random() * 100;
spawn.bodyRect(o.x + wallWidth + Math.random() * 30, o.y - floorHeight - blockSize, blockSize, blockSize, 0.4);
o.x += nodeRange.x;
if (Math.random() < 0.5) o.y += nodeRange.y; //start the next level at the top floor of the building
},
function() {
//building with several floors that goes down a couple levels
const numberOfFloors = 2 + Math.floor(Math.random() * 2);
const floorHeight = maxJump - Math.floor(Math.random() * 150); //maxJump = 390
let nodeRange = { x: 825 + Math.floor(Math.random() * 800), y: floorHeight * numberOfFloors };
const wallWidth = 20 + Math.floor(Math.random() * 40);
const frontYardWidth = 250;
o.x += frontYardWidth;
spawn.mapRect(o.x, o.y - floorHeight * 2, nodeRange.x, wallWidth); //roof level 2
if (Math.random() < 0.5) {
spawn.mapRect(o.x + 300, o.y - floorHeight, nodeRange.x - 600, wallWidth); //level 1
} else if (Math.random() < 0.5) {
spawn.mapRect(o.x + 300, o.y - floorHeight, nodeRange.x - 600, wallWidth + floorHeight); //level 1
}
spawn.mapRect(o.x - frontYardWidth, o.y, nodeRange.x + frontYardWidth - 300, wallWidth); //ground
// spawn.mapRect(o.x - frontYardWidth, o.y + 10, frontYardWidth, 100 - 10); // makes the front yard look 100 deep
let floorWidth = nodeRange.x - wallWidth - 250 - Math.random() * Math.random() * nodeRange.x * 0.4; //possible open area with only half long 2nd floor
spawn.mapRect(o.x + nodeRange.x - floorWidth, o.y + floorHeight, floorWidth, wallWidth); //B1 floor
spawn.mapRect(o.x, o.y + floorHeight * numberOfFloors, nodeRange.x, 100); //B2 floor
spawn.mapRect(o.x, o.y - floorHeight * 2, wallWidth, floorHeight * 2 - 175); //left building wall above ground
spawn.mapRect(o.x, o.y + wallWidth, wallWidth, floorHeight * numberOfFloors); //left building wall lower
spawn.mapRect(o.x + nodeRange.x - wallWidth, o.y + wallWidth - floorHeight * 2, wallWidth, floorHeight * (numberOfFloors + 2) - wallWidth - 175); //right building wall with right door
level.fill.push({
x: o.x,
y: o.y - floorHeight * 2,
width: nodeRange.x,
height: floorHeight * (numberOfFloors + 2),
color: "rgba(0,0,0,0.1)"
});
//random extras
spawn.debris(o.x, o.y - 50, nodeRange.x - 300, 1); //ground
spawn.debris(o.x, o.y + floorHeight * 2 - 50, nodeRange.x, 1); //B2
spawn.randomSmallMob(o.x + wallWidth + Math.random() * nodeRange.x - 300, o.y - 50); //ground
if (numberOfFloors === 3) {
spawn.randomBoss(o.x + nodeRange.x / 2, o.y + floorHeight * 2 - 50);
} else {
spawn.randomSmallMob(o.x + wallWidth + Math.random() * nodeRange.x * 0.8, o.y + floorHeight - 50); //B1
spawn.randomSmallMob(o.x + wallWidth + Math.random() * nodeRange.x * 0.8, o.y + floorHeight * numberOfFloors - 50); //B2
}
o.x += nodeRange.x;
o.y += nodeRange.y; //start the next level at the top floor of the building
},
function() {
//large room with boost to roof exit
const wallWidth = 20 + Math.floor(Math.random() * 40);
const boostX = 500 + Math.floor(Math.random() * 1500);
const boostPadding = 35 + Math.floor(Math.random() * 200);
let nodeRange = { x: boostX + 500 + Math.floor(Math.random() * 500), y: 700 + Math.floor(Math.random() * 600) };
//optional basement mode
if (Math.random() < 0.75 && boostX > 1000) {
spawn.mapRect(o.x, o.y, 200 + wallWidth, wallWidth); //ground entrance
const basementDepth = Math.min(400 + Math.floor(Math.random() * 300), nodeRange.y - 200);
o.y += basementDepth;
o.x += 200;
spawn.mapRect(o.x, o.y, nodeRange.x, 100); //basement ground
spawn.mapRect(o.x, o.y - nodeRange.y + 15, wallWidth, nodeRange.y - 200 - basementDepth); //left building wall
spawn.mapRect(o.x, o.y - basementDepth + 15, wallWidth, basementDepth); //left basement wall
} else {
spawn.mapRect(o.x, o.y, nodeRange.x + 200, 100); //ground
o.x += 200;
spawn.mapRect(o.x, o.y - nodeRange.y + 15, wallWidth, nodeRange.y - 200); //left building wall
}
spawn.mapRect(o.x + nodeRange.x - wallWidth, o.y - nodeRange.y + 15, wallWidth, nodeRange.y); //right building wall
spawn.mapRect(o.x, o.y - nodeRange.y, boostX - boostPadding, wallWidth); //left roof
spawn.mapRect(o.x + boostX + 100 + boostPadding, o.y - nodeRange.y, nodeRange.x - boostX - 100 - boostPadding, wallWidth); //right roof
if (boostPadding < 100 && nodeRange.y < 1300) {
spawn.boost(o.x + boostX, o.y, nodeRange.y + 600);
spawn.bodyRect(o.x + boostX - boostPadding - 100, o.y - nodeRange.y - 20, 300 + 2 * boostPadding, 10, 1);
} else {
spawn.boost(o.x + boostX, o.y, nodeRange.y);
}
spawn.debris(o.x, o.y - nodeRange.y - 50, boostX - boostPadding, 1); //on roof
spawn.debris(o.x, o.y - 50, boostX - boostPadding, 1); //on ground
let blockSize = 60 + Math.random() * 150;
spawn.bodyRect(o.x + wallWidth + Math.random() * (boostX - blockSize - wallWidth), o.y - blockSize, blockSize, blockSize, 0.8); //left
spawn.bodyRect(o.x + nodeRange.x - blockSize - 10, o.y - blockSize, blockSize, blockSize, 0.8); //right
const ledgeHeight = 500 + Math.random() * (nodeRange.y - 900) - 150;
if (Math.random() < 0.5) {
spawn.randomMob(o.x + 200, o.y - ledgeHeight, mobChance); //mob in left top corner
spawn.randomBoss(o.x + boostX + 100 + boostPadding + 100, o.y - nodeRange.y - 500, mobChance); //boss above right roof
} else {
spawn.randomBoss(o.x + 300, o.y - ledgeHeight); //mob in left top corner
spawn.randomMob(o.x + boostX + 100 + boostPadding + 100, o.y - ledgeHeight, mobChance); //mob above right ledge
}
level.fill.push({
x: o.x,
y: o.y - nodeRange.y,
width: nodeRange.x,
height: nodeRange.y,
color: "rgba(0,0,0,0.1)"
});
o.x += nodeRange.x;
if (Math.random() < 0.5) o.y -= nodeRange.y; //start the next level at the top floor of the building or not
},
function() {
//series of platforming ledges
//first platform to get up to top height
let wallWidth = 25 + Math.floor(Math.random() * 30);
const startingX = o.x;
const frontYard = 200;
let firstPlatW = 800 + Math.floor(Math.random() * 350);
o.x += frontYard;
//optional extra lower floor
let zeroFloor = 0;
if (Math.random() < 0.7) {
zeroFloor = maxJump - 100;
spawn.mapRect(o.x, o.y - zeroFloor, firstPlatW + 100, zeroFloor + 15); //0th floor
}
const firstFloorH = maxJump - Math.floor(Math.random() * 50) + zeroFloor;
const fullHeight = firstFloorH + 300 + 300;
const totalCases = 4;
switch (Math.ceil(Math.random() * totalCases)) {
case 1:
spawn.mapRect(o.x, o.y - firstFloorH, firstPlatW, 100); //1st floor
spawn.mapRect(o.x, o.y - firstFloorH - 300, 100, 315); //1st floor left wall
spawn.mapRect(o.x + 300, o.y - fullHeight, firstPlatW - 400, 450); //2st floor
level.fill.push({
//darkness under first floor left building
x: o.x,
y: o.y - firstFloorH,
width: firstPlatW,
height: firstFloorH - zeroFloor,
color: "rgba(0,0,0,0.15)"
});
level.fill.push({
//darkness under second floor left building
x: o.x + 300,
y: o.y - firstFloorH - 300,
width: firstPlatW - 400,
height: firstFloorH - zeroFloor,
color: "rgba(0,0,0,0.2)"
});
break;
case 2:
if (Math.random() < 0.1) {
spawn.mapRect(o.x + 200, o.y - firstFloorH, 200, firstFloorH + 15 - zeroFloor);
} else {
const size = 50 + Math.floor(Math.random() * 100);
for (let i = 0, len = Math.ceil(Math.random() * 8); i < len; ++i) {
spawn.bodyRect(o.x + 200, o.y - zeroFloor - size * (1 + i), size, size);
}
}
spawn.boost(o.x + firstPlatW - 100, o.y - zeroFloor, fullHeight); //-0.007
break;
case 3:
spawn.mapRect(o.x + 200, o.y - firstFloorH, firstPlatW - 200, 100); //1st floor
spawn.mapRect(o.x + 400, o.y - firstFloorH - 300, firstPlatW - 400, 315); //1st floor left wall
spawn.mapRect(o.x + 600, o.y - fullHeight, firstPlatW - 600, 450); //2st floor
level.fill.push({
//darkness under second floor left building
x: o.x + 200,
y: o.y - firstFloorH,
width: firstPlatW - 200,
height: firstFloorH - zeroFloor,
color: "rgba(0,0,0,0.1)"
});
break;
case 4:
const poleWidth = 50;
const platWidth = 200;
const secondPlatX = platWidth + 125;
const totalWidth = platWidth + secondPlatX;
spawn.mapRect(o.x + firstPlatW - totalWidth, o.y - firstFloorH - 350, platWidth, wallWidth);
spawn.mapRect(o.x + firstPlatW - totalWidth, o.y - firstFloorH + 100, platWidth, wallWidth);
spawn.mapRect(o.x + secondPlatX + firstPlatW - totalWidth, o.y - firstFloorH - 100, platWidth, wallWidth);
spawn.mapRect(o.x + secondPlatX + firstPlatW - totalWidth, o.y - fullHeight, platWidth, wallWidth);
level.fillBG.push({
x: o.x + platWidth / 2 - poleWidth / 2 + firstPlatW - totalWidth,
y: o.y - firstFloorH - 350,
width: poleWidth,
height: firstFloorH + 350 - zeroFloor,
color: "rgba(0,0,0,0.2)"
});
level.fillBG.push({
x: o.x + platWidth / 2 - poleWidth / 2 + secondPlatX + firstPlatW - totalWidth,
y: o.y - fullHeight,
width: poleWidth,
height: fullHeight - zeroFloor,
color: "rgba(0,0,0,0.2)"
});
if (Math.random() < 0.9) {
const platX = firstPlatW - totalWidth - platWidth - 125;
spawn.mapRect(o.x + platX, o.y - firstFloorH - 100, platWidth, wallWidth);
spawn.mapRect(o.x + platX, o.y - fullHeight, platWidth, wallWidth);
level.fillBG.push({
x: o.x + platWidth / 2 - poleWidth / 2 + platX,
y: o.y - fullHeight,
width: poleWidth,
height: fullHeight - zeroFloor,
color: "rgba(0,0,0,0.2)"
});
}
break;
}
spawn.debris(o.x, o.y - zeroFloor - 50, firstPlatW, 2);
spawn.randomMob(o.x + firstPlatW - 200 - Math.random() * 600, o.y - zeroFloor - 100, mobChance); //in shadow
spawn.randomMob(o.x + firstPlatW - 200 - Math.random() * 400, o.y - fullHeight - 100, mobChance); //top
spawn.randomBoss(o.x + firstPlatW - 200, o.y - fullHeight - 500, mobChance); //top
//random platforms
let offX = o.x + firstPlatW;
const len = Math.ceil(Math.random() * Math.random() * 4.5);
for (let i = 0; i < len; i++) {
const totalCases = 3;
switch (Math.ceil(Math.random() * totalCases)) {
case 1:
const width = 150 + Math.floor(Math.random() * 500);
const middle = Math.floor(width / 2);
spawn.mapRect(offX + 300, o.y - fullHeight, width, wallWidth); //top platform
if (Math.random() < 0.5) spawn.mapRect(offX + 300, o.y - 50, width, 65); //ground bump
//optional room on second floor
if (width > 400) {
roomHeight = Math.min(maxJump, width) - 100;
roomLipWidth = 200;
spawn.mapRect(offX + 300 + width - wallWidth, o.y - fullHeight - roomHeight, wallWidth, roomHeight + 15); //room right wall
spawn.mapRect(offX + 300 + roomLipWidth, o.y - fullHeight - roomHeight, width - roomLipWidth, wallWidth); //room roof
level.fill.push({
x: offX + 300 + roomLipWidth,
y: o.y - fullHeight - roomHeight + wallWidth,
width: width - roomLipWidth,
height: roomHeight - wallWidth,
color: "rgba(0,0,0,0.1)"
});
} else if (Math.random() < 0.5) {
spawn.mapRect(offX + 300, o.y - firstFloorH, width, wallWidth); //middle platform
spawn.bodyRect(offX + 300 - Math.floor(Math.random() * 100), o.y - fullHeight - 20, width + Math.floor(Math.random() * 300), 20, 0.7); //plank on top platform)
}
level.fillBG.push({
x: offX + 300 + middle - 25,
y: o.y - fullHeight,
width: 50,
height: fullHeight,
color: "rgba(0,0,0,0.2)"
});
spawn.debris(offX + 300, o.y - 50, width, 1);
spawn.randomMob(offX + 300 + Math.random() * width, o.y - fullHeight - 100, 1); //top
offX += 300 + width;
break;
case 2:
const width2 = 500 + Math.floor(Math.random() * 400);
const forkDepth = 300;
const forkBaseHeight = fullHeight - forkDepth - (maxJump - 100) - 250;
spawn.mapRect(offX + 300, o.y - maxJump + 100, width2, maxJump - 100); //base
spawn.mapRect(offX + 300, o.y - fullHeight + forkDepth, width2, forkBaseHeight); //fork base
if (Math.random() < 0.7) spawn.mapRect(offX + 300, o.y - fullHeight, 100, forkDepth); //left fork
spawn.mapRect(offX + 300 + width2 - 100, o.y - fullHeight, 100, forkDepth); //right fork
level.fill.push({
x: offX + 300,
y: o.y - fullHeight + forkDepth + forkBaseHeight,
width: width2,
height: fullHeight - forkDepth - forkBaseHeight - maxJump + 100,
color: "rgba(0,0,0,0.1)"
});
spawn.debris(offX + 300, o.y - maxJump - 100, width2, 1);
spawn.randomMob(offX + 450 + Math.random() * (width2 - 300), o.y - fullHeight + 200, 1); //top
offX += 300 + width2;
break;
case 3:
const width3 = 200 + Math.floor(Math.random() * 300);
if (Math.random() < 0.7) {
spawn.mapRect(offX + 300, o.y - fullHeight, width3, fullHeight - 150); //top platform
level.fill.push({
x: offX + 300,
y: o.y - 150,
width: width3,
height: 150,
color: "rgba(0,0,0,0.25)"
});
} else {
//add a gap
const gap = (fullHeight - 150) / 2 + 100;
spawn.mapRect(offX + 300, o.y - fullHeight, width3, fullHeight - 150 - gap); //top platform
spawn.mapRect(offX + 300, o.y - fullHeight + gap, width3, fullHeight - 150 - gap); //top platform
level.fill.push({
x: offX + 300,
y: o.y - 150,
width: width3,
height: 150,
color: "rgba(0,0,0,0.25)"
});
level.fill.push({
x: offX + 300,
y: o.y - 150 - gap,
width: width3,
height: 200,
color: "rgba(0,0,0,0.25)"
});
}
spawn.randomMob(offX + 300 + Math.random() * width3, o.y - fullHeight - 100, mobChance); //top
spawn.debris(offX + 300, o.y - fullHeight - 100, width3, 1);
offX += 300 + width3;
break;
}
}
o.x += offX - o.x + 200;
spawn.mapRect(startingX, o.y, o.x - startingX + 15, 100); //ground
spawn.mapRect(o.x, o.y - fullHeight + 15, 100, fullHeight + 85); //right wall
o.y -= fullHeight;
},
function() {
const width = 200 + Math.ceil(Math.random() * 200);
const height = (maxJump - 50) * (1 - Math.random() * 0.4);
const len = 2 + Math.ceil(Math.random() * 4);
const gapWidth = 150 + Math.ceil(Math.random() * 325);
const stairsUp = function() {
const x = o.x;
for (let i = 0; i < len; ++i) {
if (Math.random() < 0.4 && height > 200 && i !== 0) {
//hidden alcove
spawn.mapRect(o.x, o.y, width, 50); //ledge
spawn.mapRect(o.x + width - 50, o.y, (len - i - 1) * width + 50, height + 15); //back wall
level.fill.push({
x: o.x,
y: o.y + 50,
width: width - 50,
height: height - 50,
color: "rgba(0,0,0,0.15)"
});
spawn.randomMob(o.x + width - 100, o.y + height / 2 + 50);
} else {
spawn.mapRect(o.x, o.y, (len - i) * width, height + 15); //ledge
}
if (Math.random() < 0.5) spawn.debris(o.x, o.y - 50, width, 1);
o.x += width;
o.y -= height;
}
o.y += height;
};
const stairsDown = function() {
const x = o.x;
for (let i = 0; i < len; ++i) {
if (Math.random() < 0.4 && height > 200 && i !== len - 1) {
//hidden alcove
spawn.mapRect(o.x, o.y, width, 50); //ledge
spawn.mapRect(x, o.y, -x + o.x + 50, height + 15); //back wall
level.fill.push({
x: o.x + 50,
y: o.y + 50,
width: width - 50,
height: height - 50,
color: "rgba(0,0,0,0.15)"
});
spawn.randomSmallMob(o.x + 100, o.y + height / 2 + 50);
} else {
spawn.mapRect(x, o.y, width - x + o.x, height + 15); //ledge
}
if (Math.random() < 0.5) spawn.debris(o.x, o.y - 50, width, 1);
o.x += width;
o.y += height;
}
o.y -= height;
};
const spawnGapBoss = function() {
if (game.levelsCleared !== 0 || Math.random() < 0.3 + game.levelsCleared * 0.11) {
spawn.bodyRect(o.x - 50, o.y - 15, gapWidth + 100, 15); //plank over gap to catch boss
spawn.randomBoss(o.x + gapWidth / 2 - 50, o.y - 500);
} else if (game.levelsCleared < 1) {
spawn.bodyRect(o.x - 50, o.y - 15, gapWidth + 100, 15); //plank over gap
}
};
if (Math.random() < 0.1) {
spawn.mapRect(o.x, o.y, len * width + 300, 100); //front porch
o.x += 300;
spawn.mapRect(o.x + len * width + gapWidth, o.y, len * width + 300, 100); //back porch
o.y -= height;
stairsUp();
spawnGapBoss();
o.x += gapWidth;
stairsDown();
o.y += height;
o.x += 300;
} else {
spawn.mapRect(o.x, o.y, 300, 100); //front porch
o.x += 275;
stairsDown();
spawnGapBoss();
o.x += gapWidth;
stairsUp();
}
o.x -= 15;
}
// function() {
// platform = function(x, y, width, height, extend = 0) {
// spawn.mapRect(x, y - height, width, 50);
// level.fillBG.push({
// x: x + width / 2 - 25,
// y: y - height,
// width: 50,
// height: height + extend,
// color: "rgba(0,0,0,0.15)"
// });
// spawn.debris(x, y - height - 50, width, Math.floor(Math.random() * 1.5));
// spawn.randomMob(x + Math.random() * (width - 50) + 25, y - height - 50, mobChance);
// };
// let nodeRange = { x: 1500 + Math.floor(Math.random() * 500), y: 0, down: false, up: false };
// // const wallWidth = 20 + Math.floor(Math.random() * 40);
// //level 1
// const ledge = { width: nodeRange.x / 2, height: Math.max((maxJump - 200) * Math.random() + 200, 200) };
// if (Math.random() < 0.33) {
// //flat ground
// spawn.mapRect(o.x, o.y, nodeRange.x, 100); //ground
// ledge.height = 0;
// } else {
// if (Math.random() < 0.5) {
// //level down
// nodeRange.down = true;
// spawn.mapRect(o.x, o.y, ledge.width + 100 - 25, 100); //ground
// spawn.mapRect(o.x + ledge.width, o.y, 100, ledge.height + 100); //ledge wall
// o.y += ledge.height;
// spawn.mapRect(o.x + ledge.width, o.y, nodeRange.x - ledge.width, 100); //ground
// const wide = Math.min(250 + Math.random() * (ledge.width - 250), nodeRange.x - ledge.width - 350);
// platform(o.x + 250 + ledge.width, o.y, wide, ledge.height);
// } else {
// //level up
// nodeRange.down = false;
// spawn.mapRect(o.x, o.y, ledge.width + 100, 100); //ground
// spawn.mapRect(o.x + ledge.width, o.y - ledge.height, 100, ledge.height + 100); //ledge wall
// const wide = Math.min(250 + Math.random() * (ledge.width - 250), ledge.width - 250);
// platform(o.x + 150, o.y, wide, ledge.height);
// o.y -= ledge.height;
// spawn.mapRect(o.x + ledge.width + 25, o.y, nodeRange.x - ledge.width - 25, 100); //ground
// }
// }
// // platform(x, o.y, width, maxJump * 2 - 100);
// o.x += nodeRange.x;
// }
// function() {
// platform = function(x, y, width, height) {
// spawn.mapRect(x, y - height, width, 50);
// level.fillBG.push({
// x: x + width / 2 - 25,
// y: y - height,
// width: 50,
// height: height,
// color: "rgba(0,0,0,0.15)"
// });
// spawn.debris(x, y - height - 50, width, Math.floor(Math.random() * 1.5));
// spawn.randomMob(x + Math.random() * (width - 50) + 25, y - height - 50, mobChance);
// };
// let nodeRange = { x: 1500 + Math.floor(Math.random() * 500), y: 0, down: false, up: false };
// let level = maxJump - 100 * Math.random();
// // platform(x, o.y, width, maxJump * 2 - 100);
// o.x += nodeRange.x;
// }
];
//
//
//randomized zone spawns
const mapNodes = Math.min(4, 2 + game.levelsCleared);
// const mapNodes = 1;
for (let i = 0; i < mapNodes; ++i) {
// mapNode[1]();
mapNode[Math.floor(Math.random() * mapNode.length)](); //run a random mapNode
}
//ending zone
o.x += 200;
level.exit.x = o.x + 200;
level.exit.y = o.y - 35;
this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
spawn.mapRect(o.x + 200, o.y - 20, 100, 50);
spawn.mapRect(o.x + 450, o.y - 330, 50, 380);
spawn.mapRect(o.x - 200, o.y - 10, 700, 110);
spawn.mapRect(o.x, o.y - 325, 50, 100);
spawn.mapRect(o.x, o.y - 350, 500, 50);
// spawn.mapRect(o.x - 200, o.y, 300, 200);
// spawn.mapGunPowerUp(o.x - 50, o.y + 0); //spawns a gun on most early levels
// level.fillBG.push({
// x: o.x,
// y: o.y,
// width: 450,
// height: -350,
// color: "#dff"
// });
level.fill.push({
x: o.x,
y: o.y,
width: 450,
height: -350,
color: "rgba(0, 255, 255, 0.15)"
});
//set new fall height
game.fallHeight = o.y + 15000;
},
//*****************************************************************************************************************
//*****************************************************************************************************************
//*****************************************************************************************************************
//*****************************************************************************************************************
//*****************************************************************************************************************
//*****************************************************************************************************************
//*****************************************************************************************************************
enter: {
x: 0,
y: 0,
draw: function() {
ctx.beginPath();
ctx.moveTo(this.x, this.y + 30);
ctx.lineTo(this.x, this.y - 80);
ctx.bezierCurveTo(this.x, this.y - 170, this.x + 100, this.y - 170, this.x + 100, this.y - 80);
ctx.lineTo(this.x + 100, this.y + 30);
ctx.lineTo(this.x, this.y + 30);
ctx.fillStyle = "#ccc";
ctx.fill();
}
},
exit: {
x: 0,
y: 0,
draw: function() {
ctx.beginPath();
ctx.moveTo(this.x, this.y + 30);
ctx.lineTo(this.x, this.y - 80);
ctx.bezierCurveTo(this.x, this.y - 170, this.x + 100, this.y - 170, this.x + 100, this.y - 80);
ctx.lineTo(this.x + 100, this.y + 30);
ctx.lineTo(this.x, this.y + 30);
ctx.fillStyle = "#0ff";
ctx.fill();
}
},
fillBG: [],
drawFillBGs: function() {
for (let i = 0, len = level.fillBG.length; i < len; ++i) {
const f = level.fillBG[i];
ctx.fillStyle = f.color;
ctx.fillRect(f.x, f.y, f.width, f.height);
}
},
fill: [],
drawFills: function() {
for (let i = 0, len = level.fill.length; i < len; ++i) {
const f = level.fill[i];
ctx.fillStyle = f.color;
ctx.fillRect(f.x, f.y, f.width, f.height);
}
},
zones: [], //zone do actions when player is in a region // to effect everything use a query
checkZones: function() {
for (let i = 0, len = this.zones.length; i < len; ++i) {
if (
player.position.x > this.zones[i].x1 &&
player.position.x < this.zones[i].x2 &&
player.position.y > this.zones[i].y1 &&
player.position.y < this.zones[i].y2
) {
this.zoneActions[this.zones[i].action](i);
break;
}
}
},
addZone: function(x, y, width, height, action, info) {
this.zones[this.zones.length] = {
x1: x,
y1: y - 150,
x2: x + width,
y2: y + height - 70, //-70 to adjust for player height
action: action,
info: info
};
},
zoneActions: {
fling: function(i) {
Matter.Body.setVelocity(player, {
x: level.zones[i].info.Vx,
y: level.zones[i].info.Vy
});
},
nextLevel: function() {
//enter when player isn't falling
if (player.velocity.y < 0.1) {
game.dmgScale += 0.3; //damage done by mobs increases each level
b.dmgScale *= 0.92; //damage done by player decreases each level
game.levelsCleared++;
game.clearNow = true; //triggers in the physics engine to remove all physics bodies
}
},
death: function() {
mech.death();
},
laser: function(i) {
//draw these in game with spawn.background
mech.damage(level.zones[i].info.dmg);
},
slow: function() {
Matter.Body.setVelocity(player, {
x: player.velocity.x * 0.5,
y: player.velocity.y * 0.5
});
}
},
queryList: [], //queries do actions on many objects in regions (for only player use a zone)
checkQuery: function() {
let bounds, action, info;
function isInZone(targetArray) {
let results = Matter.Query.region(targetArray, bounds);
for (let i = 0, len = results.length; i < len; ++i) {
level.queryActions[action](results[i], info);
}
}
for (let i = 0, len = level.queryList.length; i < len; ++i) {
bounds = level.queryList[i].bounds;
action = level.queryList[i].action;
info = level.queryList[i].info;
for (let j = 0, l = level.queryList[i].groups.length; j < l; ++j) {
isInZone(level.queryList[i].groups[j]);
}
}
},
//oddly query regions can't get smaller than 50 width?
addQueryRegion: function(x, y, width, height, action, groups = [[player], body, mob, powerUp, bullet], info) {
this.queryList[this.queryList.length] = {
bounds: {
min: {
x: x,
y: y
},
max: {
x: x + width,
y: y + height
}
},
action: action,
groups: groups,
info: info
};
},
queryActions: {
bounce: function(target, info) {
//jerky fling upwards
Matter.Body.setVelocity(target, {
x: info.Vx + (Math.random() - 0.5) * 6,
y: info.Vy
});
target.torque = (Math.random() - 0.5) * 2 * target.mass;
},
boost: function(target, info) {
if (target.velocity.y < 0) {
mech.buttonCD_jump = 0; //reset short jump counter to pre vent short jumps on boosts
Matter.Body.setVelocity(target, {
x: target.velocity.x,
y: info
});
}
},
force: function(target, info) {
if (target.velocity.y < 0) {
//gently force up if already on the way up
target.force.x += info.Vx * target.mass;
target.force.y += info.Vy * target.mass;
} else {
target.force.y -= 0.0007 * target.mass; //gently fall in on the way down
}
},
antiGrav: function(target) {
target.force.y -= 0.0011 * target.mass;
},
death: function(target) {
target.death();
}
},
levelAnnounce: function() {
// let text = "n-gon L" + (game.levelsCleared + 1) + " " + level.levels[level.onLevel];
let text = "n-gon Level " + (game.levelsCleared + 1);
document.title = text;
// text = "Level " + (game.levelsCleared + 1) + ": " + spawn.pickList[0] + "s + " + spawn.pickList[1] + "s";
// game.makeTextLog(text, 300);
// text = text + " with population: ";
// for (let i = 0, len = spawn.pickList.length; i < len; ++i) {
// if (spawn.pickList[i] != spawn.pickList[i - 1]) {
// text += spawn.pickList[i] + ", ";
// }
// }
// this.speech(text);
// game.makeTextLog(text, 360);
},
addToWorld: function(mapName) {
//needs to be run to put bodies into the world
for (let i = 0; i < body.length; i++) {
//body[i].collisionFilter.group = 0;
body[i].collisionFilter.category = 0x0000001;
body[i].collisionFilter.mask = 0x011111;
body[i].classType = "body";
World.add(engine.world, body[i]); //add to world
}
for (let i = 0; i < map.length; i++) {
//map[i].collisionFilter.group = 0;
map[i].collisionFilter.category = 0x000001;
map[i].collisionFilter.mask = 0x111111;
Matter.Body.setStatic(map[i], true); //make static
World.add(engine.world, map[i]); //add to world
}
for (let i = 0; i < cons.length; i++) {
World.add(engine.world, cons[i]);
}
for (let i = 0; i < consBB.length; i++) {
World.add(engine.world, consBB[i]);
}
}
};

View File

@@ -1,833 +0,0 @@
//global game variables
let body = []; //non static bodies
let map = []; //all static bodies
let cons = []; //all constaints between a point and a body
let consBB = []; //all constaints between two bodies
//main object for spawning levels
const level = {
levels: ["towers", "skyscrapers", "rooftops", "warehouse", 'highrise'], // name of the level methods that the player runs through
onLevel: undefined,
start: function() {
// game.levelsCleared = 3; //for testing to simulate all possible mobs spawns
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
this[this.levels[this.onLevel]](); //spawn the level player is on, this cycles in a loop
//this.boss();
//this.warehouse();
//this.highrise();
//this.towers();
//this.skyscrapers();
//this.rooftops();
this.addToWorld(); //add map to world
this.levelAnnounce();
},
//******************************************************************************************************************
//******************************************************************************************************************
//empty map for testing mobs
boss: function() {
game.levelsCleared = 10; //for testing to simulate all possible mobs spawns
mech.setPosToSpawn(-75, -60); //normal spawn
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y + 20;
level.exit.x = 3500;
level.exit.y = -870;
this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
// this.addZone(250, -1000, 500, 1500, "laser");
spawn.debris(0, -900, 4500, 10); //20 debris per level
document.body.style.backgroundColor = "#eee";
// document.body.style.backgroundColor = "#fafcff";
// document.body.style.backgroundColor = "#bbb";
// document.body.style.backgroundColor = "#eee4e4";
// document.body.style.backgroundColor = "#dcdcde";
// document.body.style.backgroundColor = "#e0e5e0";
// this.addQueryRegion(550, -25, 100, 50, "bounce", { Vx: 0, Vy: -25 });
// level.fillBG.push({ x: 550, y: -25, width: 100, height: 50, color: "#ff0" });
spawn.mapRect(3500, -860, 100, 50); //ground bump wall
spawn.mapRect(-1200, 0, 2200, 300); //ground
spawn.mapVertex(1250, 0, "0 0 0 300 -500 600 -500 300");
spawn.mapRect(1500, -300, 2000, 300); //upper ground
spawn.mapVertex(3750, 0, "0 600 0 300 -500 0 -500 300");
spawn.mapRect(4000, 0, 1000, 300); //right lower ground
spawn.mapRect(2200, -600, 600, 50); //center platform
spawn.mapRect(1300, -850, 700, 50); //center platform
spawn.mapRect(3000, -850, 700, 50); //center platform
spawn.spawnBuilding(-200, -250, 275, 240, false, true, "left"); //far left; player spawns in side
//spawn.boost(350, 0, 0, -0.005);
powerUps.spawn(450, -125, "gun", false);
// powerUps.spawn(450, -125, "gun", false);
// powerUps.spawn(450, -125, "gun", false);
for (let i = 0; i < 5; i++) {
//powerUps.spawn(2500+i*15, -1000, "gun", false);
powerUps.spawn(2500+ i*20, -1300, "gun", false);
powerUps.spawn(2500 + i * 20, -1100, "ammo", false);
}
spawn.bodyRect(700, -50, 50, 50);
spawn.bodyRect(700, -100, 50, 50);
spawn.bodyRect(700, -150, 50, 50);
spawn.bodyRect(700, -200, 50, 50);
spawn.bodyRect(-100, -260, 250, 10);
spawn.chaser(1240, -1100, 40);
spawn.blackHoler(400, -1400);
spawn.shooter(1300, -1150, 20);
spawn.shooter(800, -1150, 50);
// spawn.shooter(400, -1150, 150);
spawn.lineBoss(900, -1470,'laserTracker',4);
// spawn.randomBoss(-100, -1470);
},
warehouse: function() {
// document.body.style.backgroundColor = (Math.random() < 0.5) ? "#aaa" : "#e3e3f0"
document.body.style.backgroundColor = "#bbb";
mech.setPosToSpawn(25, -60); //normal spawn
//mech.setPosToSpawn(-2000, -1700); // left ledge spawn
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y + 20;
level.exit.x = 425;
level.exit.y = -35;
this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
//level.addQueryRegion(-600, -250, 180, 420, "death", [[player]],{});
spawn.debris(-2250, 1330, 3000, 7); //20 debris per level
spawn.debris(-3000, -800, 3280, 7); //20 debris per level
spawn.debris(-1400, 410, 2300, 6); //20 debris per level
if (game.levelsCleared < 2) powerUps.spawn(-1250, 560, "gun", false); //starting gun
//foreground
// level.fill.push({ x: -3025, y: 50, width: 4125, height: 1350, color: "rgba(0,0,0,0.05)"});
// level.fill.push({ x: -1800, y: -500, width: 1975, height: 550, color: "rgba(0,0,0,0.05)"});
// level.fill.push({ x: -2600, y: -150, width: 700, height: 200, color: "rgba(0,0,0,0.05)"});
//background
const BGColor = "#f3f3ea";
level.fillBG.push({ x: -3025, y: 50, width: 4125, height: 1350, color: BGColor });
level.fillBG.push({ x: -1800, y: -500, width: 1975, height: 555, color: BGColor });
level.fillBG.push({ x: -2600, y: -150, width: 700, height: 205, color: BGColor });
level.fillBG.push({ x: 300, y: -250, width: 350, height: 250, color: "#cff" });
spawn.mapRect(-1500, 0, 2750, 100);
spawn.mapRect(175, -600, 125, 700);
spawn.mapRect(-1900, -600, 2200, 100);
spawn.mapRect(-1900, -600, 100, 1300);
//house
spawn.mapRect(-175, -550, 50, 400);
spawn.mapRect(-175, -15, 350, 50);
spawn.mapRect(-25, -25, 100, 50);
// spawn.mapRect(-175, -275, 350, 25);
// spawn.mapRect(-175, -250, 25, 75);
// spawn.bodyRect(-170, -175, 14, 160, 1, spawn.propsFriction); //door to starting room
//exit house
spawn.mapRect(300, -15, 350, 50);
spawn.mapRect(300, -275, 350, 25);
spawn.mapRect(625, -250, 25, 75);
spawn.mapRect(425, -25, 100, 25);
// spawn.mapRect(-1900, 600, 2700, 100);
spawn.mapRect(1100, 0, 150, 1500);
spawn.mapRect(-2850, 1400, 4100, 100);
spawn.mapRect(-2375, 875, 1775, 100);
spawn.mapRect(-1450, 950, 75, 346);
spawn.mapRect(-1433, 662, 41, 111);
spawn.bodyRect(-1418, 773, 11, 102, 1, spawn.propsFriction); //blocking path
spawn.mapRect(-2950, 1250, 175, 250);
spawn.mapRect(-3050, 1100, 150, 400);
spawn.mapRect(-3150, 50, 125, 1450);
spawn.mapRect(-2375, 600, 3175, 100);
spawn.mapRect(-2125, 300, 250, 325);
spawn.mapRect(-1950, -400, 100, 25);
spawn.mapRect(-3150, 50, 775, 100);
spawn.mapRect(-2600, -200, 775, 50);
spawn.bodyRect(-1350, -200, 200, 200, 1, spawn.propsSlide); //weight
spawn.bodyRect(-1800, 0, 300, 100, 1, spawn.propsHoist); //hoist
cons[cons.length] = Constraint.create({
pointA: {
x: -1650,
y: -500
},
bodyB: body[body.length - 1],
stiffness: 0.0005,
length: 1
});
spawn.bodyRect(400, 400, 200, 200, 1, spawn.propsSlide); //weight
spawn.bodyRect(800, 600, 300, 100, 1, spawn.propsHoist); //hoist
cons[cons.length] = Constraint.create({
pointA: {
x: 950,
y: 100
},
bodyB: body[body.length - 1],
stiffness: 0.0005,
length: 1
});
spawn.bodyRect(-2775, 1150, 190, 150, 1, spawn.propsSlide); //weight
spawn.bodyRect(-2575, 1150, 200, 150, 1, spawn.propsSlide); //weight
spawn.bodyRect(-2775, 1300, 400, 100, 1, spawn.propsHoist); //hoist
cons[cons.length] = Constraint.create({
pointA: {
x: -2575,
y: 150
},
bodyB: body[body.length - 1],
stiffness: 0.0005,
length: 220
});
//blocks
//spawn.bodyRect(-155, -150, 10, 140, 1, spawn.propsFriction);
spawn.bodyRect(-165, -150, 30, 35, 1);
spawn.bodyRect(-165, -115, 30, 35, 1);
spawn.bodyRect(-165, -80, 30, 35, 1);
spawn.bodyRect(-165, -45, 30, 35, 1);
spawn.bodyRect(-750, 400, 150, 150, 0.5);
spawn.bodyRect(-200, 1175, 250, 225, 1); //block to get to top path on bottom level
// spawn.bodyRect(-1450, 737, 75, 103, 0.5); //blocking path
spawn.bodyRect(-2525, -50, 145, 100, 0.5);
spawn.bodyRect(-2325, -300, 150, 100, 0.5);
spawn.bodyRect(-1275, -750, 200, 150, 0.5); //roof block
spawn.bodyRect(-525, -700, 125, 100, 0.5); //roof block
//mobs
spawn.randomSmallMob(-1125, 550);
spawn.randomSmallMob(-2325, 800);
spawn.randomSmallMob(-2950, -50);
spawn.randomSmallMob(825, 300);
spawn.randomSmallMob(-900, 825);
spawn.randomMob(-2025, 175, 0.7);
spawn.randomMob(-2325, 450, 0.7);
spawn.randomMob(-2925, 675, 0.7);
spawn.randomMob(-2700, 300, 0.25);
spawn.randomMob(-2500, 300, 0.25);
spawn.randomMob(-2075, -425, 0.25);
spawn.randomMob(-1550, -725, 0.25);
spawn.randomMob(375, 1100, 0.15);
spawn.randomMob(-1425, -100, 0.3);
spawn.randomMob(-800, -750, 0.2);
spawn.randomMob(400, -350, 0);
spawn.randomMob(650, 1300, 0.1);
spawn.randomMob(-750, -150, 0);
spawn.randomMob(475, 300, 0);
spawn.randomMob(-75, -700, 0);
spawn.randomMob(900, -200, -0.1);
spawn.randomBoss(-125, 275, -0.1);
spawn.randomBoss(-825, 1000, 0.3);
spawn.randomBoss(-1300, -1100, 0.1);
//spawn.randomBoss(600, -1575, 0);
//spawn.randomMob(1120, -1200, 0.3);
//spawn.randomSmallMob(2200, -1775); //
},
highrise: function() {
document.body.style.backgroundColor = "#fafcff";
mech.setPosToSpawn(0, -700); //normal spawn
//mech.setPosToSpawn(-2000, -1700); // left ledge spawn
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y + 20;
level.exit.x = -4275;
level.exit.y = -2805;
this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
if (game.levelsCleared < 2) powerUps.spawn(-2550, -700, "gun", false); //starting gun
// spawn.laserZone(-550, -350, 10, 400, 0.3)
// spawn.deathQuery(-550, -350, 50, 400)
// spawn.debris(-3950, -2575, 1050, 4); //20 debris per level
spawn.debris(-2325, -1825, 2400, 10); //20 debris per level
spawn.debris(-2625, -700, 925, 10); //20 debris per level
// if (!game.levelsCleared) powerUps.spawn(2450, -1675, "gun", false);
//background
level.fillBG.push({ x: -4425, y: -3050, width: 425, height: 275, color: "#cff"});
//foreground
level.fill.push({ x: -1650, y: -1575, width: 550, height: 425, color: "rgba(10,10,0,0.12)"});
level.fill.push({ x: -2600, y: -2400, width: 450, height: 1800, color: "rgba(10,10,0,0.12)"});
level.fill.push({ x: -3425, y: -2150, width: 525, height: 1550, color: "rgba(10,10,0,0.12)"});
level.fill.push({ x: -1850, y: -1150, width: 2025, height: 1150, color: "rgba(10,10,0,0.12)"});
//building 1
spawn.bodyRect(-1000, -675, 25, 25);
spawn.mapRect(-2225, 0, 2475, 150);
spawn.mapRect(175, -1000, 75, 1100);
spawn.mapRect(-175, -985, 25, 175);
spawn.bodyRect(-170, -810, 14, 160, 1, spawn.propsFriction); //door to starting room
spawn.mapRect(-600, -650, 825, 50);
spawn.mapRect(-1300, -650, 500, 50);
spawn.mapRect(-175, -250, 425, 300);
spawn.bodyRect(-75, -300, 50, 50);
spawn.boost(-750, 0, 0, -0.01);
spawn.bodyRect(-425, -1375, 400, 225);
spawn.mapRect(-1125, -1575, 50, 475);
spawn.bodyRect(-1475, -1275, 250, 125);
spawn.bodyRect(-825, -1160, 250, 10);
spawn.mapRect(-1650, -1575, 400, 50);
spawn.mapRect(-600, -1150, 850, 175);
spawn.mapRect(-1850, -1150, 1050, 175);
spawn.bodyRect(-1907, -1600, 550, 25);
spawn.bodyRect(-1400, -125, 125, 125);
spawn.bodyRect(-1100, -125, 150, 125);
spawn.bodyRect(-1360, -200, 75, 75);
spawn.bodyRect(-1200, -75, 75, 75);
//building 2
spawn.mapRect(-3450, -600, 1300, 750);
spawn.mapRect(-2225, -400, 175, 550);
spawn.boost(-2800, -600, 0, -0.005);
spawn.mapRect(-3450, -1325, 550, 50);
spawn.mapRect(-3425, -2200, 525, 50);
spawn.mapRect(-2600, -1750, 450, 50);
spawn.mapRect(-2600, -2450, 450, 50);
spawn.bodyRect(-2275, -2700, 50, 60);
spawn.bodyRect(-2600, -1975, 250, 225);
spawn.bodyRect(-3415, -1425, 100, 100);
spawn.bodyRect(-3400, -1525, 100, 100);
spawn.bodyRect(-3305, -1425, 100, 100);
//building 3
spawn.mapRect(-4450, -1750, 1025, 1900);
spawn.mapRect(-3750, -2000, 175, 275);
spawn.mapRect(-4000, -2425, 275, 675);
// spawn.mapRect(-4450, -2650, 475, 1000);
spawn.mapRect(-4450, -2775, 475, 1125);
spawn.bodyRect(-3715, -2050, 50, 50);
spawn.bodyRect(-3570, -1800, 50, 50);
spawn.bodyRect(-2970, -2250, 50, 50);
spawn.bodyRect(-3080, -2250, 40, 40);
spawn.bodyRect(-3420, -650, 50, 50);
//exit
spawn.mapRect(-4450, -3075, 25, 300);
spawn.mapRect(-4450, -3075, 450, 25);
spawn.mapRect(-4025, -3075, 25, 100);
spawn.mapRect(-4275, -2785, 100, 25);
//mobs
spawn.randomMob(-2500, -2700, 1);
spawn.randomMob(-3200, -750, 1);
spawn.randomMob(-1875, -775, 0.2);
spawn.randomMob(-950, -1675, 0.2);
spawn.randomMob(-1525, -1750, 0.2);
spawn.randomMob(-1375, -1400, 0.2);
spawn.randomMob(-1625, -1275, 0.2);
spawn.randomMob(-1900, -1250, 0.2);
spawn.randomMob(-2250, -1850, 0.2);
spawn.randomMob(-2475, -2200, 0.2);
spawn.randomMob(-3000, -1475, 0.2);
spawn.randomMob(-3850, -2500, 0.2);
spawn.randomMob(-3650, -2125, 0.2);
spawn.randomMob(-4010, -3200, 0.2);
spawn.randomMob(-3500, -1825, 0.2);
spawn.randomMob(-975, -100, 0);
spawn.randomMob(-1050, -725, 0.2);
spawn.randomMob(-1525, -100, 0);
spawn.randomMob(-525, -1700, -0.1);
spawn.randomMob(-125, -1500, -0.1);
spawn.randomMob(-325, -1900, -0.1);
spawn.randomMob(-550, -100, -0.1);
spawn.randomBoss(-3250, -2700, 0.2);
spawn.randomBoss(-2450, -1100, 0);
},
//******************************************************************************************************************
//******************************************************************************************************************
rooftops: function() {
document.body.style.backgroundColor = "#eee4e4";
// this.addZone(-700, -50, 4100, 100, "death");
mech.setPosToSpawn(-450, -2050); //normal spawn
//mech.setPosToSpawn(4600, -900); //normal spawn
//mech.setPosToSpawn(4400, -400); //normal spawn
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y + 20;
level.exit.x = 3600;
level.exit.y = -300;
this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
spawn.debris(1650, -1800, 3800, 20); //20 debris per level
if (game.levelsCleared < 2) powerUps.spawn(2450, -1675, "gun", false);
//foreground
level.fill.push({ x: -650, y: -2300, width: 450, height: 300, color: "rgba(0,0,0,0.15)" });
level.fill.push({ x: 3450, y: -1250, width: 1100, height: 1250, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 4550, y: -725, width: 900, height: 725, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 3400, y: 100, width: 2150, height: 900, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: -700, y: -1900, width: 2100, height: 2900, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 1950, y: -1550, width: 1025, height: 550, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 1600, y: -900, width: 1600, height: 1900, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 3450, y: -1550, width: 350, height: 300, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 700, y: -2225, width: 700, height: 225, color: "rgba(0,0,0,0.1)" });
//spawn.mapRect(-700, 0, 6250, 100); //ground
spawn.mapRect(3400, 0, 2150, 100); //ground
spawn.mapRect(-700, -2000, 2100, 100); //Top left ledge
spawn.bodyRect(1350, -2125, 50, 125, 0.8); //
spawn.bodyRect(1350, -2225, 50, 100, 0.8); //
spawn.mapRect(-700, -2350, 50, 400); //far left starting left wall
spawn.mapRect(-700, -2010, 500, 50); //far left starting ground
spawn.mapRect(-700, -2350, 500, 50); //far left starting ceiling
spawn.mapRect(-250, -2350, 50, 200); //far left starting right part of wall
spawn.bodyRect(-240, -2150, 30, 36); //door to starting room
spawn.bodyRect(-240, -2115, 30, 36); //door to starting room
spawn.bodyRect(-240, -2080, 30, 35); //door to starting room
spawn.bodyRect(-240, -2045, 30, 35); //door to starting room
spawn.bodyRect(200, -2150, 200, 220, 0.8); //
spawn.mapRect(700, -2275, 700, 50); //
spawn.bodyRect(1050, -2350, 30, 30, 0.8); //
spawn.boost(1800, -1000);
spawn.bodyRect(1625, -1100, 100, 75); //
spawn.bodyRect(1350, -1025, 400, 25); //
spawn.mapRect(-700, -1000, 2100, 100); //lower left ledge
spawn.bodyRect(350, -1100, 200, 100, 0.8); //
spawn.bodyRect(370, -1200, 100, 100, 0.8); //
spawn.bodyRect(360, -1300, 100, 100, 0.8); //
spawn.bodyRect(950, -1050, 300, 50, 0.8); //
spawn.bodyRect(-600, -1250, 400, 250, 0.8); //
spawn.mapRect(1600, -1000, 1600, 100); //middle ledge
spawn.bodyRect(2600, -1950, 100, 250, 0.8); //
spawn.bodyRect(2700, -1125, 125, 125, 0.8); //
spawn.bodyRect(2710, -1250, 125, 125, 0.8); //
spawn.bodyRect(2705, -1350, 75, 100, 0.8); //
spawn.mapRect(3450, -1600, 350, 50); //
spawn.mapRect(1950, -1600, 1025, 50); //
spawn.bodyRect(3100, -1015, 375, 15, 0.8); //
spawn.bodyRect(3500, -850, 75, 125, 0.8); //
spawn.mapRect(3400, -1000, 100, 1100); //left building wall
spawn.mapRect(5450, -775, 100, 875); //right building wall
spawn.bodyRect(4850, -750, 300, 25, 0.8); //
spawn.bodyRect(3925, -1400, 100, 150, 0.8); //
spawn.mapRect(3450, -1250, 1100, 50); //
spawn.mapRect(3450, -1225, 50, 75); //
spawn.mapRect(4500, -1225, 50, 350); //
spawn.mapRect(3450, -725, 1450, 50); //
spawn.mapRect(5100, -725, 400, 50); //
spawn.mapRect(4500, -700, 50, 600); //
spawn.bodyRect(4500, -100, 50, 100, 0.8); //
// spawn.boost(4950, 0, 0, -0.005);
spawn.spawnStairs(3800, 0, 3, 150, 206); //stairs top exit
spawn.mapRect(3500, -275, 350, 275); //exit platform
spawn.mapRect(3600, -285, 100, 50); //ground bump wall
spawn.randomSmallMob(2200, -1775); //
spawn.randomSmallMob(4000, -825); //
spawn.randomSmallMob(4100, -100);
spawn.randomSmallMob(4600, -100);
spawn.randomSmallMob(-350, -2400); //
spawn.randomMob(4250, -1350, 0.8); //
spawn.randomMob(2550, -1350, 0.8); //
spawn.randomMob(1225, -2400, 0.3); //
spawn.randomMob(1120, -1200, 0.3);
spawn.randomMob(3000, -1150, 0.2); //
spawn.randomMob(3200, -1150, 0.3); //
spawn.randomMob(3300, -1750, 0.3); //
spawn.randomMob(3650, -1350, 0.3); //
spawn.randomMob(3600, -1800, 0.1); //
spawn.randomMob(5200, -100, 0.3);
spawn.randomMob(5275, -900, 0.2);
spawn.randomMob(3765, -450, 0.3); //
spawn.randomMob(900, -2125, 0.3); //
spawn.randomBoss(600, -1575, 0);
spawn.randomBoss(2225, -1325, 0.4); //
spawn.randomBoss(4900, -1200, 0); //
//spawn.randomBoss(4850, -1250,0.7);
},
//******************************************************************************************************************
//******************************************************************************************************************
towers: function() {
mech.setPosToSpawn(1375, -1550); //normal spawn
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y + 20;
level.exit.x = 3250;
level.exit.y = -530;
this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
document.body.style.backgroundColor = "#e0e5e0";
//foreground
level.fill.push({ x: -550, y: -1700, width: 1300, height: 1700, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 750, y: -1450, width: 650, height: 1450, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 750, y: -1950, width: 800, height: 450, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 3000, y: -1000, width: 650, height: 1000, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 3650, y: -1300, width: 1300, height: 1300, color: "rgba(0,0,0,0.1)" });
//background
level.fillBG.push({ x: 2495, y: -500, width: 10, height: 525, color: "#ccc" });
//mech.setPosToSpawn(600, -1200); //normal spawn
//mech.setPosToSpawn(525, -150); //ground first building
//mech.setPosToSpawn(3150, -700); //near exit spawn
spawn.debris(-300, -200, 4800, 10); //ground debris //20 debris per level
spawn.debris(-300, -650, 4800, 10); //1st floor debris //20 debris per level
if (game.levelsCleared < 2) powerUps.spawn(525, -700, "gun", false);
spawn.mapRect(-600, 25, 5600, 300); //ground
spawn.mapRect(-600, 0, 2000, 50); //ground
spawn.mapRect(-600, -1700, 50, 2000 - 100); //left wall
spawn.bodyRect(-295, -1540, 40, 40); //center block under wall
spawn.bodyRect(-298, -1580, 40, 40); //center block under wall
spawn.bodyRect(1500, -1540, 30, 30); //left of entrance
spawn.mapRect(1550, -2000, 50, 550); //right wall
spawn.mapRect(1350, -2000 + 505, 50, 1295); //right wall
spawn.mapRect(-600, -2000 + 250, 2000 - 700, 50); //roof left
spawn.mapRect(-600 + 1300, -2000, 50, 300); //right roof wall
spawn.mapRect(-600 + 1300, -2000, 900, 50); //center wall
map[map.length] = Bodies.polygon(425, -1700, 0, 15); //circle above door
spawn.bodyRect(420, -1675, 15, 170, 1, spawn.propsDoor); // door
//makes door swing
consBB[consBB.length] = Constraint.create({
bodyA: body[body.length - 1],
pointA: {
x: 0,
y: -90
},
bodyB: map[map.length - 1],
stiffness: 1
});
spawn.mapRect(-600 + 300, -2000 * 0.75, 1900, 50); //3rd floor
spawn.mapRect(-600 + 2000 * 0.7, -2000 * 0.74, 50, 375); //center wall
spawn.bodyRect(-600 + 2000 * 0.7, -2000 * 0.5 - 106, 50, 106); //center block under wall
spawn.mapRect(-600, -1000, 1100, 50); //2nd floor
spawn.mapRect(600, -1000, 500, 50); //2nd floor
spawn.spawnStairs(-600, -1000, 4, 250, 350); //stairs 2nd
spawn.mapRect(350, -600, 350, 150); //center table
spawn.mapRect(-600 + 300, -2000 * 0.25, 2000 - 300, 50); //1st floor
spawn.spawnStairs(-600 + 2000 - 50, -500, 4, 250, 350, true); //stairs 1st
spawn.spawnStairs(-600, 0, 4, 250, 350); //stairs ground
spawn.bodyRect(700, -200, 100, 100); //center block under wall
spawn.bodyRect(700, -300, 100, 100); //center block under wall
spawn.bodyRect(700, -400, 100, 100); //center block under wall
spawn.mapRect(1390, 13, 30, 20); //step left
spawn.mapRect(2980, 13, 30, 20); //step right
spawn.mapRect(3000, 0, 2000, 50); //ground
spawn.bodyRect(4250, -700, 50, 100);
spawn.bodyRect(3000, -200, 50, 200); //door
spawn.mapRect(3000, -1000, 50, 800); //left wall
spawn.mapRect(3000 + 2000 - 50, -1300, 50, 1100); //right wall
spawn.mapRect(4150, -600, 350, 150); //table
spawn.mapRect(3650, -1300, 50, 650); //exit wall
spawn.mapRect(3650, -1300, 1350, 50); //exit wall
spawn.mapRect(3000 + 250, -510, 100, 50); //ground bump wall
spawn.mapRect(3000, -2000 * 0.5, 700, 50); //exit roof
spawn.mapRect(3000, -2000 * 0.25, 2000 - 300, 50); //1st floor
spawn.spawnStairs(3000 + 2000 - 50, 0, 4, 250, 350, true); //stairs ground
//teatherball
spawn[spawn.pickList[0]](2850, -80, 40 + game.levelsCleared * 8);
cons[cons.length] = Constraint.create({
pointA: {
x: 2500,
y: -500
},
bodyB: mob[mob.length - 1],
stiffness: 0.0004
});
spawn.randomSmallMob(3550, -550);
spawn.randomSmallMob(4575, -560, 1);
spawn.randomSmallMob(1315, -880, 1);
spawn.randomSmallMob(800, -600);
spawn.randomSmallMob(-100, -1600);
spawn.randomMob(4100, -225, 0.8);
spawn.randomMob(-250, -700, 0.8);
spawn.randomMob(4500, -225, 0.15);
spawn.randomMob(3250, -225, 0.15);
spawn.randomMob(-100, -225, 0.1);
spawn.randomMob(1150, -225, 0.15);
spawn.randomMob(2000, -225, 0.15);
spawn.randomMob(450, -225, 0.15);
spawn.randomMob(100, -1200, 1);
spawn.randomMob(950, -1150, -0.1);
spawn.randomBoss(1800, -800, 0.4);
spawn.randomBoss(4150, -1000, 0.6);
},
//******************************************************************************************************************
//******************************************************************************************************************
skyscrapers: function() {
mech.setPosToSpawn(-50, -50); //normal spawn
//mech.setPosToSpawn(1550, -1200); //spawn left high
//mech.setPosToSpawn(1800, -2000); //spawn near exit
level.enter.x = mech.spawnPos.x - 50;
level.enter.y = mech.spawnPos.y + 20;
level.exit.x = 1500;
level.exit.y = -1875;
this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
if (game.levelsCleared < 2) powerUps.spawn(1475, -1175, "gun", false);
spawn.debris(0, -2200, 4500, 20); //20 debris per level
document.body.style.backgroundColor = "#dcdcde";
//foreground
level.fill.push({ x: 2500, y: -1100, width: 450, height: 250, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 2400, y: -550, width: 600, height: 150, color: "rgba(0,0,0,0.1)" });
level.fill.push({ x: 2550, y: -1650, width: 250, height: 200, color: "rgba(0,0,0,0.1)" });
//level.fill.push({ x: 1350, y: -2100, width: 400, height: 250, color: "rgba(0,255,255,0.1)" });
level.fill.push({ x: 700, y: -110, width: 400, height: 110, color: "rgba(0,0,0,0.2)" });
level.fill.push({ x: 3600, y: -110, width: 400, height: 110, color: "rgba(0,0,0,0.2)" });
level.fill.push({ x: -250, y: -300, width: 450, height: 300, color: "rgba(0,0,0,0.15)" });
//background
level.fillBG.push({ x: 1300, y: -1800, width: 750, height: 1800, color: "#d4d4d7" });
level.fillBG.push({ x: 3350, y: -1325, width: 50, height: 1325, color: "#d4d4d7" });
level.fillBG.push({ x: 1350, y: -2100, width: 400, height: 250, color: "#d4f4f4" });
spawn.mapRect(-300, 0, 5000, 300); //***********ground
spawn.mapRect(-300, -350, 50, 400); //far left starting left wall
spawn.mapRect(-300, -10, 500, 50); //far left starting ground
spawn.mapRect(-300, -350, 500, 50); //far left starting ceiling
spawn.mapRect(150, -350, 50, 200); //far left starting right part of wall
spawn.bodyRect(170, -130, 14, 140, 1, spawn.propsFriction); //door to starting room
spawn.boost(475, 0, 0.0005, -0.007);
spawn.mapRect(700, -1100, 400, 990); //far left building
spawn.mapRect(1600, -400, 1500, 500); //long center building
spawn.mapRect(1345, -1100, 250, 25); //left platform
spawn.mapRect(1755, -1100, 250, 25); //right platform
spawn.mapRect(1300, -1850, 750, 50); //left higher platform
spawn.mapRect(1300, -2150, 50, 350); //left higher platform left edge wall
spawn.mapRect(1300, -2150, 450, 50); //left higher platform roof
spawn.mapRect(1500, -1860, 100, 50); //ground bump wall
spawn.mapRect(2400, -850, 600, 300); //center floating large square
//spawn.bodyRect(2500, -1100, 25, 250); //wall before chasers
spawn.mapRect(2500, -1450, 450, 350); //higher center floating large square
spawn.mapRect(2500, -1700, 50, 300); //left wall on higher center floating large square
spawn.mapRect(2500, -1700, 300, 50); //roof on higher center floating large square
spawn.mapRect(3300, -850, 150, 25); //ledge by far right building
spawn.mapRect(3300, -1350, 150, 25); //higher ledge by far right building
spawn.mapRect(3600, -1100, 400, 990); //far right building
spawn.boost(4150, 0, -0.0005, -0.007);
spawn.bodyRect(3200, -1375, 300, 25, 0.9);
spawn.bodyRect(1825, -1875, 400, 25, 0.9);
// spawn.bodyRect(1800, -575, 250, 150, 0.8);
spawn.bodyRect(1800, -600, 250, 200, 0.8);
spawn.bodyRect(2557, -450, 35, 55, 0.7);
spawn.bodyRect(2957, -450, 30, 15, 0.7);
spawn.bodyRect(2900, -450, 60, 45, 0.7);
spawn.bodyRect(1915, -1200, 60, 100, 0.8);
spawn.bodyRect(1925, -1300, 50, 100, 0.8);
if (Math.random() < 0.9) {
spawn.bodyRect(2300, -1720, 400, 20);
spawn.bodyRect(2590, -1780, 80, 80);
}
spawn.bodyRect(2925, -1100, 25, 250, 0.8);
spawn.bodyRect(3325, -1550, 50, 200, 0.3);
if (Math.random() < 0.8) {
spawn.bodyRect(1400, -75, 200, 75); //block to get up ledge from ground
spawn.bodyRect(1525, -125, 50, 50); //block to get up ledge from ground
}
spawn.bodyRect(1025, -1110, 400, 10, 0.9); //block on far left building
spawn.bodyRect(1550, -1110, 250, 10, 0.9); //block on far left building
spawn.randomSmallMob(1300, -70);
spawn.randomSmallMob(3200, -100);
spawn.randomSmallMob(4450, -100);
spawn.randomSmallMob(2700, -475);
spawn.randomMob(2650, -975, 0.8);
spawn.randomMob(2650, -1550, 0.8);
spawn.randomMob(4150, -200, 0.15);
spawn.randomMob(1700, -1300, 0.2);
spawn.randomMob(1850, -1950, 0.25);
spawn.randomMob(2610, -1880, 0.25);
spawn.randomMob(3350, -950, 0.25);
spawn.randomMob(1690, -2250, 0.25);
spawn.randomMob(2200, -600, 0.2);
spawn.randomMob(900, -1300, 0.25);
spawn.randomMob(-100, -900, -0.2);
spawn.randomBoss(3700, -1500, 0.4);
spawn.randomBoss(1700, -900, 0.4);
},
//*****************************************************************************************************************
//*****************************************************************************************************************
enter: {
x: 0,
y: 0,
draw: function() {
ctx.beginPath();
ctx.moveTo(this.x, this.y + 30);
ctx.lineTo(this.x, this.y - 80);
ctx.bezierCurveTo(this.x, this.y - 170, this.x + 100, this.y - 170, this.x + 100, this.y - 80);
ctx.lineTo(this.x + 100, this.y + 30);
ctx.lineTo(this.x, this.y + 30);
ctx.fillStyle = "#ccc";
ctx.fill();
}
},
exit: {
x: 0,
y: 0,
draw: function() {
ctx.beginPath();
ctx.moveTo(this.x, this.y + 30);
ctx.lineTo(this.x, this.y - 80);
ctx.bezierCurveTo(this.x, this.y - 170, this.x + 100, this.y - 170, this.x + 100, this.y - 80);
ctx.lineTo(this.x + 100, this.y + 30);
ctx.lineTo(this.x, this.y + 30);
ctx.fillStyle = "#0ff";
ctx.fill();
}
},
fillBG: [],
drawFillBGs: function() {
for (let i = 0, len = level.fillBG.length; i < len; ++i) {
const f = level.fillBG[i];
ctx.fillStyle = f.color;
ctx.fillRect(f.x, f.y, f.width, f.height);
}
},
fill: [],
drawFills: function() {
for (let i = 0, len = level.fill.length; i < len; ++i) {
const f = level.fill[i];
ctx.fillStyle = f.color;
ctx.fillRect(f.x, f.y, f.width, f.height);
}
},
zones: [], //zone do actions when player is in a region // to effect everything use a query
checkZones: function() {
for (let i = 0, len = this.zones.length; i < len; ++i) {
if (
player.position.x > this.zones[i].x1 &&
player.position.x < this.zones[i].x2 &&
player.position.y > this.zones[i].y1 &&
player.position.y < this.zones[i].y2
) {
this.zoneActions[this.zones[i].action](i);
break;
}
}
},
addZone: function(x, y, width, height, action, info) {
this.zones[this.zones.length] = {
x1: x,
y1: y - 150,
x2: x + width,
y2: y + height - 70, //-70 to adjust for player height
action: action,
info: info
};
},
zoneActions: {
fling: function(i) {
Matter.Body.setVelocity(player, {
x: level.zones[i].info.Vx,
y: level.zones[i].info.Vy
});
},
nextLevel: function() {
level.onLevel++;
if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
game.dmgScale += 0.2; //damage done by mobs increases each level
b.dmgScale *= 0.85; //damage done by player decreases each level
game.levelsCleared++;
game.clearNow = true;
},
death: function() {
mech.death();
},
laser: function(i) {
//draw these in game with spawn.background
mech.damage(level.zones[i].info.dmg);
},
slow: function() {
Matter.Body.setVelocity(player, {
//reduce player velocity every cycle until not true
x: player.velocity.x * 0.5,
y: player.velocity.y * 0.5
});
}
},
queryList: [], //queries do actions on many objects in regions
checkQuery: function() {
let bounds, action, info;
function isInZone(targetArray) {
let results = Matter.Query.region(targetArray, bounds);
for (let i = 0, len = results.length; i < len; ++i) {
level.queryActions[action](results[i], info);
}
}
for (let i = 0, len = level.queryList.length; i < len; ++i) {
bounds = level.queryList[i].bounds;
action = level.queryList[i].action;
info = level.queryList[i].info;
for (let j = 0, l = level.queryList[i].groups.length; j < l; ++j) {
isInZone(level.queryList[i].groups[j]);
}
}
},
//oddly query regions can't get smaller than 50 width?
addQueryRegion: function(x, y, width, height, action, groups = [[player], body, mob, powerUp, bullet], info) {
this.queryList[this.queryList.length] = {
bounds: {
min: {
x: x,
y: y
},
max: {
x: x + width,
y: y + height
}
},
action: action,
groups: groups,
info: info
};
},
queryActions: {
bounce: function(target, info) {
//jerky fling upwards
Matter.Body.setVelocity(target, { x: info.Vx + (Math.random() - 0.5) * 6, y: info.Vy });
target.torque = (Math.random() - 0.5) * 2 * target.mass;
},
force: function(target, info) {
if (target.velocity.y < 0) {
//gently force up if already on the way up
target.force.x += info.Vx * target.mass;
target.force.y += info.Vy * target.mass;
} else {
target.force.y -= 0.0007 * target.mass; //gently fall in on the way down
}
},
antiGrav: function(target) {
target.force.y -= 0.0011 * target.mass;
},
death: function(target){
target.death()
}
},
levelAnnounce: function() {
let text = "level " + (game.levelsCleared + 1) + " " + level.levels[level.onLevel];
document.title = text;
// text = text + " with population: ";
// for (let i = 0, len = spawn.pickList.length; i < len; ++i) {
// if (spawn.pickList[i] != spawn.pickList[i - 1]) {
// text += spawn.pickList[i] + ", ";
// }
// }
// this.speech(text);
// game.makeTextLog(text, 360);
},
addToWorld: function(mapName) {
//needs to be run to put bodies into the world
for (let i = 0; i < body.length; i++) {
//body[i].collisionFilter.group = 0;
body[i].collisionFilter.category = 0x0000001;
body[i].collisionFilter.mask = 0x111101;
body[i].classType = "body";
World.add(engine.world, body[i]); //add to world
}
for (let i = 0; i < map.length; i++) {
//map[i].collisionFilter.group = 0;
map[i].collisionFilter.category = 0x000001;
map[i].collisionFilter.mask = 0x111111;
Matter.Body.setStatic(map[i], true); //make static
World.add(engine.world, map[i]); //add to world
}
for (let i = 0; i < cons.length; i++) {
World.add(engine.world, cons[i]);
}
for (let i = 0; i < consBB.length; i++) {
World.add(engine.world, consBB[i]);
}
}
};

View File

@@ -1,89 +0,0 @@
/**
* matter-js 0.12.0 by @liabru 2017-02-02
* 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 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 u=n[s]={exports:{}};t[s][0].call(u.exports,function(e){var n=t[s][1][e];return i(n?n:e)},u,u.exports,e,t,n,o)}return n[s].exports}for(var r="function"==typeof require&&require,s=0;s<o.length;s++)i(o[s]);return i}({1:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../geometry/Vector"),s=e("../core/Sleeping"),a=(e("../render/Render"),e("../core/Common")),l=e("../geometry/Bounds"),c=e("../geometry/Axes");!function(){o._inertiaScale=4,o._nextCollidingGroupId=1,
o._nextNonCollidingGroupId=-1,o._nextCategory=1,o.create=function(t){var n={id:a.nextId(),type:"body",label:"Body",parts:[],plugin:{},angle:0,vertices:i.fromPath("L 0 0 L 40 0 L 40 40 L 0 40"),position:{x:0,y:0},force:{x:0,y:0},torque:0,positionImpulse:{x:0,y:0},constraintImpulse:{x:0,y:0,angle:0},totalContacts:0,speed:0,angularSpeed:0,velocity:{x:0,y:0},angularVelocity:0,isSensor:!1,isStatic:!1,isSleeping:!1,motion:0,sleepThreshold:60,density:.001,restitution:0,friction:.1,frictionStatic:.5,frictionAir:.01,collisionFilter:{category:1,mask:4294967295,group:0},slop:.05,timeScale:1,render:{visible:!0,opacity:1,sprite:{xScale:1,yScale:1,xOffset:0,yOffset:0},lineWidth:0}},o=a.extend(n,t);return e(o,t),o},o.nextGroup=function(e){return e?o._nextNonCollidingGroupId--:o._nextCollidingGroupId++},o.nextCategory=function(){return o._nextCategory=o._nextCategory<<1,o._nextCategory};var e=function(e,t){t=t||{},o.set(e,{bounds:e.bounds||l.create(e.vertices),positionPrev:e.positionPrev||r.clone(e.position),
anglePrev:e.anglePrev||e.angle,vertices:e.vertices,parts:e.parts||[e],isStatic:e.isStatic,isSleeping:e.isSleeping,parent:e.parent||e}),i.rotate(e.vertices,e.angle,e.position),c.rotate(e.axes,e.angle),l.update(e.bounds,e.vertices,e.velocity),o.set(e,{axes:t.axes||e.axes,area:t.area||e.area,mass:t.mass||e.mass,inertia:t.inertia||e.inertia});var n=e.isStatic?"#2e2b44":a.choose(["#006BA6","#0496FF","#FFBC42","#D81159","#8F2D56"]),s=a.shadeColor(n,-20);e.render.fillStyle=e.render.fillStyle||n,e.render.strokeStyle=e.render.strokeStyle||s,e.render.sprite.xOffset+=-(e.bounds.min.x-e.position.x)/(e.bounds.max.x-e.bounds.min.x),e.render.sprite.yOffset+=-(e.bounds.min.y-e.position.y)/(e.bounds.max.y-e.bounds.min.y)};o.set=function(e,t,n){var i;"string"==typeof t&&(i=t,t={},t[i]=n);for(i in t)if(n=t[i],t.hasOwnProperty(i))switch(i){case"isStatic":o.setStatic(e,n);break;case"isSleeping":s.set(e,n);break;case"mass":o.setMass(e,n);break;case"density":o.setDensity(e,n);break;case"inertia":o.setInertia(e,n);
break;case"vertices":o.setVertices(e,n);break;case"position":o.setPosition(e,n);break;case"angle":o.setAngle(e,n);break;case"velocity":o.setVelocity(e,n);break;case"angularVelocity":o.setAngularVelocity(e,n);break;case"parts":o.setParts(e,n);break;default:e[i]=n}},o.setStatic=function(e,t){for(var n=0;n<e.parts.length;n++){var o=e.parts[n];o.isStatic=t,t?(o._original={restitution:o.restitution,friction:o.friction,mass:o.mass,inertia:o.inertia,density:o.density,inverseMass:o.inverseMass,inverseInertia:o.inverseInertia},o.restitution=0,o.friction=1,o.mass=o.inertia=o.density=1/0,o.inverseMass=o.inverseInertia=0,o.positionPrev.x=o.position.x,o.positionPrev.y=o.position.y,o.anglePrev=o.angle,o.angularVelocity=0,o.speed=0,o.angularSpeed=0,o.motion=0):o._original&&(o.restitution=o._original.restitution,o.friction=o._original.friction,o.mass=o._original.mass,o.inertia=o._original.inertia,o.density=o._original.density,o.inverseMass=o._original.inverseMass,o.inverseInertia=o._original.inverseInertia,
delete o._original)}},o.setMass=function(e,t){e.mass=t,e.inverseMass=1/e.mass,e.density=e.mass/e.area},o.setDensity=function(e,t){o.setMass(e,t*e.area),e.density=t},o.setInertia=function(e,t){e.inertia=t,e.inverseInertia=1/e.inertia},o.setVertices=function(e,t){t[0].body===e?e.vertices=t:e.vertices=i.create(t,e),e.axes=c.fromVertices(e.vertices),e.area=i.area(e.vertices),o.setMass(e,e.density*e.area);var n=i.centre(e.vertices);i.translate(e.vertices,n,-1),o.setInertia(e,o._inertiaScale*i.inertia(e.vertices,e.mass)),i.translate(e.vertices,e.position),l.update(e.bounds,e.vertices,e.velocity)},o.setParts=function(e,n,r){var s;for(n=n.slice(0),e.parts.length=0,e.parts.push(e),e.parent=e,s=0;s<n.length;s++){var a=n[s];a!==e&&(a.parent=e,e.parts.push(a))}if(1!==e.parts.length){if(r="undefined"==typeof r||r){var l=[];for(s=0;s<n.length;s++)l=l.concat(n[s].vertices);i.clockwiseSort(l);var c=i.hull(l),u=i.centre(c);o.setVertices(e,c),i.translate(e.vertices,u)}var d=t(e);e.area=d.area,e.parent=e,
e.position.x=d.centre.x,e.position.y=d.centre.y,e.positionPrev.x=d.centre.x,e.positionPrev.y=d.centre.y,o.setMass(e,d.mass),o.setInertia(e,d.inertia),o.setPosition(e,d.centre)}},o.setPosition=function(e,t){var n=r.sub(t,e.position);e.positionPrev.x+=n.x,e.positionPrev.y+=n.y;for(var o=0;o<e.parts.length;o++){var s=e.parts[o];s.position.x+=n.x,s.position.y+=n.y,i.translate(s.vertices,n),l.update(s.bounds,s.vertices,e.velocity)}},o.setAngle=function(e,t){var n=t-e.angle;e.anglePrev+=n;for(var o=0;o<e.parts.length;o++){var s=e.parts[o];s.angle+=n,i.rotate(s.vertices,n,e.position),c.rotate(s.axes,n),l.update(s.bounds,s.vertices,e.velocity),o>0&&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){o.setAngle(e,e.angle+t)},o.scale=function(e,n,r,s){for(var a=0;a<e.parts.length;a++){var u=e.parts[a];i.scale(u.vertices,n,r,e.position),u.axes=c.fromVertices(u.vertices),e.isStatic||(u.area=i.area(u.vertices),o.setMass(u,e.density*u.area),i.translate(u.vertices,{x:-u.position.x,y:-u.position.y}),o.setInertia(u,i.inertia(u.vertices,u.mass)),i.translate(u.vertices,{x:u.position.x,y:u.position.y})),l.update(u.bounds,u.vertices,e.velocity)}if(e.circleRadius&&(n===r?e.circleRadius*=n:e.circleRadius=null),!e.isStatic){var d=t(e);e.area=d.area,o.setMass(e,d.mass),o.setInertia(e,d.inertia)}},o.update=function(e,t,n,o){var s=Math.pow(t*n*e.timeScale,2),a=1-e.frictionAir*n*e.timeScale,u=e.position.x-e.positionPrev.x,d=e.position.y-e.positionPrev.y;e.velocity.x=u*a*o+e.force.x/e.mass*s,e.velocity.y=d*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;p<e.parts.length;p++){var f=e.parts[p];i.translate(f.vertices,e.velocity),p>0&&(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};var t=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n<e.parts.length;n++){var o=e.parts[n];t.mass+=o.mass,t.area+=o.area,t.inertia+=o.inertia,t.centre=r.add(t.centre,r.mult(o.position,o.mass!==1/0?o.mass:1))}return t.centre=r.div(t.centre,t.mass!==1/0?t.mass:e.parts.length),t}}()},{"../core/Common":14,"../core/Sleeping":22,"../geometry/Axes":25,
"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29,"../render/Render":31}],2:[function(e,t,n){var o={};t.exports=o;var i=e("../core/Events"),r=e("../core/Common"),s=e("./Body");!function(){o.create=function(e){return r.extend({id:r.nextId(),type:"composite",parent:null,isModified:!1,bodies:[],constraints:[],composites:[],label:"Composite",plugin:{}},e)},o.setModified=function(e,t,n,i){if(e.isModified=t,n&&e.parent&&o.setModified(e.parent,t,n,i),i)for(var r=0;r<e.composites.length;r++){var s=e.composites[r];o.setModified(s,t,n,i)}},o.add=function(e,t){var n=[].concat(t);i.trigger(e,"beforeAdd",{object:t});for(var s=0;s<n.length;s++){var a=n[s];switch(a.type){case"body":if(a.parent!==a){r.warn("Composite.add: skipped adding a compound body part (you must add its parent instead)");break}o.addBody(e,a);break;case"constraint":o.addConstraint(e,a);break;case"composite":o.addComposite(e,a);break;case"mouseConstraint":o.addConstraint(e,a.constraint)}}return i.trigger(e,"afterAdd",{
object:t}),e},o.remove=function(e,t,n){var r=[].concat(t);i.trigger(e,"beforeRemove",{object:t});for(var s=0;s<r.length;s++){var a=r[s];switch(a.type){case"body":o.removeBody(e,a,n);break;case"constraint":o.removeConstraint(e,a,n);break;case"composite":o.removeComposite(e,a,n);break;case"mouseConstraint":o.removeConstraint(e,a.constraint)}}return i.trigger(e,"afterRemove",{object:t}),e},o.addComposite=function(e,t){return e.composites.push(t),t.parent=e,o.setModified(e,!0,!0,!1),e},o.removeComposite=function(e,t,n){var i=r.indexOf(e.composites,t);if(i!==-1&&(o.removeCompositeAt(e,i),o.setModified(e,!0,!0,!1)),n)for(var s=0;s<e.composites.length;s++)o.removeComposite(e.composites[s],t,!0);return e},o.removeCompositeAt=function(e,t){return e.composites.splice(t,1),o.setModified(e,!0,!0,!1),e},o.addBody=function(e,t){return e.bodies.push(t),o.setModified(e,!0,!0,!1),e},o.removeBody=function(e,t,n){var i=r.indexOf(e.bodies,t);if(i!==-1&&(o.removeBodyAt(e,i),o.setModified(e,!0,!0,!1)),n)for(var s=0;s<e.composites.length;s++)o.removeBody(e.composites[s],t,!0);
return e},o.removeBodyAt=function(e,t){return e.bodies.splice(t,1),o.setModified(e,!0,!0,!1),e},o.addConstraint=function(e,t){return e.constraints.push(t),o.setModified(e,!0,!0,!1),e},o.removeConstraint=function(e,t,n){var i=r.indexOf(e.constraints,t);if(i!==-1&&o.removeConstraintAt(e,i),n)for(var s=0;s<e.composites.length;s++)o.removeConstraint(e.composites[s],t,!0);return e},o.removeConstraintAt=function(e,t){return e.constraints.splice(t,1),o.setModified(e,!0,!0,!1),e},o.clear=function(e,t,n){if(n)for(var i=0;i<e.composites.length;i++)o.clear(e.composites[i],t,!0);return t?e.bodies=e.bodies.filter(function(e){return e.isStatic}):e.bodies.length=0,e.constraints.length=0,e.composites.length=0,o.setModified(e,!0,!0,!1),e},o.allBodies=function(e){for(var t=[].concat(e.bodies),n=0;n<e.composites.length;n++)t=t.concat(o.allBodies(e.composites[n]));return t},o.allConstraints=function(e){for(var t=[].concat(e.constraints),n=0;n<e.composites.length;n++)t=t.concat(o.allConstraints(e.composites[n]));
return t},o.allComposites=function(e){for(var t=[].concat(e.composites),n=0;n<e.composites.length;n++)t=t.concat(o.allComposites(e.composites[n]));return t},o.get=function(e,t,n){var i,r;switch(n){case"body":i=o.allBodies(e);break;case"constraint":i=o.allConstraints(e);break;case"composite":i=o.allComposites(e).concat(e)}return i?(r=i.filter(function(e){return e.id.toString()===t.toString()}),0===r.length?null:r[0]):null},o.move=function(e,t,n){return o.remove(e,t),o.add(n,t),e},o.rebase=function(e){for(var t=o.allBodies(e).concat(o.allConstraints(e)).concat(o.allComposites(e)),n=0;n<t.length;n++)t[n].id=r.nextId();return o.setModified(e,!0,!0,!1),e},o.translate=function(e,t,n){for(var i=n?o.allBodies(e):e.bodies,r=0;r<i.length;r++)s.translate(i[r],t);return o.setModified(e,!0,!0,!1),e},o.rotate=function(e,t,n,i){for(var r=Math.cos(t),a=Math.sin(t),l=i?o.allBodies(e):e.bodies,c=0;c<l.length;c++){var u=l[c],d=u.position.x-n.x,p=u.position.y-n.y;s.setPosition(u,{x:n.x+(d*r-p*a),y:n.y+(d*a+p*r)
}),s.rotate(u,t)}return o.setModified(e,!0,!0,!1),e},o.scale=function(e,t,n,i,r){for(var a=r?o.allBodies(e):e.bodies,l=0;l<a.length;l++){var c=a[l],u=c.position.x-i.x,d=c.position.y-i.y;s.setPosition(c,{x:i.x+u*t,y:i.y+d*n}),s.scale(c,t,n)}return o.setModified(e,!0,!0,!1),e}}()},{"../core/Common":14,"../core/Events":16,"./Body":1}],3:[function(e,t,n){var o={};t.exports=o;var i=e("./Composite"),r=(e("../constraint/Constraint"),e("../core/Common"));!function(){o.create=function(e){var t=i.create(),n={label:"World",gravity:{x:0,y:1,scale:.001},bounds:{min:{x:-(1/0),y:-(1/0)},max:{x:1/0,y:1/0}}};return r.extend(t,n,e)}}()},{"../constraint/Constraint":12,"../core/Common":14,"./Composite":2}],4:[function(e,t,n){var o={};t.exports=o,function(){o.create=function(e){return{id:o.id(e),vertex:e,normalImpulse:0,tangentImpulse:0}},o.id=function(e){return e.body.id+"_"+e.index}}()},{}],5:[function(e,t,n){var o={};t.exports=o;var i=e("./SAT"),r=e("./Pair"),s=e("../geometry/Bounds");!function(){o.collisions=function(e,t){
for(var n=[],a=t.pairs.table,l=0;l<e.length;l++){var c=e[l][0],u=e[l][1];if((!c.isStatic&&!c.isSleeping||!u.isStatic&&!u.isSleeping)&&o.canCollide(c.collisionFilter,u.collisionFilter)&&s.overlaps(c.bounds,u.bounds))for(var d=c.parts.length>1?1:0;d<c.parts.length;d++)for(var p=c.parts[d],f=u.parts.length>1?1:0;f<u.parts.length;f++){var m=u.parts[f];if(p===c&&m===u||s.overlaps(p.bounds,m.bounds)){var v,y=r.id(p,m),g=a[y];v=g&&g.isActive?g.collision:null;var x=i.collides(p,m,v);x.collided&&n.push(x)}}}return n},o.canCollide=function(e,t){return e.group===t.group&&0!==e.group?e.group>0: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(n,o,i,r){var s,p,f,m,v,y=i.world,g=n.buckets,x=!1;
for(s=0;s<o.length;s++){var h=o[s];if((!h.isSleeping||r)&&!(h.bounds.max.x<y.bounds.min.x||h.bounds.min.x>y.bounds.max.x||h.bounds.max.y<y.bounds.min.y||h.bounds.min.y>y.bounds.max.y)){var b=t(n,h);if(!h.region||b.id!==h.region.id||r){h.region&&!r||(h.region=b);var w=e(b,h.region);for(p=w.startCol;p<=w.endCol;p++)for(f=w.startRow;f<=w.endRow;f++){v=a(p,f),m=g[v];var S=p>=b.startCol&&p<=b.endCol&&f>=b.startRow&&f<=b.endRow,C=p>=h.region.startCol&&p<=h.region.endCol&&f>=h.region.startRow&&f<=h.region.endRow;!S&&C&&C&&m&&u(n,m,h),(h.region===b||S&&!C||r)&&(m||(m=l(g,v)),c(n,m,h))}h.region=b,x=!0}}}x&&(n.pairsList=d(n))},o.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]};var e=function(e,t){var o=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 n(o,i,r,s)},t=function(e,t){var o=t.bounds,i=Math.floor(o.min.x/e.bucketWidth),r=Math.floor(o.max.x/e.bucketWidth),s=Math.floor(o.min.y/e.bucketHeight),a=Math.floor(o.max.y/e.bucketHeight);
return n(i,r,s,a)},n=function(e,t,n,o){return{id:e+","+t+","+n+","+o,startCol:e,endCol:t,startRow:n,endRow:o}},a=function(e,t){return"C"+e+"R"+t},l=function(e,t){var n=e[t]=[];return n},c=function(e,t,n){for(var o=0;o<t.length;o++){var r=t[o];if(!(n.id===r.id||n.isStatic&&r.isStatic)){var s=i.id(n,r),a=e.pairs[s];a?a[2]+=1:e.pairs[s]=[n,r,1]}}t.push(n)},u=function(e,t,n){t.splice(s.indexOf(t,n),1);for(var o=0;o<t.length;o++){var r=t[o],a=i.id(n,r),l=e.pairs[a];l&&(l[2]-=1)}},d=function(e){var t,n,o=[];t=s.keys(e.pairs);for(var i=0;i<t.length;i++)n=e.pairs[t[i]],n[2]>0?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 u=0;u<s.length;u++){var d=s[u],p=i.id(d),f=r[p];f?a.push(f):a.push(r[p]=i.create(d))}e.separation=t.depth,o.setActive(e,!0,n)}else e.isActive===!0&&o.setActive(e,!1,n)},o.setActive=function(e,t,n){t?(e.isActive=!0,e.timeUpdated=n):(e.isActive=!1,e.activeContacts.length=0)},o.id=function(e,t){return e.id<t.id?"A"+e.id+"B"+t.id:"A"+t.id+"B"+e.id}}()},{"./Contact":4}],8:[function(e,t,n){var o={};t.exports=o;var i=e("./Pair"),r=e("../core/Common");!function(){var e=1e3;
o.create=function(e){return r.extend({table:{},list:[],collisionStart:[],collisionActive:[],collisionEnd:[]},e)},o.update=function(e,t,n){var o,s,a,l,c=e.list,u=e.table,d=e.collisionStart,p=e.collisionEnd,f=e.collisionActive,m=[];for(d.length=0,p.length=0,f.length=0,l=0;l<t.length;l++)o=t[l],o.collided&&(s=i.id(o.bodyA,o.bodyB),m.push(s),a=u[s],a?(a.isActive?f.push(a):d.push(a),i.update(a,o,n)):(a=i.create(o,n),u[s]=a,d.push(a),c.push(a)));for(l=0;l<c.length;l++)a=c[l],a.isActive&&r.indexOf(m,a.id)===-1&&(i.setActive(a,!1,n),p.push(a))},o.removeOld=function(t,n){var o,i,r,s,a=t.list,l=t.table,c=[];for(s=0;s<a.length;s++)o=a[s],i=o.collision,i.bodyA.isSleeping||i.bodyB.isSleeping?o.timeUpdated=n:n-o.timeUpdated>e&&c.push(s);for(s=0;s<c.length;s++)r=c[s]-s,o=a[r],delete l[o.id],a.splice(r,1)},o.clear=function(e){return e.table={},e.list.length=0,e.collisionStart.length=0,e.collisionActive.length=0,e.collisionEnd.length=0,e}}()},{"../core/Common":14,"./Pair":7}],9:[function(e,t,n){var o={};
t.exports=o;var i=e("../geometry/Vector"),r=e("./SAT"),s=e("../geometry/Bounds"),a=e("../factory/Bodies"),l=e("../geometry/Vertices");!function(){o.ray=function(e,t,n,o){o=o||1e-100;for(var l=i.angle(t,n),c=i.magnitude(i.sub(t,n)),u=.5*(n.x+t.x),d=.5*(n.y+t.y),p=a.rectangle(u,d,c,o,{angle:l}),f=[],m=0;m<e.length;m++){var v=e[m];if(s.overlaps(v.bounds,p.bounds))for(var y=1===v.parts.length?0:1;y<v.parts.length;y++){var g=v.parts[y];if(s.overlaps(g.bounds,p.bounds)){var x=r.collides(g,p);if(x.collided){x.body=x.bodyA=x.bodyB=v,f.push(x);break}}}}return f},o.region=function(e,t,n){for(var o=[],i=0;i<e.length;i++){var r=e[i],a=s.overlaps(r.bounds,t);(a&&!n||!a&&n)&&o.push(r)}return o},o.point=function(e,t){for(var n=[],o=0;o<e.length;o++){var i=e[o];if(s.contains(i.bounds,t))for(var r=1===i.parts.length?0:1;r<i.parts.length;r++){var a=i.parts[r];if(s.contains(a.bounds,t)&&l.contains(a.vertices,t)){n.push(i);break}}}return n}}()},{"../factory/Bodies":23,"../geometry/Bounds":26,"../geometry/Vector":28,
"../geometry/Vertices":29,"./SAT":11}],10:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../geometry/Vector"),s=e("../core/Common"),a=e("../geometry/Bounds");!function(){o._restingThresh=4,o._restingThreshTangent=6,o._positionDampen=.9,o._positionWarming=.8,o._frictionNormalMultiplier=5,o.preSolvePosition=function(e){var t,n,o;for(t=0;t<e.length;t++)n=e[t],n.isActive&&(o=n.activeContacts.length,n.collision.parentA.totalContacts+=o,n.collision.parentB.totalContacts+=o)},o.solvePosition=function(e,t){var n,i,s,a,l,c,u,d,p,f=r._temp[0],m=r._temp[1],v=r._temp[2],y=r._temp[3];for(n=0;n<e.length;n++)i=e[n],i.isActive&&!i.isSensor&&(s=i.collision,a=s.parentA,l=s.parentB,c=s.normal,u=r.sub(r.add(l.positionImpulse,l.position,f),r.add(a.positionImpulse,r.sub(l.position,s.penetration,m),v),y),i.separation=r.dot(c,u));for(n=0;n<e.length;n++)i=e[n],!i.isActive||i.isSensor||i.separation<0||(s=i.collision,a=s.parentA,l=s.parentB,c=s.normal,p=(i.separation-i.slop)*t,(a.isStatic||l.isStatic)&&(p*=2),
a.isStatic||a.isSleeping||(d=o._positionDampen/a.totalContacts,a.positionImpulse.x+=c.x*p*d,a.positionImpulse.y+=c.y*p*d),l.isStatic||l.isSleeping||(d=o._positionDampen/l.totalContacts,l.positionImpulse.x-=c.x*p*d,l.positionImpulse.y-=c.y*p*d))},o.postSolvePosition=function(e){for(var t=0;t<e.length;t++){var n=e[t];if(n.totalContacts=0,0!==n.positionImpulse.x||0!==n.positionImpulse.y){for(var s=0;s<n.parts.length;s++){var l=n.parts[s];i.translate(l.vertices,n.positionImpulse),a.update(l.bounds,l.vertices,n.velocity),l.position.x+=n.positionImpulse.x,l.position.y+=n.positionImpulse.y}n.positionPrev.x+=n.positionImpulse.x,n.positionPrev.y+=n.positionImpulse.y,r.dot(n.positionImpulse,n.velocity)<0?(n.positionImpulse.x=0,n.positionImpulse.y=0):(n.positionImpulse.x*=o._positionWarming,n.positionImpulse.y*=o._positionWarming)}}},o.preSolveVelocity=function(e){var t,n,o,i,s,a,l,c,u,d,p,f,m,v,y=r._temp[0],g=r._temp[1];for(t=0;t<e.length;t++)if(o=e[t],o.isActive&&!o.isSensor)for(i=o.activeContacts,
s=o.collision,a=s.parentA,l=s.parentB,c=s.normal,u=s.tangent,n=0;n<i.length;n++)d=i[n],p=d.vertex,f=d.normalImpulse,m=d.tangentImpulse,0===f&&0===m||(y.x=c.x*f+u.x*m,y.y=c.y*f+u.y*m,a.isStatic||a.isSleeping||(v=r.sub(p,a.position,g),a.positionPrev.x+=y.x*a.inverseMass,a.positionPrev.y+=y.y*a.inverseMass,a.anglePrev+=r.cross(v,y)*a.inverseInertia),l.isStatic||l.isSleeping||(v=r.sub(p,l.position,g),l.positionPrev.x-=y.x*l.inverseMass,l.positionPrev.y-=y.y*l.inverseMass,l.anglePrev-=r.cross(v,y)*l.inverseInertia))},o.solveVelocity=function(e,t){for(var n=t*t,i=r._temp[0],a=r._temp[1],l=r._temp[2],c=r._temp[3],u=r._temp[4],d=r._temp[5],p=0;p<e.length;p++){var f=e[p];if(f.isActive&&!f.isSensor){var m=f.collision,v=m.parentA,y=m.parentB,g=m.normal,x=m.tangent,h=f.activeContacts,b=1/h.length;v.velocity.x=v.position.x-v.positionPrev.x,v.velocity.y=v.position.y-v.positionPrev.y,y.velocity.x=y.position.x-y.positionPrev.x,y.velocity.y=y.position.y-y.positionPrev.y,v.angularVelocity=v.angle-v.anglePrev,
y.angularVelocity=y.angle-y.anglePrev;for(var w=0;w<h.length;w++){var S=h[w],C=S.vertex,A=r.sub(C,v.position,a),P=r.sub(C,y.position,l),B=r.add(v.velocity,r.mult(r.perp(A),v.angularVelocity),c),M=r.add(y.velocity,r.mult(r.perp(P),y.angularVelocity),u),k=r.sub(B,M,d),I=r.dot(g,k),T=r.dot(x,k),V=Math.abs(T),R=s.sign(T),_=(1+f.restitution)*I,E=s.clamp(f.separation+I,0,1)*o._frictionNormalMultiplier,F=T,O=1/0;V>f.friction*f.frictionStatic*E*n&&(O=V,F=s.clamp(f.friction*R*n,-O,O));var L=r.cross(A,g),W=r.cross(P,g),q=b/(v.inverseMass+y.inverseMass+v.inverseInertia*L*L+y.inverseInertia*W*W);if(_*=q,F*=q,I<0&&I*I>o._restingThresh*n)S.normalImpulse=0;else{var N=S.normalImpulse;S.normalImpulse=Math.min(S.normalImpulse+_,0),_=S.normalImpulse-N}if(T*T>o._restingThreshTangent*n)S.tangentImpulse=0;else{var D=S.tangentImpulse;S.tangentImpulse=s.clamp(S.tangentImpulse+F,-O,O),F=S.tangentImpulse-D}i.x=g.x*_+x.x*F,i.y=g.y*_+x.y*F,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(t,o,s){var a,l,c,u,d=!1;if(s){var p=t.parent,f=o.parent,m=p.speed*p.speed+p.angularSpeed*p.angularSpeed+f.speed*f.speed+f.angularSpeed*f.angularSpeed;d=s&&s.collided&&m<.2,u=s}else u={collided:!1,bodyA:t,bodyB:o};if(s&&d){var v=u.axisBody,y=v===t?o:t,g=[v.axes[s.axisNumber]];if(c=e(v.vertices,y.vertices,g),u.reused=!0,c.overlap<=0)return u.collided=!1,u}else{if(a=e(t.vertices,o.vertices,t.axes),a.overlap<=0)return u.collided=!1,u;if(l=e(o.vertices,t.vertices,o.axes),l.overlap<=0)return u.collided=!1,u;a.overlap<l.overlap?(c=a,u.axisBody=t):(c=l,u.axisBody=o),u.axisNumber=c.axisNumber;
}u.bodyA=t.id<o.id?t:o,u.bodyB=t.id<o.id?o:t,u.collided=!0,u.depth=c.overlap,u.parentA=u.bodyA.parent,u.parentB=u.bodyB.parent,t=u.bodyA,o=u.bodyB,r.dot(c.axis,r.sub(o.position,t.position))<0?u.normal={x:c.axis.x,y:c.axis.y}:u.normal={x:-c.axis.x,y:-c.axis.y},u.tangent=r.perp(u.normal),u.penetration=u.penetration||{},u.penetration.x=u.normal.x*u.depth,u.penetration.y=u.normal.y*u.depth;var x=n(t,o,u.normal),h=[];if(i.contains(t.vertices,x[0])&&h.push(x[0]),i.contains(t.vertices,x[1])&&h.push(x[1]),h.length<2){var b=n(o,t,r.neg(u.normal));i.contains(o.vertices,b[0])&&h.push(b[0]),h.length<2&&i.contains(o.vertices,b[1])&&h.push(b[1])}return h.length<1&&(h=[x[0]]),u.supports=h,u};var e=function(e,n,o){for(var i,s,a=r._temp[0],l=r._temp[1],c={overlap:Number.MAX_VALUE},u=0;u<o.length;u++){if(s=o[u],t(a,e,s),t(l,n,s),i=Math.min(a.max-l.min,l.max-a.min),i<=0)return c.overlap=i,c;i<c.overlap&&(c.overlap=i,c.axis=s,c.axisNumber=u)}return c},t=function(e,t,n){for(var o=r.dot(t[0],n),i=o,s=1;s<t.length;s+=1){
var a=r.dot(t[s],n);a>i?i=a:a<o&&(o=a)}e.min=o,e.max=i},n=function(e,t,n){for(var o,i,s,a,l=Number.MAX_VALUE,c=r._temp[0],u=t.vertices,d=e.position,p=0;p<u.length;p++)i=u[p],c.x=i.x-d.x,c.y=i.y-d.y,o=-r.dot(n,c),o<l&&(l=o,s=i);var f=s.index-1>=0?s.index-1:u.length-1;i=u[f],c.x=i.x-d.x,c.y=i.y-d.y,l=-r.dot(n,c),a=i;var m=(s.index+1)%u.length;return i=u[m],c.x=i.x-d.x,c.y=i.y-d.y,o=-r.dot(n,c),o<l&&(a=i),[s,a]}}()},{"../geometry/Vector":28,"../geometry/Vertices":29}],12:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../geometry/Vector"),s=e("../core/Sleeping"),a=e("../geometry/Bounds"),l=e("../geometry/Axes"),c=e("../core/Common");!function(){var e=1e-6,t=.001;o.create=function(t){var n=t;n.bodyA&&!n.pointA&&(n.pointA={x:0,y:0}),n.bodyB&&!n.pointB&&(n.pointB={x:0,y:0});var o=n.bodyA?r.add(n.bodyA.position,n.pointA):n.pointA,i=n.bodyB?r.add(n.bodyB.position,n.pointB):n.pointB,s=r.magnitude(r.sub(o,i));n.length=n.length||s||e;var a={visible:!0,lineWidth:2,strokeStyle:"#ffffff"
};return n.render=c.extend(a,n.render),n.id=n.id||c.nextId(),n.label=n.label||"Constraint",n.type="constraint",n.stiffness=n.stiffness||1,n.angularStiffness=n.angularStiffness||0,n.angleA=n.bodyA?n.bodyA.angle:n.angleA,n.angleB=n.bodyB?n.bodyB.angle:n.angleB,n.plugin={},n},o.solveAll=function(e,t){for(var n=0;n<e.length;n++)o.solve(e[n],t)},o.solve=function(n,o){var i=n.bodyA,s=n.bodyB,a=n.pointA,l=n.pointB;i&&!i.isStatic&&(n.pointA=r.rotate(a,i.angle-n.angleA),n.angleA=i.angle),s&&!s.isStatic&&(n.pointB=r.rotate(l,s.angle-n.angleB),n.angleB=s.angle);var c=a,u=l;if(i&&(c=r.add(i.position,a)),s&&(u=r.add(s.position,l)),c&&u){var d=r.sub(c,u),p=r.magnitude(d);0===p&&(p=e);var f=(p-n.length)/p,m=r.div(d,p),v=r.mult(d,.5*f*n.stiffness*o*o);if(!(Math.abs(1-p/n.length)<t*o)){var y,g,x,h,b,w,S,C;i&&!i.isStatic?(x={x:c.x-i.position.x+v.x,y:c.y-i.position.y+v.y},i.velocity.x=i.position.x-i.positionPrev.x,i.velocity.y=i.position.y-i.positionPrev.y,i.angularVelocity=i.angle-i.anglePrev,y=r.add(i.velocity,r.mult(r.perp(x),i.angularVelocity)),
b=r.dot(x,m),S=i.inverseMass+i.inverseInertia*b*b):(y={x:0,y:0},S=i?i.inverseMass:0),s&&!s.isStatic?(h={x:u.x-s.position.x-v.x,y:u.y-s.position.y-v.y},s.velocity.x=s.position.x-s.positionPrev.x,s.velocity.y=s.position.y-s.positionPrev.y,s.angularVelocity=s.angle-s.anglePrev,g=r.add(s.velocity,r.mult(r.perp(h),s.angularVelocity)),w=r.dot(h,m),C=s.inverseMass+s.inverseInertia*w*w):(g={x:0,y:0},C=s?s.inverseMass:0);var A=r.sub(g,y),P=r.dot(m,A)/(S+C);P>0&&(P=0);var B,M={x:m.x*P,y:m.y*P};i&&!i.isStatic&&(B=r.cross(x,M)*i.inverseInertia*(1-n.angularStiffness),i.constraintImpulse.x-=v.x,i.constraintImpulse.y-=v.y,i.constraintImpulse.angle+=B,i.position.x-=v.x,i.position.y-=v.y,i.angle+=B),s&&!s.isStatic&&(B=r.cross(h,M)*s.inverseInertia*(1-n.angularStiffness),s.constraintImpulse.x+=v.x,s.constraintImpulse.y+=v.y,s.constraintImpulse.angle-=B,s.position.x+=v.x,s.position.y+=v.y,s.angle-=B)}}},o.postSolveAll=function(e){for(var t=0;t<e.length;t++){var n=e[t],o=n.constraintImpulse;if(0!==o.x||0!==o.y||0!==o.angle){
s.set(n,!1);for(var c=0;c<n.parts.length;c++){var u=n.parts[c];i.translate(u.vertices,o),c>0&&(u.position.x+=o.x,u.position.y+=o.y),0!==o.angle&&(i.rotate(u.vertices,o.angle,n.position),l.rotate(u.axes,o.angle),c>0&&r.rotateAbout(u.position,o.angle,n.position,u.position)),a.update(u.bounds,u.vertices,n.velocity)}o.angle=0,o.x=0,o.y=0}}}}()},{"../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"),u=e("../body/Composite"),d=e("../core/Common"),p=e("../geometry/Bounds");!function(){o.create=function(t,n){var i=(t?t.mouse:null)||(n?n.mouse:null);i||(t&&t.render&&t.render.canvas?i=s.create(t.render.canvas):n&&n.element?i=s.create(n.element):(i=s.create(),d.warn("MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected")));
var r=c.create({label:"Mouse Constraint",pointA:i.position,pointB:{x:0,y:0},length:.01,stiffness:.1,angularStiffness:1,render:{strokeStyle:"#90EE90",lineWidth:3}}),l={type:"mouseConstraint",mouse:i,element:null,body:null,constraint:r,collisionFilter:{category:1,mask:4294967295,group:0}},p=d.extend(l,n);return a.on(t,"beforeUpdate",function(){var n=u.allBodies(t.world);o.update(p,n),e(p)}),p},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;c<t.length;c++)if(s=t[c],p.contains(s.bounds,n.position)&&l.canCollide(s.collisionFilter,e.collisionFilter))for(var u=s.parts.length>1?1:0;u<s.parts.length;u++){var d=s.parts[u];if(i.contains(d.vertices,n.position)){o.pointA=n.position,o.bodyB=e.body=s,o.pointB={x:n.position.x-s.position.x,y:n.position.y-s.position.y},o.angleB=s.angle,r.set(s,!1),a.trigger(e,"startdrag",{mouse:n,body:s});break}}}else o.bodyB=e.body=null,o.pointB=null,s&&a.trigger(e,"enddrag",{
mouse:n,body:s})};var e=function(e){var t=e.mouse,n=t.sourceEvents;n.mousemove&&a.trigger(e,"mousemove",{mouse:t}),n.mousedown&&a.trigger(e,"mousedown",{mouse:t}),n.mouseup&&a.trigger(e,"mouseup",{mouse:t}),s.clearSourceEvents(t)}}()},{"../body/Composite":2,"../collision/Detector":5,"../core/Common":14,"../core/Events":16,"../core/Mouse":19,"../core/Sleeping":22,"../geometry/Bounds":26,"../geometry/Vertices":29,"./Constraint":12}],14:[function(e,t,n){var o={};t.exports=o,function(){o._nextId=0,o._seed=0,o.extend=function(e,t){var n,i;"boolean"==typeof t?(n=2,i=t):(n=1,i=!0);for(var r=n;r<arguments.length;r++){var s=arguments[r];if(s)for(var a in s)i&&s[a]&&s[a].constructor===Object?e[a]&&e[a].constructor!==Object?e[a]=s[a]:(e[a]=e[a]||{},o.extend(e[a],i,s[a])):e[a]=s[a]}return e},o.clone=function(e,t){return o.extend({},t,e)},o.keys=function(e){if(Object.keys)return Object.keys(e);var t=[];for(var n in e)t.push(n);return t},o.values=function(e){var t=[];if(Object.keys){for(var n=Object.keys(e),o=0;o<n.length;o++)t.push(e[n[o]]);
return t}for(var i in e)t.push(e[i]);return t},o.get=function(e,t,n,o){t=t.split(".").slice(n,o);for(var i=0;i<t.length;i+=1)e=e[t[i]];return e},o.set=function(e,t,n,i,r){var s=t.split(".").slice(i,r);return o.get(e,t,0,-1)[s[s.length-1]]=n,n},o.shadeColor=function(e,t){var n=parseInt(e.slice(1),16),o=Math.round(2.55*t),i=(n>>16)+o,r=(n>>8&255)+o,s=(255&n)+o;return"#"+(16777216+65536*(i<255?i<1?0:i:255)+256*(r<255?r<1?0:r:255)+(s<255?s<1?0:s:255)).toString(16).slice(1)},o.shuffle=function(e){for(var t=e.length-1;t>0;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){try{return e instanceof HTMLElement}catch(t){return"object"==typeof e&&1===e.nodeType&&"object"==typeof e.style&&"object"==typeof e.ownerDocument}},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 e<t?t:e>n?n:e},o.sign=function(e){return e<0?-1:1},o.now=function(){var e=window.performance||{};return e.now=function(){return e.now||e.webkitNow||e.msNow||e.oNow||e.mozNow||function(){return+new Date}}(),e.now()},o.random=function(t,n){return t="undefined"!=typeof t?t:0,n="undefined"!=typeof n?n:1,t+e()*(n-t)};var e=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;n<e.length;n++)if(e[n]===t)return n;return-1},o.map=function(e,t){if(e.map)return e.map(t);for(var n=[],o=0;o<e.length;o+=1)n.push(t(e[o]));return n},o.topologicalSort=function(e){var n=[],o=[],i=[];for(var r in e)o[r]||i[r]||t(r,o,i,e,n);return n};var t=function(e,n,o,i,r){var s=i[e]||[];o[e]=!0;for(var a=0;a<s.length;a+=1){var l=s[a];o[l]||n[l]||t(l,n,o,i,r)}o[e]=!1,n[e]=!0,r.push(e)};o.chain=function(){for(var e=[],t=0;t<arguments.length;t+=1){var n=arguments[t];n._chained?e.push.apply(e,n._chained):e.push(n)}var o=function(){for(var t,n=new Array(arguments.length),o=0,i=arguments.length;o<i;o++)n[o]=arguments[o];for(o=0;o<e.length;o+=1){var r=e[o].apply(t,n);"undefined"!=typeof r&&(t=r)}return t};return o._chained=e,o},o.chainPathBefore=function(e,t,n){return o.set(e,t,o.chain(n,o.get(e,t)))},o.chainPathAfter=function(e,t,n){return o.set(e,t,o.chain(o.get(e,t),n))}}()},{}],
15:[function(e,t,n){var o={};t.exports=o;var i=e("../body/World"),r=e("./Sleeping"),s=e("../collision/Resolver"),a=e("../render/Render"),l=e("../collision/Pairs"),c=(e("./Metrics"),e("../collision/Grid")),u=e("./Events"),d=e("../body/Composite"),p=e("../constraint/Constraint"),f=e("./Common"),m=e("../body/Body");!function(){o.create=function(e,t){t=f.isElement(e)?t:e,e=f.isElement(e)?e:null,t=t||{},(e||t.render)&&f.warn("Engine.create: engine.render is deprecated (see docs)");var n={positionIterations:6,velocityIterations:4,constraintIterations:2,enableSleeping:!1,events:[],plugin:{},timing:{timestamp:0,timeScale:1},broadphase:{controller:c}},o=f.extend(n,t);if(e||o.render){var r={element:e,controller:a};o.render=f.extend(r,o.render)}return o.render&&o.render.controller&&(o.render=o.render.controller.create(o.render)),o.render&&(o.render.engine=o),o.world=t.world||i.create(o.world),o.pairs=l.create(),o.broadphase=o.broadphase.controller.create(o.broadphase),o.metrics=o.metrics||{extended:!1
},o},o.update=function(o,i,a){i=i||1e3/60,a=a||1;var c,f=o.world,m=o.timing,v=o.broadphase,y=[];m.timestamp+=i*m.timeScale;var g={timestamp:m.timestamp};u.trigger(o,"beforeUpdate",g);var x=d.allBodies(f),h=d.allConstraints(f);for(o.enableSleeping&&r.update(x,m.timeScale),t(x,f.gravity),n(x,i,m.timeScale,a,f.bounds),c=0;c<o.constraintIterations;c++)p.solveAll(h,m.timeScale);p.postSolveAll(x),v.controller?(f.isModified&&v.controller.clear(v),v.controller.update(v,x,o,f.isModified),y=v.pairsList):y=x,f.isModified&&d.setModified(f,!1,!1,!0);var b=v.detector(y,o),w=o.pairs,S=m.timestamp;for(l.update(w,b,S),l.removeOld(w,S),o.enableSleeping&&r.afterCollisions(w.list,m.timeScale),w.collisionStart.length>0&&u.trigger(o,"collisionStart",{pairs:w.collisionStart}),s.preSolvePosition(w.list),c=0;c<o.positionIterations;c++)s.solvePosition(w.list,m.timeScale);for(s.postSolvePosition(x),s.preSolveVelocity(w.list),c=0;c<o.velocityIterations;c++)s.solveVelocity(w.list,m.timeScale);return w.collisionActive.length>0&&u.trigger(o,"collisionActive",{
pairs:w.collisionActive}),w.collisionEnd.length>0&&u.trigger(o,"collisionEnd",{pairs:w.collisionEnd}),e(x),u.trigger(o,"afterUpdate",g),o},o.merge=function(e,t){if(f.extend(e,t),t.world){e.world=t.world,o.clear(e);for(var n=d.allBodies(e.world),i=0;i<n.length;i++){var s=n[i];r.set(s,!1),s.id=f.nextId()}}},o.clear=function(e){var t=e.world;l.clear(e.pairs);var n=e.broadphase;if(n.controller){var o=d.allBodies(t);n.controller.clear(n),n.controller.update(n,o,e,!0)}};var e=function(e){for(var t=0;t<e.length;t++){var n=e[t];n.force.x=0,n.force.y=0,n.torque=0}},t=function(e,t){var n="undefined"!=typeof t.scale?t.scale:.001;if((0!==t.x||0!==t.y)&&0!==n)for(var o=0;o<e.length;o++){var i=e[o];i.isStatic||i.isSleeping||(i.force.y+=i.mass*t.y*n,i.force.x+=i.mass*t.x*n)}},n=function(e,t,n,o,i){for(var r=0;r<e.length;r++){var s=e[r];s.isStatic||s.isSleeping||m.update(s,t,n,o)}}}()},{"../body/Body":1,"../body/Composite":2,"../body/World":3,"../collision/Grid":6,"../collision/Pairs":8,"../collision/Resolver":10,
"../constraint/Constraint":12,"../render/Render":31,"./Common":14,"./Events":16,"./Metrics":18,"./Sleeping":22}],16:[function(e,t,n){var o={};t.exports=o;var i=e("./Common");!function(){o.on=function(e,t,n){for(var o,i=t.split(" "),r=0;r<i.length;r++)o=i[r],e.events=e.events||{},e.events[o]=e.events[o]||[],e.events[o].push(n);return n},o.off=function(e,t,n){if(!t)return void(e.events={});"function"==typeof t&&(n=t,t=i.keys(e.events).join(" "));for(var o=t.split(" "),r=0;r<o.length;r++){var s=e.events[o[r]],a=[];if(n&&s)for(var l=0;l<s.length;l++)s[l]!==n&&a.push(s[l]);e.events[o[r]]=a}},o.trigger=function(e,t,n){var o,r,s,a;if(e.events){n||(n={}),o=t.split(" ");for(var l=0;l<o.length;l++)if(r=o[l],s=e.events[r]){a=i.clone(n,!1),a.name=r,a.source=e;for(var c=0;c<s.length;c++)s[c].apply(e,[a])}}}}()},{"./Common":14}],17:[function(e,t,n){var o={};t.exports=o;var i=e("./Plugin"),r=e("./Common");!function(){o.name="matter-js",o.version="0.12.0",o.uses=[],o.used=[],o.use=function(){i.use(o,Array.prototype.slice.call(arguments));
},o.before=function(e,t){return e=e.replace(/^Matter./,""),r.chainPathBefore(o,e,t)},o.after=function(e,t){return e=e.replace(/^Matter./,""),r.chainPathAfter(o,e,t)}}()},{"./Common":14,"./Plugin":20}],18:[function(e,t,n){},{"../body/Composite":2,"./Common":14}],19:[function(e,t,n){var o={};t.exports=o;var i=e("../core/Common");!function(){o.create=function(t){var n={};return t||i.log("Mouse.create: element was undefined, defaulting to document.body","warn"),n.element=t||document.body,n.absolute={x:0,y:0},n.position={x:0,y:0},n.mousedownPosition={x:0,y:0},n.mouseupPosition={x:0,y:0},n.offset={x:0,y:0},n.scale={x:1,y:1},n.wheelDelta=0,n.button=-1,n.pixelRatio=n.element.getAttribute("data-pixel-ratio")||1,n.sourceEvents={mousemove:null,mousedown:null,mouseup:null,mousewheel:null},n.mousemove=function(t){var o=e(t,n.element,n.pixelRatio),i=t.changedTouches;i&&(n.button=0,t.preventDefault()),n.absolute.x=o.x,n.absolute.y=o.y,n.position.x=n.absolute.x*n.scale.x+n.offset.x,n.position.y=n.absolute.y*n.scale.y+n.offset.y,
n.sourceEvents.mousemove=t},n.mousedown=function(t){var o=e(t,n.element,n.pixelRatio),i=t.changedTouches;i?(n.button=0,t.preventDefault()):n.button=t.button,n.absolute.x=o.x,n.absolute.y=o.y,n.position.x=n.absolute.x*n.scale.x+n.offset.x,n.position.y=n.absolute.y*n.scale.y+n.offset.y,n.mousedownPosition.x=n.position.x,n.mousedownPosition.y=n.position.y,n.sourceEvents.mousedown=t},n.mouseup=function(t){var o=e(t,n.element,n.pixelRatio),i=t.changedTouches;i&&t.preventDefault(),n.button=-1,n.absolute.x=o.x,n.absolute.y=o.y,n.position.x=n.absolute.x*n.scale.x+n.offset.x,n.position.y=n.absolute.y*n.scale.y+n.offset.y,n.mouseupPosition.x=n.position.x,n.mouseupPosition.y=n.position.y,n.sourceEvents.mouseup=t},n.mousewheel=function(e){n.wheelDelta=Math.max(-1,Math.min(1,e.wheelDelta||-e.detail)),e.preventDefault()},o.setElement(n,n.element),n},o.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)},o.clearSourceEvents=function(e){e.sourceEvents.mousemove=null,e.sourceEvents.mousedown=null,e.sourceEvents.mouseup=null,e.sourceEvents.mousewheel=null,e.wheelDelta=0},o.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},o.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};var e=function(e,t,n){var o,i,r=t.getBoundingClientRect(),s=document.documentElement||document.body.parentNode||document.body,a=void 0!==window.pageXOffset?window.pageXOffset:s.scrollLeft,l=void 0!==window.pageYOffset?window.pageYOffset:s.scrollTop,c=e.changedTouches;return c?(o=c[0].pageX-r.left-a,i=c[0].pageY-r.top-l):(o=e.pageX-r.left-a,
i=e.pageY-r.top-l),{x:o/(t.clientWidth/(t.width||t.clientWidth)*n),y:i/(t.clientHeight/(t.height||t.clientHeight)*n)}}}()},{"../core/Common":14}],20:[function(e,t,n){var o={};t.exports=o;var i=e("./Common");!function(){o._registry={},o.register=function(e){if(o.isPlugin(e)||i.warn("Plugin.register:",o.toString(e),"does not implement all required fields."),e.name in o._registry){var t=o._registry[e.name],n=o.versionParse(e.version).number,r=o.versionParse(t.version).number;n>r?(i.warn("Plugin.register:",o.toString(t),"was upgraded to",o.toString(e)),o._registry[e.name]=e):n<r?i.warn("Plugin.register:",o.toString(t),"can not be downgraded to",o.toString(e)):e!==t&&i.warn("Plugin.register:",o.toString(e),"is already registered to different plugin object")}else o._registry[e.name]=e;return e},o.resolve=function(e){return o._registry[o.dependencyParse(e).name]},o.toString=function(e){return"string"==typeof e?e:(e.name||"anonymous")+"@"+(e.version||e.range||"0.0.0")},o.isPlugin=function(e){return e&&e.name&&e.version&&e.install;
},o.isUsed=function(e,t){return e.used.indexOf(t)>-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;a<r.length;a+=1)if(r[a]!==e.name){var l=o.resolve(r[a]);l?o.isUsed(e,l.name)||(o.isFor(l,e)||(i.warn("Plugin.use:",o.toString(l),"is for",l.for,"but installed on",o.toString(e)+"."),l._warned=!0),l.install?l.install(e):(i.warn("Plugin.use:",o.toString(l),"does not specify an install function."),l._warned=!0),l._warned?(s.push("🔶 "+o.toString(l)),delete l._warned):s.push("✅ "+o.toString(l)),e.used.push(l.name)):s.push("❌ "+r[a])}s.length>0&&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<t[r].length;s+=1)o.dependencies(t[r][s],t);return t}},o.dependencyParse=function(e){if(i.isString(e)){var t=/^[\w-]+(@(\*|[\^~]?\d+\.\d+\.\d+(-[0-9A-Za-z-]+)?))?$/;return t.test(e)||i.warn("Plugin.dependencyParse:",e,"is not a valid dependency string."),{name:e.split("@")[0],range:e.split("@")[1]||"*"}}return{name:e.name,range:e.range||e.version}},o.versionParse=function(e){var t=/^\*|[\^~]?\d+\.\d+\.\d+(-[0-9A-Za-z-]+)?$/;t.test(e)||i.warn("Plugin.versionParse:",e,"is not a valid version or range.");var n=e.split("-");e=n[0];var o=isNaN(Number(e[0])),r=o?e.substr(1):e,s=i.map(r.split("."),function(e){return Number(e);
});return{isRange:o,version:r,range:e,operator:o?e[0]:"",parts:s,prerelease:n[1],number:1e8*s[0]+1e4*s[1]+s[2]}},o.versionSatisfies=function(e,t){t=t||"*";var n=o.versionParse(t),i=n.parts,r=o.versionParse(e),s=r.parts;if(n.isRange){if("*"===n.operator||"*"===e)return!0;if("~"===n.operator)return s[0]===i[0]&&s[1]===i[1]&&s[2]>=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"undefined"!=typeof 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=o<e.deltaMin?e.deltaMin:o,o=o>e.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;i<e.length;i++){var r=e[i],s=r.speed*r.speed+r.angularSpeed*r.angularSpeed;if(0===r.force.x&&0===r.force.y){var a=Math.min(r.motion,s),l=Math.max(r.motion,s);r.motion=o._minBias*a+(1-o._minBias)*l,
r.sleepThreshold>0&&r.motion<o._motionSleepThreshold*n?(r.sleepCounter+=1,r.sleepCounter>=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;i<e.length;i++){var r=e[i];if(r.isActive){var s=r.collision,a=s.bodyA.parent,l=s.bodyB.parent;if(!(a.isSleeping&&l.isSleeping||a.isStatic||l.isStatic)&&(a.isSleeping||l.isSleeping)){var c=a.isSleeping&&!a.isStatic?a:l,u=c===a?l:a;!c.isStatic&&u.motion>o._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){(function(n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../core/Common"),s=e("../body/Body"),a=e("../geometry/Bounds"),l=e("../geometry/Vector"),c="undefined"!=typeof window?window.decomp:"undefined"!=typeof n?n.decomp:null;
!function(){o.rectangle=function(e,t,n,o,a){a=a||{};var l={label:"Rectangle Body",position:{x:e,y:t},vertices:i.fromPath("L 0 0 L "+n+" 0 L "+n+" "+o+" L 0 "+o)};if(a.chamfer){var c=a.chamfer;l.vertices=i.chamfer(l.vertices,c.radius,c.quality,c.qualityMin,c.qualityMax),delete a.chamfer}return s.create(r.extend({},l,a))},o.trapezoid=function(e,t,n,o,a,l){l=l||{},a*=.5;var c,u=(1-2*a)*n,d=n*a,p=d+u,f=p+d;c=a<.5?"L 0 0 L "+d+" "+-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:i.fromPath(c)};if(l.chamfer){var v=l.chamfer;m.vertices=i.chamfer(m.vertices,v.radius,v.quality,v.qualityMin,v.qualityMax),delete l.chamfer}return s.create(r.extend({},m,l))},o.circle=function(e,t,n,i,s){i=i||{};var a={label:"Circle Body",circleRadius:n};s=s||25;var l=Math.ceil(Math.max(10,Math.min(s,n)));return l%2===1&&(l+=1),o.polygon(e,t,l,n,r.extend({},a,i))},o.polygon=function(e,t,n,a,l){if(l=l||{},n<3)return o.circle(e,t,a,l);for(var c=2*Math.PI/n,u="",d=.5*c,p=0;p<n;p+=1){
var f=d+p*c,m=Math.cos(f)*a,v=Math.sin(f)*a;u+="L "+m.toFixed(3)+" "+v.toFixed(3)+" "}var y={label:"Polygon Body",position:{x:e,y:t},vertices:i.fromPath(u)};if(l.chamfer){var g=l.chamfer;y.vertices=i.chamfer(y.vertices,g.radius,g.quality,g.qualityMin,g.qualityMax),delete l.chamfer}return s.create(r.extend({},y,l))},o.fromVertices=function(e,t,n,o,u,d,p){var f,m,v,y,g,x,h,b,w;for(o=o||{},m=[],u="undefined"!=typeof u&&u,d="undefined"!=typeof d?d:.01,p="undefined"!=typeof p?p:10,c||r.warn("Bodies.fromVertices: poly-decomp.js required. Could not decompose vertices. Fallback to convex hull."),r.isArray(n[0])||(n=[n]),b=0;b<n.length;b+=1)if(y=n[b],v=i.isConvex(y),v||!c)y=v?i.clockwiseSort(y):i.hull(y),m.push({position:{x:e,y:t},vertices:y});else{var S=y.map(function(e){return[e.x,e.y]});c.makeCCW(S),d!==!1&&c.removeCollinearPoints(S,d);var C=c.quickDecomp(S);for(g=0;g<C.length;g++){var A=C[g],P=A.map(function(e){return{x:e[0],y:e[1]}});p>0&&i.area(P)<p||m.push({position:i.centre(P),vertices:P
})}}for(g=0;g<m.length;g++)m[g]=s.create(r.extend(m[g],o));if(u){var B=5;for(g=0;g<m.length;g++){var M=m[g];for(x=g+1;x<m.length;x++){var k=m[x];if(a.overlaps(M.bounds,k.bounds)){var I=M.vertices,T=k.vertices;for(h=0;h<M.vertices.length;h++)for(w=0;w<k.vertices.length;w++){var V=l.magnitudeSquared(l.sub(I[(h+1)%I.length],T[w])),R=l.magnitudeSquared(l.sub(I[h],T[(w+1)%T.length]));V<B&&R<B&&(I[h].isInternal=!0,T[w].isInternal=!0)}}}}}return m.length>1?(f=s.create(r.extend({parts:m.slice(0)},o)),s.setPosition(f,{x:e,y:t}),f):m[0]}}()}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../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,u=i.create({label:"Stack"
}),d=e,p=t,f=0,m=0;m<o;m++){for(var v=0,y=0;y<n;y++){var g=l(d,p,y,m,c,f);if(g){var x=g.bounds.max.y-g.bounds.min.y,h=g.bounds.max.x-g.bounds.min.x;x>v&&(v=x),a.translate(g,{x:.5*h,y:.5*x}),d=g.bounds.max.x+r,i.addBody(u,g),c=g,f+=1}else d+=r}p+=v+s,d=e}return u},o.chain=function(e,t,n,o,a,l){for(var c=e.bodies,u=1;u<c.length;u++){var d=c[u-1],p=c[u],f=d.bounds.max.y-d.bounds.min.y,m=d.bounds.max.x-d.bounds.min.x,v=p.bounds.max.y-p.bounds.min.y,y=p.bounds.max.x-p.bounds.min.x,g={bodyA:d,pointA:{x:m*t,y:f*n},bodyB:p,pointB:{x:y*o,y:v*a}},x=s.extend(g,l);i.addConstraint(e,r.create(x))}return e.label+=" Chain",e},o.mesh=function(e,t,n,o,a){var l,c,u,d,p,f=e.bodies;for(l=0;l<n;l++){for(c=1;c<t;c++)u=f[c-1+l*t],d=f[c+l*t],i.addConstraint(e,r.create(s.extend({bodyA:u,bodyB:d},a)));if(l>0)for(c=0;c<t;c++)u=f[c+(l-1)*t],d=f[c+l*t],i.addConstraint(e,r.create(s.extend({bodyA:u,bodyB:d},a))),o&&c>0&&(p=f[c-1+(l-1)*t],i.addConstraint(e,r.create(s.extend({bodyA:p,bodyB:d},a)))),o&&c<t-1&&(p=f[c+1+(l-1)*t],
i.addConstraint(e,r.create(s.extend({bodyA:p,bodyB:d},a))))}return e.label+=" Mesh",e},o.pyramid=function(e,t,n,i,r,s,l){return o.stack(e,t,n,i,r,s,function(t,o,s,c,u,d){var p=Math.min(i,Math.ceil(n/2)),f=u?u.bounds.max.x-u.bounds.min.x:0;if(!(c>p)){c=p-c;var m=c,v=n-1-c;if(!(s<m||s>v)){1===d&&a.translate(u,{x:(s+(n%2===1?1:-1))*f,y:0});var y=u?s*f:0;return l(e+y+s*r,o,s,c,u,d)}}})},o.newtonsCradle=function(e,t,n,o,s){for(var a=i.create({label:"Newtons Cradle"}),c=0;c<n;c++){var u=1.9,d=l.circle(e+c*(o*u),t+s,o,{inertia:1/0,restitution:1,friction:0,frictionAir:1e-4,slop:1}),p=r.create({pointA:{x:e+c*(o*u),y:t},bodyB:d});i.addBody(a,d),i.addConstraint(a,p)}return a},o.car=function(e,t,n,o,s){var c=a.nextGroup(!0),u=-20,d=.5*-n+u,p=.5*n-u,f=0,m=i.create({label:"Car"}),v=l.trapezoid(e,t,n,o,.3,{collisionFilter:{group:c},friction:.01,chamfer:{radius:10}}),y=l.circle(e+d,t+f,s,{collisionFilter:{group:c},friction:.8,density:.01}),g=l.circle(e+p,t+f,s,{collisionFilter:{group:c},friction:.8,density:.01
}),x=r.create({bodyA:v,pointA:{x:d,y:f},bodyB:y,stiffness:.2,render:{lineWidth:0}}),h=r.create({bodyA:v,pointA:{x:p,y:f},bodyB:g,stiffness:.2,render:{lineWidth:0}});return i.addBody(m,v),i.addBody(m,y),i.addBody(m,g),i.addConstraint(m,x),i.addConstraint(m,h),m},o.softBody=function(e,t,n,i,r,a,c,u,d,p){d=s.extend({inertia:1/0},d),p=s.extend({stiffness:.4},p);var f=o.stack(e,t,n,i,r,a,function(e,t){return l.circle(e,t,u,d)});return o.mesh(f,n,i,c,p),f.label="Soft Body",f}}()},{"../body/Body":1,"../body/Composite":2,"../constraint/Constraint":12,"../core/Common":14,"./Bodies":23}],25:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vector"),r=e("../core/Common");!function(){o.fromVertices=function(e){for(var t={},n=0;n<e.length;n++){var o=(n+1)%e.length,s=i.normalise({x:e[o].y-e[n].y,y:e[n].x-e[o].x}),a=0===s.y?1/0:s.x/s.y;a=a.toFixed(3).toString(),t[a]=s}return r.values(t)},o.rotate=function(e,t){if(0!==t)for(var n=Math.cos(t),o=Math.sin(t),i=0;i<e.length;i++){var r,s=e[i];r=s.x*n-s.y*o,
s.y=s.x*o+s.y*n,s.x=r}}}()},{"../core/Common":14,"../geometry/Vector":28}],26:[function(e,t,n){var o={};t.exports=o,function(){o.create=function(e){var t={min:{x:0,y:0},max:{x:0,y:0}};return e&&o.update(t,e),t},o.update=function(e,t,n){e.min.x=1/0,e.max.x=-(1/0),e.min.y=1/0,e.max.y=-(1/0);for(var o=0;o<t.length;o++){var i=t[o];i.x>e.max.x&&(e.max.x=i.x),i.x<e.min.x&&(e.min.x=i.x),i.y>e.max.y&&(e.max.y=i.y),i.y<e.min.y&&(e.min.y=i.y)}n&&(n.x>0?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;e("../geometry/Bounds");!function(){o.pathToVertices=function(t,n){
var o,i,r,s,a,l,c,u,d,p,f,m,v=[],y=0,g=0,x=0;n=n||15;var h=function(e,t,n){var o=n%2===1&&n>1;if(!d||e!=d.x||t!=d.y){d&&o?(f=d.x,m=d.y):(f=0,m=0);var i={x:f+e,y:m+t};!o&&d||(d=i),v.push(i),g=f+e,x=m+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(e(t),r=t.getTotalLength(),l=[],o=0;o<t.pathSegList.numberOfItems;o+=1)l.push(t.pathSegList.getItem(o));for(c=l.concat();y<r;){if(p=t.getPathSegAtLength(y),a=l[p],a!=u){for(;c.length&&c[0]!=a;)b(c.shift());u=a}switch(a.pathSegTypeAsLetter.toUpperCase()){case"C":case"T":case"S":case"Q":case"A":s=t.getPointAtLength(y),h(s.x,s.y,0)}y+=n}for(o=0,i=c.length;o<i;++o)b(c[o]);return v};var e=function(e){for(var t,n,o,i,r,s,a=e.pathSegList,l=0,c=0,u=a.numberOfItems,d=0;d<u;++d){var p=a.getItem(d),f=p.pathSegTypeAsLetter;if(/[MLHVCSQTA]/.test(f))"x"in p&&(l=p.x),"y"in p&&(c=p.y);else switch("x1"in p&&(o=l+p.x1),
"x2"in p&&(r=l+p.x2),"y1"in p&&(i=c+p.y1),"y2"in p&&(s=c+p.y2),"x"in p&&(l+=p.x),"y"in p&&(c+=p.y),f){case"m":a.replaceItem(e.createSVGPathSegMovetoAbs(l,c),d);break;case"l":a.replaceItem(e.createSVGPathSegLinetoAbs(l,c),d);break;case"h":a.replaceItem(e.createSVGPathSegLinetoHorizontalAbs(l),d);break;case"v":a.replaceItem(e.createSVGPathSegLinetoVerticalAbs(c),d);break;case"c":a.replaceItem(e.createSVGPathSegCurvetoCubicAbs(l,c,o,i,r,s),d);break;case"s":a.replaceItem(e.createSVGPathSegCurvetoCubicSmoothAbs(l,c,r,s),d);break;case"q":a.replaceItem(e.createSVGPathSegCurvetoQuadraticAbs(l,c,o,i),d);break;case"t":a.replaceItem(e.createSVGPathSegCurvetoQuadraticSmoothAbs(l,c),d);break;case"a":a.replaceItem(e.createSVGPathSegArcAbs(l,c,p.r1,p.r2,p.angle,p.largeArcFlag,p.sweepFlag),d);break;case"z":case"Z":l=t,c=n}"M"!=f&&"m"!=f||(t=l,n=c)}}}()},{"../geometry/Bounds":26}],28:[function(e,t,n){var o={};t.exports=o,function(){o.create=function(e,t){return{x:e||0,y:t||0}},o.clone=function(e){return{
x:e.x,y:e.y}},o.magnitude=function(e){return Math.sqrt(e.x*e.x+e.y*e.y)},o.magnitudeSquared=function(e){return e.x*e.x+e.y*e.y},o.rotate=function(e,t){var n=Math.cos(t),o=Math.sin(t);return{x:e.x*n-e.y*o,y:e.x*o+e.y*n}},o.rotateAbout=function(e,t,n,o){var i=Math.cos(t),r=Math.sin(t);o||(o={});var s=n.x+((e.x-n.x)*i-(e.y-n.y)*r);return o.y=n.y+((e.x-n.x)*r+(e.y-n.y)*i),o.x=s,o},o.normalise=function(e){var t=o.magnitude(e);return 0===t?{x:0,y:0}:{x:e.x/t,y:e.y/t}},o.dot=function(e,t){return e.x*t.x+e.y*t.y},o.cross=function(e,t){return e.x*t.y-e.y*t.x},o.cross3=function(e,t,n){return(t.x-e.x)*(n.y-e.y)-(t.y-e.y)*(n.x-e.x)},o.add=function(e,t,n){return n||(n={}),n.x=e.x+t.x,n.y=e.y+t.y,n},o.sub=function(e,t,n){return n||(n={}),n.x=e.x-t.x,n.y=e.y-t.y,n},o.mult=function(e,t){return{x:e.x*t,y:e.y*t}},o.div=function(e,t){return{x:e.x/t,y:e.y/t}},o.perp=function(e,t){return t=t===!0?-1:1,{x:t*-e.y,y:t*e.x}},o.neg=function(e){return{x:-e.x,y:-e.y}},o.angle=function(e,t){return Math.atan2(t.y-e.y,t.x-e.x);
},o._temp=[o.create(),o.create(),o.create(),o.create(),o.create(),o.create()]}()},{}],29:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vector"),r=e("../core/Common");!function(){o.create=function(e,t){for(var n=[],o=0;o<e.length;o++){var i=e[o],r={x:i.x,y:i.y,index:o,body:t,isInternal:!1};n.push(r)}return n},o.fromPath=function(e,t){var n=/L?\s*([\-\d\.e]+)[\s,]*([\-\d\.e]+)*/gi,i=[];return e.replace(n,function(e,t,n){i.push({x:parseFloat(t),y:parseFloat(n)})}),o.create(i,t)},o.centre=function(e){for(var t,n,r,s=o.area(e,!0),a={x:0,y:0},l=0;l<e.length;l++)r=(l+1)%e.length,t=i.cross(e[l],e[r]),n=i.mult(i.add(e[l],e[r]),t),a=i.add(a,n);return i.div(a,6*s)},o.mean=function(e){for(var t={x:0,y:0},n=0;n<e.length;n++)t.x+=e[n].x,t.y+=e[n].y;return i.div(t,e.length)},o.area=function(e,t){for(var n=0,o=e.length-1,i=0;i<e.length;i++)n+=(e[o].x-e[i].x)*(e[o].y+e[i].y),o=i;return t?n/2:Math.abs(n)/2},o.inertia=function(e,t){for(var n,o,r=0,s=0,a=e,l=0;l<a.length;l++)o=(l+1)%a.length,n=Math.abs(i.cross(a[o],a[l])),
r+=n*(i.dot(a[o],a[o])+i.dot(a[o],a[l])+i.dot(a[l],a[l])),s+=n;return t/6*(r/s)},o.translate=function(e,t,n){var o;if(n)for(o=0;o<e.length;o++)e[o].x+=t.x*n,e[o].y+=t.y*n;else for(o=0;o<e.length;o++)e[o].x+=t.x,e[o].y+=t.y;return e},o.rotate=function(e,t,n){if(0!==t){for(var o=Math.cos(t),i=Math.sin(t),r=0;r<e.length;r++){var s=e[r],a=s.x-n.x,l=s.y-n.y;s.x=n.x+(a*o-l*i),s.y=n.y+(a*i+l*o)}return e}},o.contains=function(e,t){for(var n=0;n<e.length;n++){var o=e[n],i=e[(n+1)%e.length];if((t.x-o.x)*(i.y-o.y)+(t.y-o.y)*(o.x-i.x)>0)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<e.length;l++)s=e[l],a=i.sub(s,r),e[l].x=r.x+a.x*t,e[l].y=r.y+a.y*n;return e},o.chamfer=function(e,t,n,o,s){t=t||[8],t.length||(t=[t]),n="undefined"!=typeof n?n:-1,o=o||2,s=s||14;for(var a=[],l=0;l<e.length;l++){var c=e[l-1>=0?l-1:e.length-1],u=e[l],d=e[(l+1)%e.length],p=t[l<t.length?l:t.length-1];if(0!==p){var f=i.normalise({x:u.y-c.y,y:c.x-u.x}),m=i.normalise({x:d.y-u.y,
y:u.x-d.x}),v=Math.sqrt(2*Math.pow(p,2)),y=i.mult(r.clone(f),p),g=i.normalise(i.mult(i.add(f,m),.5)),x=i.sub(u,i.mult(g,v)),h=n;n===-1&&(h=1.75*Math.pow(p,.32)),h=r.clamp(h,o,s),h%2===1&&(h+=1);for(var b=Math.acos(i.dot(f,m)),w=b/h,S=0;S<h;S++)a.push(i.add(i.rotate(y,w*S),x))}else a.push(u)}return a},o.clockwiseSort=function(e){var t=o.mean(e);return e.sort(function(e,n){return i.angle(t,e)-i.angle(t,n)}),e},o.isConvex=function(e){var t,n,o,i,r=0,s=e.length;if(s<3)return null;for(t=0;t<s;t++)if(n=(t+1)%s,o=(t+2)%s,i=(e[n].x-e[t].x)*(e[o].y-e[n].y),i-=(e[n].y-e[t].y)*(e[o].x-e[n].x),i<0?r|=1:i>0&&(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<e.length;n++){for(t=e[n];r.length>=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--){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"),u=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):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=d(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="undefined"==typeof 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;s<t.length;s+=1){var a=t[s],l=a.bounds?a.bounds.min:a.min||a.position||a,c=a.bounds?a.bounds.max:a.max||a.position||a;l&&c&&(l.x<r.min.x&&(r.min.x=l.x),c.x>r.max.x&&(r.max.x=c.x),l.y<r.min.y&&(r.min.y=l.y),c.y>r.max.y&&(r.max.y=c.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,m=e.canvas.width,v=m/f,y=d/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+d*g,e.bounds.min.y=r.min.y,e.bounds.max.y=r.min.y+p*x,o&&(e.bounds.min.x+=.5*d-d*g*.5,e.bounds.max.x+=.5*d-d*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&&(u.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
}),u.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,d=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,d.width,d.height),p.globalCompositeOperation="source-over",m.hasBounds){for(t=0;t<v.length;t++){var w=v[t];s.overlaps(w.bounds,e.bounds)&&x.push(w)}for(t=0;t<y.length;t++){var S=y[t],C=S.bodyA,A=S.bodyB,P=S.pointA,B=S.pointB;C&&(P=c.add(C.position,S.pointA)),A&&(B=c.add(A.position,S.pointB)),
P&&B&&(s.contains(e.bounds,P)||s.contains(e.bounds,B))&&h.push(S)}o.startViewTransform(e),e.mouse&&(u.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}),u.setOffset(e.mouse,e.bounds.min))}else h=y,x=v;!m.wireframes||n.enableSleeping&&m.showSleeping?o.bodies(e,x,p):(m.showConvexHulls&&o.bodyConvexHulls(e,x,p),o.bodyWireframes(e,x,p)),m.showBounds&&o.bodyBounds(e,x,p),(m.showAxes||m.showAngleIndicator)&&o.bodyAxes(e,x,p),m.showPositions&&o.bodyPositions(e,x,p),m.showVelocity&&o.bodyVelocity(e,x,p),m.showIds&&o.bodyIds(e,x,p),m.showSeparations&&o.separations(e,n.pairs.list,p),m.showCollisions&&o.collisions(e,n.pairs.list,p),m.showVertexNumbers&&o.vertexNumbers(e,x,p),m.showMousePosition&&o.mousePosition(e,e.mouse,p),o.constraints(h,p),m.showBroadphase&&n.broadphase.controller===l&&o.grid(e,n.broadphase,p),m.showDebug&&o.debug(e,p),m.hasBounds&&o.endViewTransform(e),a.trigger(e,"afterRender",b)},o.debug=function(e,t){var n=t,o=e.engine,i=o.world,s=o.metrics,a=e.options,l=(r.allBodies(i),
" ");if(o.timing.timestamp-(e.debugTimestamp||0)>=500){var c="";s.timing&&(c+="fps: "+Math.round(s.timing.fps)+l),e.debugString=c,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 u=e.debugString.split("\n"),d=0;d<u.length;d++)n.fillText(u[d],50,50+18*d)}},o.constraints=function(e,t){for(var n=t,o=0;o<e.length;o++){var i=e[o];if(i.render.visible&&i.pointA&&i.pointB){var r=i.bodyA,s=i.bodyB;r?(n.beginPath(),n.moveTo(r.position.x+i.pointA.x,r.position.y+i.pointA.y)):(n.beginPath(),n.moveTo(i.pointA.x,i.pointA.y)),s?n.lineTo(s.position.x+i.pointB.x,s.position.y+i.pointB.y):n.lineTo(i.pointB.x,i.pointB.y),i.render.lineWidth&&(n.lineWidth=i.render.lineWidth,n.strokeStyle=i.render.strokeStyle,n.stroke())}}},o.bodyShadows=function(e,t,n){for(var o=n,i=(e.engine,0);i<t.length;i++){var r=t[i];if(r.render.visible){if(r.circleRadius)o.beginPath(),o.arc(r.position.x,r.position.y,r.circleRadius,0,2*Math.PI),
o.closePath();else{o.beginPath(),o.moveTo(r.vertices[0].x,r.vertices[0].y);for(var s=1;s<r.vertices.length;s++)o.lineTo(r.vertices[s].x,r.vertices[s].y);o.closePath()}var a=r.position.x-.5*e.options.width,l=r.position.y-.2*e.options.height,c=Math.abs(a)+Math.abs(l);o.shadowColor="rgba(0,0,0,0.15)",o.shadowOffsetX=.05*a,o.shadowOffsetY=.05*l,o.shadowBlur=1+12*Math.min(1,c/1e3),o.fill(),o.shadowColor=null,o.shadowOffsetX=null,o.shadowOffsetY=null,o.shadowBlur=null}}},o.bodies=function(e,t,n){var o,i,r,s,a=n,l=(e.engine,e.options),c=l.showInternalEdges||!l.wireframes;for(r=0;r<t.length;r++)if(o=t[r],o.render.visible)for(s=o.parts.length>1?1:0;s<o.parts.length;s++)if(i=o.parts[s],i.render.visible){if(l.showSleeping&&o.isSleeping?a.globalAlpha=.5*i.render.opacity:1!==i.render.opacity&&(a.globalAlpha=i.render.opacity),i.render.sprite&&i.render.sprite.texture&&!l.wireframes){var u=i.render.sprite,d=p(e,u.texture);a.translate(i.position.x,i.position.y),a.rotate(i.angle),a.drawImage(d,d.width*-u.xOffset*u.xScale,d.height*-u.yOffset*u.yScale,d.width*u.xScale,d.height*u.yScale),
a.rotate(-i.angle),a.translate(-i.position.x,-i.position.y)}else{if(i.circleRadius)a.beginPath(),a.arc(i.position.x,i.position.y,i.circleRadius,0,2*Math.PI);else{a.beginPath(),a.moveTo(i.vertices[0].x,i.vertices[0].y);for(var f=1;f<i.vertices.length;f++)!i.vertices[f-1].isInternal||c?a.lineTo(i.vertices[f].x,i.vertices[f].y):a.moveTo(i.vertices[f].x,i.vertices[f].y),i.vertices[f].isInternal&&!c&&a.moveTo(i.vertices[(f+1)%i.vertices.length].x,i.vertices[(f+1)%i.vertices.length].y);a.lineTo(i.vertices[0].x,i.vertices[0].y),a.closePath()}l.wireframes?(a.lineWidth=1,a.strokeStyle="#bbb",a.stroke()):(a.fillStyle=i.render.fillStyle,i.render.lineWidth&&(a.lineWidth=i.render.lineWidth,a.strokeStyle=i.render.strokeStyle,a.stroke()),a.fill())}a.globalAlpha=1}},o.bodyWireframes=function(e,t,n){var o,i,r,s,a,l=n,c=e.options.showInternalEdges;for(l.beginPath(),r=0;r<t.length;r++)if(o=t[r],o.render.visible)for(a=o.parts.length>1?1:0;a<o.parts.length;a++){for(i=o.parts[a],l.moveTo(i.vertices[0].x,i.vertices[0].y),
s=1;s<i.vertices.length;s++)!i.vertices[s-1].isInternal||c?l.lineTo(i.vertices[s].x,i.vertices[s].y):l.moveTo(i.vertices[s].x,i.vertices[s].y),i.vertices[s].isInternal&&!c&&l.moveTo(i.vertices[(s+1)%i.vertices.length].x,i.vertices[(s+1)%i.vertices.length].y);l.lineTo(i.vertices[0].x,i.vertices[0].y)}l.lineWidth=1,l.strokeStyle="#bbb",l.stroke()},o.bodyConvexHulls=function(e,t,n){var o,i,r,s=n;for(s.beginPath(),i=0;i<t.length;i++)if(o=t[i],o.render.visible&&1!==o.parts.length){for(s.moveTo(o.vertices[0].x,o.vertices[0].y),r=1;r<o.vertices.length;r++)s.lineTo(o.vertices[r].x,o.vertices[r].y);s.lineTo(o.vertices[0].x,o.vertices[0].y)}s.lineWidth=1,s.strokeStyle="rgba(255,255,255,0.2)",s.stroke()},o.vertexNumbers=function(e,t,n){var o,i,r,s=n;for(o=0;o<t.length;o++){var a=t[o].parts;for(r=a.length>1?1:0;r<a.length;r++){var l=a[r];for(i=0;i<l.vertices.length;i++)s.fillStyle="rgba(255,255,255,0.2)",s.fillText(o+"_"+i,l.position.x+.8*(l.vertices[i].x-l.position.x),l.position.y+.8*(l.vertices[i].y-l.position.y));
}}},o.mousePosition=function(e,t,n){var o=n;o.fillStyle="rgba(255,255,255,0.8)",o.fillText(t.position.x+" "+t.position.y,t.position.x+5,t.position.y-5)},o.bodyBounds=function(e,t,n){var o=n,i=(e.engine,e.options);o.beginPath();for(var r=0;r<t.length;r++){var s=t[r];if(s.render.visible)for(var a=t[r].parts,l=a.length>1?1:0;l<a.length;l++){var c=a[l];o.rect(c.bounds.min.x,c.bounds.min.y,c.bounds.max.x-c.bounds.min.x,c.bounds.max.y-c.bounds.min.y)}}i.wireframes?o.strokeStyle="rgba(255,255,255,0.08)":o.strokeStyle="rgba(0,0,0,0.1)",o.lineWidth=1,o.stroke()},o.bodyAxes=function(e,t,n){var o,i,r,s,a=n,l=(e.engine,e.options);for(a.beginPath(),i=0;i<t.length;i++){var c=t[i],u=c.parts;if(c.render.visible)if(l.showAxes)for(r=u.length>1?1:0;r<u.length;r++)for(o=u[r],s=0;s<o.axes.length;s++){var d=o.axes[s];a.moveTo(o.position.x,o.position.y),a.lineTo(o.position.x+20*d.x,o.position.y+20*d.y)}else for(r=u.length>1?1:0;r<u.length;r++)for(o=u[r],s=0;s<o.axes.length;s++)a.moveTo(o.position.x,o.position.y),
a.lineTo((o.vertices[0].x+o.vertices[o.vertices.length-1].x)/2,(o.vertices[0].y+o.vertices[o.vertices.length-1].y)/2)}l.wireframes?(a.strokeStyle="indianred",a.lineWidth=1):(a.strokeStyle="rgba(255, 255, 255, 0.4)",a.globalCompositeOperation="overlay",a.lineWidth=2),a.stroke(),a.globalCompositeOperation="source-over"},o.bodyPositions=function(e,t,n){var o,i,r,s,a=n,l=(e.engine,e.options);for(a.beginPath(),r=0;r<t.length;r++)if(o=t[r],o.render.visible)for(s=0;s<o.parts.length;s++)i=o.parts[s],a.arc(i.position.x,i.position.y,3,0,2*Math.PI,!1),a.closePath();for(l.wireframes?a.fillStyle="indianred":a.fillStyle="rgba(0,0,0,0.5)",a.fill(),a.beginPath(),r=0;r<t.length;r++)o=t[r],o.render.visible&&(a.arc(o.positionPrev.x,o.positionPrev.y,2,0,2*Math.PI,!1),a.closePath());a.fillStyle="rgba(255,165,0,0.8)",a.fill()},o.bodyVelocity=function(e,t,n){var o=n;o.beginPath();for(var i=0;i<t.length;i++){var r=t[i];r.render.visible&&(o.moveTo(r.position.x,r.position.y),o.lineTo(r.position.x+2*(r.position.x-r.positionPrev.x),r.position.y+2*(r.position.y-r.positionPrev.y)));
}o.lineWidth=3,o.strokeStyle="cornflowerblue",o.stroke()},o.bodyIds=function(e,t,n){var o,i,r=n;for(o=0;o<t.length;o++)if(t[o].render.visible){var s=t[o].parts;for(i=s.length>1?1:0;i<s.length;i++){var a=s[i];r.font="12px Arial",r.fillStyle="rgba(255,255,255,0.5)",r.fillText(a.id,a.position.x+10,a.position.y-10)}}},o.collisions=function(e,t,n){var o,i,r,s,a=n,l=e.options;for(a.beginPath(),r=0;r<t.length;r++)if(o=t[r],o.isActive)for(i=o.collision,s=0;s<o.activeContacts.length;s++){var c=o.activeContacts[s],u=c.vertex;a.rect(u.x-1.5,u.y-1.5,3.5,3.5)}for(l.wireframes?a.fillStyle="rgba(255,255,255,0.7)":a.fillStyle="orange",a.fill(),a.beginPath(),r=0;r<t.length;r++)if(o=t[r],o.isActive&&(i=o.collision,o.activeContacts.length>0)){var d=o.activeContacts[0].vertex.x,p=o.activeContacts[0].vertex.y;2===o.activeContacts.length&&(d=(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||i.bodyA.isStatic===!0?a.moveTo(d-8*i.normal.x,p-8*i.normal.y):a.moveTo(d+8*i.normal.x,p+8*i.normal.y),
a.lineTo(d,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;a<t.length;a++)if(o=t[a],o.isActive){i=o.collision,r=i.bodyA,s=i.bodyB;var u=1;s.isStatic||r.isStatic||(u=.5),s.isStatic&&(u=0),l.moveTo(s.position.x,s.position.y),l.lineTo(s.position.x-i.penetration.x*u,s.position.y-i.penetration.y*u),u=1,s.isStatic||r.isStatic||(u=.5),r.isStatic&&(u=0),l.moveTo(r.position.x,r.position.y),l.lineTo(r.position.x+i.penetration.x*u,r.position.y+i.penetration.y*u)}c.wireframes?l.strokeStyle="rgba(255,165,0,0.5)":l.strokeStyle="orange",l.stroke()},o.grid=function(e,t,n){var o=n,r=e.options;r.wireframes?o.strokeStyle="rgba(255,180,0,0.1)":o.strokeStyle="rgba(255,180,0,0.5)",o.beginPath();for(var s=i.keys(t.buckets),a=0;a<s.length;a++){var l=s[a];if(!(t.buckets[l].length<2)){var c=l.split(/C|R/);o.rect(.5+parseInt(c[1],10)*t.bucketWidth,.5+parseInt(c[2],10)*t.bucketHeight,t.bucketWidth,t.bucketHeight);
}}o.lineWidth=1,o.stroke()},o.inspector=function(e,t){var n,o=(e.engine,e.selected),i=e.render,r=i.options;if(r.hasBounds){var s=i.bounds.max.x-i.bounds.min.x,a=i.bounds.max.y-i.bounds.min.y,l=s/i.options.width,c=a/i.options.height;t.scale(1/l,1/c),t.translate(-i.bounds.min.x,-i.bounds.min.y)}for(var u=0;u<o.length;u++){var d=o[u].data;switch(t.translate(.5,.5),t.lineWidth=1,t.strokeStyle="rgba(255,165,0,0.9)",t.setLineDash([1,2]),d.type){case"body":n=d.bounds,t.beginPath(),t.rect(Math.floor(n.min.x-3),Math.floor(n.min.y-3),Math.floor(n.max.x-n.min.x+6),Math.floor(n.max.y-n.min.y+6)),t.closePath(),t.stroke();break;case"constraint":var p=d.pointA;d.bodyA&&(p=d.pointB),t.beginPath(),t.arc(p.x,p.y,10,0,2*Math.PI),t.closePath(),t.stroke()}t.setLineDash([]),t.translate(-.5,-.5)}null!==e.selectStart&&(t.translate(.5,.5),t.lineWidth=1,t.strokeStyle="rgba(255,165,0,0.6)",t.fillStyle="rgba(255,165,0,0.1)",n=e.selectBounds,t.beginPath(),t.rect(Math.floor(n.min.x),Math.floor(n.min.y),Math.floor(n.max.x-n.min.x),Math.floor(n.max.y-n.min.y)),
t.closePath(),t.stroke(),t.fill(),t.translate(-.5,-.5)),r.hasBounds&&t.setTransform(1,0,0,1,0,0)};var n=function(e,t){var n=document.createElement("canvas");return n.width=e,n.height=t,n.oncontextmenu=function(){return!1},n.onselectstart=function(){return!1},n},d=function(e){var t=e.getContext("2d"),n=window.devicePixelRatio||1,o=t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1;return n/o},p=function(e,t){var n=e.textures[t];return n?n:(n=e.textures[t]=new Image,n.src=t,n)},f=function(e,t){var n=t;/(jpg|gif|png)$/.test(t)&&(n="url("+t+")"),e.canvas.style.background=n,e.canvas.style.backgroundSize="contain",e.currentBackground=t}}()},{"../body/Composite":2,"../collision/Grid":6,"../core/Common":14,"../core/Events":16,"../core/Mouse":19,"../geometry/Bounds":26,"../geometry/Vector":28}],32:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Bounds"),r=e("../body/Composite"),s=e("../core/Common"),a=e("../core/Events"),l=e("../geometry/Vector");
!function(){var e,t;"undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(function(){e(s.now())},1e3/60)},t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),o.create=function(e){s.warn("RenderPixi.create: Matter.RenderPixi is deprecated (see docs)");var t={controller:o,engine:null,element:null,frameRequestId:null,canvas:null,renderer:null,container:null,spriteContainer:null,pixiOptions:null,options:{width:800,height:600,background:"#fafafa",wireframeBackground:"#222",hasBounds:!1,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showBroadphase:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showShadows:!1}},n=s.extend(t,e),i=!n.options.wireframes&&"transparent"===n.options.background;return n.pixiOptions=n.pixiOptions||{
view:n.canvas,transparent:i,antialias:!0,backgroundColor:e.background},n.mouse=e.mouse,n.engine=e.engine,n.renderer=n.renderer||new PIXI.WebGLRenderer(n.options.width,n.options.height,n.pixiOptions),n.container=n.container||new PIXI.Container,n.spriteContainer=n.spriteContainer||new PIXI.Container,n.canvas=n.canvas||n.renderer.view,n.bounds=n.bounds||{min:{x:0,y:0},max:{x:n.options.width,y:n.options.height}},a.on(n.engine,"beforeUpdate",function(){o.clear(n)}),n.textures={},n.sprites={},n.primitives={},n.container.addChild(n.spriteContainer),s.isElement(n.element)?n.element.appendChild(n.canvas):s.warn('No "render.element" passed, "render.canvas" was not inserted into document.'),n.canvas.oncontextmenu=function(){return!1},n.canvas.onselectstart=function(){return!1},n},o.run=function(t){!function n(i){t.frameRequestId=e(n),o.world(t)}()},o.stop=function(e){t(e.frameRequestId)},o.clear=function(e){for(var t=e.container,n=e.spriteContainer;t.children[0];)t.removeChild(t.children[0]);for(;n.children[0];)n.removeChild(n.children[0]);
var o=e.sprites["bg-0"];e.textures={},e.sprites={},e.primitives={},e.sprites["bg-0"]=o,o&&t.addChildAt(o,0),e.container.addChild(e.spriteContainer),e.currentBackground=null,t.scale.set(1,1),t.position.set(0,0)},o.setBackground=function(e,t){if(e.currentBackground!==t){var n=t.indexOf&&t.indexOf("#")!==-1,o=e.sprites["bg-0"];if(n){var i=s.colorToNumber(t);e.renderer.backgroundColor=i,o&&e.container.removeChild(o)}else if(!o){var r=u(e,t);o=e.sprites["bg-0"]=new PIXI.Sprite(r),o.position.x=0,o.position.y=0,e.container.addChildAt(o,0)}e.currentBackground=t}},o.world=function(e){var t,n=e.engine,s=n.world,a=e.renderer,c=e.container,u=e.options,d=r.allBodies(s),p=r.allConstraints(s),f=[];u.wireframes?o.setBackground(e,u.wireframeBackground):o.setBackground(e,u.background);var m=e.bounds.max.x-e.bounds.min.x,v=e.bounds.max.y-e.bounds.min.y,y=m/e.options.width,g=v/e.options.height;if(u.hasBounds){for(t=0;t<d.length;t++){var x=d[t];x.render.sprite.visible=i.overlaps(x.bounds,e.bounds)}for(t=0;t<p.length;t++){
var h=p[t],b=h.bodyA,w=h.bodyB,S=h.pointA,C=h.pointB;b&&(S=l.add(b.position,h.pointA)),w&&(C=l.add(w.position,h.pointB)),S&&C&&(i.contains(e.bounds,S)||i.contains(e.bounds,C))&&f.push(h)}c.scale.set(1/y,1/g),c.position.set(-e.bounds.min.x*(1/y),-e.bounds.min.y*(1/g))}else f=p;for(t=0;t<d.length;t++)o.body(e,d[t]);for(t=0;t<f.length;t++)o.constraint(e,f[t]);a.render(c)},o.constraint=function(e,t){var n=(e.engine,t.bodyA),o=t.bodyB,i=t.pointA,r=t.pointB,a=e.container,l=t.render,c="c-"+t.id,u=e.primitives[c];return u||(u=e.primitives[c]=new PIXI.Graphics),l.visible&&t.pointA&&t.pointB?(s.indexOf(a.children,u)===-1&&a.addChild(u),u.clear(),u.beginFill(0,0),u.lineStyle(l.lineWidth,s.colorToNumber(l.strokeStyle),1),n?u.moveTo(n.position.x+i.x,n.position.y+i.y):u.moveTo(i.x,i.y),o?u.lineTo(o.position.x+r.x,o.position.y+r.y):u.lineTo(r.x,r.y),void u.endFill()):void u.clear()},o.body=function(e,t){var o=(e.engine,t.render);if(o.visible)if(o.sprite&&o.sprite.texture){var i="b-"+t.id,r=e.sprites[i],a=e.spriteContainer;
r||(r=e.sprites[i]=n(e,t)),s.indexOf(a.children,r)===-1&&a.addChild(r),r.position.x=t.position.x,r.position.y=t.position.y,r.rotation=t.angle,r.scale.x=o.sprite.xScale||1,r.scale.y=o.sprite.yScale||1}else{var l="b-"+t.id,u=e.primitives[l],d=e.container;u||(u=e.primitives[l]=c(e,t),u.initialAngle=t.angle),s.indexOf(d.children,u)===-1&&d.addChild(u),u.position.x=t.position.x,u.position.y=t.position.y,u.rotation=t.angle-u.initialAngle}};var n=function(e,t){var n=t.render,o=n.sprite.texture,i=u(e,o),r=new PIXI.Sprite(i);return r.anchor.x=t.render.sprite.xOffset,r.anchor.y=t.render.sprite.yOffset,r},c=function(e,t){var n,o=t.render,i=e.options,r=new PIXI.Graphics,a=s.colorToNumber(o.fillStyle),l=s.colorToNumber(o.strokeStyle),c=s.colorToNumber(o.strokeStyle),u=s.colorToNumber("#bbb"),d=s.colorToNumber("#CD5C5C");r.clear();for(var p=t.parts.length>1?1:0;p<t.parts.length;p++){n=t.parts[p],i.wireframes?(r.beginFill(0,0),r.lineStyle(1,u,1)):(r.beginFill(a,1),r.lineStyle(o.lineWidth,l,1)),r.moveTo(n.vertices[0].x-t.position.x,n.vertices[0].y-t.position.y);
for(var f=1;f<n.vertices.length;f++)r.lineTo(n.vertices[f].x-t.position.x,n.vertices[f].y-t.position.y);r.lineTo(n.vertices[0].x-t.position.x,n.vertices[0].y-t.position.y),r.endFill(),(i.showAngleIndicator||i.showAxes)&&(r.beginFill(0,0),i.wireframes?r.lineStyle(1,d,1):r.lineStyle(1,c),r.moveTo(n.position.x-t.position.x,n.position.y-t.position.y),r.lineTo((n.vertices[0].x+n.vertices[n.vertices.length-1].x)/2-t.position.x,(n.vertices[0].y+n.vertices[n.vertices.length-1].y)/2-t.position.y),r.endFill())}return r},u=function(e,t){var n=e.textures[t];return n||(n=e.textures[t]=PIXI.Texture.fromImage(t)),n}}()},{"../body/Composite":2,"../core/Common":14,"../core/Events":16,"../geometry/Bounds":26,"../geometry/Vector":28}]},{},[30])(30)});

View File

@@ -1,417 +0,0 @@
// randomColor by David Merfield under the CC0 license
// https://github.com/davidmerfield/randomColor/
(function(root, factory) {
// Support CommonJS
if (typeof exports === "object") {
var randomColor = factory();
// Support NodeJS & Component, which allow module.exports to be a function
if (typeof module === "object" && module && module.exports) {
exports = module.exports = randomColor;
}
// Support CommonJS 1.1.1 spec
exports.randomColor = randomColor;
// Support AMD
} else if (typeof define === "function" && define.amd) {
define([], factory);
// Support vanilla script loading
} else {
root.randomColor = factory();
}
})(this, function() {
// Seed to get repeatable colors
var seed = null;
// Shared color dictionary
var colorDictionary = {};
// Populate the color dictionary
loadColorBounds();
var randomColor = function(options) {
options = options || {};
// Check if there is a seed and ensure it's an
// integer. Otherwise, reset the seed value.
if (options.seed !== undefined && options.seed !== null && options.seed === parseInt(options.seed, 10)) {
seed = options.seed;
// A string was passed as a seed
} else if (typeof options.seed === "string") {
seed = stringToInteger(options.seed);
// Something was passed as a seed but it wasn't an integer or string
} else if (options.seed !== undefined && options.seed !== null) {
throw new TypeError("The seed value must be an integer or string");
// No seed, reset the value outside.
} else {
seed = null;
}
var H, S, B;
// Check if we need to generate multiple colors
if (options.count !== null && options.count !== undefined) {
var totalColors = options.count,
colors = [];
options.count = null;
while (totalColors > colors.length) {
// Since we're generating multiple colors,
// incremement the seed. Otherwise we'd just
// generate the same color each time...
if (seed && options.seed) options.seed += 1;
colors.push(randomColor(options));
}
options.count = totalColors;
return colors;
}
// First we pick a hue (H)
H = pickHue(options);
// Then use H to determine saturation (S)
S = pickSaturation(H, options);
// Then use S and H to determine brightness (B).
B = pickBrightness(H, S, options);
// Then we return the HSB color in the desired format
return setFormat([H, S, B], options);
};
function pickHue(options) {
var hueRange = getHueRange(options.hue),
hue = randomWithin(hueRange);
// Instead of storing red as two seperate ranges,
// we group them, using negative numbers
if (hue < 0) {
hue = 360 + hue;
}
return hue;
}
function pickSaturation(hue, options) {
if (options.hue === "monochrome") {
return 0;
}
if (options.luminosity === "random") {
return randomWithin([0, 100]);
}
var saturationRange = getSaturationRange(hue);
var sMin = saturationRange[0],
sMax = saturationRange[1];
switch (options.luminosity) {
case "bright":
sMin = 55;
break;
case "dark":
sMin = sMax - 10;
break;
case "light":
sMax = 55;
break;
}
return randomWithin([sMin, sMax]);
}
function pickBrightness(H, S, options) {
var bMin = getMinimumBrightness(H, S),
bMax = 100;
switch (options.luminosity) {
case "dark":
bMax = bMin + 20;
break;
case "light":
bMin = (bMax + bMin) / 2;
break;
case "random":
bMin = 0;
bMax = 100;
break;
}
return randomWithin([bMin, bMax]);
}
function setFormat(hsv, options) {
switch (options.format) {
case "hsvArray":
return hsv;
case "hslArray":
return HSVtoHSL(hsv);
case "hsl":
var hsl = HSVtoHSL(hsv);
return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)";
case "hsla":
var hslColor = HSVtoHSL(hsv);
var alpha = options.alpha || Math.random();
return "hsla(" + hslColor[0] + ", " + hslColor[1] + "%, " + hslColor[2] + "%, " + alpha + ")";
case "rgbArray":
return HSVtoRGB(hsv);
case "rgb":
var rgb = HSVtoRGB(hsv);
return "rgb(" + rgb.join(", ") + ")";
case "rgba":
var rgbColor = HSVtoRGB(hsv);
var alpha = options.alpha || Math.random();
return "rgba(" + rgbColor.join(", ") + ", " + alpha + ")";
default:
return HSVtoHex(hsv);
}
}
function getMinimumBrightness(H, S) {
var lowerBounds = getColorInfo(H).lowerBounds;
for (var i = 0; i < lowerBounds.length - 1; i++) {
var s1 = lowerBounds[i][0],
v1 = lowerBounds[i][1];
var s2 = lowerBounds[i + 1][0],
v2 = lowerBounds[i + 1][1];
if (S >= s1 && S <= s2) {
var m = (v2 - v1) / (s2 - s1),
b = v1 - m * s1;
return m * S + b;
}
}
return 0;
}
function getHueRange(colorInput) {
if (typeof parseInt(colorInput) === "number") {
var number = parseInt(colorInput);
if (number < 360 && number > 0) {
return [number, number];
}
}
if (typeof colorInput === "string") {
if (colorDictionary[colorInput]) {
var color = colorDictionary[colorInput];
if (color.hueRange) {
return color.hueRange;
}
} else if (colorInput.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)) {
var hue = HexToHSB(colorInput)[0];
return [hue, hue];
}
}
return [0, 360];
}
function getSaturationRange(hue) {
return getColorInfo(hue).saturationRange;
}
function getColorInfo(hue) {
// Maps red colors to make picking hue easier
if (hue >= 334 && hue <= 360) {
hue -= 360;
}
for (var colorName in colorDictionary) {
var color = colorDictionary[colorName];
if (color.hueRange && hue >= color.hueRange[0] && hue <= color.hueRange[1]) {
return colorDictionary[colorName];
}
}
return "Color not found";
}
function randomWithin(range) {
if (seed === null) {
return Math.floor(range[0] + Math.random() * (range[1] + 1 - range[0]));
} else {
//Seeded random algorithm from http://indiegamr.com/generate-repeatable-random-numbers-in-js/
var max = range[1] || 1;
var min = range[0] || 0;
seed = (seed * 9301 + 49297) % 233280;
var rnd = seed / 233280.0;
return Math.floor(min + rnd * (max - min));
}
}
function HSVtoHex(hsv) {
var rgb = HSVtoRGB(hsv);
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
var hex = "#" + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
return hex;
}
function defineColor(name, hueRange, lowerBounds) {
var sMin = lowerBounds[0][0],
sMax = lowerBounds[lowerBounds.length - 1][0],
bMin = lowerBounds[lowerBounds.length - 1][1],
bMax = lowerBounds[0][1];
colorDictionary[name] = {
hueRange: hueRange,
lowerBounds: lowerBounds,
saturationRange: [sMin, sMax],
brightnessRange: [bMin, bMax]
};
}
function loadColorBounds() {
defineColor("monochrome", null, [[0, 0], [100, 0]]);
defineColor("red", [-26, 18], [[20, 100], [30, 92], [40, 89], [50, 85], [60, 78], [70, 70], [80, 60], [90, 55], [100, 50]]);
defineColor("orange", [19, 46], [[20, 100], [30, 93], [40, 88], [50, 86], [60, 85], [70, 70], [100, 70]]);
defineColor("yellow", [47, 62], [[25, 100], [40, 94], [50, 89], [60, 86], [70, 84], [80, 82], [90, 80], [100, 75]]);
defineColor("green", [63, 178], [[30, 100], [40, 90], [50, 85], [60, 81], [70, 74], [80, 64], [90, 50], [100, 40]]);
defineColor("blue", [179, 257], [[20, 100], [30, 86], [40, 80], [50, 74], [60, 60], [70, 52], [80, 44], [90, 39], [100, 35]]);
defineColor("purple", [258, 282], [[20, 100], [30, 87], [40, 79], [50, 70], [60, 65], [70, 59], [80, 52], [90, 45], [100, 42]]);
defineColor("pink", [283, 334], [[20, 100], [30, 90], [40, 86], [60, 84], [80, 80], [90, 75], [100, 73]]);
}
function HSVtoRGB(hsv) {
// this doesn't work for the values of 0 and 360
// here's the hacky fix
var h = hsv[0];
if (h === 0) {
h = 1;
}
if (h === 360) {
h = 359;
}
// Rebase the h,s,v values
h = h / 360;
var s = hsv[1] / 100,
v = hsv[2] / 100;
var h_i = Math.floor(h * 6),
f = h * 6 - h_i,
p = v * (1 - s),
q = v * (1 - f * s),
t = v * (1 - (1 - f) * s),
r = 256,
g = 256,
b = 256;
switch (h_i) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
var result = [Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)];
return result;
}
function HexToHSB(hex) {
hex = hex.replace(/^#/, "");
hex = hex.length === 3 ? hex.replace(/(.)/g, "$1$1") : hex;
var red = parseInt(hex.substr(0, 2), 16) / 255,
green = parseInt(hex.substr(2, 2), 16) / 255,
blue = parseInt(hex.substr(4, 2), 16) / 255;
var cMax = Math.max(red, green, blue),
delta = cMax - Math.min(red, green, blue),
saturation = cMax ? delta / cMax : 0;
switch (cMax) {
case red:
return [60 * (((green - blue) / delta) % 6) || 0, saturation, cMax];
case green:
return [60 * ((blue - red) / delta + 2) || 0, saturation, cMax];
case blue:
return [60 * ((red - green) / delta + 4) || 0, saturation, cMax];
}
}
function HSVtoHSL(hsv) {
var h = hsv[0],
s = hsv[1] / 100,
v = hsv[2] / 100,
k = (2 - s) * v;
return [h, Math.round(s * v / (k < 1 ? k : 2 - k) * 10000) / 100, k / 2 * 100];
}
function stringToInteger(string) {
var total = 0;
for (var i = 0; i !== string.length; i++) {
if (total >= Number.MAX_SAFE_INTEGER) break;
total += string.charCodeAt(i);
}
return total;
}
return randomColor;
});

5
js/lib/stats.min.js vendored
View File

@@ -1,5 +0,0 @@
// stats.js - http://github.com/mrdoob/stats.js
(function(f,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"===typeof define&&define.amd?define(e):f.Stats=e()})(this,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;d<c.children.length;d++)c.children[d].style.display=d===a?"block":"none";l=a}var l=0,c=document.createElement("div");c.style.cssText="position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";c.addEventListener("click",function(a){a.preventDefault();
u(++l%c.children.length)},!1);var k=(performance||Date).now(),g=k,a=0,r=e(new f.Panel("FPS","#0ff","#002")),h=e(new f.Panel("MS","#0f0","#020"));if(self.performance&&self.performance.memory)var t=e(new f.Panel("MB","#f08","#201"));u(0);return{REVISION:16,dom:c,addPanel:e,showPanel:u,begin:function(){k=(performance||Date).now()},end:function(){a++;var c=(performance||Date).now();h.update(c-k,200);if(c>g+1E3&&(r.update(1E3*a/(c-g),100),g=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/
1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){k=this.end()},domElement:c,setMode:u}};f.Panel=function(e,f,l){var c=Infinity,k=0,g=Math.round,a=g(window.devicePixelRatio||1),r=80*a,h=48*a,t=3*a,v=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=h;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,h);b.fillStyle=f;b.fillText(e,t,v);
b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(h,w){c=Math.min(c,h);k=Math.max(k,h);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=f;b.fillText(g(h)+" "+e+" ("+g(c)+"-"+g(k)+")",t,v);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,g((1-h/w)*p))}}};return f});

View File

@@ -796,6 +796,7 @@ const mech = {
fieldUpgrades: [
() => {
mech.fieldMode = 0;
game.makeTextLog("<strong style='font-size:30px;'>Field Emitter</strong><br> (right click or spacebar)<p>lets you pick up and throw objects<br>shields you from damage</p>", 1200);
mech.setHoldDefaults();
mech.hold = function () {
if (mech.isHolding) {
@@ -817,7 +818,7 @@ const mech = {
},
() => {
mech.fieldMode = 1;
game.makeTextLog("<strong style='font-size:30px;'>Time Dilation Field</strong><br> (right mouse or space bar)<p> field emitter slows objects in range</p>", 1000);
game.makeTextLog("<strong style='font-size:30px;'>Time Dilation Field</strong><br> (right mouse or space bar)<p> field slows objects in range<br> field does <span style='color:#a00;'>not</span> shield player</p>", 1200);
mech.setHoldDefaults();
mech.fieldArc = 1; //field covers full 360 degrees
mech.calculateFieldThreshold();
@@ -859,6 +860,7 @@ const mech = {
slow(mob);
slow(body);
slow(bullet);
slow(powerUp);
} else {
mech.fieldCDcycle = game.cycle + 120;
}
@@ -872,7 +874,7 @@ const mech = {
},
() => {
mech.fieldMode = 2;
game.makeTextLog("<strong style='font-size:30px;'>Kinetic Energy Field</strong><br> (right mouse or space bar)<p> field emitter does damage on contact<br> blocks are thrown at a higher velocity</p>", 1000);
game.makeTextLog("<strong style='font-size:30px;'>Kinetic Energy Field</strong><br> (right mouse or space bar)<p> field does damage on contact<br> blocks are thrown at a higher velocity</p>", 1200);
mech.setHoldDefaults();
//throw quicker and harder
mech.throwChargeRate = 3; //0.5
@@ -922,10 +924,12 @@ const mech = {
},
() => {
mech.fieldMode = 3;
game.makeTextLog("<strong style='font-size:30px;'>Negative Mass Field</strong><br> (right mouse or space bar)<p> field emitter nullifies gravity around player<br> field emitter holds more massive objects</p>", 1000);
game.makeTextLog("<strong style='font-size:30px;'>Negative Mass Field</strong><br> (right mouse or space bar)<p> nullifies gravity around player<br> can hold more massive objects<br> field does <span style='color:#a00;'>not</span> shield player</p>", 1200);
mech.setHoldDefaults();
mech.holdingMassScale = 0.05; //can hold heavier blocks
mech.fieldArc = 1; //field covers full 360 degrees
// mech.fieldArc = 1; //field covers full 360 degrees
mech.grabRange = 150;
mech.fieldArc = 0.1;
mech.calculateFieldThreshold();
mech.hold = function () {
@@ -969,6 +973,9 @@ const mech = {
ctx.fill();
ctx.globalCompositeOperation = "source-over";
mech.drawField();
mech.pushMobs();
} else {
//trigger cool down
mech.fieldCDcycle = game.cycle + 120;
@@ -983,7 +990,7 @@ const mech = {
},
() => {
mech.fieldMode = 4;
game.makeTextLog("<strong style='font-size:30px;'>Zero-Point Energy Field</strong><br> (right mouse or space bar) <p>improved energy regeneration<br> field emitter surrounds player</p>", 1000);
game.makeTextLog("<strong style='font-size:30px;'>Zero-Point Energy Field</strong><br> (right mouse or space bar) <p>improved energy regeneration<br> field emitter shield surrounds player</p>", 1200);
mech.setHoldDefaults();
mech.fieldRegen = 0.01; //0.0015
mech.fieldArc = 1; //field covers full 360 degrees
@@ -1011,14 +1018,14 @@ const mech = {
},
() => {
mech.fieldMode = 5;
game.makeTextLog("<strong style='font-size:30px;'>Nano-Scale Manufacturing</strong><br> (passive effect) <p>when energy is full, build a drone using 20 energy</p>", 1000);
game.makeTextLog("<strong style='font-size:30px;'>Nano-Scale Manufacturing</strong><br> (passive effect) <p>excess field energy builds drones<br> field does <span style='color:#a00;'>not</span> shield player</p>", 1200);
mech.setHoldDefaults();
mech.grabRange = 160;
mech.fieldArc = 0.11;
mech.fieldArc = 0.11; //0.2 is normal
// mech.fieldRegen = 0.0008 //0.0015;
mech.hold = function () {
if (mech.fieldMeter === 1) {
mech.fieldMeter -= 0.2;
mech.fieldMeter -= 0.21;
b.guns[12].fire() //spawn drone
}
@@ -1027,9 +1034,7 @@ const mech = {
mech.holding();
mech.throw();
} else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed
// mech.drawField();
//draw field
const range = this.grabRange - 20;
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, range, this.angle - Math.PI * this.fieldArc, this.angle + Math.PI * this.fieldArc, false);
@@ -1055,9 +1060,10 @@ const mech = {
},
() => {
mech.fieldMode = 6;
game.makeTextLog("<strong style='font-size:30px;'>Metamaterial Refractive Optics</strong><br> (right mouse or space bar) <p>localized invisibility field</p>", 1000);
game.makeTextLog("<strong style='font-size:30px;'>Metamaterial Refractive Optics</strong><br> (right mouse or space bar) <p>localized invisibility field</p>", 1200);
mech.setHoldDefaults();
// mech.grabRange = 100;
mech.grabRange = 200;
mech.fieldArc = 0.1; //0.2 is normal
// mech.fieldArc = 1; //field covers full 360 degrees
mech.calculateFieldThreshold();
@@ -1069,21 +1075,23 @@ const mech = {
mech.holding();
mech.throw();
} else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < game.cycle) {
const DRAIN = 0.0015 //mech.fieldRegen = 0.0015
const DRAIN = 0.001 //mech.fieldRegen = 0.0015
if (mech.fieldMeter > DRAIN) {
mech.fieldMeter -= DRAIN;
mech.isStealth = true //isStealth is checked in mob foundPlayer()
//draw stealth field
ctx.fillStyle = "rgba(255,255,255,0.5)";
ctx.fillStyle = "rgba(255,255,255,0.4)";
ctx.fill();
ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y + 25, mech.grabRange, 0, 2 * Math.PI);
ctx.arc(mech.pos.x, mech.pos.y, mech.grabRange - 20, 0, 2 * Math.PI);
ctx.globalCompositeOperation = "destination-in"; //in or atop
ctx.fill();
ctx.globalCompositeOperation = "source-over";
mech.drawField();
mech.grabPowerUp();
mech.pushMobs();
mech.lookForPickUp();
} else {
mech.fieldCDcycle = game.cycle + 120;
@@ -1095,7 +1103,81 @@ const mech = {
}
mech.drawFieldMeter()
}
}
},
() => {
mech.fieldMode = 7;
game.makeTextLog("<strong style='font-size:30px;'>Thermal Radiation Field</strong><br> (right mouse or space bar) <p>field damages all targets within range, <span style='color:#a00;'>including player</span><br>field does <span style='color:#a00;'>not</span> shield player</p>", 1200);
// game.makeTextLog("<strong style='font-size:30px;'>Thermal Radiation Field</strong><br> (right mouse or space bar) <p>field damages and pushes all targets within range<br> <span style='color:#a00;'>field damages player</span><br>field does <span style='color:#a00;'>not</span> shield player</p>", 1200);
mech.setHoldDefaults();
mech.grabRange = 160;
mech.fieldArc = 0.11; //0.2 is normal
mech.rangeSmoothing = 0
// mech.fieldRegen = 0.0008 //0.0015;
mech.hold = function () {
if (mech.isHolding) {
mech.drawHold(mech.holdingTarget);
mech.holding();
mech.throw();
} else if ((keys[32] || game.mouseDownRight && mech.fieldCDcycle < game.cycle)) { //not hold but field button is pressed
mech.grabPowerUp();
mech.lookForPickUp();
//draw grab field
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, this.grabRange - 20, this.angle - Math.PI * this.fieldArc, this.angle + Math.PI * this.fieldArc, false);
let EYE_RADIUS = 13;
ctx.lineTo(mech.pos.x + EYE_RADIUS * Math.cos(this.angle), mech.pos.y + EYE_RADIUS * Math.sin(this.angle));
if (this.holdingTarget) {
ctx.fillStyle = "rgba(150,150,150," + (0.05 + 0.1 * Math.random()) + ")";
} else {
ctx.fillStyle = "rgba(150,150,150," + (0.15 + 0.15 * Math.random()) + ")";
}
ctx.fill();
if (mech.health > 0.1) {
const DRAIN = 0.0011 //mech.fieldRegen = 0.0015
if (mech.fieldMeter > DRAIN) {
mech.fieldMeter -= DRAIN;
mech.damage(0.0001)
//draw damage field
mech.rangeSmoothing = mech.rangeSmoothing * 0.997 + (1350 + 60 * Math.cos(game.cycle / 20)) * 0.003
let gradient = ctx.createRadialGradient(this.pos.x, this.pos.y, 0, this.pos.x, this.pos.y, mech.rangeSmoothing);
gradient.addColorStop(0, 'rgba(255,255,255,0)');
gradient.addColorStop(1, 'rgba(255,0,50,0.5)');
// gradient.addColorStop(1, 'rgba(255,0,0,0.05)');
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, mech.rangeSmoothing, 0, 2 * Math.PI);
ctx.fillStyle = gradient //rgba(255,0,0,0.2)
ctx.fill();
//damage and gently push mobs in range of field
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive) {
sub = Matter.Vector.sub(this.pos, mob[i].position);
dist = Matter.Vector.magnitude(sub);
if (dist < mech.rangeSmoothing) {
mob[i].damage(0.01);
mob[i].locatePlayer();
// mech.fieldMeter -= DRAIN * 0.1; //extra drain for each additional target
// push
mob[i].force = Matter.Vector.mult(Matter.Vector.normalise(sub), -0.0005 * mob[i].mass) //gently push mobs back
}
}
}
} else {
mech.fieldCDcycle = game.cycle + 120;
}
}
} else if (mech.holdingTarget && mech.fireCDcycle < game.cycle) { //holding, but field button is released
mech.rangeSmoothing = 0
mech.pickUp();
} else {
mech.rangeSmoothing = 0
mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
}
mech.drawFieldMeter()
}
},
],
drawLeg(stroke) {
// if (game.mouseInGame.x > this.pos.x) {

View File

@@ -117,14 +117,14 @@ const powerUps = {
if (b.inventory.length === 1) {
game.makeTextLog(
// "<div style='font-size:120%;' >new gun: " + b.guns[newGun].name + "</div><span class = 'box'>E</span> / <span class = 'box'>Q</span>",
"<div style='font-size:120%;' >new gun: " + b.guns[newGun].name + "</div> <br> Use <strong>Q</strong>, <strong>E</strong>, or <strong>mouse wheel</strong> to change weapons.",
360
"<div style='font-size:150%;'><strong>" + b.guns[newGun].name + "</strong></div> (left click) <br> <p style='font-size:90%;'><strong>Q</strong>, <strong>E</strong>, and <strong>mouse wheel</strong> change weapons</p>",
500
);
} else {
game.makeTextLog(
// "<div style='font-size:120%;' >new gun: " + b.guns[newGun].name + "</div><span class = 'box'>E</span> / <span class = 'box'>Q</span>",
"<div style='font-size:120%;' >new gun: " + b.guns[newGun].name + "</div>",
360
"<div style='font-size:150%;'><strong>" + b.guns[newGun].name + "</strong></div> (left click)",
400
);
}
b.guns[newGun].have = true;

View File

@@ -793,7 +793,7 @@ const spawn = {
me.collisionFilter.mask = 0x001100; //move through walls
spawn.shield(me, x, y);
me.onDeath = function () {
if (Math.random() < 0.2 || mech.fieldMode === 0) powerUps.spawn(this.position.x, this.position.y, "field"); //bosss spawn field upgrades
if (Math.random() < 0.35 || mech.fieldMode === 0) powerUps.spawn(this.position.x, this.position.y, "field"); //bosss spawn field upgrades
};
me.do = function () {
this.healthBar();
@@ -844,7 +844,7 @@ const spawn = {
Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(game.levelsCleared)); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y);
me.onDeath = function () {
if (Math.random() < 0.2 || mech.fieldMode === 0) powerUps.spawn(this.position.x, this.position.y, "field"); //boss spawns field upgrades
if (Math.random() < 0.35 || mech.fieldMode === 0) powerUps.spawn(this.position.x, this.position.y, "field"); //boss spawns field upgrades
};
me.do = function () {
this.healthBar();
@@ -944,7 +944,7 @@ const spawn = {
spawn.shield(me, x, y);
if (Math.random() < Math.min((game.levelsCleared - 1) * 0.1, 0.7)) spawn.shield(me, x, y);
me.onDeath = function () {
if (Math.random() < 0.2 || mech.fieldMode === 0) powerUps.spawn(this.position.x, this.position.y, "field"); //boss spawns field upgrades
if (Math.random() < 0.35 || mech.fieldMode === 0) powerUps.spawn(this.position.x, this.position.y, "field"); //boss spawns field upgrades
};
me.do = function () {
this.healthBar();
@@ -988,7 +988,7 @@ const spawn = {
if (Math.random() < Math.min((game.levelsCleared - 1) * 0.1, 0.7)) spawn.shield(me, x, y);
me.onDeath = function () {
if (Math.random() < 0.2 || mech.fieldMode === 0) powerUps.spawn(this.position.x, this.position.y, "field"); //boss spawns field upgrades
if (Math.random() < 0.35 || mech.fieldMode === 0) powerUps.spawn(this.position.x, this.position.y, "field"); //boss spawns field upgrades
this.removeCons(); //remove constraint
};
me.do = function () {
@@ -1649,7 +1649,7 @@ const spawn = {
propsHoist: {
inertia: Infinity, //prevents rotation
frictionAir: 0.001,
friction: 0,
friction: 0.0001,
frictionStatic: 0,
restitution: 0,
isNotHoldable: true