diff --git a/index.html b/index.html index 1ae67a3..7b18c8b 100644 --- a/index.html +++ b/index.html @@ -33,6 +33,9 @@
+
+ Auto-Loading Heuristics +
diff --git a/js/bullets.js b/js/bullets.js index 4f600cd..5c92d0d 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -12,6 +12,7 @@ const b = { modHealthDrain: null, modNoAmmo: null, modBulletsLastLonger: null, + // modNonEuclidean: null, setModDefaults() { b.modFireRate = 1; b.modExplosionRadius = 1; @@ -20,58 +21,101 @@ const b = { b.modHealthDrain = 0; b.modNoAmmo = 0; b.modBulletsLastLonger = 1; + // b.modNonEuclidean = false; }, - mods: [ - () => { - b.mod = 0; - game.makeTextLog("Auto-Loading Heuristics
(left click)

your rate of fire 15% is faster

", 1200); - b.setModDefaults(); //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls - b.modFireRate = 0.85 - //ADD: maybe add in something that changes game play + modText: function () { + game.makeTextLog(`${b.mods[b.mod].name}
(left click)

${b.mods[b.mod].description}

`, 1200); + document.getElementById("mods").innerHTML = b.mods[b.mod].name + }, + mods: [{ + name: "Auto-Loading Heuristics", + description: "your rate of fire 15% is faster", + effect: () => { + b.mod = 0 + b.modText(); + b.setModDefaults(); //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls + b.modFireRate = 0.85 + //ADD: maybe add in something that changes game play + } }, - () => { - b.mod = 1; - game.makeTextLog("Anti-Matter Cores
(left click)

your explosions are larger and do more damage

", 1200); - b.setModDefaults(); //at 1.4 gives a flat 40% increase, and increased range, balanced by limited guns and self damage - //testing at 1.3: grenade(+0.3), missiles, flak, M80 - b.modExplosionRadius = 2; //good for guns with explosions: + { + name: "Anti-Matter Cores", + description: "your explosions are larger and do more damage", + effect: () => { + b.mod = 1 + b.modText(); + b.setModDefaults(); //at 1.4 gives a flat 40% increase, and increased range, balanced by limited guns and self damage + //testing at 1.3: grenade(+0.3), missiles, flak, M80 + b.modExplosionRadius = 2; //good for guns with explosions: + } }, - () => { - b.mod = 2; - game.makeTextLog("High Caliber Bullets
(left click)

your bullets are larger and do more physical damage

", 1200); - b.setModDefaults(); //good for guns that do mostly projectile damage: - //testing done at 1.15: one shot(+0.38), rapid fire(+0.25), spray, wave beam(+0.4 adds range and dmg), needles(+0.1) - //testing at 1.08: spray(point blank)(+0.25), one shot(+0.16), wave beam(point blank)(+0.14) - b.modBulletSize = 1.07; - //ADD: maybe add in something that changes game play + { + name: "High Caliber Bullets", + description: "your bullets are larger and do more physical damage", + effect: () => { + b.mod = 2 + b.modText(); + b.setModDefaults(); //good for guns that do mostly projectile damage: + //testing done at 1.15: one shot(+0.38), rapid fire(+0.25), spray, wave beam(+0.4 adds range and dmg), needles(+0.1) + //testing at 1.08: spray(point blank)(+0.25), one shot(+0.16), wave beam(point blank)(+0.14) + b.modBulletSize = 1.07; + //ADD: maybe add in something that changes game play + } }, - () => { - b.mod = 3; - game.makeTextLog("Energy Siphon
(left click)

regenerate energy proportional to your damage done

", 1200); - b.setModDefaults(); //good with laser, Nano-Scale Manufacturing, Standing Wave Harmonics, Phase Decoherence Field - b.modEnergySiphon = 0.2; + { + name: "Energy Siphon", + description: "regenerate energy proportional to your damage done", + effect: () => { + b.mod = 3 + b.modText(); + b.setModDefaults(); //good with laser, Nano-Scale Manufacturing, Standing Wave Harmonics, Phase Decoherence Field + b.modEnergySiphon = 0.2; + } }, - () => { - b.mod = 4; - game.makeTextLog("Entropy Transfer
(left click)

heal proportional to your damage done

", 1200); - b.setModDefaults(); //good with guns that overkill: one shot, grenade - b.modHealthDrain = 0.01; + { + name: "Entropy Transfer", + description: "heal proportional to your damage done", + effect: () => { + b.mod = 4 + b.modText(); + b.setModDefaults(); //good with guns that overkill: one shot, grenade + b.modHealthDrain = 0.01; + } }, - () => { - b.mod = 5; - game.makeTextLog("Desublimated Ammunition
(left click)

1 out of 2 shots will not consume ammo when crouching

", 1200); - b.setModDefaults(); //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray - b.modNoAmmo = 1 + { + name: "Desublimated Ammunition", + description: "use 50% less ammo when crouching", + effect: () => { + b.mod = 5 + b.modText(); + b.setModDefaults(); //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray + b.modNoAmmo = 1 + } }, - () => { - b.mod = 6; - game.makeTextLog("Anti-Decay Coating
(left click)

your bullets last 25% longer

", 1200); - b.setModDefaults(); //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range) - b.modBulletsLastLonger = 1.25 + { + name: "Anti-Decay Coating", + description: "your bullets last 25% longer", + effect: () => { + b.mod = 6 + b.modText(); + b.setModDefaults(); //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range) + b.modBulletsLastLonger = 1.25 + } }, + // { + // name: "Non-Euclidean Geometry", + // description: "after you fall loop back to the top of the map", + // have: false, + // effect: () => { + // b.mod = 7 + // b.modText(); + // b.setModDefaults(); //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range) + // b.modNonEuclidean = true + // } + // }, // () => { // b.mod = 8; - // game.makeTextLog("Relativistic Velocity
(left click)

Your bullets are effected extra by your own velocity

", 1200); + // game.makeTextLog("Relativistic Velocity
(left click)

Your bullets are effected extra by your own velocity

", 1200); // b.setModDefaults(); //good with: one shot, rapid fire, spray, super balls // }, ], diff --git a/js/game.js b/js/game.js index c60d35d..d922d65 100644 --- a/js/game.js +++ b/js/game.js @@ -289,9 +289,9 @@ const game = { } if (keys[89]) { //cycle fields with F if (b.mod === b.mods.length - 1) { - b.mods[0]() + b.mods[0].effect() } else { - b.mods[b.mod + 1]() + b.mods[b.mod + 1].effect() } } if (keys[82]) { // teleport to mouse with R @@ -541,7 +541,33 @@ const game = { }, fallChecks() { // if 4000px deep - if (mech.pos.y > game.fallHeight) mech.death(); + if (mech.pos.y > game.fallHeight) { + mech.death(); + // if (b.modNonEuclidean) { + // Matter.Body.setPosition(player, { + // x: player.position.x, + // y: player.position.y - 12000 + // }); + // Matter.Body.setVelocity(player, { + // x: player.velocity.x, + // y: player.velocity.y * 0 + // }); + + // mech.pos.x = player.position.x; + // mech.pos.y = playerBody.position.y - mech.yOff; + + // //smoothed mouse look translations + // const scale = 10; + // mech.transSmoothX = canvas.width2 - mech.pos.x - (game.mouse.x - canvas.width2) * scale; + // mech.transSmoothY = canvas.height2 - mech.pos.y - (game.mouse.y - canvas.height2) * scale; + + // mech.transX = mech.transSmoothX + // mech.transY = mech.transSmoothY + + // } else { + // mech.death(); + // } + } if (!(mech.cycle % 420)) { remove = function (who) { diff --git a/js/index.js b/js/index.js index c4d74f7..ae179bb 100644 --- a/js/index.js +++ b/js/index.js @@ -2,6 +2,16 @@ /* TODO: ******************************************* ***************************************************** +make power ups keep moving to player if the field is turned off + +levels spawn by having the map aspects randomly fly into place + +new map with repeating endlessness + get ideas from Manifold Garden game + if falling, get teleported above the map + this can apply to blocks mobs, and power ups as well + + when paused show details on field, mods, guns? Find a diegetic way to see player damage (and or field meter too) diff --git a/js/level.js b/js/level.js index 19a5dc8..7b75d31 100644 --- a/js/level.js +++ b/js/level.js @@ -15,12 +15,12 @@ const level = { // game.levelsCleared = 5; //for testing to simulate possible mobs spawns // b.giveGuns("all", 1000) // b.giveGuns(3) // set a starting gun for testing - // mech.fieldUpgrades[1](); //give a field power up for testing - // b.mods[6](); //give specific mod + // mech.fieldUpgrades[2](); //give a field power up for testing + // b.mods[6].effect(); //give specific mod - // this.intro(); //starting level + this.intro(); //starting level // this.testingMap(); - this.bosses(); + // this.bosses(); // this.aerie(); // this.rooftops(); // this.warehouse(); @@ -645,14 +645,17 @@ const level = { spawn.bodyRect(1750, -800, 700, 35); } spawn.mapVertex(2225, -2100, "0 0 450 0 300 -2500 150 -2500") - spawn.mapRect(2000, -750, 450, 300); + spawn.mapRect(2000, -700, 450, 300); spawn.bodyRect(2360, -450, 100, 300, 0.6); - spawn.mapRect(2000, -150, 450, 350); + spawn.mapRect(2000, -75, 450, 275); spawn.bodyRect(2450, 150, 150, 150, 0.4); spawn.mapRect(1550, 300, 4600, 200); //ground //floor below right tall tower spawn.bodyRect(3000, 50, 150, 250, 0.9); spawn.bodyRect(4500, -500, 300, 250, 0.7); + spawn.bodyRect(3500, -100, 100, 150, 0.7); + spawn.bodyRect(4200, -500, 110, 30, 0.7); + spawn.bodyRect(3800, -500, 150, 130, 0.7); spawn.bodyRect(4000, 50, 200, 150, 0.9); spawn.bodyRect(4500, 50, 300, 200, 0.9); spawn.bodyRect(4200, -350, 200, 50, 0.9); diff --git a/js/player.js b/js/player.js index 089bb57..1ca8e98 100644 --- a/js/player.js +++ b/js/player.js @@ -161,16 +161,6 @@ const mech = { this.transX += (this.transSmoothX - this.transX) * 0.07; this.transY += (this.transSmoothY - this.transY) * 0.07; }, - gamepadLook() { - this.angle = Math.atan2( - game.gamepad.rightAxis.y, - game.gamepad.rightAxis.x - ); - // this.transX += (canvas.width2 - this.pos.x - this.transX) * 0.07 - game.gamepad.rightAxis.x * 12; - // this.transY += (canvas.height2 - this.pos.y - this.transY) * 0.03 - game.gamepad.rightAxis.y * 6; - this.transX += (canvas.width2 - this.pos.x - this.transX) * 0.02 - game.gamepad.leftAxis.x * 6; - this.transY += (canvas.height2 - this.pos.y - this.transY) * 0.02 + game.gamepad.leftAxis.y * 8; - }, doCrouch() { if (!this.crouch) { this.crouch = true; @@ -857,7 +847,7 @@ const mech = { fieldUpgrades: [ () => { mech.fieldMode = 0; - game.makeTextLog("Field Emitter
(right click or space bar)

lets you pick up and throw objects
shields you from damage

", 1200); + game.makeTextLog("Field Emitter
(right click or space bar)

lets you pick up and throw objects
shields you from damage

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

stop time while field is active
can fire while field is active

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

stop time while field is active
can fire while field is active

", 1200); mech.setHoldDefaults(); mech.fieldFire = true; mech.grabRange = 130 @@ -946,16 +936,17 @@ const mech = { }, () => { mech.fieldMode = 2; - game.makeTextLog("Kinetic Energy Field
(right mouse or space bar)

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

", 1200); + game.makeTextLog("Electrostatic Force Field
(right click or space bar)

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

", 1200); mech.setHoldDefaults(); //throw quicker and harder - mech.fieldShieldingScale = 3; + mech.grabRange = 225; + mech.fieldShieldingScale = 2; mech.fieldRegen *= 3; mech.throwChargeRate = 3; mech.throwChargeMax = 140; - mech.fieldDamage = 3; //passive field does extra damage - mech.fieldArc = 0.11 - mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) + mech.fieldDamage = 5; //passive field does extra damage + // mech.fieldArc = 0.11 + // mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.hold = function () { if (mech.isHolding) { @@ -963,12 +954,28 @@ const mech = { mech.holding(); mech.throw(); } else if ((keys[32] || game.mouseDownRight) && mech.fieldMeter > 0.15) { //not hold but field button is pressed - //draw field - const range = mech.grabRange - 15; + //draw electricity + const Dx = Math.cos(mech.angle); + const Dy = Math.sin(mech.angle); + let x = mech.pos.x + 20 * Dx; + let y = mech.pos.y + 20 * Dy; ctx.beginPath(); - ctx.arc(mech.pos.x, mech.pos.y, range, mech.angle - Math.PI * mech.fieldArc, mech.angle + Math.PI * mech.fieldArc, false); - let eye = 13; - ctx.lineTo(mech.pos.x + eye * Math.cos(mech.angle), mech.pos.y + eye * Math.sin(mech.angle)); + ctx.moveTo(x, y); + for (let i = 0; i < 8; i++) { + x += 18 * (Dx + 2 * (Math.random() - 0.5)) + y += 18 * (Dy + 2 * (Math.random() - 0.5)) + ctx.lineTo(x, y); + } + ctx.lineWidth = 1 //0.5 + 2 * Math.random(); + ctx.strokeStyle = `rgba(100,20,50,${0.5+0.5*Math.random()})`; + ctx.stroke(); + + //draw field + const range = 170; + const arc = Math.PI * 0.11 + ctx.beginPath(); + ctx.arc(mech.pos.x, mech.pos.y, range, mech.angle - arc, mech.angle + arc, false); + ctx.lineTo(mech.pos.x + 13 * Math.cos(mech.angle), mech.pos.y + 13 * Math.sin(mech.angle)); if (mech.holdingTarget) { ctx.fillStyle = "rgba(255,50,150," + (0.05 + 0.1 * Math.random()) + ")"; } else { @@ -977,13 +984,13 @@ const mech = { ctx.fill(); //draw random lines in field for cool effect - eye = 15; - ctx.beginPath(); - ctx.moveTo(mech.pos.x + eye * Math.cos(mech.angle), mech.pos.y + eye * Math.sin(mech.angle)); - const offAngle = mech.angle + 2 * Math.PI * mech.fieldArc * (Math.random() - 0.5); - ctx.lineTo(mech.pos.x + range * Math.cos(offAngle), mech.pos.y + range * Math.sin(offAngle)); - ctx.strokeStyle = "rgba(100,20,50,0.2)"; - ctx.stroke(); + // eye = 15; + // ctx.beginPath(); + // ctx.moveTo(mech.pos.x + eye * Math.cos(mech.angle), mech.pos.y + eye * Math.sin(mech.angle)); + // const offAngle = mech.angle + 2 * Math.PI * mech.fieldArc * (Math.random() - 0.5); + // ctx.lineTo(mech.pos.x + range * Math.cos(offAngle), mech.pos.y + range * Math.sin(offAngle)); + // ctx.strokeStyle = "rgba(100,20,50,0.2)"; + // ctx.stroke(); mech.grabPowerUp(); mech.pushMobs(); @@ -998,16 +1005,12 @@ const mech = { }, () => { mech.fieldMode = 3; - game.makeTextLog("Negative Mass Field
(right mouse or space bar)

field nullifies gravity
player can hold more massive objects
can fire while field is active

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

field nullifies gravity
player can hold more massive objects
can fire while field is active

", 1200); //
decreased field shielding efficiency mech.setHoldDefaults(); mech.fieldFire = true; mech.holdingMassScale = 0.05; //can hold heavier blocks with lower cost to jumping mech.fieldShieldingScale = 2; - // mech.fieldArc = 1; //field covers full 360 degrees - // mech.grabRange = 150; - // mech.fieldArc = 1 //0.08; - // mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.hold = function () { if (mech.isHolding) { @@ -1066,12 +1069,8 @@ const mech = { ctx.arc(mech.pos.x, mech.pos.y, mech.grabRange, 0, 2 * Math.PI); ctx.fillStyle = "#f5f5ff"; ctx.globalCompositeOperation = "difference"; - // ctx.strokeStyle = "#888" - // ctx.stroke(); ctx.fill(); ctx.globalCompositeOperation = "source-over"; - - } else { //trigger cool down mech.fieldCDcycle = mech.cycle + 120; @@ -1088,7 +1087,7 @@ const mech = { }, () => { mech.fieldMode = 4; - game.makeTextLog("Standing Wave Harmonics
(right mouse or space bar)

oscillating shields always surround player
decreased field regeneration

", 1200); + game.makeTextLog("Standing Wave Harmonics
(right click or space bar)

oscillating shields always surround player
decreased field regeneration

", 1200); mech.setHoldDefaults(); // mech.fieldShieldingScale = 0.5; mech.fieldRegen *= 0.2; @@ -1128,15 +1127,12 @@ const mech = { }, () => { mech.fieldMode = 5; - game.makeTextLog("Nano-Scale Manufacturing
(passive effect)

excess field energy used to build drones
decreased field shielding efficiency

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

excess field energy used to build drones
increased field regeneration

", 1200); mech.setHoldDefaults(); - mech.fieldShieldingScale = 15; - 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.fieldRegen *= 3; mech.hold = function () { if (mech.fieldMeter === 1) { - mech.fieldMeter -= 0.2; + mech.fieldMeter -= 0.5; b.guns[12].fire() //spawn drone } if (mech.isHolding) { @@ -1158,10 +1154,9 @@ const mech = { }, () => { mech.fieldMode = 6; - game.makeTextLog("Phase Decoherence Field
(right mouse or space bar)

intangible while field is active
can't see or be seen outside field

", 1200); + game.makeTextLog("Phase Decoherence Field
(right click or space bar)

intangible while field is active
can't see or be seen outside field

", 1200); mech.setHoldDefaults(); // mech.grabRange = 230 - mech.hold = function () { mech.isStealth = false //isStealth is checked in mob foundPlayer() player.collisionFilter.mask = 0x010011 //0x010011 is normal @@ -1170,7 +1165,7 @@ const mech = { mech.holding(); mech.throw(); } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { - const DRAIN = 0.0035 + const DRAIN = 0.002 if (mech.fieldMeter > DRAIN) { mech.fieldMeter -= DRAIN; @@ -1187,8 +1182,6 @@ const mech = { ctx.lineWidth = 2; ctx.stroke(); - - // mech.pushMobs360(150); mech.grabPowerUp(); mech.lookForPickUp(110); } else { @@ -1204,7 +1197,7 @@ const mech = { }, // () => { // mech.fieldMode = 7; - // game.makeTextLog("Thermal Radiation Field
(right mouse or space bar)

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

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

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

", 1200); // mech.setHoldDefaults(); // mech.fieldShieldingScale = 10; // mech.rangeSmoothing = 0 diff --git a/js/powerups.js b/js/powerups.js index 8954b86..84108d6 100644 --- a/js/powerups.js +++ b/js/powerups.js @@ -53,9 +53,9 @@ const powerUps = { while (mode === b.mod) { mode = Math.floor(Math.random() * b.mods.length) } - b.mods[mode](); //choose random upgrade that you don't already have + b.mods[mode].effect(); //choose random upgrade that you don't already have } else { - b.mods[this.mode](); //set a predetermined power up + b.mods[this.mode].effect(); //set a predetermined power up } if (previousMode != null) { //pop the old field out in case player wants to swap back mech.fieldCDcycle = mech.cycle + 40; //trigger fieldCD to stop power up grab automatic pick up of spawn @@ -109,8 +109,12 @@ const powerUps = { effect() { //find what guns I don't have let options = []; - for (let i = 0; i < b.guns.length; ++i) { - if (!b.guns[i].have) options.push(i); + if (b.activeGun === null) { //the first gun is good for the early game + options = [0, 1, 2, 3, 4, 5, 6, 8, 9, 12] + } else { + for (let i = 0; i < b.guns.length; ++i) { + if (!b.guns[i].have) options.push(i); + } } //give player a gun they don't already have if possible if (options.length > 0) { @@ -125,9 +129,9 @@ const powerUps = { ); } if (b.inventory.length === 1) { //on the second gun pick up tell player how to change guns - game.makeTextLog(`${b.guns[newGun].name}
(left click)
(Q, E, and mouse wheel change weapons)

${b.guns[newGun].description}

`, 1000); + game.makeTextLog(`(Q, E, and mouse wheel change weapons)

${b.guns[newGun].name}
(left click)

${b.guns[newGun].description}

`, 1000); } else { - game.makeTextLog(`${b.guns[newGun].name}
(left click)

${b.guns[newGun].description}

`, 1000); + game.makeTextLog(`${b.guns[newGun].name}
(left click)

${b.guns[newGun].description}

`, 1000); } b.guns[newGun].have = true; b.inventory.push(newGun); diff --git a/style.css b/style.css index 23836cf..32cdab1 100644 --- a/style.css +++ b/style.css @@ -132,6 +132,22 @@ summary { /*border: 2px solid rgba(0, 0, 0, 0.4);*/ } +#mods { + position: absolute; + top: 20px; + right: 20px; + z-index: 2; + font-size: 21px; + color: #111; + opacity: 0.5; + background-color: rgba(255, 255, 255, 0.4); + user-select: none; + pointer-events: none; + padding: 0px 5px 0px 5px; + border-radius: 5px; + /*border: 2px solid rgba(0, 0, 0, 0.4);*/ +} + #text-log { position: absolute; top: 20px; @@ -155,6 +171,11 @@ summary { background-color: rgba(255, 255, 255, 0.5); } +.faded { + opacity: 0.5; + font-size: 85%; +} + .wrapper { display: grid; grid-template-columns: 360px 10px;