diff --git a/index.html b/index.html index c764dfa..5767650 100644 --- a/index.html +++ b/index.html @@ -404,7 +404,7 @@ - + diff --git a/js/backup.js b/js/backup.js deleted file mode 100644 index 586a585..0000000 --- a/js/backup.js +++ /dev/null @@ -1,1449 +0,0 @@ -//global player variables -let player, jumpSensor, playerBody, playerHead, headSensor; - -// player Object Prototype ********************************************* -mech = { - -} - -const mech = { - spawn: function () { - //player as a series of vertices - let vector = Vertices.fromPath('0 40 0 115 20 130 30 130 50 115 50 40'); - playerBody = Matter.Bodies.fromVertices(0, 0, vector); - //this sensor check if the player is on the ground to enable jumping - jumpSensor = Bodies.rectangle(0, 46, 36, 6, { - sleepThreshold: 99999999999, - isSensor: true, - }); - //this part of the player lowers on crouch - vector = Vertices.fromPath('0 -66 18 -82 0 -37 50 -37 50 -66 32 -82'); - playerHead = Matter.Bodies.fromVertices(0, -55, vector); - //a part of player that senses if the player's head is empty and can return after crouching - headSensor = Bodies.rectangle(0, -57, 48, 45, { - sleepThreshold: 99999999999, - isSensor: true, - }); - player = Body.create({ //combine jumpSensor and playerBody - parts: [playerBody, playerHead, jumpSensor, headSensor], - inertia: Infinity, //prevents player rotation - friction: 0.002, - //frictionStatic: 0.5, - restitution: 0.3, - sleepThreshold: Infinity, - collisionFilter: { - group: 0, - category: 0x001000, - mask: 0x010001 - }, - }); - //Matter.Body.setPosition(player, mech.spawnPos); - //Matter.Body.setVelocity(player, mech.spawnVel); - Matter.Body.setMass(player, mech.mass); - World.add(engine.world, [player]); - //holding body constraint - const holdConstraint = Constraint.create({ - pointA: { - x: 0, - y: 0 - }, - //setting constaint to jump sensor because it has to be on something until the player picks up things - bodyB: jumpSensor, - stiffness: 0.4, - }); - World.add(engine.world, holdConstraint); - }, - width: 50, - radius: 30, - fillColor: '#fff', - fillColorDark: '#ddd', - fireCDcycle: 0, - gun: 'machine', //current gun in use - gunOptions: { //keeps track of keys that switch guns (used in the onkeypress event) - 49: 'machine', - 50: 'needle', - 51: 'shot', - 52: 'rail', - 53: 'cannon', - 54: 'super', - 55: 'lob', - // 55: 'spiritBomb', - // 56: 'experimental' - } - height: 42, - yOffWhen: { - crouch: 22, - stand: 49, - jump: 70 - }, - yOff: 70, - yOffGoal: 70, - onGround: false, //checks if on ground or in air - onBody: { - id: 0, - index: 0, - type: "map", - action: '' - }, - numTouching = 0, - crouch = false, - isHeadClear = true, - spawnPos = { - x: 0, - y: 0 - }, - spawnVel = { - x: 0, - y: 0 - }, - pos = { - x: this.spawnPos.x, - y: this.spawnPos.y - }, - setPosToSpawn = function (xPos, yPos) { - this.spawnPos.x = xPos - this.spawnPos.y = yPos - this.pos.x = xPos; - this.pos.y = yPos; - this.Vx = this.spawnVel.x; - this.Vy = this.spawnVel.y; - Matter.Body.setPosition(player, this.spawnPos); - Matter.Body.setVelocity(player, this.spawnVel); - }; - this.Sy = this.pos.y; //adds a smoothing effect to vertical only - this.Vx = 0; - this.Vy = 0; - this.VxMax = 7; - this.mass = 5; - this.Fx = 0.004 * this.mass; //run Force on ground - this.FxAir = 0.0006 * this.mass; //run Force in Air - this.Fy = -0.05 * this.mass; //jump Force - this.angle = 0; - this.walk_cycle = 0; - this.stepSize = 0; - this.flipLegs = -1; - this.hip = { - x: 12, - y: 24, - }; - this.knee = { - x: 0, - y: 0, - x2: 0, - y2: 0 - }; - this.foot = { - x: 0, - y: 0 - }; - this.legLength1 = 55; - this.legLength2 = 45; - this.canvasX = canvas.width / 2; - this.canvasY = canvas.height / 2; - this.transX = this.canvasX - this.pos.x; - this.transY = this.canvasX - this.pos.x; - this.mouse = { - x: canvas.width / 3, - y: canvas.height - }; - this.getMousePos = function (x, y) { - this.mouse.x = x; - this.mouse.y = y; - }; - this.testingMoveLook = function () { - //move - this.pos.x = player.position.x; - this.pos.y = playerBody.position.y - this.yOff; - this.Vx = player.velocity.x; - this.Vy = player.velocity.y; - //look - this.canvasX = canvas.width / 2 - this.canvasY = canvas.height / 2 - this.transX = this.canvasX - this.pos.x; - this.transY = this.canvasY - this.pos.y; - this.angle = Math.atan2(this.mouse.y - this.canvasY, this.mouse.x - this.canvasX); - } - - this.move = function () { - this.pos.x = player.position.x; - this.pos.y = playerBody.position.y - this.yOff; - this.Vx = player.velocity.x; - this.Vy = player.velocity.y; - }; - this.look = function () { - //set a max on mouse look - let mX = this.mouse.x; - if (mX > canvas.width * 0.8) { - mX = canvas.width * 0.8; - } else if (mX < canvas.width * 0.2) { - mX = canvas.width * 0.2; - } - let mY = this.mouse.y; - if (mY > canvas.height * 0.8) { - mY = canvas.height * 0.8; - } else if (mY < canvas.height * 0.2) { - mY = canvas.height * 0.2; - } - //set mouse look - this.canvasX = this.canvasX * 0.94 + (canvas.width - mX) * 0.06; - this.canvasY = this.canvasY * 0.94 + (canvas.height - mY) * 0.06; - - //set translate values - this.transX = this.canvasX - this.pos.x; - this.Sy = 0.99 * this.Sy + 0.01 * (this.pos.y); - //hard caps how behind y position tracking can get. - if (this.Sy - this.pos.y > canvas.height / 2) { - this.Sy = this.pos.y + canvas.height / 2; - } else if (this.Sy - this.pos.y < -canvas.height / 2) { - this.Sy = this.pos.y - canvas.height / 2; - } - this.transY = this.canvasY - this.Sy; //gradual y camera tracking - //this.transY = this.canvasY - this.pos.y; //normal y camera tracking - - //make player head angled towards mouse - //this.angle = Math.atan2(this.mouse.y - this.canvasY, this.mouse.x - this.canvasX); - this.angle = Math.atan2(this.mouse.y + (this.Sy - this.pos.y) * game.zoom - this.canvasY, this.mouse.x - this.canvasX); - }; - this.doCrouch = function () { - if (!this.crouch) { - this.crouch = true; - this.yOffGoal = this.yOffWhen.crouch; - Matter.Body.translate(playerHead, { - x: 0, - y: 40 - }) - } - } - this.undoCrouch = function () { - this.crouch = false; - this.yOffGoal = this.yOffWhen.stand; - Matter.Body.translate(playerHead, { - x: 0, - y: -40 - }) - } - this.enterAir = function () { - this.onGround = false; - player.frictionAir = 0.001; - if (this.isHeadClear) { - if (this.crouch) { - this.undoCrouch(); - } - this.yOffGoal = this.yOffWhen.jump; - }; - } - this.enterLand = function () { - this.onGround = true; - if (this.crouch) { - if (this.isHeadClear) { - this.undoCrouch(); - player.frictionAir = 0.12; - } else { - this.yOffGoal = this.yOffWhen.crouch; - player.frictionAir = 0.5; - } - } else { - this.yOffGoal = this.yOffWhen.stand; - player.frictionAir = 0.12; - } - }; - this.buttonCD_jump = 0; //cooldown for player buttons - this.keyMove = function () { - if (this.onGround) { //on ground ********************** - if (this.crouch) { //crouch - if (!(keys[40] || keys[83]) && this.isHeadClear) { //not pressing crouch anymore - this.undoCrouch(); - player.frictionAir = 0.12; - } - } else if (keys[40] || keys[83]) { //on ground && not crouched and pressing s or down - this.doCrouch(); - player.frictionAir = 0.5; - } else if ((keys[32] || keys[38] || keys[87]) && this.buttonCD_jump + 20 < game.cycle) { //jump - this.buttonCD_jump = game.cycle; //can't jump until 20 cycles pass - Matter.Body.setVelocity(player, { //zero player velocity for consistant jumps - x: player.velocity.x, - y: 0 - }); - player.force.y = this.Fy / game.delta; //jump force / delta so that force is the same on game slowdowns - } - //horizontal move on ground - if (keys[37] || keys[65]) { //left or a - if (player.velocity.x > -this.VxMax) { - player.force.x += -this.Fx / game.delta; - } - } else if (keys[39] || keys[68]) { //right or d - if (player.velocity.x < this.VxMax) { - player.force.x += this.Fx / game.delta; - } - } - - } else { // in air ********************************** - //check for short jumps - if (this.buttonCD_jump + 60 > game.cycle && //just pressed jump - !(keys[32] || keys[38] || keys[87]) && //but not pressing jump key - this.Vy < 0) { // and velocity is up - Matter.Body.setVelocity(player, { //reduce player velocity every cycle until not true - x: player.velocity.x, - y: player.velocity.y * 0.94 - }); - } - if (keys[37] || keys[65]) { // move player left / a - if (player.velocity.x > -this.VxMax + 2) { - player.force.x += -this.FxAir / game.delta; - } - } else if (keys[39] || keys[68]) { //move player right / d - if (player.velocity.x < this.VxMax - 2) { - player.force.x += this.FxAir / game.delta; - } - } - } - //smoothly move height towards height goal ************ - this.yOff = this.yOff * 0.85 + this.yOffGoal * 0.15 - }; - this.death = function () { - location.reload(); - //Matter.Body.setPosition(player, this.spawnPos); - //Matter.Body.setVelocity(player, this.spawnVel); - //this.dropBody(); - //game.zoom = 0; //zooms out all the way - //this.health = 1; - } - this.health = 1; - this.regen = function () { - if (this.health < 1 && game.cycle % 15 === 0) { - this.addHealth(0.01); - } - }; - this.drawHealth = function () { - if (this.health < 1) { - ctx.fillStyle = 'rgba(100, 100, 100, 0.5)'; - ctx.fillRect(this.pos.x - this.radius, this.pos.y - 50, 60, 10); - ctx.fillStyle = "#f00"; - ctx.fillRect(this.pos.x - this.radius, this.pos.y - 50, 60 * this.health, 10); - } - }; - this.addHealth = function (heal) { - this.health += heal; - if (this.health > 1) this.health = 1; - } - this.damage = function (dmg) { - this.health -= dmg; - if (this.health <= 0) { - this.death(); - } - } - this.deathCheck = function () { - if (this.pos.y > game.fallHeight) { // if player is 4000px deep reset to spawn Position and Velocity - this.death(); - } - }; - this.hitMob = function (i, dmg) { - this.damage(dmg); - playSound("dmg" + Math.floor(Math.random() * 4)); - //extra kick between player and mob - //this section would be better with forces but they don't work... - let angle = Math.atan2(player.position.y - mob[i].position.y, player.position.x - mob[i].position.x); - Matter.Body.setVelocity(player, { - x: player.velocity.x + 8 * Math.cos(angle), - y: player.velocity.y + 8 * Math.sin(angle) - }); - Matter.Body.setVelocity(mob[i], { - x: mob[i].velocity.x - 8 * Math.cos(angle), - y: mob[i].velocity.y - 8 * Math.sin(angle) - }); - } - - this.buttonCD = 0; //cooldown for player buttons - this.eaten = []; - this.eat = function () { - if (keys[81] && this.buttonCD < game.cycle) { - this.buttonCD = game.cycle + 5; - this.findClosestBody(); - let i = this.closest.index - if (this.closest.dist < 150) { - //draw eating - ctx.lineWidth = 10; - ctx.strokeStyle = '#5f9'; - ctx.beginPath(); - ctx.moveTo(this.pos.x + 15 * Math.cos(this.angle), this.pos.y + 15 * Math.sin(this.angle)); - ctx.lineTo(body[i].position.x, body[i].position.y); - ctx.stroke(); - //set to eaten - body[i].eaten = true; - //drop body - body[i].frictionAir = 0; - this.isHolding = false; - holdConstraint.bodyB = jumpSensor; //set on sensor to get the constraint on somethign else - //add to eaten - body[i].collisionFilter.category = 0x000000; - body[i].collisionFilter.mask = 0x000000; - //Matter.Body.setStatic(body[i], true) - Matter.Sleeping.set(body[i], true) - Matter.Body.scale(body[i], 0.5, 0.5) - Matter.Body.setVelocity(body[i], { - x: 0, - y: 0 - }); - Matter.Body.setAngularVelocity(body[i], 0.08) //(Math.random()*0.5-1)*0.1) - //Matter.World.remove(engine.world, body[i]); - //body.splice(i, 1); - this.eaten[this.eaten.length] = { - index: i, - cycle: game.cycle - } - } - } - //control behavior of eaten bodies - for (let j = 0; j < this.eaten.length; j++) { - const pos = { - x: this.pos.x + 60 * Math.cos((game.cycle + this.eaten[j].cycle) * 0.05), - y: this.pos.y + 30 * Math.sin((game.cycle + this.eaten[j].cycle) * 0.05), - } - Matter.Body.setPosition(body[this.eaten[j].index], pos); - //Matter.Body.setVelocity(body[this.eaten[j].index],{x:0, y:0}); - - } - - if (keys[69] && this.buttonCD < game.cycle && this.eaten.length) { - this.buttonCD = game.cycle + 5; - let i = this.eaten[this.eaten.length - 1].index; - body[i].eaten = false; - body[i].collisionFilter.category = 0x000001; - body[i].collisionFilter.mask = 0x000101; - Matter.Body.setVelocity(body[i], { - x: 0, - y: 0 - }); - //Matter.Body.setStatic(body[i], false) - Matter.Sleeping.set(body[i], false) - Matter.Body.scale(body[i], 2, 2); - Matter.Body.setPosition(body[i], { - x: this.pos.x + 20 * Math.cos(this.angle), - y: this.pos.y + 20 * Math.sin(this.angle) - }); - const impulse = 0.06 * body[i].mass; - const f = { - x: impulse * Math.cos(this.angle) / game.delta, - y: impulse * Math.sin(this.angle) / game.delta - } - body[i].force = f; - this.eaten.pop(); - } - }; - - this.holdKeyDown = 0; - this.keyHold = function () { //checks for holding/dropping/picking up bodies - if (this.isHolding) { - //give the constaint more length and less stiffness if it is pulled out of position - const Dx = body[this.holdingBody].position.x - holdConstraint.pointA.x; - const Dy = body[this.holdingBody].position.y - holdConstraint.pointA.y; - holdConstraint.length = Math.sqrt(Dx * Dx + Dy * Dy) * 0.95; - holdConstraint.stiffness = -0.01 * holdConstraint.length + 1; - if (holdConstraint.length > 90) this.dropBody(); //drop it if the constraint gets too long - holdConstraint.pointA = { //set constraint position - x: this.pos.x + 50 * Math.cos(this.angle), //just in front of player nose - y: this.pos.y + 50 * Math.sin(this.angle) - }; - if (keys[81]) { // q = rotate the body - body[this.holdingBody].torque = 0.05 * body[this.holdingBody].mass; - } - //look for dropping held body - if (this.buttonCD < game.cycle) { - if (keys[69]) { //if holding e drops - this.holdKeyDown++; - } else if (this.holdKeyDown && !keys[69]) { - this.dropBody(); //if you hold down e long enough the body is thrown - this.throwBody(); - } - } - } else if (keys[69]) { //when not holding e = pick up body - this.findClosestBody(); - if (this.closest.dist < 150) { //pick up if distance closer then 100*100 - this.isHolding = true; - this.holdKeyDown = 0; - this.buttonCD = game.cycle + 20; - this.holdingBody = this.closest.index; //set new body to be the holdingBody - //body[this.closest.index].isSensor = true; //sensor seems a bit inconsistant - //body[this.holdingBody].collisionFilter.group = -2; //don't collide with player - body[mech.holdingBody].collisionFilter.category = 0x000001; - body[mech.holdingBody].collisionFilter.mask = 0x000001; - body[this.holdingBody].frictionAir = 0.1; //makes the holding body less jittery - holdConstraint.bodyB = body[this.holdingBody]; - holdConstraint.length = 0; - holdConstraint.pointA = { - x: this.pos.x + 50 * Math.cos(this.angle), - y: this.pos.y + 50 * Math.sin(this.angle) - }; - } - } - }; - this.dropBody = function () { - let timer; //reset player collision - function resetPlayerCollision() { - timer = setTimeout(function () { - const dx = mech.pos.x - body[mech.holdingBody].position.x - const dy = mech.pos.y - body[mech.holdingBody].position.y - if (dx * dx + dy * dy > 15000) { - body[mech.holdingBody].collisionFilter.category = 0x000001; - body[mech.holdingBody].collisionFilter.mask = 0x001101; - //body[mech.holdingBody].collisionFilter.group = 2; //can collide with player - } else { - resetPlayerCollision(); - } - }, 100); - } - resetPlayerCollision(); - this.isHolding = false; - body[this.holdingBody].frictionAir = 0.01; - holdConstraint.bodyB = jumpSensor; //set on sensor to get the constaint on somethign else - }; - this.throwMax = 150; - this.throwBody = function () { - let throwMag = 0; - if (this.holdKeyDown > 20) { - if (this.holdKeyDown > this.throwMax) this.holdKeyDown = this.throwMax; - //scale fire with mass and with holdKeyDown time - throwMag = body[this.holdingBody].mass * this.holdKeyDown * 0.001; - } - body[this.holdingBody].force.x = throwMag * Math.cos(this.angle); - body[this.holdingBody].force.y = throwMag * Math.sin(this.angle); - }; - this.isHolding = false; - this.holdingBody = 0; - this.closest = { - dist: 1000, - index: 0 - }; - this.lookingAtMob = function (mob, threshold) { - //calculate a vector from mob to player and make it length 1 - const diff = Matter.Vector.normalise(Matter.Vector.sub(mob.position, player.position)); - const dir = { //make a vector for the player's direction of length 1 - x: Math.cos(mech.angle), - y: Math.sin(mech.angle) - } - //the dot prodcut of diff and dir will return how much over lap between the vectors - const dot = Matter.Vector.dot(dir, diff); - if (dot > threshold) { - return true; - } else { - return false; - } - } - this.lookingAt = function (i) { - //calculate a vector from mob to player and make it length 1 - const diff = Matter.Vector.normalise(Matter.Vector.sub(body[i].position, player.position)); - const dir = { //make a vector for the player's direction of length 1 - x: Math.cos(mech.angle), - y: Math.sin(mech.angle) - } - //the dot prodcut of diff and dir will return how much over lap between the vectors - const dot = Matter.Vector.dot(dir, diff); - //console.log(dot); - if (dot > 0.9) { - return true; - } else { - return false; - } - } - this.findClosestBody = function () { - let mag = 100000; - let index = 0; - for (let i = 0; i < body.length; i++) { - let isLooking = this.lookingAt(i); - let collisionM = Matter.Query.ray(map, body[i].position, this.pos) - //let collisionB = Matter.Query.ray(body, body[i].position, this.pos) - if (collisionM.length) isLooking = false; - //magnitude of the distance between the poistion vectors of player and each body - const dist = Matter.Vector.magnitude(Matter.Vector.sub(body[i].position, this.pos)); - if (dist < mag && body[i].mass < player.mass && isLooking && !body[i].eaten) { - mag = dist; - index = i; - } - } - this.closest.dist = mag; - this.closest.index = index; - }; - this.exit = function () { - game.nextLevel(); - window.location.reload(false); - } - this.standingOnActions = function () { - if (this.onBody.type === 'map') { - var that = this; //brings the thisness of the player deeper into the actions object - var actions = { - 'death': function () { - that.death(); - }, - 'exit': function () { - that.exit(); - }, - '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 - }); - }, - 'launch': function () { - //that.dropBody(); - Matter.Body.setVelocity(player, { //zero player velocity for consistant jumps - x: player.velocity.x, - y: 0 - }); - player.force.y = -0.1 * that.mass / game.delta; - }, - 'default': function () {} - }; - (actions[map[this.onBody.index].action] || actions['default'])(); - } - } - this.drawLeg = function (stroke) { - ctx.save(); - ctx.scale(this.flipLegs, 1); //leg lines - ctx.strokeStyle = stroke; - ctx.lineWidth = 7; - ctx.beginPath(); - ctx.moveTo(this.hip.x, this.hip.y); - ctx.lineTo(this.knee.x, this.knee.y); - ctx.lineTo(this.foot.x, this.foot.y); - ctx.stroke(); - //toe lines - ctx.lineWidth = 4; - ctx.beginPath(); - ctx.moveTo(this.foot.x, this.foot.y); - ctx.lineTo(this.foot.x - 15, this.foot.y + 5); - ctx.moveTo(this.foot.x, this.foot.y); - ctx.lineTo(this.foot.x + 15, this.foot.y + 5); - ctx.stroke(); - //hip joint - ctx.strokeStyle = '#333'; - ctx.fillStyle = this.fillColor; - ctx.lineWidth = 2; - ctx.beginPath(); - ctx.arc(this.hip.x, this.hip.y, 11, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - //knee joint - ctx.beginPath(); - ctx.arc(this.knee.x, this.knee.y, 7, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - //foot joint - ctx.beginPath(); - ctx.arc(this.foot.x, this.foot.y, 6, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - ctx.restore(); - }; - this.calcLeg = function (cycle_offset, offset) { - this.hip.x = 12 + offset; - this.hip.y = 24 + offset; - //stepSize goes to zero if Vx is zero or not on ground (make this transition cleaner) - this.stepSize = 0.9 * this.stepSize + 0.1 * (8 * Math.sqrt(Math.abs(this.Vx)) * this.onGround); - //changes to stepsize are smoothed by adding only a percent of the new value each cycle - const stepAngle = 0.037 * this.walk_cycle + cycle_offset; - this.foot.x = 2 * this.stepSize * Math.cos(stepAngle) + offset; - this.foot.y = offset + this.stepSize * Math.sin(stepAngle) + this.yOff + this.height; - const Ymax = this.yOff + this.height; - if (this.foot.y > Ymax) this.foot.y = Ymax; - - //calculate knee position as intersection of circle from hip and foot - const d = Math.sqrt((this.hip.x - this.foot.x) * (this.hip.x - this.foot.x) + - (this.hip.y - this.foot.y) * (this.hip.y - this.foot.y)); - const l = (this.legLength1 * this.legLength1 - this.legLength2 * this.legLength2 + d * d) / (2 * d); - const h = Math.sqrt(this.legLength1 * this.legLength1 - l * l); - this.knee.x = l / d * (this.foot.x - this.hip.x) - h / d * (this.foot.y - this.hip.y) + this.hip.x + offset; - this.knee.y = l / d * (this.foot.y - this.hip.y) + h / d * (this.foot.x - this.hip.x) + this.hip.y; - }; - this.draw = function () { - ctx.fillStyle = this.fillColor; - if (this.mouse.x > canvas.width / 2) { - this.flipLegs = 1; - } else { - this.flipLegs = -1; - } - this.walk_cycle += this.flipLegs * this.Vx; - - //draw body - ctx.save(); - ctx.translate(this.pos.x, this.pos.y); - this.calcLeg(Math.PI, -3); - this.drawLeg('#444'); - this.calcLeg(0, 0); - this.drawLeg('#333'); - ctx.rotate(this.angle); - ctx.strokeStyle = '#333'; - ctx.lineWidth = 2; - //ctx.fillStyle = this.fillColor; - let grd = ctx.createLinearGradient(-30, 0, 30, 0); - grd.addColorStop(0, this.fillColorDark); - grd.addColorStop(1, this.fillColor); - ctx.fillStyle = grd; - ctx.beginPath(); - //ctx.moveTo(0, 0); - ctx.arc(0, 0, 30, 0, 2 * Math.PI); - ctx.arc(15, 0, 4, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - ctx.restore(); - - //draw holding graphics - if (this.isHolding) { - if (this.holdKeyDown > 20) { - if (this.holdKeyDown > this.throwMax) { - ctx.strokeStyle = 'rgba(255, 0, 255, 0.8)'; - } else { - ctx.strokeStyle = 'rgba(255, 0, 255, ' + (0.2 + 0.4 * this.holdKeyDown / this.throwMax) + ')'; - } - } else { - ctx.strokeStyle = 'rgba(0, 255, 255, 0.2)'; - } - ctx.lineWidth = 10; - ctx.beginPath(); - ctx.moveTo(holdConstraint.bodyB.position.x + Math.random() * 2, - holdConstraint.bodyB.position.y + Math.random() * 2); - ctx.lineTo(this.pos.x + 15 * Math.cos(this.angle), this.pos.y + 15 * Math.sin(this.angle)); - //ctx.lineTo(holdConstraint.pointA.x,holdConstraint.pointA.y); - ctx.stroke(); - } - }; -}; - - - - -//global player variables -let player, jumpSensor, playerBody, playerHead, headSensor; - -// player Object Prototype ********************************************* -const mechProto = function () { - this.spawn = function () { - //player as a series of vertices - let vector = Vertices.fromPath('0 40 0 115 20 130 30 130 50 115 50 40'); - playerBody = Matter.Bodies.fromVertices(0, 0, vector); - //this sensor check if the player is on the ground to enable jumping - jumpSensor = Bodies.rectangle(0, 46, 36, 6, { - sleepThreshold: 99999999999, - isSensor: true, - }); - //this part of the player lowers on crouch - vector = Vertices.fromPath('0 -66 18 -82 0 -37 50 -37 50 -66 32 -82'); - playerHead = Matter.Bodies.fromVertices(0, -55, vector); - //a part of player that senses if the player's head is empty and can return after crouching - headSensor = Bodies.rectangle(0, -57, 48, 45, { - sleepThreshold: 99999999999, - isSensor: true, - }); - player = Body.create({ //combine jumpSensor and playerBody - parts: [playerBody, playerHead, jumpSensor, headSensor], - inertia: Infinity, //prevents player rotation - friction: 0.002, - //frictionStatic: 0.5, - restitution: 0.3, - sleepThreshold: Infinity, - collisionFilter: { - group: 0, - category: 0x001000, - mask: 0x010001 - }, - }); - //Matter.Body.setPosition(player, mech.spawnPos); - //Matter.Body.setVelocity(player, mech.spawnVel); - Matter.Body.setMass(player, mech.mass); - World.add(engine.world, [player]); - //holding body constraint - const holdConstraint = Constraint.create({ - pointA: { - x: 0, - y: 0 - }, - //setting constaint to jump sensor because it has to be on something until the player picks up things - bodyB: jumpSensor, - stiffness: 0.4, - }); - World.add(engine.world, holdConstraint); - }; - this.width = 50; - this.radius = 30; - this.fillColor = '#fff'; - this.fillColorDark = '#ddd'; - // const hue = '353'; - // const sat = '100'; - // const lit = '90'; - // this.fillColor = 'hsl('+hue+','+sat+'%,'+lit+'%)'; - // this.fillColorDark = 'hsl('+hue+','+(sat-10)+'%,'+(lit-10)+'%)'; - // this.guns = { - // machine: { - // key: 49, - // ammo: infinite, - // isActive: true, - // isAvailable: true, - // }, - // needle: { - // key: 50, - // ammo: 10, - // isActive: false, - // isAvailable: true, - // }, - // shot: { - // key: 51, - // ammo: 10, - // isActive: false, - // isAvailable: true, - // } - // } - this.fireCDcycle = 0; - this.gun = 'machine'; //current gun in use - this.gunOptions = { //keeps track of keys that switch guns (used in the onkeypress event) - 49: 'machine', - 50: 'needle', - 51: 'shot', - 52: 'rail', - 53: 'cannon', - 54: 'super', - 55: 'lob', - // 55: 'spiritBomb', - // 56: 'experimental' - } - this.height = 42; - this.yOffWhen = { - crouch: 22, - stand: 49, - jump: 70 - } - this.yOff = 70; - this.yOffGoal = 70; - this.onGround = false; //checks if on ground or in air - this.onBody = { - id: 0, - index: 0, - type: "map", - action: '' - }; - this.numTouching = 0; - this.crouch = false; - this.isHeadClear = true; - this.spawnPos = { - x: 0, - y: 0 - }; - this.spawnVel = { - x: 0, - y: 0 - }; - this.pos = { - x: this.spawnPos.x, - y: this.spawnPos.y - }; - this.setPosToSpawn = function (xPos, yPos) { - this.spawnPos.x = xPos - this.spawnPos.y = yPos - this.pos.x = xPos; - this.pos.y = yPos; - this.Vx = this.spawnVel.x; - this.Vy = this.spawnVel.y; - Matter.Body.setPosition(player, this.spawnPos); - Matter.Body.setVelocity(player, this.spawnVel); - }; - this.Sy = this.pos.y; //adds a smoothing effect to vertical only - this.Vx = 0; - this.Vy = 0; - this.VxMax = 7; - this.mass = 5; - this.Fx = 0.004 * this.mass; //run Force on ground - this.FxAir = 0.0006 * this.mass; //run Force in Air - this.Fy = -0.05 * this.mass; //jump Force - this.angle = 0; - this.walk_cycle = 0; - this.stepSize = 0; - this.flipLegs = -1; - this.hip = { - x: 12, - y: 24, - }; - this.knee = { - x: 0, - y: 0, - x2: 0, - y2: 0 - }; - this.foot = { - x: 0, - y: 0 - }; - this.legLength1 = 55; - this.legLength2 = 45; - this.canvasX = canvas.width / 2; - this.canvasY = canvas.height / 2; - this.transX = this.canvasX - this.pos.x; - this.transY = this.canvasX - this.pos.x; - this.mouse = { - x: canvas.width / 3, - y: canvas.height - }; - this.getMousePos = function (x, y) { - this.mouse.x = x; - this.mouse.y = y; - }; - this.testingMoveLook = function () { - //move - this.pos.x = player.position.x; - this.pos.y = playerBody.position.y - this.yOff; - this.Vx = player.velocity.x; - this.Vy = player.velocity.y; - //look - this.canvasX = canvas.width / 2 - this.canvasY = canvas.height / 2 - this.transX = this.canvasX - this.pos.x; - this.transY = this.canvasY - this.pos.y; - this.angle = Math.atan2(this.mouse.y - this.canvasY, this.mouse.x - this.canvasX); - } - - this.move = function () { - this.pos.x = player.position.x; - this.pos.y = playerBody.position.y - this.yOff; - this.Vx = player.velocity.x; - this.Vy = player.velocity.y; - }; - this.look = function () { - //set a max on mouse look - let mX = this.mouse.x; - if (mX > canvas.width * 0.8) { - mX = canvas.width * 0.8; - } else if (mX < canvas.width * 0.2) { - mX = canvas.width * 0.2; - } - let mY = this.mouse.y; - if (mY > canvas.height * 0.8) { - mY = canvas.height * 0.8; - } else if (mY < canvas.height * 0.2) { - mY = canvas.height * 0.2; - } - //set mouse look - this.canvasX = this.canvasX * 0.94 + (canvas.width - mX) * 0.06; - this.canvasY = this.canvasY * 0.94 + (canvas.height - mY) * 0.06; - - //set translate values - this.transX = this.canvasX - this.pos.x; - this.Sy = 0.99 * this.Sy + 0.01 * (this.pos.y); - //hard caps how behind y position tracking can get. - if (this.Sy - this.pos.y > canvas.height / 2) { - this.Sy = this.pos.y + canvas.height / 2; - } else if (this.Sy - this.pos.y < -canvas.height / 2) { - this.Sy = this.pos.y - canvas.height / 2; - } - this.transY = this.canvasY - this.Sy; //gradual y camera tracking - //this.transY = this.canvasY - this.pos.y; //normal y camera tracking - - //make player head angled towards mouse - //this.angle = Math.atan2(this.mouse.y - this.canvasY, this.mouse.x - this.canvasX); - this.angle = Math.atan2(this.mouse.y + (this.Sy - this.pos.y) * game.zoom - this.canvasY, this.mouse.x - this.canvasX); - }; - this.doCrouch = function () { - if (!this.crouch) { - this.crouch = true; - this.yOffGoal = this.yOffWhen.crouch; - Matter.Body.translate(playerHead, { - x: 0, - y: 40 - }) - } - } - this.undoCrouch = function () { - this.crouch = false; - this.yOffGoal = this.yOffWhen.stand; - Matter.Body.translate(playerHead, { - x: 0, - y: -40 - }) - } - this.enterAir = function () { - this.onGround = false; - player.frictionAir = 0.001; - if (this.isHeadClear) { - if (this.crouch) { - this.undoCrouch(); - } - this.yOffGoal = this.yOffWhen.jump; - }; - } - this.enterLand = function () { - this.onGround = true; - if (this.crouch) { - if (this.isHeadClear) { - this.undoCrouch(); - player.frictionAir = 0.12; - } else { - this.yOffGoal = this.yOffWhen.crouch; - player.frictionAir = 0.5; - } - } else { - this.yOffGoal = this.yOffWhen.stand; - player.frictionAir = 0.12; - } - }; - this.buttonCD_jump = 0; //cooldown for player buttons - this.keyMove = function () { - if (this.onGround) { //on ground ********************** - if (this.crouch) { //crouch - if (!(keys[40] || keys[83]) && this.isHeadClear) { //not pressing crouch anymore - this.undoCrouch(); - player.frictionAir = 0.12; - } - } else if (keys[40] || keys[83]) { //on ground && not crouched and pressing s or down - this.doCrouch(); - player.frictionAir = 0.5; - } else if ((keys[32] || keys[38] || keys[87]) && this.buttonCD_jump + 20 < game.cycle) { //jump - this.buttonCD_jump = game.cycle; //can't jump until 20 cycles pass - Matter.Body.setVelocity(player, { //zero player velocity for consistant jumps - x: player.velocity.x, - y: 0 - }); - player.force.y = this.Fy / game.delta; //jump force / delta so that force is the same on game slowdowns - } - //horizontal move on ground - if (keys[37] || keys[65]) { //left or a - if (player.velocity.x > -this.VxMax) { - player.force.x += -this.Fx / game.delta; - } - } else if (keys[39] || keys[68]) { //right or d - if (player.velocity.x < this.VxMax) { - player.force.x += this.Fx / game.delta; - } - } - - } else { // in air ********************************** - //check for short jumps - if (this.buttonCD_jump + 60 > game.cycle && //just pressed jump - !(keys[32] || keys[38] || keys[87]) && //but not pressing jump key - this.Vy < 0) { // and velocity is up - Matter.Body.setVelocity(player, { //reduce player velocity every cycle until not true - x: player.velocity.x, - y: player.velocity.y * 0.94 - }); - } - if (keys[37] || keys[65]) { // move player left / a - if (player.velocity.x > -this.VxMax + 2) { - player.force.x += -this.FxAir / game.delta; - } - } else if (keys[39] || keys[68]) { //move player right / d - if (player.velocity.x < this.VxMax - 2) { - player.force.x += this.FxAir / game.delta; - } - } - } - //smoothly move height towards height goal ************ - this.yOff = this.yOff * 0.85 + this.yOffGoal * 0.15 - }; - this.death = function () { - location.reload(); - //Matter.Body.setPosition(player, this.spawnPos); - //Matter.Body.setVelocity(player, this.spawnVel); - //this.dropBody(); - //game.zoom = 0; //zooms out all the way - //this.health = 1; - } - this.health = 1; - this.regen = function () { - if (this.health < 1 && game.cycle % 15 === 0) { - this.addHealth(0.01); - } - }; - this.drawHealth = function () { - if (this.health < 1) { - ctx.fillStyle = 'rgba(100, 100, 100, 0.5)'; - ctx.fillRect(this.pos.x - this.radius, this.pos.y - 50, 60, 10); - ctx.fillStyle = "#f00"; - ctx.fillRect(this.pos.x - this.radius, this.pos.y - 50, 60 * this.health, 10); - } - }; - this.addHealth = function (heal) { - this.health += heal; - if (this.health > 1) this.health = 1; - } - this.damage = function (dmg) { - this.health -= dmg; - if (this.health <= 0) { - this.death(); - } - } - this.deathCheck = function () { - if (this.pos.y > game.fallHeight) { // if player is 4000px deep reset to spawn Position and Velocity - this.death(); - } - }; - this.hitMob = function (i, dmg) { - this.damage(dmg); - playSound("dmg" + Math.floor(Math.random() * 4)); - //extra kick between player and mob - //this section would be better with forces but they don't work... - let angle = Math.atan2(player.position.y - mob[i].position.y, player.position.x - mob[i].position.x); - Matter.Body.setVelocity(player, { - x: player.velocity.x + 8 * Math.cos(angle), - y: player.velocity.y + 8 * Math.sin(angle) - }); - Matter.Body.setVelocity(mob[i], { - x: mob[i].velocity.x - 8 * Math.cos(angle), - y: mob[i].velocity.y - 8 * Math.sin(angle) - }); - } - - this.buttonCD = 0; //cooldown for player buttons - this.eaten = []; - this.eat = function () { - if (keys[81] && this.buttonCD < game.cycle) { - this.buttonCD = game.cycle + 5; - this.findClosestBody(); - let i = this.closest.index - if (this.closest.dist < 150) { - //draw eating - ctx.lineWidth = 10; - ctx.strokeStyle = '#5f9'; - ctx.beginPath(); - ctx.moveTo(this.pos.x + 15 * Math.cos(this.angle), this.pos.y + 15 * Math.sin(this.angle)); - ctx.lineTo(body[i].position.x, body[i].position.y); - ctx.stroke(); - //set to eaten - body[i].eaten = true; - //drop body - body[i].frictionAir = 0; - this.isHolding = false; - holdConstraint.bodyB = jumpSensor; //set on sensor to get the constraint on somethign else - //add to eaten - body[i].collisionFilter.category = 0x000000; - body[i].collisionFilter.mask = 0x000000; - //Matter.Body.setStatic(body[i], true) - Matter.Sleeping.set(body[i], true) - Matter.Body.scale(body[i], 0.5, 0.5) - Matter.Body.setVelocity(body[i], { - x: 0, - y: 0 - }); - Matter.Body.setAngularVelocity(body[i], 0.08) //(Math.random()*0.5-1)*0.1) - //Matter.World.remove(engine.world, body[i]); - //body.splice(i, 1); - this.eaten[this.eaten.length] = { - index: i, - cycle: game.cycle - } - } - } - //control behavior of eaten bodies - for (let j = 0; j < this.eaten.length; j++) { - const pos = { - x: this.pos.x + 60 * Math.cos((game.cycle + this.eaten[j].cycle) * 0.05), - y: this.pos.y + 30 * Math.sin((game.cycle + this.eaten[j].cycle) * 0.05), - } - Matter.Body.setPosition(body[this.eaten[j].index], pos); - //Matter.Body.setVelocity(body[this.eaten[j].index],{x:0, y:0}); - - } - - if (keys[69] && this.buttonCD < game.cycle && this.eaten.length) { - this.buttonCD = game.cycle + 5; - let i = this.eaten[this.eaten.length - 1].index; - body[i].eaten = false; - body[i].collisionFilter.category = 0x000001; - body[i].collisionFilter.mask = 0x000101; - Matter.Body.setVelocity(body[i], { - x: 0, - y: 0 - }); - //Matter.Body.setStatic(body[i], false) - Matter.Sleeping.set(body[i], false) - Matter.Body.scale(body[i], 2, 2); - Matter.Body.setPosition(body[i], { - x: this.pos.x + 20 * Math.cos(this.angle), - y: this.pos.y + 20 * Math.sin(this.angle) - }); - const impulse = 0.06 * body[i].mass; - const f = { - x: impulse * Math.cos(this.angle) / game.delta, - y: impulse * Math.sin(this.angle) / game.delta - } - body[i].force = f; - this.eaten.pop(); - } - }; - - this.holdKeyDown = 0; - this.keyHold = function () { //checks for holding/dropping/picking up bodies - if (this.isHolding) { - //give the constaint more length and less stiffness if it is pulled out of position - const Dx = body[this.holdingBody].position.x - holdConstraint.pointA.x; - const Dy = body[this.holdingBody].position.y - holdConstraint.pointA.y; - holdConstraint.length = Math.sqrt(Dx * Dx + Dy * Dy) * 0.95; - holdConstraint.stiffness = -0.01 * holdConstraint.length + 1; - if (holdConstraint.length > 90) this.dropBody(); //drop it if the constraint gets too long - holdConstraint.pointA = { //set constraint position - x: this.pos.x + 50 * Math.cos(this.angle), //just in front of player nose - y: this.pos.y + 50 * Math.sin(this.angle) - }; - if (keys[81]) { // q = rotate the body - body[this.holdingBody].torque = 0.05 * body[this.holdingBody].mass; - } - //look for dropping held body - if (this.buttonCD < game.cycle) { - if (keys[69]) { //if holding e drops - this.holdKeyDown++; - } else if (this.holdKeyDown && !keys[69]) { - this.dropBody(); //if you hold down e long enough the body is thrown - this.throwBody(); - } - } - } else if (keys[69]) { //when not holding e = pick up body - this.findClosestBody(); - if (this.closest.dist < 150) { //pick up if distance closer then 100*100 - this.isHolding = true; - this.holdKeyDown = 0; - this.buttonCD = game.cycle + 20; - this.holdingBody = this.closest.index; //set new body to be the holdingBody - //body[this.closest.index].isSensor = true; //sensor seems a bit inconsistant - //body[this.holdingBody].collisionFilter.group = -2; //don't collide with player - body[mech.holdingBody].collisionFilter.category = 0x000001; - body[mech.holdingBody].collisionFilter.mask = 0x000001; - body[this.holdingBody].frictionAir = 0.1; //makes the holding body less jittery - holdConstraint.bodyB = body[this.holdingBody]; - holdConstraint.length = 0; - holdConstraint.pointA = { - x: this.pos.x + 50 * Math.cos(this.angle), - y: this.pos.y + 50 * Math.sin(this.angle) - }; - } - } - }; - this.dropBody = function () { - let timer; //reset player collision - function resetPlayerCollision() { - timer = setTimeout(function () { - const dx = mech.pos.x - body[mech.holdingBody].position.x - const dy = mech.pos.y - body[mech.holdingBody].position.y - if (dx * dx + dy * dy > 15000) { - body[mech.holdingBody].collisionFilter.category = 0x000001; - body[mech.holdingBody].collisionFilter.mask = 0x001101; - //body[mech.holdingBody].collisionFilter.group = 2; //can collide with player - } else { - resetPlayerCollision(); - } - }, 100); - } - resetPlayerCollision(); - this.isHolding = false; - body[this.holdingBody].frictionAir = 0.01; - holdConstraint.bodyB = jumpSensor; //set on sensor to get the constaint on somethign else - }; - this.throwMax = 150; - this.throwBody = function () { - let throwMag = 0; - if (this.holdKeyDown > 20) { - if (this.holdKeyDown > this.throwMax) this.holdKeyDown = this.throwMax; - //scale fire with mass and with holdKeyDown time - throwMag = body[this.holdingBody].mass * this.holdKeyDown * 0.001; - } - body[this.holdingBody].force.x = throwMag * Math.cos(this.angle); - body[this.holdingBody].force.y = throwMag * Math.sin(this.angle); - }; - this.isHolding = false; - this.holdingBody = 0; - this.closest = { - dist: 1000, - index: 0 - }; - this.lookingAtMob = function (mob, threshold) { - //calculate a vector from mob to player and make it length 1 - const diff = Matter.Vector.normalise(Matter.Vector.sub(mob.position, player.position)); - const dir = { //make a vector for the player's direction of length 1 - x: Math.cos(mech.angle), - y: Math.sin(mech.angle) - } - //the dot prodcut of diff and dir will return how much over lap between the vectors - const dot = Matter.Vector.dot(dir, diff); - if (dot > threshold) { - return true; - } else { - return false; - } - } - this.lookingAt = function (i) { - //calculate a vector from mob to player and make it length 1 - const diff = Matter.Vector.normalise(Matter.Vector.sub(body[i].position, player.position)); - const dir = { //make a vector for the player's direction of length 1 - x: Math.cos(mech.angle), - y: Math.sin(mech.angle) - } - //the dot prodcut of diff and dir will return how much over lap between the vectors - const dot = Matter.Vector.dot(dir, diff); - //console.log(dot); - if (dot > 0.9) { - return true; - } else { - return false; - } - } - this.findClosestBody = function () { - let mag = 100000; - let index = 0; - for (let i = 0; i < body.length; i++) { - let isLooking = this.lookingAt(i); - let collisionM = Matter.Query.ray(map, body[i].position, this.pos) - //let collisionB = Matter.Query.ray(body, body[i].position, this.pos) - if (collisionM.length) isLooking = false; - //magnitude of the distance between the poistion vectors of player and each body - const dist = Matter.Vector.magnitude(Matter.Vector.sub(body[i].position, this.pos)); - if (dist < mag && body[i].mass < player.mass && isLooking && !body[i].eaten) { - mag = dist; - index = i; - } - } - this.closest.dist = mag; - this.closest.index = index; - }; - this.exit = function () { - game.nextLevel(); - window.location.reload(false); - } - this.standingOnActions = function () { - if (this.onBody.type === 'map') { - var that = this; //brings the thisness of the player deeper into the actions object - var actions = { - 'death': function () { - that.death(); - }, - 'exit': function () { - that.exit(); - }, - '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 - }); - }, - 'launch': function () { - //that.dropBody(); - Matter.Body.setVelocity(player, { //zero player velocity for consistant jumps - x: player.velocity.x, - y: 0 - }); - player.force.y = -0.1 * that.mass / game.delta; - }, - 'default': function () {} - }; - (actions[map[this.onBody.index].action] || actions['default'])(); - } - } - this.drawLeg = function (stroke) { - ctx.save(); - ctx.scale(this.flipLegs, 1); //leg lines - ctx.strokeStyle = stroke; - ctx.lineWidth = 7; - ctx.beginPath(); - ctx.moveTo(this.hip.x, this.hip.y); - ctx.lineTo(this.knee.x, this.knee.y); - ctx.lineTo(this.foot.x, this.foot.y); - ctx.stroke(); - //toe lines - ctx.lineWidth = 4; - ctx.beginPath(); - ctx.moveTo(this.foot.x, this.foot.y); - ctx.lineTo(this.foot.x - 15, this.foot.y + 5); - ctx.moveTo(this.foot.x, this.foot.y); - ctx.lineTo(this.foot.x + 15, this.foot.y + 5); - ctx.stroke(); - //hip joint - ctx.strokeStyle = '#333'; - ctx.fillStyle = this.fillColor; - ctx.lineWidth = 2; - ctx.beginPath(); - ctx.arc(this.hip.x, this.hip.y, 11, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - //knee joint - ctx.beginPath(); - ctx.arc(this.knee.x, this.knee.y, 7, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - //foot joint - ctx.beginPath(); - ctx.arc(this.foot.x, this.foot.y, 6, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - ctx.restore(); - }; - this.calcLeg = function (cycle_offset, offset) { - this.hip.x = 12 + offset; - this.hip.y = 24 + offset; - //stepSize goes to zero if Vx is zero or not on ground (make this transition cleaner) - this.stepSize = 0.9 * this.stepSize + 0.1 * (8 * Math.sqrt(Math.abs(this.Vx)) * this.onGround); - //changes to stepsize are smoothed by adding only a percent of the new value each cycle - const stepAngle = 0.037 * this.walk_cycle + cycle_offset; - this.foot.x = 2 * this.stepSize * Math.cos(stepAngle) + offset; - this.foot.y = offset + this.stepSize * Math.sin(stepAngle) + this.yOff + this.height; - const Ymax = this.yOff + this.height; - if (this.foot.y > Ymax) this.foot.y = Ymax; - - //calculate knee position as intersection of circle from hip and foot - const d = Math.sqrt((this.hip.x - this.foot.x) * (this.hip.x - this.foot.x) + - (this.hip.y - this.foot.y) * (this.hip.y - this.foot.y)); - const l = (this.legLength1 * this.legLength1 - this.legLength2 * this.legLength2 + d * d) / (2 * d); - const h = Math.sqrt(this.legLength1 * this.legLength1 - l * l); - this.knee.x = l / d * (this.foot.x - this.hip.x) - h / d * (this.foot.y - this.hip.y) + this.hip.x + offset; - this.knee.y = l / d * (this.foot.y - this.hip.y) + h / d * (this.foot.x - this.hip.x) + this.hip.y; - }; - this.draw = function () { - ctx.fillStyle = this.fillColor; - if (this.mouse.x > canvas.width / 2) { - this.flipLegs = 1; - } else { - this.flipLegs = -1; - } - this.walk_cycle += this.flipLegs * this.Vx; - - //draw body - ctx.save(); - ctx.translate(this.pos.x, this.pos.y); - this.calcLeg(Math.PI, -3); - this.drawLeg('#444'); - this.calcLeg(0, 0); - this.drawLeg('#333'); - ctx.rotate(this.angle); - ctx.strokeStyle = '#333'; - ctx.lineWidth = 2; - //ctx.fillStyle = this.fillColor; - let grd = ctx.createLinearGradient(-30, 0, 30, 0); - grd.addColorStop(0, this.fillColorDark); - grd.addColorStop(1, this.fillColor); - ctx.fillStyle = grd; - ctx.beginPath(); - //ctx.moveTo(0, 0); - ctx.arc(0, 0, 30, 0, 2 * Math.PI); - ctx.arc(15, 0, 4, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - ctx.restore(); - - //draw holding graphics - if (this.isHolding) { - if (this.holdKeyDown > 20) { - if (this.holdKeyDown > this.throwMax) { - ctx.strokeStyle = 'rgba(255, 0, 255, 0.8)'; - } else { - ctx.strokeStyle = 'rgba(255, 0, 255, ' + (0.2 + 0.4 * this.holdKeyDown / this.throwMax) + ')'; - } - } else { - ctx.strokeStyle = 'rgba(0, 255, 255, 0.2)'; - } - ctx.lineWidth = 10; - ctx.beginPath(); - ctx.moveTo(holdConstraint.bodyB.position.x + Math.random() * 2, - holdConstraint.bodyB.position.y + Math.random() * 2); - ctx.lineTo(this.pos.x + 15 * Math.cos(this.angle), this.pos.y + 15 * Math.sin(this.angle)); - //ctx.lineTo(holdConstraint.pointA.x,holdConstraint.pointA.y); - ctx.stroke(); - } - }; -}; - - - - -//makes the player object based on mechprototype -const mech = new mechProto(); \ No newline at end of file diff --git a/js/bullets.js b/js/bullets.js index 7f7ab9f..99b794b 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -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("
NO AMMO
E / Q", 200); + // game.makeTextLog("
NO AMMO
E / Q", 200); + game.makeTextLog("
NO AMMO

