From 624553186cc74086de237667dc697a90e8002d41 Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 29 Dec 2019 15:27:05 -0800 Subject: [PATCH] difficulty rebalance, gun balance, draft polish --- index.html | 13 +++++++------ js/bullets.js | 45 +++++++++++++++++++++++---------------------- js/game.js | 13 +++++-------- js/level.js | 48 +++++++++++++++++++++++------------------------- js/player.js | 8 ++++---- js/powerups.js | 21 +++++++++++---------- js/spawn.js | 27 ++++++++++++++------------- 7 files changed, 87 insertions(+), 88 deletions(-) diff --git a/index.html b/index.html index dded14a..b86a359 100644 --- a/index.html +++ b/index.html @@ -80,11 +80,13 @@
+ Select 5 power ups and see how far you can progress. custom + When you gain a new a power up choose between 3 random options. draft @@ -96,14 +98,13 @@
- +
diff --git a/js/bullets.js b/js/bullets.js index 0ce979b..89b765b 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -18,7 +18,7 @@ const b = { isModDroneOnDamage: null, modExtraDmg: null, annihilation: null, - isModFullHeal: null, + isModRecursiveHealing: null, modSquirrelFx: null, modIsCrit: null, modMoreDrops: null, @@ -41,7 +41,7 @@ const b = { b.modSpores = 0; b.modExtraDmg = 0; b.modAnnihilation = false; - b.isModFullHeal = false; + b.isModRecursiveHealing = false; b.modSquirrelFx = 1; b.modIsCrit = false; b.modMoreDrops = 0; @@ -199,10 +199,10 @@ const b = { }, { name: "recursive healing", - description: "healing power ups bring you to max health", + description: "healing power ups are twice as effective", have: false, //18 effect: () => { // good with ablative synthesis, melee builds - b.isModFullHeal = true + b.isModRecursiveHealing = true } }, { @@ -215,10 +215,10 @@ const b = { }, { name: "Bayesian inference", - description: "20% chance for double power ups to drop", + description: "15% chance for double power ups to drop", have: false, //20 effect: () => { // good with long term planning - b.modMoreDrops = 0.20; + b.modMoreDrops = 0.15; } }, { @@ -494,8 +494,8 @@ const b = { knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 30); mob[i].force.x += knock.x; mob[i].force.y += knock.y; - radius *= 0.9 //reduced range for each additional explosion target - damageScale *= 0.75 //reduced damage for each additional explosion target + radius *= 0.93 //reduced range for each additional explosion target + damageScale *= 0.8 //reduced damage for each additional explosion target } else if (!mob[i].seePlayer.recall && dist < alertRange) { mob[i].locatePlayer(); knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 50); @@ -587,8 +587,8 @@ const b = { knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 30); mob[i].force.x += knock.x; mob[i].force.y += knock.y; - radius *= 0.9 //reduced range for each additional explosion target - damageScale *= 0.75 //reduced damage for each additional explosion target + radius *= 0.93 //reduced range for each additional explosion target + damageScale *= 0.8 //reduced damage for each additional explosion target } else if (!mob[i].seePlayer.recall && dist < alertRange) { mob[i].locatePlayer(); knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 50); @@ -609,7 +609,7 @@ const b = { restitution: 0.5, angle: Math.random() * 2 * Math.PI, friction: 0, - frictionAir: 0.018, + frictionAir: 0.02, dmg: 1.8, //damage done in addition to the damage from momentum classType: "bullet", collisionFilter: { @@ -630,7 +630,7 @@ const b = { this.lockedOn = null; let closeDist = Infinity; for (let i = 0, len = mob.length; i < len; ++i) { - if (Matter.Query.ray(map, this.position, mob[i].position).length === 0) { + if (mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) { // Matter.Query.ray(body, this.position, mob[i].position).length === 0 const targetVector = Vector.sub(this.position, mob[i].position) const dist = Vector.magnitude(targetVector); @@ -703,6 +703,7 @@ const b = { let closeDist = Infinity; for (let i = 0, len = mob.length; i < len; ++i) { if ( + mob[i].dropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && Matter.Query.ray(body, this.position, mob[i].position).length === 0 ) { @@ -789,7 +790,7 @@ const b = { have: false, isStarterGun: true, fire() { - mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 65 : 45) * b.modFireRate); // cool down + mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 50 : 35) * b.modFireRate); // cool down b.muzzleFlash(35); // mobs.alert(650); @@ -856,32 +857,32 @@ const b = { name: "fléchettes", //3 description: "fire a volley of precise high velocity needles", ammo: 0, - ammoPack: 70, + ammoPack: 75, have: false, isStarterGun: true, count: 0, //used to track how many shots are in a volley before a big CD lastFireCycle: 0, //use to remember how longs its been since last fire, used to reset count fire() { - const CD = (mech.crouch) ? 35 : 25 + const CD = (mech.crouch) ? 40 : 20 if (this.lastFireCycle + CD < mech.cycle) this.count = 0 //reset count if it cycles past the CD this.lastFireCycle = mech.cycle - if (this.count > ((mech.crouch) ? 4 : 1)) { + if (this.count > ((mech.crouch) ? 6 : 1)) { this.count = 0 mech.fireCDcycle = mech.cycle + Math.floor(CD * b.modFireRate); // cool down } else { this.count++ - mech.fireCDcycle = mech.cycle + Math.floor(3 * b.modFireRate); // cool down + mech.fireCDcycle = mech.cycle + Math.floor(2 * b.modFireRate); // cool down } const me = bullet.length; bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle), 45 * b.modBulletSize, 1.4 * b.modBulletSize, b.fireAttributes(mech.angle)); bullet[me].endCycle = game.cycle + Math.floor(180 * b.isModBulletsLastLonger); - bullet[me].dmg = 0.9 + b.modExtraDmg; + bullet[me].dmg = 1 + b.modExtraDmg; bullet[me].do = function () { - this.force.y += this.mass * 0.0002; //low gravity + if (this.speed < 10) this.force.y += this.mass * 0.0003; //no gravity until it slows don to improve aiming }; - const SPEED = 49 + const SPEED = 50 Matter.Body.setVelocity(bullet[me], { x: mech.Vx / 2 + SPEED * Math.cos(mech.angle), y: mech.Vy / 2 + SPEED * Math.sin(mech.angle) @@ -1036,9 +1037,9 @@ const b = { } else { // charging on mouse down mech.fireCDcycle = Infinity //can't fire until mouse is released if (mech.crouch) { - this.charge = this.charge * 0.97 + 0.03 // this.charge converges to 1 + this.charge = this.charge * 0.96 + 0.04 // this.charge converges to 1 } else { - this.charge = this.charge * 0.987 + 0.013 // this.charge converges to 1 + this.charge = this.charge * 0.98 + 0.02 // this.charge converges to 1 } //gently push away mobs while charging diff --git a/js/game.js b/js/game.js index 0b21d76..508b82e 100644 --- a/js/game.js +++ b/js/game.js @@ -82,9 +82,9 @@ const game = { delta: 1000 / 60, //speed of game engine //looks like it has to be 16 to match player input buttonCD: 0, isBodyDamage: true, - isEasyMode: false, + difficultyMode: null, + difficulty: 0, isDraftMode: false, - difficulty: null, // dropFPS(cap = 40, time = 15) { // game.fpsCap = cap // game.fpsInterval = 1000 / game.fpsCap; @@ -473,13 +473,10 @@ const game = { game.accelScale = 1; game.lookFreqScale = 1; game.CDScale = 1; - if (document.getElementById("difficulty-select").value === 'easy') { - game.difficulty = 0; - game.isEasyMode = true; + game.difficultyMode = Number(document.getElementById("difficulty-select").value) + if (game.difficultyMode === 0) { + game.difficultyMode = 1 level.difficultyDecrease(6); - } else { - game.difficulty = parseInt(document.getElementById("difficulty-select").value) - level.difficultyIncrease(game.difficulty) } game.clearNow = true; diff --git a/js/level.js b/js/level.js index 7398eba..5e0cc8d 100644 --- a/js/level.js +++ b/js/level.js @@ -41,21 +41,22 @@ const level = { difficultyIncrease(num = 1) { // if (level.isBuildRun) num++ for (let i = 0; i < num; i++) { - game.dmgScale += 0.2; //damage done by mobs increases each level - b.dmgScale *= 0.95; //damage done by player decreases each level - game.accelScale *= 1.05 //mob acceleration increases each level - game.lookFreqScale *= 0.95 //mob cycles between looks decreases each level - game.CDScale *= 0.95 //mob CD time decreases each level + game.difficulty++ + game.dmgScale += 0.15; //damage done by mobs increases each level + b.dmgScale *= 0.94; //damage done by player decreases each level + game.accelScale *= 1.03 //mob acceleration increases each level + game.lookFreqScale *= 0.97 //mob cycles between looks decreases each level + game.CDScale *= 0.97 //mob CD time decreases each level } }, difficultyDecrease(num = 1) { //used in easy mode for game.reset() for (let i = 0; i < num; i++) { - game.dmgScale -= 0.2; //damage done by mobs increases each level + game.dmgScale -= 0.15; //damage done by mobs increases each level if (game.dmgScale < 0.1) game.dmgScale = 0.1; - b.dmgScale /= 0.95; //damage done by player decreases each level - game.accelScale /= 1.05 //mob acceleration increases each level - game.lookFreqScale /= 0.95 //mob cycles between looks decreases each level - game.CDScale /= 0.95 //mob CD time decreases each level + b.dmgScale /= 0.94; //damage done by player decreases each level + game.accelScale /= 1.03 //mob acceleration increases each level + game.lookFreqScale /= 0.97 //mob cycles between looks decreases each level + game.CDScale /= 0.97 //mob CD time decreases each level } }, //****************************************************************************************************************** @@ -112,11 +113,11 @@ const level = { // powerUps.spawn(450, -400, "mod", false, 6); // powerUps.spawn(450, -400, "mod", false); // spawn.bodyRect(-45, -100, 40, 50); - // spawn.shooter(800, -1050); - // spawn.shooter(400, -1050); - // spawn.shooter(1200, -1050); + spawn.groupBoss(800, -1050); + spawn.shooter(400, -1050); + spawn.shooter(1200, -1050); // spawn.groupBoss(-600, -550); - // spawn.hopper(800, -150); + spawn.hopper(800, -150); // spawn.beamer(800, -150); // spawn.grower(800, -250); // spawn.blinker(800, -250, 40); @@ -325,12 +326,12 @@ const level = { powerUps.spawn(2050, -150, "heal", false); //starting gun // powerUps.spawn(2050, -150, "field", false); //starting gun powerUps.spawn(2300, -150, "gun", false); //starting gun - if (game.isEasyMode) { - // powerUps.spawn(2050, -150, "mod", false); //starting gun - // powerUps.spawn(2050, -150, "mod", false); //starting gun - // powerUps.spawn(-100, -150, "ammo", false); //starting gun - powerUps.spawn(-100, 0, "heal", false); //starting gun - } + // if (game.isEasyMode) { + // // powerUps.spawn(2050, -150, "mod", false); //starting gun + // // powerUps.spawn(2050, -150, "mod", false); //starting gun + // // powerUps.spawn(-100, -150, "ammo", false); //starting gun + // powerUps.spawn(-100, 0, "heal", false); //starting gun + // } spawn.wireFoot(); spawn.wireFootLeft(); @@ -1459,11 +1460,8 @@ const level = { nextLevel() { //enter when player isn't falling if (player.velocity.y < 0.1) { - game.difficulty++; - if (game.difficulty > 1) { - level.difficultyIncrease() - if (level.isBuildRun) level.difficultyIncrease() - } + //increase difficulty based on modes + level.difficultyIncrease(game.difficultyMode + level.isBuildRun) //cycles map to next level level.levelsCleared++; level.onLevel++; diff --git a/js/player.js b/js/player.js index 7af49ed..fb9a7a3 100644 --- a/js/player.js +++ b/js/player.js @@ -1143,12 +1143,12 @@ const mech = { mech.holding(); mech.throw(); } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed - const DRAIN = 0.0006 + const DRAIN = 0.0005 if (mech.fieldMeter > DRAIN) { mech.fieldMeter -= DRAIN; mech.grabPowerUp(); mech.lookForPickUp(); - mech.pushMobs360(120); + mech.pushMobs360(130); //calculate laser collision let best; @@ -1222,7 +1222,7 @@ const mech = { y: best.y }; if (best.who.alive) { - const dmg = 0.35 * b.dmgScale; //********** SCALE DAMAGE HERE ********************* + const dmg = 0.4 * b.dmgScale; //********** SCALE DAMAGE HERE ********************* best.who.damage(dmg); best.who.locatePlayer(); @@ -1311,7 +1311,7 @@ const mech = { if (mech.fieldMeter > DRAIN) { mech.grabPowerUp(); mech.lookForPickUp(170); - mech.pushMobs360(170); + mech.pushMobs360(200); //look for nearby objects to make zero-g function zeroG(who, mag = 1.06) { for (let i = 0, len = who.length; i < len; ++i) { diff --git a/js/powerups.js b/js/powerups.js index 0e2ac8a..b556e74 100644 --- a/js/powerups.js +++ b/js/powerups.js @@ -39,9 +39,10 @@ const powerUps = { return 40 * Math.sqrt(0.1 + Math.random() * 0.5); }, effect() { - let heal = (this.size / 40) ** 2 + let heal = ((this.size / 40) ** 2) + heal /= (0.95 + game.difficulty * 0.01) heal = Math.min(mech.maxHealth - mech.health, heal) - if (b.isModFullHeal) heal = mech.maxHealth + if (b.isModRecursiveHealing) heal *= 2 mech.addHealth(heal); if (heal > 0) game.makeTextLog("
  heal " + (heal * 100).toFixed(0) + "%", 300) } @@ -76,8 +77,8 @@ const powerUps = { if (!game.lastLogTime) game.makeTextLog("+energy", 300); } else { //ammo given scales as mobs take more hits to kill - let ammo = Math.ceil((target.ammoPack * (0.45 + 0.06 * Math.random())) / Math.sqrt(b.dmgScale)); - if (level.isBuildRun) ammo = Math.floor(ammo * 1.2) + let ammo = Math.ceil((target.ammoPack * (0.4 + 0.05 * Math.random()))); + if (level.isBuildRun) ammo = Math.floor(ammo * 1.1) //extra ammo on build run because no ammo from getting a new gun target.ammo += ammo; game.updateGunHUD(); game.makeTextLog("
  +" + ammo + " ammo for " + target.name + "", 300); @@ -269,12 +270,12 @@ const powerUps = { if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "ammo"); return; } - if (Math.random() < 0.004 * (4 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun to drop + if (Math.random() < 0.004 * (4 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun up to 4 powerUps.spawn(x, y, "gun"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun"); return; } - if (Math.random() < 0.0035 * (7 - b.modCount)) { + if (Math.random() < 0.0035 * (9 - b.modCount)) { //a new mod has a low chance for each not acquired mod up to 7 powerUps.spawn(x, y, "mod"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod"); return; @@ -289,16 +290,16 @@ const powerUps = { if (mech.fieldMode === 0) { powerUps.spawn(x, y, "field") if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field") - } else if (Math.random() < 0.4) { + } else if (Math.random() < 0.5) { powerUps.spawn(x, y, "mod") if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod") } else if (Math.random() < 0.3) { powerUps.spawn(x, y, "gun") if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun") - } else if (Math.random() < 0.15) { + } else if (Math.random() < 0.1) { powerUps.spawn(x, y, "field"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field"); - } else if (mech.health < 0.6) { + } else if (mech.health < 0.65) { powerUps.spawn(x, y, "heal"); powerUps.spawn(x, y, "heal"); if (Math.random() < b.modMoreDrops) { @@ -322,7 +323,7 @@ const powerUps = { } }, spawnStartingPowerUps(x, y) { //used for map specific power ups, mostly to give player a starting gun - if (b.inventory.length < 2 || game.isEasyMode) { + if (b.inventory.length < 2) { powerUps.spawn(x, y, "gun", false); //starting gun } else { powerUps.spawnRandomPowerUp(x, y); diff --git a/js/spawn.js b/js/spawn.js index ca75ddd..ebff30d 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -79,21 +79,22 @@ const spawn = { //mob templates ********************************************************************************************* //*********************************************************************************************************** - groupBoss(x, y, num = 5 + Math.random() * 8) { + groupBoss(x, y, num = 3 + Math.random() * 8) { for (let i = 0; i < num; i++) { const radius = 25 + Math.floor(Math.random() * 20) spawn.grouper(x + Math.random() * radius, y + Math.random() * radius, radius); } }, - grouper(x, y, radius = 27 + Math.floor(Math.random() * 10)) { + grouper(x, y, radius = 25 + Math.floor(Math.random() * 20)) { mobs.spawn(x, y, 4, radius, "#777"); let me = mob[mob.length - 1]; - me.g = 0.0002; //required if using 'gravity' - me.accelMag = 0.0007 * game.accelScale; + me.g = 0.00015; //required if using 'gravity' + me.accelMag = 0.0008 * game.accelScale; me.groupingRangeMax = 250000 + Math.random() * 100000; me.groupingRangeMin = (radius * 8) * (radius * 8); me.groupingStrength = 0.0005 me.memory = 200; + me.isGrouper = true; me.do = function () { this.gravity(); @@ -103,7 +104,7 @@ const spawn = { //tether to other blocks ctx.beginPath(); for (let i = 0, len = mob.length; i < len; i++) { - if (mob[i] != this && mob[i].dropPowerUp) { //don't tether to self, bullets, shields, ... + if (mob[i].isGrouper && mob[i] != this && mob[i].dropPowerUp) { //don't tether to self, bullets, shields, ... const distance2 = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) if (distance2 < this.groupingRangeMax) { if (!mob[i].seePlayer.recall) mob[i].seePlayerByDistAndLOS(); //wake up sleepy mobs @@ -232,7 +233,7 @@ const spawn = { me.accelMag = 0.001 * game.accelScale;; me.g = me.accelMag * 0.6; //required if using 'gravity' me.memory = 50; - if (Math.random() < Math.min((game.difficulty - 1) * 0.1, 0.7)) spawn.shield(me, x, y); + if (Math.random() < Math.min((game.difficulty - 1) * 0.07, 0.5)) spawn.shield(me, x, y); me.do = function () { this.gravity(); this.seePlayerCheck(); @@ -292,7 +293,7 @@ const spawn = { me.onDeath = function () { this.removeCons(); }; - if (Math.random() < Math.min((game.difficulty - 1) * 0.1, 0.7)) spawn.shield(me, x, y); + if (Math.random() < Math.min((game.difficulty - 1) * 0.07, 0.5)) spawn.shield(me, x, y); me.do = function () { this.gravity(); this.searchSpring(); @@ -561,7 +562,7 @@ const spawn = { me.accelMag = 0.0005 * game.accelScale; me.frictionStatic = 0; me.friction = 0; - if (Math.random() < Math.min(0.2 + (game.difficulty - 1) * 0.1, 0.7)) spawn.shield(me, x, y); + if (Math.random() < Math.min(0.2 + (game.difficulty - 1) * 0.07, 0.5)) spawn.shield(me, x, y); me.do = function () { this.seePlayerByLookingAt(); this.attraction(); @@ -861,7 +862,7 @@ const spawn = { x: 0, y: 0 }; - if (Math.random() < Math.min(0.15 + (game.difficulty - 1) * 0.1, 0.7)) spawn.shield(me, x, y); + if (Math.random() < Math.min(0.15 + (game.difficulty - 1) * 0.07, 0.5)) spawn.shield(me, x, y); me.do = function () { this.seePlayerByLookingAt(); this.fire(); @@ -931,7 +932,7 @@ const spawn = { }); } }; - if (Math.random() < Math.min((game.difficulty - 1) * 0.1, 0.5)) spawn.shield(me, x, y); + if (Math.random() < Math.min((game.difficulty - 1) * 0.05, 0.4)) spawn.shield(me, x, y); me.do = function () { this.gravity(); this.seePlayerCheck(); @@ -980,7 +981,7 @@ const spawn = { me.laserRange = 500; Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger spawn.shield(me, x, y); - if (Math.random() < Math.min((game.difficulty - 1) * 0.1, 0.7)) spawn.shield(me, x, y); + if (Math.random() < Math.min((game.difficulty - 1) * 0.07, 0.5)) spawn.shield(me, x, y); me.onDeath = function () { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; @@ -1021,7 +1022,7 @@ const spawn = { me.memory = 20; Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger spawn.shield(me, x, y); - if (Math.random() < Math.min((game.difficulty - 1) * 0.1, 0.7)) spawn.shield(me, x, y); + if (Math.random() < Math.min((game.difficulty - 1) * 0.07, 0.5)) spawn.shield(me, x, y); me.onDeath = function () { powerUps.spawnBossPowerUp(this.position.x, this.position.y) @@ -1137,7 +1138,7 @@ const spawn = { l = Math.ceil(Math.random() * 80) + 30, stiffness = Math.random() * 0.06 + 0.01 ) { - this.allowShields = false; //dont' want shields on boss mobs + this.allowShields = false; //don't want shields on boss mobs for (let i = 0; i < nodes; ++i) { let whoSpawn = spawn; if (spawn === "random") {