From aec697c63d51e0850039477256283d210173d772 Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 29 Sep 2019 08:21:33 -0700 Subject: [PATCH] field balance --- js/bullets.js | 2 +- js/game.js | 5 +- js/level.js | 2 +- js/player.js | 180 ++++++++++++++++++++++++------------------------- js/powerups.js | 6 +- 5 files changed, 95 insertions(+), 100 deletions(-) diff --git a/js/bullets.js b/js/bullets.js index 99b794b..e3402ad 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -308,7 +308,7 @@ const b = { }; const laserHitMob = function (dmg) { if (best.who.alive) { - dmg *= b.dmgScale * 0.045; + dmg *= b.dmgScale * 0.06; best.who.damage(dmg); best.who.locatePlayer(); //draw mob damage circle diff --git a/js/game.js b/js/game.js index ed6e843..5995907 100644 --- a/js/game.js +++ b/js/game.js @@ -38,11 +38,11 @@ const game = { mobs.draw(); game.draw.cons(); game.draw.body(); + mobs.loop(); mech.draw(); mech.hold(); level.drawFills(); game.draw.drawMapPath(); - mobs.loop(); b.draw(); b.fire(); game.drawCircle(); @@ -222,7 +222,8 @@ const game = { paused: false, testing: false, //testing mode: shows wireframe and some variables cycle: 0, //total cycles, 60 per second - fpsCap: 72, //limits frames per second to 144/2=72+1=73, on most monitors the fps is capped at 60fps by the hardware + fpsCap: 72, //limits frames per second to 144/2=72, on most monitors the fps is capped at 60fps by the hardware + fpsCapDefault: 72, //use to change fpsCap back to normal after a hit from a mob cyclePaused: 0, fallHeight: 3000, //below this y position the player dies lastTimeStamp: 0, //tracks time stamps for measuring delta diff --git a/js/level.js b/js/level.js index 5678d64..40a5f0b 100644 --- a/js/level.js +++ b/js/level.js @@ -24,7 +24,7 @@ const level = { // game.levelsCleared = 3; //for testing to simulate possible mobs spawns // b.giveGuns(0) // set a starting gun for testing - // mech.fieldUpgrades[7]() //give a field power up for testing + mech.fieldUpgrades[7]() //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 diff --git a/js/player.js b/js/player.js index b937159..3da46c1 100644 --- a/js/player.js +++ b/js/player.js @@ -435,14 +435,14 @@ const mech = { game.fpsCap = 4 //40 - Math.min(25, 100 * dmg) game.fpsInterval = 1000 / game.fpsCap; } else { - game.fpsCap = 72 + game.fpsCap = game.fpsCapDefault game.fpsInterval = 1000 / game.fpsCap; } mech.defaultFPSCycle = game.cycle const normalFPS = function () { if (mech.defaultFPSCycle < game.cycle) { //back to default values - game.fpsCap = 72 + game.fpsCap = game.fpsCapDefault game.fpsInterval = 1000 / game.fpsCap; document.getElementById("dmg").style.transition = "opacity 1s"; document.getElementById("dmg").style.opacity = "0"; @@ -484,6 +484,7 @@ const mech = { throwChargeMax: 0, fieldFireCD: 0, fieldDamage: 0, + fieldBlockScale: 0, grabRange: 0, fieldArc: 0, fieldThreshold: 0, @@ -500,6 +501,7 @@ const mech = { this.throwChargeMax = 50; this.fieldFireCD = 15; this.fieldDamage = 0; // a value of 1.0 kills a small mob in 2-3 hits on level 1 + this.fieldBlockScale = 1; //scale energy loss after collision with mob this.grabRange = 175; this.fieldArc = 0.2; this.calculateFieldThreshold(); @@ -710,9 +712,37 @@ const mech = { // push all mobs in range for (let i = 0, len = mob.length; i < len; ++i) { if (this.lookingAt(mob[i]) && Matter.Vector.magnitude(Matter.Vector.sub(mob[i].position, this.pos)) < this.grabRange && Matter.Query.ray(map, mob[i].position, this.pos).length === 0) { + const fieldBlockCost = Math.max(0.02, mob[i].mass * 0.012) //0.012 + if (this.fieldMeter > fieldBlockCost) { + this.fieldMeter -= fieldBlockCost * this.fieldBlockScale; + if (this.fieldDamage) mob[i].damage(b.dmgScale * this.fieldDamage); + mob[i].locatePlayer(); + this.drawHold(mob[i]); + //mob and player knock back + const angle = Math.atan2(player.position.y - mob[i].position.y, player.position.x - mob[i].position.x); + const mass = Math.min(Math.sqrt(mob[i].mass), 4); + // console.log(mob[i].mass, Math.sqrt(mob[i].mass), mass) + Matter.Body.setVelocity(mob[i], { + x: player.velocity.x - (15 * Math.cos(angle)) / mass, + y: player.velocity.y - (15 * Math.sin(angle)) / mass + }); + Matter.Body.setVelocity(player, { + x: player.velocity.x + 5 * Math.cos(angle) * mass, + y: player.velocity.y + 5 * Math.sin(angle) * mass + }); + } + } + } + }, + pushMobs360(range = this.grabRange * 0.75) { + // push all mobs in range + for (let i = 0, len = mob.length; i < len; ++i) { + if (Matter.Vector.magnitude(Matter.Vector.sub(mob[i].position, this.pos)) < range && Matter.Query.ray(map, mob[i].position, this.pos).length === 0) { const fieldBlockCost = Math.max(0.02, mob[i].mass * 0.012) if (this.fieldMeter > fieldBlockCost) { - this.fieldMeter -= fieldBlockCost; + this.fieldMeter -= fieldBlockCost * this.fieldBlockScale; + if (this.fieldMeter < 0) this.fieldMeter = 0 + if (this.fieldDamage) mob[i].damage(b.dmgScale * this.fieldDamage); mob[i].locatePlayer(); this.drawHold(mob[i]); @@ -808,7 +838,7 @@ const mech = { mech.grabPowerUp(); mech.pushMobs(); mech.lookForPickUp(); - } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle) { //holding, but field button is released + } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released mech.pickUp(); } else { 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) @@ -818,11 +848,12 @@ const mech = { }, () => { mech.fieldMode = 1; - game.makeTextLog("Time Dilation Field
(right mouse or space bar)

field slows objects in range

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

field slows objects in range
decreased field efficiency

", 1200); //
field does not shield player mech.setHoldDefaults(); - mech.fieldArc = 1; //field covers full 360 degrees - mech.calculateFieldThreshold(); + mech.fieldBlockScale = 7; + // mech.fieldArc = 1; //field covers full 360 degrees + // mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.hold = function () { if (mech.isHolding) { @@ -835,6 +866,7 @@ const mech = { mech.fieldMeter -= DRAIN; mech.grabPowerUp(); // mech.pushMobs(); + mech.pushMobs360(); mech.lookForPickUp(130); const range = 900; @@ -865,7 +897,7 @@ const mech = { } else { mech.fieldCDcycle = game.cycle + 120; } - } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle) { //holding, but field button is released + } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released mech.pickUp(); } else { 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) @@ -885,6 +917,7 @@ const mech = { // const startingArc = 0. mech.fieldArc = 0.09 + mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) const STARTING_RANGE = 30 mech.grabRange = STARTING_RANGE; @@ -924,7 +957,7 @@ const mech = { mech.grabPowerUp(); mech.pushMobs(); mech.lookForPickUp(); - } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle) { //holding, but field button is released + } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released mech.pickUp(); mech.grabRange = STARTING_RANGE; } else { @@ -936,13 +969,14 @@ const mech = { }, () => { mech.fieldMode = 3; - game.makeTextLog("Negative Mass Field
(right mouse or space bar)

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

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

field nullifies gravity
player can hold more massive objects
decreased field efficiency

", 1200); mech.setHoldDefaults(); mech.holdingMassScale = 0.05; //can hold heavier blocks with lower cost to jumping + mech.fieldBlockScale = 10; // mech.fieldArc = 1; //field covers full 360 degrees // mech.grabRange = 150; - mech.fieldArc = 1 //0.08; - mech.calculateFieldThreshold(); + // mech.fieldArc = 1 //0.08; + // mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.hold = function () { const range = 500 @@ -951,23 +985,10 @@ const mech = { mech.holding(); mech.throw(); } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < game.cycle) { //push away - const DRAIN = 0.0005 //mech.fieldRegen = 0.0015 + const DRAIN = 0.001 //mech.fieldRegen = 0.0015 if (mech.fieldMeter > DRAIN) { mech.fieldMeter -= DRAIN; - - // //draw 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 = 13; - // ctx.lineTo(mech.pos.x + eye * Math.cos(this.angle), mech.pos.y + eye * 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(); - // mech.drawField(); - // mech.pushMobs(); + mech.pushMobs360(); mech.grabPowerUp(); mech.lookForPickUp(); //look for nearby objects to make zero-g @@ -1024,7 +1045,7 @@ const mech = { //trigger cool down mech.fieldCDcycle = game.cycle + 120; } - } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle && mech.fieldCDcycle < game.cycle) { //holding, but field button is released + } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released mech.pickUp(); } else { 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) @@ -1036,9 +1057,10 @@ const mech = { mech.fieldMode = 4; game.makeTextLog("Zero-Point Energy Field
(right mouse or space bar)

improved energy regeneration
field emitter shield surrounds player

", 1200); mech.setHoldDefaults(); + // mech.fieldBlockScale = 1; mech.fieldRegen = 0.01; //0.0015 mech.fieldArc = 1; //field covers full 360 degrees - mech.calculateFieldThreshold(); + mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.hold = function () { mech.grabRange = 190 + 35 * Math.sin(game.cycle / 30) @@ -1050,7 +1072,7 @@ const mech = { } else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed mech.drawField(); mech.grabPowerUp(); - mech.pushMobs(); + mech.pushMobs360(); mech.lookForPickUp(); } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle) { //holding, but field button is released mech.pickUp(); @@ -1062,40 +1084,27 @@ const mech = { }, () => { mech.fieldMode = 5; - game.makeTextLog("Nano-Scale Manufacturing
(passive effect)

excess field energy builds drones
field does not shield player

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

excess field energy builds drones
shield has decreased efficiency

", 1200); mech.setHoldDefaults(); - mech.grabRange = 160; - mech.fieldArc = 0.11; //0.2 is normal - // mech.fieldRegen = 0.0008 //0.0015; + mech.fieldBlockScale = 10; + mech.grabRange = 155; + mech.fieldArc = 0.1; //0.2 is normal + mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.hold = function () { if (mech.fieldMeter === 1) { mech.fieldMeter -= 0.21; b.guns[12].fire() //spawn drone } - if (mech.isHolding) { mech.drawHold(mech.holdingTarget); mech.holding(); mech.throw(); } else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed - //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); - let eye = 13; - ctx.lineTo(mech.pos.x + eye * Math.cos(this.angle), mech.pos.y + eye * 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.12 + 0.06 * Math.random()) + ")"; - } - ctx.fill(); - - // mech.pushMobs(); - // mech.drawField(); + mech.pushMobs(); + mech.drawField(); mech.grabPowerUp(); mech.lookForPickUp(); - } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle) { //holding, but field button is released + } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released mech.pickUp(); } else { 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) @@ -1105,12 +1114,10 @@ const mech = { }, () => { mech.fieldMode = 6; - game.makeTextLog("Metamaterial Refractive Optics
(right mouse or space bar)

localized invisibility field
after shielding player field drains to zero

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

localized invisibility field
decreased field efficiency

", 1200); mech.setHoldDefaults(); - mech.grabRange = 150; - mech.fieldArc = 1; //0.2 is normal - // mech.fieldArc = 1; //field covers full 360 degrees - mech.calculateFieldThreshold(); + mech.fieldBlockScale = 10; + mech.grabRange = 140; mech.hold = function () { mech.isStealth = false //isStealth is checked in mob foundPlayer() @@ -1136,38 +1143,13 @@ const mech = { ctx.fillStyle = `rgba(0,30,50,${0.5+0.07*Math.random()})` //"rgba(210,230," + HUE + ",0.5)"; ctx.fill(); - // mech.drawField(); - - // push all mobs in range - for (let i = 0, len = mob.length; i < len; ++i) { - if (this.lookingAt(mob[i]) && Matter.Vector.magnitude(Matter.Vector.sub(mob[i].position, this.pos)) < this.grabRange && Matter.Query.ray(map, mob[i].position, this.pos).length === 0) { - const fieldBlockCost = Math.max(0.02, mob[i].mass * 0.012) - if (this.fieldMeter > fieldBlockCost) { - this.fieldMeter = 0; //any mob push sets field to zero for stealth - if (this.fieldDamage) mob[i].damage(b.dmgScale * this.fieldDamage); - mob[i].locatePlayer(); - this.drawHold(mob[i]); - //mob and player knock back - const angle = Math.atan2(player.position.y - mob[i].position.y, player.position.x - mob[i].position.x); - const mass = Math.min(Math.sqrt(mob[i].mass), 4); - // console.log(mob[i].mass, Math.sqrt(mob[i].mass), mass) - Matter.Body.setVelocity(mob[i], { - x: player.velocity.x - (15 * Math.cos(angle)) / mass, - y: player.velocity.y - (15 * Math.sin(angle)) / mass - }); - Matter.Body.setVelocity(player, { - x: player.velocity.x + 5 * Math.cos(angle) * mass, - y: player.velocity.y + 5 * Math.sin(angle) * mass - }); - } - } - } + mech.pushMobs360(); mech.grabPowerUp(); mech.lookForPickUp(); } else { mech.fieldCDcycle = game.cycle + 120; } - } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle) { //holding, but field button is released + } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released mech.pickUp(); } else { 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) @@ -1177,14 +1159,10 @@ const mech = { }, () => { mech.fieldMode = 7; - game.makeTextLog("Thermal Radiation Field
(right mouse or space bar)

field size grows while field is active
damages all targets within range, including player

", 1200); - //
field does not shield player
- // 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); + game.makeTextLog("Thermal Radiation Field
(right mouse or space bar)

field grows while active
damages all targets within range, including player
decreased field efficiency

", 1200); mech.setHoldDefaults(); - // mech.grabRange = 160; - mech.fieldArc = 1; //0.2 is normal + mech.fieldBlockScale = 5; mech.rangeSmoothing = 0 - // mech.fieldRegen = 0.0008 //0.0015; mech.hold = function () { if (mech.isHolding) { mech.drawHold(mech.holdingTarget); @@ -1193,6 +1171,7 @@ const mech = { } else if ((keys[32] || game.mouseDownRight && mech.fieldCDcycle < game.cycle)) { //not hold but field button is pressed mech.grabPowerUp(); mech.lookForPickUp(); + mech.pushMobs360(150); // //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); @@ -1215,13 +1194,28 @@ const mech = { mech.grabRange = mech.grabRange * 0.997 + (1350 + 150 * Math.cos(game.cycle / 30)) * 0.003 let gradient = ctx.createRadialGradient(this.pos.x, this.pos.y, 0, this.pos.x, this.pos.y, mech.grabRange); 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)'); + gradient.addColorStop(1, 'rgba(255,0,50,' + (0.4 + 0.2 * Math.random()) + ')'); + ctx.beginPath(); - ctx.arc(this.pos.x, this.pos.y, mech.grabRange, 0, 2 * Math.PI); + const RAND = 10 + 0.1 * mech.grabRange + let x = mech.grabRange * Math.cos(0) + RAND * (Math.random() - 0.5) + let y = mech.grabRange * Math.sin(0) + RAND * (Math.random() - 0.5) + ctx.moveTo(this.pos.x + x, this.pos.y + y) + for (let A = 0.314, end = 2 * Math.PI - 0.314; A < end; A += 0.314) { + x = mech.grabRange * Math.cos(A) + RAND * (Math.random() - 0.5) + y = mech.grabRange * Math.sin(A) + RAND * (Math.random() - 0.5) + ctx.lineTo(this.pos.x + x, this.pos.y + y) + } ctx.fillStyle = gradient //rgba(255,0,0,0.2) ctx.fill(); + // ctx.beginPath(); + // ctx.arc(this.pos.x, this.pos.y, mech.grabRange, 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) { @@ -1240,7 +1234,7 @@ const mech = { mech.fieldCDcycle = game.cycle + 120; } } - } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle) { //holding, but field button is released + } else if (mech.holdingTarget && mech.fireCDcycle < game.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released mech.grabRange = 0 mech.pickUp(); } else { diff --git a/js/powerups.js b/js/powerups.js index fbae832..40717ff 100644 --- a/js/powerups.js +++ b/js/powerups.js @@ -146,15 +146,15 @@ const powerUps = { powerUps.spawn(x, y, "heal"); return; } - if (Math.random() < 0.18) { + if (Math.random() < 0.19) { if (b.inventory.length > 0) powerUps.spawn(x, y, "ammo"); return; } - if (Math.random() < 0.005 * (8 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun to drop + if (Math.random() < 0.006 * (6 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun to drop powerUps.spawn(x, y, "gun"); return; } - if (Math.random() < 0.006) { + if (Math.random() < 0.005) { powerUps.spawn(x, y, "field"); return; }