From 42338ea49e8fd0c7c139efe3fca10362f501654c Mon Sep 17 00:00:00 2001 From: landgreen Date: Thu, 23 Apr 2020 16:22:49 -0700 Subject: [PATCH] RPG and MIRV mods + bug fixes --- js/bullets.js | 184 +++++++++++++++++++++++++++++++++++++++++--------- js/engine.js | 65 +++++++++--------- js/game.js | 13 +++- js/index.js | 3 + js/level.js | 18 ++--- js/mobs.js | 8 +-- js/player.js | 75 ++++++++++++++------ js/spawn.js | 98 +++++++++++++++------------ todo.txt | 62 +++++++++-------- 9 files changed, 350 insertions(+), 176 deletions(-) diff --git a/js/bullets.js b/js/bullets.js index 7f20aad..922f550 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -80,6 +80,9 @@ const b = { isModEnergyHealth: null, isModPulseStun: null, isModPilotFreeze: null, + isModRest: null, + isModRPG: null, + isMod3Missiles: null, modOnHealthChange() { //used with acid mod if (b.isModAcidDmg && mech.health > 0.8) { b.modAcidDmg = 0.5 @@ -96,13 +99,13 @@ const b = { }, 10); } } - if (b.isModLowHealthDmg) { - if (!build.isCustomSelection) { - setTimeout(function () { - if (document.getElementById("mod-low-health-damage")) document.getElementById("mod-low-health-damage").innerHTML = " +" + (((3 / (2 + Math.min(mech.health, 1))) - 1) * 100).toFixed(0) + "%" - }, 10); - } - } + // if (b.isModLowHealthDmg) { + // if (!build.isCustomSelection) { + // setTimeout(function () { + // if (document.getElementById("mod-low-health-damage")) document.getElementById("mod-low-health-damage").innerHTML = " +" + (((3 / (2 + Math.min(mech.health, 1))) - 1) * 100).toFixed(0) + "%" + // }, 10); + // } + // } }, resetModText() { setTimeout(function () { @@ -112,7 +115,7 @@ const b = { }, mods: [{ name: "capacitor", - nameInfo: "", + // nameInfo: "", description: "increase damage based on stored energy
+1% damage for every 5% energy", maxCount: 1, count: 0, @@ -127,6 +130,23 @@ const b = { b.isModEnergyDamage = false; } }, + { + name: "rest frame", + // nameInfo: "", + description: "increase damage by 20% when at rest", + maxCount: 1, + count: 0, + allowed() { + return true + }, + requires: "", + effect: () => { + b.isModRest = true // used in mech.grabPowerUp + }, + remove() { + b.isModRest = false; + } + }, { name: "kinetic bombardment", description: "do up to 33% more damage at a distance
increase maxes out at about 40 steps away", @@ -181,7 +201,7 @@ const b = { }, { name: "negative feedback", - nameInfo: "", + // nameInfo: "", description: "do extra damage at low health
up to 50% increase when near death", maxCount: 1, count: 0, @@ -1057,7 +1077,7 @@ const b = { }, { name: "self-replication", - description: "when missiles explode
they fire +1 smaller missiles", + description: "after missiles explode
they launch +1 smaller missile", maxCount: 9, count: 0, allowed() { @@ -1071,6 +1091,22 @@ const b = { b.modBabyMissiles = 0; } }, + { + name: "MIRV", + description: "launch 3 small missiles instead of 1
2x increase in delay after firing", + maxCount: 1, + count: 0, + allowed() { + return b.haveGunCheck("missiles") + }, + requires: "missiles", + effect() { + b.isMod3Missiles = true; + }, + remove() { + b.isMod3Missiles = false; + } + }, { name: "optimized shell packing", description: "flak ammo drops contain 3x more shells", @@ -1107,6 +1143,22 @@ const b = { b.modGrenadeFragments = 0 } }, + { + name: "rocket-propelled grenade", + description: "grenades are rapidly accelerated forward
map collisions trigger an explosion", + maxCount: 1, + count: 0, + allowed() { + return b.haveGunCheck("grenades") + }, + requires: "grenades", + effect() { + b.isModRPG = true; + }, + remove() { + b.isModRPG = false; + } + }, { name: "electromagnetic pulse", description: "vacuum bomb's explosion destroys shields
and does 20% more damage", @@ -1467,7 +1519,7 @@ const b = { }, { name: "renormalization", - description: "phase decoherence field has increased visibility
and 3x less energy drain when firing", + description: "phase decoherence has increased visibility
and 3x less energy drain when firing", maxCount: 1, count: 0, allowed() { @@ -1613,6 +1665,15 @@ const b = { } } }, + damageFromMods() { + let dmg = 1 + if (b.isModLowHealthDmg) dmg *= (3 / (2 + Math.min(mech.health, 1))) //up to 50% dmg at zero player health //if this changes all update display in modOnHealthChange() + if (b.isModHarmDamage && mech.lastHarmCycle + 300 > mech.cycle) dmg *= 2; + if (b.isModEnergyLoss) dmg *= 1.33; + if (b.isModRest && player.speed < 1) dmg *= 1.20; + if (b.isModEnergyDamage) dmg *= 1 + mech.energy / 5; + return dmg + }, bulletRemove() { //run in main loop //remove bullet if at end cycle for that bullet let i = bullet.length; @@ -1842,12 +1903,12 @@ const b = { bullet[me].onEnd = function () { b.explosion(this.position, this.explodeRad * size); //makes bullet do explosive damage at end for (let i = 0; i < spawn; i++) { - b.missile(this.position, 2 * Math.PI * Math.random(), 0, 0.65) + b.missile(this.position, 2 * Math.PI * Math.random(), 0, 0.7 * size) } } bullet[me].onDmg = function () { this.tryToLockOn(); - // this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion + this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion }; bullet[me].lockedOn = null; bullet[me].tryToLockOn = function () { @@ -1874,7 +1935,7 @@ const b = { if (this.lockedOn && Vector.magnitude(Vector.sub(this.position, this.lockedOn.position)) < this.explodeRad) { // console.log('hit') this.endCycle = 0; //bullet ends cycle after doing damage //also triggers explosion - this.lockedOn.damage(b.dmgScale * 5 * size); //does extra damage to target + this.lockedOn.damage(b.dmgScale * 4 * size); //does extra damage to target } }; bullet[me].do = function () { @@ -2875,7 +2936,7 @@ const b = { }, { name: "missiles", - description: "fire missiles that accelerate towards mobs
explodes when near target", + description: "launch missiles that accelerate towards mobs
explodes when near target", ammo: 0, ammoPack: 4, have: false, @@ -2884,15 +2945,51 @@ const b = { fireCycle: 0, ammoLoaded: 0, fire() { - mech.fireCDcycle = mech.cycle + Math.floor(mech.crouch ? 50 : 25); // cool down - b.missile({ - x: mech.pos.x + 40 * Math.cos(mech.angle), - y: mech.pos.y + 40 * Math.sin(mech.angle) - 3 - }, - mech.angle + (0.5 - Math.random()) * (mech.crouch ? 0 : 0.2), - -3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8) * b.modFireRate, - 1, b.modBabyMissiles) - bullet[bullet.length - 1].force.y += 0.0006; //a small push down at first to make it seem like the missile is briefly falling + if (b.isMod3Missiles) { + if (mech.crouch) { + mech.fireCDcycle = mech.cycle + 80; // cool down + const direction = { + x: Math.cos(mech.angle), + y: Math.sin(mech.angle) + } + const push = Vector.mult(Vector.perp(direction), 0.0007) + for (let i = 0; i < 3; i++) { + //missile(where, dir, speed, size = 1, spawn = 0) { + b.missile({ + x: mech.pos.x + 40 * direction.x, + y: mech.pos.y + 40 * direction.y + }, mech.angle + 0.06 * (1 - i), 0, 0.7, b.modBabyMissiles) + bullet[bullet.length - 1].force.x += push.x * (i - 1); + bullet[bullet.length - 1].force.y += push.y * (i - 1); + } + } else { + mech.fireCDcycle = mech.cycle + 60; // cool down + const direction = { + x: Math.cos(mech.angle), + y: Math.sin(mech.angle) + } + const push = Vector.mult(Vector.perp(direction), 0.0008) + for (let i = 0; i < 3; i++) { + //missile(where, dir, speed, size = 1, spawn = 0) { + b.missile({ + x: mech.pos.x + 40 * direction.x, + y: mech.pos.y + 40 * direction.y + }, mech.angle, 0, 0.7, b.modBabyMissiles) + bullet[bullet.length - 1].force.x += push.x * (i - 1); + bullet[bullet.length - 1].force.y += push.y * (i - 1); + } + } + } else { + mech.fireCDcycle = mech.cycle + Math.floor(mech.crouch ? 50 : 30); // cool down + b.missile({ + x: mech.pos.x + 40 * Math.cos(mech.angle), + y: mech.pos.y + 40 * Math.sin(mech.angle) - 3 + }, + mech.angle + (0.5 - Math.random()) * (mech.crouch ? 0 : 0.2), + -3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8) * b.modFireRate, + 1, b.modBabyMissiles) + bullet[bullet.length - 1].force.y += 0.0006; //a small push down at first to make it seem like the missile is briefly falling + } } }, { @@ -2953,11 +3050,7 @@ const b = { const me = bullet.length; const dir = mech.angle; // + Math.random() * 0.05; bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20, b.fireAttributes(dir, true)); - b.fireProps(mech.crouch ? 30 : 20, mech.crouch ? 43 : 32, dir, me); //cd , speed Matter.Body.setDensity(bullet[me], 0.0005); - bullet[me].totalCycles = 100; - bullet[me].endCycle = game.cycle + Math.floor(mech.crouch ? 120 : 80); - bullet[me].restitution = 0.2; bullet[me].explodeRad = 275; bullet[me].onEnd = function () { b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end @@ -2997,10 +3090,35 @@ const b = { bullet[me].onDmg = function () { this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion }; - bullet[me].do = function () { - //extra gravity for harder arcs - this.force.y += this.mass * 0.0025; - }; + + if (b.isModRPG) { + b.fireProps(25, mech.crouch ? 60 : -15, dir, me); //cd , speed + bullet[me].endCycle = game.cycle + 70; + bullet[me].frictionAir = 0.07; + const MAG = 0.015 + bullet[me].thrust = { + x: bullet[me].mass * MAG * Math.cos(dir), + y: bullet[me].mass * MAG * Math.sin(dir) + } + bullet[me].do = function () { + this.force.x += this.thrust.x; + this.force.y += this.thrust.y; + if (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length) { + this.endCycle = 0; //explode if touching map or blocks + } + }; + } else { + b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 43 : 32, dir, me); //cd , speed + bullet[me].endCycle = game.cycle + Math.floor(mech.crouch ? 120 : 80); + bullet[me].restitution = 0.2; + bullet[me].explodeRad = 275; + bullet[me].do = function () { + //extra gravity for harder arcs + this.force.y += this.mass * 0.0025; + }; + } + + } }, { @@ -3195,7 +3313,7 @@ const b = { name: "drones", description: "deploy drones that crash into mobs
collisions reduce their lifespan by 1 second", ammo: 0, - ammoPack: 12, + ammoPack: 13, have: false, isStarterGun: true, isEasyToAim: true, diff --git a/js/engine.js b/js/engine.js index f41da53..cb46a7f 100644 --- a/js/engine.js +++ b/js/engine.js @@ -87,40 +87,41 @@ function collisionChecks(event) { //body + player collision - // if (game.isBodyDamage) { - // if (pairs[i].bodyA === playerBody || pairs[i].bodyA === playerHead) { - // collidePlayer(pairs[i].bodyB) - // } else if (pairs[i].bodyB === playerBody || pairs[i].bodyB === playerHead) { - // collidePlayer(pairs[i].bodyA) - // } - // } + if (game.isBodyDamage) { + if (pairs[i].bodyA === playerBody || pairs[i].bodyA === playerHead) { + collidePlayer(pairs[i].bodyB) + } else if (pairs[i].bodyB === playerBody || pairs[i].bodyB === playerHead) { + collidePlayer(pairs[i].bodyA) + } + } - // function collidePlayer(obj) { - // //player dmg from hitting a body - // if (obj.classType === "body" && mech.collisionImmuneCycle < mech.cycle) { - // const velocityThreshold = 13 - // if (player.position.y > obj.position.y) { //block is above the player look at total momentum difference - // const velocityDiffMag = Vector.magnitude(Vector.sub(player.velocity, obj.velocity)) - // if (velocityDiffMag > velocityThreshold) hit(velocityDiffMag - velocityThreshold) - // } else { //block is below player only look at horizontal momentum difference - // const velocityDiffMagX = Math.abs(obj.velocity.x - player.velocity.x) - // if (velocityDiffMagX > velocityThreshold) hit(velocityDiffMagX - velocityThreshold) - // } + function collidePlayer(obj) { + //player dmg from hitting a body + // if ( mech.collisionImmuneCycle < mech.cycle) { + if (obj.classType === "body" && obj.speed > 10 && mech.collisionImmuneCycle < mech.cycle) { + const velocityThreshold = 30 //keep this lines up with player.enterLand numbers (130/5 = 26) + if (player.position.y > obj.position.y) { //block is above the player look at total momentum difference + const velocityDiffMag = Vector.magnitude(Vector.sub(player.velocity, obj.velocity)) + if (velocityDiffMag > velocityThreshold) hit(velocityDiffMag - velocityThreshold) + } else { //block is below player only look at horizontal momentum difference + const velocityDiffMagX = Math.abs(obj.velocity.x - player.velocity.x) + if (velocityDiffMagX > velocityThreshold) hit(velocityDiffMagX - velocityThreshold) + } - // function hit(dmg) { - // mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles - // dmg = Math.min(Math.max(Math.sqrt(dmg) * obj.mass * 0.01, 0.02), 0.15); - // mech.damage(dmg); - // game.drawList.push({ //add dmg to draw queue - // x: pairs[i].activeContacts[0].vertex.x, - // y: pairs[i].activeContacts[0].vertex.y, - // radius: dmg * 500, - // color: game.mobDmgColor, - // time: game.drawTime - // }); - // } - // } - // } + function hit(dmg) { + mech.collisionImmuneCycle = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles + dmg = Math.min(Math.max(Math.sqrt(dmg) * obj.mass * 0.01, 0.02), 0.15); + mech.damage(dmg); + game.drawList.push({ //add dmg to draw queue + x: pairs[i].activeContacts[0].vertex.x, + y: pairs[i].activeContacts[0].vertex.y, + radius: dmg * 500, + color: game.mobDmgColor, + time: game.drawTime + }); + } + } + } // function collidePlayer(obj, speedThreshold = 12, massThreshold = 2) { // //player dmg from hitting a body diff --git a/js/game.js b/js/game.js index a3c8c0f..f4be07d 100644 --- a/js/game.js +++ b/js/game.js @@ -711,9 +711,16 @@ const game = { } } - if (b.isModEnergyDamage) { - document.getElementById("mod-capacitor").innerHTML = `(+${(mech.energy/0.05).toFixed(0)}%)` - } + // if (b.isModEnergyDamage) { + // document.getElementById("mod-capacitor").innerHTML = `(+${(mech.energy/0.05).toFixed(0)}%)` + // } + // if (b.isModRest) { + // if (player.speed < 1) { + // document.getElementById("mod-rest").innerHTML = `(+20%)` + // } else { + // document.getElementById("mod-rest").innerHTML = `(+0%)` + // } + // } if (mech.lastKillCycle + 300 > mech.cycle) { //effects active for 5 seconds after killing a mob if (b.isModEnergyRecovery) { diff --git a/js/index.js b/js/index.js index bea7ae1..c7b3ea3 100644 --- a/js/index.js +++ b/js/index.js @@ -83,8 +83,11 @@ const build = {

health: ${(mech.health*100).toFixed(0)}%   energy: ${(mech.energy*100).toFixed(0)}%   mass: ${player.mass.toFixed(1)}
position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)})   velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)}) +
global damage increase: ${((b.damageFromMods()-1)*100).toFixed(0)}% +
global harm reduction: ${((1-mech.harmReduction())*100).toFixed(0)}% `; + let countGuns = 0 let countMods = 0 for (let i = 0, len = b.guns.length; i < len; i++) { diff --git a/js/level.js b/js/level.js index da21787..5a24b26 100644 --- a/js/level.js +++ b/js/level.js @@ -15,12 +15,12 @@ const level = { if (build.isURLBuild && level.levelsCleared === 0) build.onLoadPowerUps(); if (level.levelsCleared === 0) { //this code only runs on the first level // level.difficultyIncrease(9) - // b.giveGuns("wave beam") - // mech.setField("phase decoherence field") + // b.giveGuns("missiles") + // mech.setField("time dilation field") // b.giveMod("renormalization"); // b.giveMod("pocket universe"); - // b.giveMod("wave packet"); - // b.giveGuns("laser") + // b.giveGuns("grenades") + // b.giveMod("rocket-propelled grenade"); // mech.setField("pilot wave") level.intro(); //starting level @@ -154,7 +154,7 @@ const level = { // spawn.bomberBoss(2900, -500) spawn.stabber(1200, -500) - spawn.chaser(1200, -500) + // spawn.chaser(1200, -500) // spawn.nodeBoss(1200, -500, "spiker") // spawn.hopper(1200, -500) // spawn.timeSkipBoss(2900, -500) @@ -264,7 +264,7 @@ const level = { y: -600, width: 400, height: 500, - color: "#cee" + color: "#dee" }); level.fill.push({ @@ -272,7 +272,7 @@ const level = { y: -1000, width: 2750, height: 1000, - color: "rgba(0,20,40,0.1)" + color: "rgba(0,10,30,0.04)" }); const lineColor = "#ddd" @@ -606,6 +606,7 @@ const level = { level.exit.y = -300; spawn.mapRect(3600, -285, 100, 50); //ground bump wall //mobs that spawn in exit room + spawn.bodyRect(4850, -750, 300, 25, 0.6); // spawn.randomSmallMob(4100, -100); spawn.randomSmallMob(4600, -100); spawn.randomMob(3765, -450, 0.3); @@ -629,7 +630,7 @@ const level = { level.exit.x = -550; level.exit.y = -2030; spawn.mapRect(-550, -2015, 100, 50); //ground bump wall - spawn.boost(4950, 0, 1600); + spawn.boost(4950, 0, 1100); level.fillBG.push({ x: -650, y: -2300, @@ -761,7 +762,6 @@ const level = { spawn.mapRect(3450, -1000, 50, 580); //left building wall spawn.bodyRect(3460, -420, 30, 144); 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, 1090, 50); // spawn.mapRect(3450, -1225, 50, 75); diff --git a/js/mobs.js b/js/mobs.js index bae4987..ae98f40 100644 --- a/js/mobs.js +++ b/js/mobs.js @@ -946,13 +946,13 @@ const mobs = { }, damage(dmg, isBypassShield = false) { if (!this.isShielded || isBypassShield) { + dmg *= b.damageFromMods() + //mobs specific damage changes dmg /= Math.sqrt(this.mass) if (this.shield) dmg *= 0.04 - if (b.isModLowHealthDmg) dmg *= (3 / (2 + Math.min(mech.health, 1))) //up to 50% dmg at zero player health //if this changes all update display in modOnHealthChange() - if (b.isModHarmDamage && mech.lastHarmCycle + 300 > mech.cycle) dmg *= 2; - if (b.isModEnergyLoss) dmg *= 1.33; - if (b.isModEnergyDamage) dmg *= 1 + mech.energy / 5; if (b.isModFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 50% dmg at max range of 3500 + + //energy and heal drain should be calculated after damage boosts if (b.modEnergySiphon && dmg !== Infinity) mech.energy += Math.min(this.health, dmg) * b.modEnergySiphon if (b.modHealthDrain && dmg !== Infinity) mech.addHealth(Math.min(this.health, dmg) * b.modHealthDrain) this.health -= dmg diff --git a/js/player.js b/js/player.js index 8fde508..10fba08 100644 --- a/js/player.js +++ b/js/player.js @@ -202,7 +202,7 @@ const mech = { } else { //sets a hard land where player stays in a crouch for a bit and can't jump //crouch is forced in keyMove() on ground section below - const momentum = player.velocity.y * player.mass //player mass is 5 so this triggers at 20 down velocity, unless the player is holding something + const momentum = player.velocity.y * player.mass //player mass is 5 so this triggers at 26 down velocity, unless the player is holding something if (momentum > 130) { mech.doCrouch(); mech.yOff = mech.yOffWhen.jump; @@ -503,6 +503,17 @@ const mech = { }, defaultFPSCycle: 0, //tracks when to return to normal fps collisionImmuneCycle: 0, //used in engine + harmReduction() { + let dmg = 1 + dmg *= mech.fieldDamageResistance + if (b.modEnergyRegen === 0) dmg *= 0.5 //0.22 + 0.78 * mech.energy //77% damage reduction at zero energy + if (b.isModEntanglement && b.inventory[0] === b.activeGun) { + for (let i = 0, len = b.inventory.length; i < len; i++) { + dmg *= 0.84 // 1 - 0.16 + } + } + return dmg + }, damage(dmg) { mech.lastHarmCycle = mech.cycle @@ -522,14 +533,8 @@ const mech = { y: 0 }) } + dmg *= mech.harmReduction() - dmg *= mech.fieldDamageResistance - if (b.modEnergyRegen === 0) dmg *= 0.5 //0.22 + 0.78 * mech.energy //77% damage reduction at zero energy - if (b.isModEntanglement && b.inventory[0] === b.activeGun) { - for (let i = 0, len = b.inventory.length; i < len; i++) { - dmg *= 0.84 // 1 - 0.16 - } - } if (b.isModEnergyHealth) { mech.energy -= dmg; if (mech.energy < 0 || isNaN(mech.energy)) { @@ -1820,7 +1825,7 @@ const mech = { mech.hold = function () { function drawField(radius) { - radius *= 0.7 + 0.6 * mech.energy; + radius *= 0.8 + 0.7 * mech.energy; const rotate = mech.cycle * 0.005; mech.fieldPhase += 0.5 - 0.5 * Math.sqrt(Math.max(0.01, Math.min(mech.energy, 1))); const off1 = 1 + 0.06 * Math.sin(mech.fieldPhase); @@ -1858,13 +1863,14 @@ const mech = { mech.lookForPickUp(); const DRAIN = 0.0004 + 0.0002 * player.speed + ((!b.modRenormalization && mech.fireCDcycle > mech.cycle) ? 0.005 : 0.0017) + mech.energy -= DRAIN; if (mech.energy > DRAIN) { - mech.energy -= DRAIN; - if (mech.energy < 0.001) { - mech.fieldCDcycle = mech.cycle + 120; - mech.energy = 0; - } - this.fieldRange = this.fieldRange * 0.9 + 0.1 * 160 + // if (mech.energy < 0.001) { + // mech.fieldCDcycle = mech.cycle + 120; + // mech.energy = 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) + // } + this.fieldRange = this.fieldRange * 0.87 + 0.13 * 160 drawField(this.fieldRange) mech.isStealth = true //isStealth disables most uses of foundPlayer() @@ -1903,32 +1909,33 @@ const mech = { } } } + } else { + mech.fieldCDcycle = mech.cycle + 120; + mech.energy = 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) + drawField(this.fieldRange) } } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released mech.pickUp(); } else { // this.fieldRange = 3000 if (this.fieldRange < 2000 && mech.holdingTarget === null) { - this.fieldRange += 20 + this.fieldRange += 40 drawField(this.fieldRange) } 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() + if (mech.energy < mech.fieldEnergyMax) { mech.energy += mech.fieldRegen; const xOff = mech.pos.x - mech.radius * mech.fieldEnergyMax const yOff = mech.pos.y - 50 - ctx.fillStyle = "rgba(0, 0, 0, 0.3)"; ctx.fillRect(xOff, yOff, 60 * mech.fieldEnergyMax, 10); - ctx.fillStyle = mech.fieldMeterColor; ctx.fillRect(xOff, yOff, 60 * mech.energy, 10); - ctx.beginPath() ctx.rect(xOff, yOff, 60 * mech.fieldEnergyMax, 10); - // ctx.fill(); ctx.strokeStyle = "rgb(0, 0, 0)"; ctx.lineWidth = 1; ctx.stroke(); @@ -1992,7 +1999,31 @@ const mech = { y: mech.fieldPosition.y * smooth + game.mouseInGame.y * (1 - smooth), } } - mech.grabPowerUp(); + + for (let i = 0, len = powerUp.length; i < len; ++i) { + const dxP = mech.fieldPosition.x - powerUp[i].position.x; + const dyP = mech.fieldPosition.y - powerUp[i].position.y; + const dist2 = dxP * dxP + dyP * dyP; + // float towards field if looking at and in range or if very close to player + if (dist2 < mech.fieldRadius * mech.fieldRadius && (mech.lookingAt(powerUp[i]) || dist2 < 16000) && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) { + powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass; + powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity + //extra friction + Matter.Body.setVelocity(powerUp[i], { + x: powerUp[i].velocity.x * 0.11, + y: powerUp[i].velocity.y * 0.11 + }); + if (dist2 < 5000 && !game.isChoosing) { //use power up if it is close enough + if (b.isModMassEnergy) mech.energy = mech.fieldEnergyMax * 2; + powerUp[i].effect(); + Matter.World.remove(engine.world, powerUp[i]); + powerUp.splice(i, 1); + mech.fieldRadius += 50 + break; //because the array order is messed up after splice + } + } + } + if (mech.energy > 0.01) { //find mouse velocity const diff = Vector.sub(mech.fieldPosition, mech.lastFieldPosition) diff --git a/js/spawn.js b/js/spawn.js index e524d58..184c02c 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -937,7 +937,7 @@ const spawn = { } }, stabber(x, y, radius = 25 + Math.ceil(Math.random() * 15)) { - mobs.spawn(x, y, 4, radius, "rgb(220,50,205)"); //can't have sides above 6 or collision events don't work (probably because of a convex problem) + mobs.spawn(x, y, 6, radius, "rgb(220,50,205)"); //can't have sides above 6 or collision events don't work (probably because of a convex problem) let me = mob[mob.length - 1]; me.accelMag = 0.0006 * game.accelScale; // me.g = 0.0002; //required if using 'gravity' @@ -948,54 +948,64 @@ const spawn = { me.isSpikeReset = true; Matter.Body.rotate(me, Math.PI * 0.1); spawn.shield(me, x, y); - me.onDamage = function () {}; - me.do = function () { - // this.gravity(); - this.seePlayerByLookingAt(); - this.checkStatus(); - this.attraction(); - - if (this.isSpikeReset) { - if (this.seePlayer.recall) { - const dist = Vector.sub(this.seePlayer.position, this.position); - const distMag = Vector.magnitude(dist); - if (distMag < this.radius * 7) { - //find nearest vertex - let nearestDistance = Infinity - for (let i = 0, len = this.vertices.length; i < len; i++) { - //find distance to player for each vertex - const dist = Vector.sub(this.seePlayer.position, this.vertices[i]); - const distMag = Vector.magnitude(dist); - //save the closest distance - if (distMag < nearestDistance) { - this.spikeVertex = i - nearestDistance = distMag - } - } - this.spikeLength = 1 - this.isSpikeGrowing = true; - this.isSpikeReset = false; - Matter.Body.setAngularVelocity(this, 0) - } - } - } else { - if (this.isSpikeGrowing) { - this.spikeLength += 1 - if (this.spikeLength > 9) { - this.isSpikeGrowing = false; - } - } else { - this.spikeLength -= 0.1 - if (this.spikeLength < 1) { - this.spikeLength = 1 - this.isSpikeReset = true - } - } + // me.onDamage = function () {}; + me.onDeath = function () { + if (this.spikeLength > 4) { + this.spikeLength = 4 const spike = Vector.mult(Vector.normalise(Vector.sub(this.vertices[this.spikeVertex], this.position)), this.radius * this.spikeLength) this.vertices[this.spikeVertex].x = this.position.x + spike.x this.vertices[this.spikeVertex].y = this.position.y + spike.y } }; + me.do = function () { + if (!mech.isBodiesAsleep) { + // this.gravity(); + this.seePlayerByLookingAt(); + this.checkStatus(); + this.attraction(); + + if (this.isSpikeReset) { + if (this.seePlayer.recall) { + const dist = Vector.sub(this.seePlayer.position, this.position); + const distMag = Vector.magnitude(dist); + if (distMag < this.radius * 7) { + //find nearest vertex + let nearestDistance = Infinity + for (let i = 0, len = this.vertices.length; i < len; i++) { + //find distance to player for each vertex + const dist = Vector.sub(this.seePlayer.position, this.vertices[i]); + const distMag = Vector.magnitude(dist); + //save the closest distance + if (distMag < nearestDistance) { + this.spikeVertex = i + nearestDistance = distMag + } + } + this.spikeLength = 1 + this.isSpikeGrowing = true; + this.isSpikeReset = false; + Matter.Body.setAngularVelocity(this, 0) + } + } + } else { + if (this.isSpikeGrowing) { + this.spikeLength += 1 + if (this.spikeLength > 9) { + this.isSpikeGrowing = false; + } + } else { + this.spikeLength -= 0.1 + if (this.spikeLength < 1) { + this.spikeLength = 1 + this.isSpikeReset = true + } + } + const spike = Vector.mult(Vector.normalise(Vector.sub(this.vertices[this.spikeVertex], this.position)), this.radius * this.spikeLength) + this.vertices[this.spikeVertex].x = this.position.x + spike.x + this.vertices[this.spikeVertex].y = this.position.y + spike.y + } + } + }; }, striker(x, y, radius = 14 + Math.ceil(Math.random() * 25)) { mobs.spawn(x, y, 5, radius, "rgb(221,102,119)"); diff --git a/todo.txt b/todo.txt index 7f3bf37..ce9d391 100644 --- a/todo.txt +++ b/todo.txt @@ -2,6 +2,38 @@ ************** TODO - n-gon ************** +foam - check for touching map / blocks and slow foam down rather then bounce off walls +quantum foam should just skip the shield + +red flashes when you take damage were replaced with the color of your energy bar + When you have mass energy equivalence + +mod - missiles: fire 3 small missiles + disables missile replication mod + +lore - a robot (the player) gains self awareness + each mod/gun/field is a new tech + all the technology leads to the singularity + each game run is actually the mech simulating a possible escape + this is why the graphics are so bad, its just a simulation + final mod is "this is just a simulation" + you get immortality and Infinity damage + the next level is the final level + when you die with Quantum Immortality there is a chance of lore text + +atmosphere levels: change the pace, give the user a rest between combat + low or no combat, but more graphics + explore lore + find power ups in "wrecked" mechs representing previous simulations + how you could leave something in one simulation that effects a different simulation + Maybe some strange quantum physics principle. + add text for player thoughts? + simple puzzles + cool looking stuff + large rotating fan that the player has to move through + nonaggressive mobs + in the final level you see your self at the starting level, with the wires + you shoot your self to wake up? bullets cost 5 life instead of ammo, but return 5 life when they hit a mob replace life with energy or ammo? @@ -37,8 +69,6 @@ boss mob - just a faster and larger version of a springer mob mob - time skipper: sends a pulse wave out that will cause time to jump forward 1 second. -mob stabber - extends one vector like the shooter, but quickly in order to stab - mob sniper - targeting laser, then a high speed, no gravity bullet mod - increase laser bot range, and reduce energy drain @@ -50,35 +80,9 @@ mod - blocks stun mobs settings - custom keys binding -lore - a robot (the player) gains self awareness - each mod/gun/field is a new tech - all the technology leads to the singularity - each game run is actually the mech simulating a possible escape - this is why the graphics are so bad, its just a simulation - final mod is "this is just a simulation" - you get immortality and Infinity damage - the next level is the final level - when you die with Quantum Immortality there is a chance of lore text - -atmosphere levels: change the pace, give the user a rest between combat - low or no combat, but more graphics - explore lore - find power ups in "wrecked" mechs representing previous simulations - how you could leave something in one simulation that effects a different simulation - Maybe some strange quantum physics principle. - add text for player thoughts? - simple puzzles - cool looking stuff - large rotating fan that the player has to move through - nonaggressive mobs - in the final level you see your self at the starting level, with the wires - you shoot your self to wake up? - css transition for pause menu -mod - do extra damage based on your speed - do more damage when not moving? - take less damage when not moving? +mod - do more damage when not moving? gun/field: portals use the code from mines to get them to stick to walls