Q, E, and mouse wheel change weapons

", 200); } } }, @@ -966,7 +971,7 @@ const b = { game.updateGunHUD(); } else { mech.fireCDcycle = game.cycle + 30; //cooldown - game.makeTextLog("
NO AMMO
E / Q", 200); + game.makeTextLog("
NO AMMO

Q, E, and mouse wheel change weapons

", 200); } } }, diff --git a/js/game.js b/js/game.js index db2bf18..89aa3ce 100644 --- a/js/game.js +++ b/js/game.js @@ -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() { diff --git a/js/index.js b/js/index.js index bfafe9a..bb1afe9 100644 --- a/js/index.js +++ b/js/index.js @@ -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 diff --git a/js/level.js b/js/level.js index 061f594..121ede3 100644 --- a/js/level.js +++ b/js/level.js @@ -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 = { // "

W
A S D
", // Infinity // ); - - game.makeTextLog( - // "



right mouse / space bar:
pick up things
", - "Use right mouse or space bar 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 diff --git a/js/level.procedural.js b/js/level.procedural.js deleted file mode 100644 index 7a47a19..0000000 --- a/js/level.procedural.js +++ /dev/null @@ -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]); - } - } -}; diff --git a/js/levelold.js b/js/levelold.js deleted file mode 100644 index 576addd..0000000 --- a/js/levelold.js +++ /dev/null @@ -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]); - } - } -}; diff --git a/js/lib/matter 0.12.min.js b/js/lib/matter 0.12.min.js deleted file mode 100644 index 46eafe8..0000000 --- a/js/lib/matter 0.12.min.js +++ /dev/null @@ -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;s0&&r.rotateAbout(s.position,n,e.position,s.position)}},o.setVelocity=function(e,t){e.positionPrev.x=e.position.x-t.x,e.positionPrev.y=e.position.y-t.y,e.velocity.x=t.x,e.velocity.y=t.y,e.speed=r.magnitude(e.velocity)},o.setAngularVelocity=function(e,t){e.anglePrev=e.angle-t,e.angularVelocity=t,e.angularSpeed=Math.abs(e.angularVelocity)},o.translate=function(e,t){ -o.setPosition(e,r.add(e.position,t))},o.rotate=function(e,t){o.setAngle(e,e.angle+t)},o.scale=function(e,n,r,s){for(var a=0;a0&&(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;n1?1:0;d1?1:0;f0:0!==(e.mask&t.category)&&0!==(t.mask&e.category)}}()},{"../geometry/Bounds":26,"./Pair":7,"./SAT":11}],6:[function(e,t,n){var o={};t.exports=o;var i=e("./Pair"),r=e("./Detector"),s=e("../core/Common");!function(){o.create=function(e){var t={controller:o,detector:r.collisions,buckets:{},pairs:{},pairsList:[],bucketWidth:48,bucketHeight:48};return s.extend(t,e)},o.update=function(n,o,i,r){var s,p,f,m,v,y=i.world,g=n.buckets,x=!1; -for(s=0;sy.bounds.max.x||h.bounds.max.yy.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;o0?o.push(n):delete e.pairs[t[i]];return o}}()},{"../core/Common":14,"./Detector":5,"./Pair":7}],7:[function(e,t,n){var o={};t.exports=o;var i=e("./Contact");!function(){o.create=function(e,t){var n=e.bodyA,i=e.bodyB,r=e.parentA,s=e.parentB,a={id:o.id(n,i),bodyA:n,bodyB:i,contacts:{},activeContacts:[],separation:0,isActive:!0,isSensor:n.isSensor||i.isSensor,timeCreated:t,timeUpdated:t,inverseMass:r.inverseMass+s.inverseMass,friction:Math.min(r.friction,s.friction), -frictionStatic:Math.max(r.frictionStatic,s.frictionStatic),restitution:Math.max(r.restitution,s.restitution),slop:Math.max(r.slop,s.slop)};return o.update(a,e,t),a},o.update=function(e,t,n){var r=e.contacts,s=t.supports,a=e.activeContacts,l=t.parentA,c=t.parentB;if(e.collision=t,e.inverseMass=l.inverseMass+c.inverseMass,e.friction=Math.min(l.friction,c.friction),e.frictionStatic=Math.max(l.frictionStatic,c.frictionStatic),e.restitution=Math.max(l.restitution,c.restitution),e.slop=Math.max(l.slop,c.slop),a.length=0,t.collided){for(var u=0;ue&&c.push(s);for(s=0;sf.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.overlapi?i=a:a=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),o0&&(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;t0&&(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;c1?1:0;u>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 en?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;n0&&u.trigger(o,"collisionStart",{pairs:w.collisionStart}),s.preSolvePosition(w.list),c=0;c0&&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;ir?(i.warn("Plugin.register:",o.toString(t),"was upgraded to",o.toString(e)),o._registry[e.name]=e):n-1},o.isFor=function(e,t){var n=e.for&&o.dependencyParse(e.for);return!e.for||t.name===n.name&&o.versionSatisfies(t.version,n.range)},o.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0===e.uses.length)return void i.warn("Plugin.use:",o.toString(e),"does not specify any dependencies to install.");for(var n=o.dependencies(e),r=i.topologicalSort(n),s=[],a=0;a0&&i.info(s.join(" "))},o.dependencies=function(e,t){var n=o.dependencyParse(e),r=n.name;if(t=t||{},!(r in t)){e=o.resolve(e)||e,t[r]=i.map(e.uses||[],function(t){ -o.isPlugin(t)&&o.register(t);var r=o.dependencyParse(t),s=o.resolve(t);return s&&!o.versionSatisfies(s.version,r.range)?(i.warn("Plugin.dependencies:",o.toString(s),"does not satisfy",o.toString(r),"used by",o.toString(n)+"."),s._warned=!0,e._warned=!0):s||(i.warn("Plugin.dependencies:",o.toString(t),"used by",o.toString(n),"could not be resolved."),e._warned=!0),r.name});for(var s=0;s=i[2];if("^"===n.operator)return i[0]>0?s[0]===i[0]&&r.number>=n.number:i[1]>0?s[1]===i[1]&&s[2]>=i[2]:s[2]===i[2]}return e===t||"*"===e}}()},{"./Common":14}],21:[function(e,t,n){var o={};t.exports=o;var i=e("./Events"),r=e("./Engine"),s=e("./Common");!function(){var e,t;if("undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame,t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),!e){var n;e=function(e){n=setTimeout(function(){e(s.now())},1e3/60)},t=function(){clearTimeout(n)}}o.create=function(e){ -var t={fps:60,correction:1,deltaSampleSize:60,counterTimestamp:0,frameCounter:0,deltaHistory:[],timePrev:null,timeScalePrev:1,frameRequestId:null,isFixed:!1,enabled:!0},n=s.extend(t,e);return n.delta=n.delta||1e3/n.fps,n.deltaMin=n.deltaMin||1e3/n.fps,n.deltaMax=n.deltaMax||1e3/(.5*n.fps),n.fps=1e3/n.delta,n},o.run=function(t,n){return"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=oe.deltaMax?e.deltaMax:o,a=o/e.delta,e.delta=o),0!==e.timeScalePrev&&(a*=s.timeScale/e.timeScalePrev),0===s.timeScale&&(a=0),e.timeScalePrev=s.timeScale,e.correction=a,e.frameCounter+=1,n-e.counterTimestamp>=1e3&&(e.fps=e.frameCounter*((n-e.counterTimestamp)/1e3), -e.counterTimestamp=n,e.frameCounter=0),i.trigger(e,"tick",l),i.trigger(t,"tick",l),t.world.isModified&&t.render&&t.render.controller&&t.render.controller.clear&&t.render.controller.clear(t.render),i.trigger(e,"beforeUpdate",l),r.update(t,o,a),i.trigger(e,"afterUpdate",l),t.render&&t.render.controller&&(i.trigger(e,"beforeRender",l),i.trigger(t,"beforeRender",l),t.render.controller.world(t.render),i.trigger(e,"afterRender",l),i.trigger(t,"afterRender",l)),i.trigger(e,"afterTick",l),i.trigger(t,"afterTick",l)},o.stop=function(e){t(e.frameRequestId)},o.start=function(e,t){o.run(e,t)}}()},{"./Common":14,"./Engine":15,"./Events":16}],22:[function(e,t,n){var o={};t.exports=o;var i=e("./Events");!function(){o._motionWakeThreshold=.18,o._motionSleepThreshold=.08,o._minBias=.9,o.update=function(e,t){for(var n=t*t*t,i=0;i0&&r.motion=r.sleepThreshold&&o.set(r,!0)):r.sleepCounter>0&&(r.sleepCounter-=1)}else o.set(r,!1)}},o.afterCollisions=function(e,t){for(var n=t*t*t,i=0;io._motionWakeThreshold*n&&o.set(c,!1)}}}},o.set=function(e,t){var n=e.isSleeping;t?(e.isSleeping=!0,e.sleepCounter=e.sleepThreshold,e.positionImpulse.x=0,e.positionImpulse.y=0,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.anglePrev=e.angle,e.speed=0,e.angularSpeed=0,e.motion=0,n||i.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&i.trigger(e,"sleepEnd"))}}()},{"./Events":16}],23:[function(e,t,n){(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;p0&&i.area(P)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;mv&&(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;u0)for(c=0;c0&&(p=f[c-1+(l-1)*t],i.addConstraint(e,r.create(s.extend({bodyA:p,bodyB:d},a)))),o&&cp)){c=p-c;var m=c,v=n-1-c;if(!(sv)){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;ce.max.x&&(e.max.x=i.x),i.xe.max.y&&(e.max.y=i.y),i.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},o.contains=function(e,t){return t.x>=e.min.x&&t.x<=e.max.x&&t.y>=e.min.y&&t.y<=e.max.y},o.overlaps=function(e,t){return e.min.x<=t.max.x&&e.max.x>=t.min.x&&e.max.y>=t.min.y&&e.min.y<=t.max.y},o.translate=function(e,t){e.min.x+=t.x,e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},o.shift=function(e,t){var n=e.max.x-e.min.x,o=e.max.y-e.min.y;e.min.x=t.x,e.max.x=t.x+n,e.min.y=t.y,e.max.y=t.y+o}}()},{}],27:[function(e,t,n){var o={};t.exports=o;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;o0)return!1}return!0},o.scale=function(e,t,n,r){if(1===t&&1===n)return e;r=r||o.centre(e);for(var s,a,l=0;l=0?l-1:e.length-1],u=e[l],d=e[(l+1)%e.length],p=t[l0&&(r|=2),3===r)return!1;return 0!==r||null},o.hull=function(e){var t,n,o=[],r=[];for(e=e.slice(0),e.sort(function(e,t){var n=e.x-t.x;return 0!==n?n:e.y-t.y}),n=0;n=2&&i.cross3(r[r.length-2],r[r.length-1],t)<=0;)r.pop();r.push(t)}for(n=e.length-1;n>=0;n--){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;sr.max.x&&(r.max.x=c.x),l.yr.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=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;d1?1:0;s1?1:0;a1?1:0;r1?1:0;l1?1:0;r1?1:0;r1?1:0;i0)){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;a1?1:0;p 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; -}); diff --git a/js/lib/stats.min.js b/js/lib/stats.min.js deleted file mode 100644 index 61757f3..0000000 --- a/js/lib/stats.min.js +++ /dev/null @@ -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;dg+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}); diff --git a/js/player.js b/js/player.js index c903884..e47d018 100644 --- a/js/player.js +++ b/js/player.js @@ -796,6 +796,7 @@ const mech = { fieldUpgrades: [ () => { mech.fieldMode = 0; + game.makeTextLog("Field Emitter
(right click or spacebar)

lets you pick up and throw objects
shields you from damage

", 1200); mech.setHoldDefaults(); mech.hold = function () { if (mech.isHolding) { @@ -817,7 +818,7 @@ const mech = { }, () => { mech.fieldMode = 1; - game.makeTextLog("Time Dilation Field
(right mouse or space bar)

field emitter slows objects in range

", 1000); + game.makeTextLog("Time Dilation Field
(right mouse or space bar)

field slows objects in range
field does not shield player

", 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("Kinetic Energy Field
(right mouse or space bar)

field emitter does damage on contact
blocks are thrown at a higher velocity

", 1000); + game.makeTextLog("Kinetic Energy Field
(right mouse or space bar)

field does damage on contact
blocks are thrown at a higher velocity

", 1200); mech.setHoldDefaults(); //throw quicker and harder mech.throwChargeRate = 3; //0.5 @@ -922,10 +924,12 @@ const mech = { }, () => { mech.fieldMode = 3; - game.makeTextLog("Negative Mass Field
(right mouse or space bar)

field emitter nullifies gravity around player
field emitter holds more massive objects

", 1000); + game.makeTextLog("Negative Mass Field
(right mouse or space bar)

nullifies gravity around player
can hold more massive objects
field does not shield player

", 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("Zero-Point Energy Field
(right mouse or space bar)

improved energy regeneration
field emitter surrounds player

", 1000); + game.makeTextLog("Zero-Point Energy Field
(right mouse or space bar)

improved energy regeneration
field emitter shield surrounds player

", 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("Nano-Scale Manufacturing
(passive effect)

when energy is full, build a drone using 20 energy

", 1000); + game.makeTextLog("Nano-Scale Manufacturing
(passive effect)

excess field energy builds drones
field does not shield player

", 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("Metamaterial Refractive Optics
(right mouse or space bar)

localized invisibility field

", 1000); + game.makeTextLog("Metamaterial Refractive Optics
(right mouse or space bar)

localized invisibility field

", 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("Thermal Radiation Field
(right mouse or space bar)

field damages all targets within range, including player
field does not shield player

", 1200); + // game.makeTextLog("Thermal Radiation Field
(right mouse or space bar)

field damages and pushes all targets within range
field damages player
field does not shield player

", 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) { diff --git a/js/powerups.js b/js/powerups.js index 8a47327..34d380f 100644 --- a/js/powerups.js +++ b/js/powerups.js @@ -117,14 +117,14 @@ const powerUps = { if (b.inventory.length === 1) { game.makeTextLog( // "
new gun: " + b.guns[newGun].name + "
E / Q", - "
new gun: " + b.guns[newGun].name + "

Use Q, E, or mouse wheel to change weapons.", - 360 + "
" + b.guns[newGun].name + "
(left click)

Q, E, and mouse wheel change weapons

", + 500 ); } else { game.makeTextLog( // "
new gun: " + b.guns[newGun].name + "
E / Q", - "
new gun: " + b.guns[newGun].name + "
", - 360 + "
" + b.guns[newGun].name + "
(left click)", + 400 ); } b.guns[newGun].have = true; diff --git a/js/spawn.js b/js/spawn.js index 1e6669e..645c0d7 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -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 diff --git a/sounds/ammo.ogg b/sounds/ammo.ogg deleted file mode 100644 index be7c28e..0000000 Binary files a/sounds/ammo.ogg and /dev/null differ diff --git a/sounds/boom.ogg b/sounds/boom.ogg deleted file mode 100644 index f757ced..0000000 Binary files a/sounds/boom.ogg and /dev/null differ diff --git a/sounds/click.ogg b/sounds/click.ogg deleted file mode 100644 index 1fc734c..0000000 Binary files a/sounds/click.ogg and /dev/null differ diff --git a/sounds/dmg/dmg0.ogg b/sounds/dmg/dmg0.ogg deleted file mode 100644 index e45402d..0000000 Binary files a/sounds/dmg/dmg0.ogg and /dev/null differ diff --git a/sounds/dmg/dmg1.ogg b/sounds/dmg/dmg1.ogg deleted file mode 100644 index 9826a50..0000000 Binary files a/sounds/dmg/dmg1.ogg and /dev/null differ diff --git a/sounds/dmg/dmg2.ogg b/sounds/dmg/dmg2.ogg deleted file mode 100644 index 95ba12f..0000000 Binary files a/sounds/dmg/dmg2.ogg and /dev/null differ diff --git a/sounds/dmg/dmg3.ogg b/sounds/dmg/dmg3.ogg deleted file mode 100644 index 1d9a32c..0000000 Binary files a/sounds/dmg/dmg3.ogg and /dev/null differ diff --git a/sounds/guns/airgun.ogg b/sounds/guns/airgun.ogg deleted file mode 100644 index 0325bc1..0000000 Binary files a/sounds/guns/airgun.ogg and /dev/null differ diff --git a/sounds/guns/bass.ogg b/sounds/guns/bass.ogg deleted file mode 100644 index 7976251..0000000 Binary files a/sounds/guns/bass.ogg and /dev/null differ diff --git a/sounds/guns/basssnaredrum.ogg b/sounds/guns/basssnaredrum.ogg deleted file mode 100644 index 87b3862..0000000 Binary files a/sounds/guns/basssnaredrum.ogg and /dev/null differ diff --git a/sounds/guns/blaster.ogg b/sounds/guns/blaster.ogg deleted file mode 100644 index 180489f..0000000 Binary files a/sounds/guns/blaster.ogg and /dev/null differ diff --git a/sounds/guns/glock.ogg b/sounds/guns/glock.ogg deleted file mode 100644 index 4402b09..0000000 Binary files a/sounds/guns/glock.ogg and /dev/null differ diff --git a/sounds/guns/launcher.ogg b/sounds/guns/launcher.ogg deleted file mode 100644 index 6190db2..0000000 Binary files a/sounds/guns/launcher.ogg and /dev/null differ diff --git a/sounds/guns/launcher2.ogg b/sounds/guns/launcher2.ogg deleted file mode 100644 index dfe7f00..0000000 Binary files a/sounds/guns/launcher2.ogg and /dev/null differ diff --git a/sounds/guns/reload.ogg b/sounds/guns/reload.ogg deleted file mode 100644 index f45f720..0000000 Binary files a/sounds/guns/reload.ogg and /dev/null differ diff --git a/sounds/guns/shotgun.mp3 b/sounds/guns/shotgun.mp3 deleted file mode 100644 index 3002ada..0000000 Binary files a/sounds/guns/shotgun.mp3 and /dev/null differ diff --git a/sounds/guns/snare.ogg b/sounds/guns/snare.ogg deleted file mode 100644 index df9a83a..0000000 Binary files a/sounds/guns/snare.ogg and /dev/null differ diff --git a/sounds/guns/snare2.ogg b/sounds/guns/snare2.ogg deleted file mode 100644 index 34f21b7..0000000 Binary files a/sounds/guns/snare2.ogg and /dev/null differ diff --git a/sounds/guns/sniper.ogg b/sounds/guns/sniper.ogg deleted file mode 100644 index 48254b8..0000000 Binary files a/sounds/guns/sniper.ogg and /dev/null differ diff --git a/sounds/no.ogg b/sounds/no.ogg deleted file mode 100644 index 7f358e6..0000000 Binary files a/sounds/no.ogg and /dev/null differ diff --git a/sounds/powerup4.ogg b/sounds/powerup4.ogg deleted file mode 100644 index b42ba70..0000000 Binary files a/sounds/powerup4.ogg and /dev/null differ