added 5 new mods, power up display, game balance

This commit is contained in:
landgreen
2019-12-01 18:22:50 -08:00
parent 927933a754
commit 65977ce5aa
10 changed files with 524 additions and 397 deletions

View File

@@ -30,7 +30,6 @@
</head> </head>
<body> <body>
<!-- <body oncontextmenu="return false"> --> <!-- <body oncontextmenu="return false"> -->
<div id='guns'></div> <div id='guns'></div>
<div id='field'></div> <div id='field'></div>
@@ -77,34 +76,82 @@
<canvas id="canvas"></canvas> <canvas id="canvas"></canvas>
<!-- ********** intro page *********************************************** <!-- ********** intro page ***********************************************
******************************************************************************* --> ******************************************************************************* -->
<!-- <div id="build-details">
<div class="build-grid-module"></div>
<details>
<summary>build</summary>
<div id="details-div">
</div>
</details>
</div> -->
<div id="build-grid">
</div>
<button type="button" id="build-button">builds</button>
<!-- <div id="build">
<details>
<summary>builds</summary>
</details>
</div> -->
<div id="controls"> <div id="controls">
<details> <details>
<summary>info</summary> <summary>about</summary>
<div id="details-div"> <div id="details-div">
<div style="line-height: 150%;">
<label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed">combat difficulty:</label>
<select name="difficulty-select" id="difficulty-select">
<option value="easy">easy</option>
<option value="0" selected>normal</option>
<option value="4">hard</option>
<option value="8">why...</option>
</select>
<br>
<label for="body-damage" title="allow damage from heavy, fast moving blocks">collision damage from blocks:</label>
<input type="checkbox" id="body-damage" name="body-damage" checked style="width:16px; height:16px;">
<br>
<label for="fps-select" title="use this to slow the game down">frames per second cap:</label>
<select name="fps-select" id="fps-select">
<option value="max">no fps cap</option>
<option value="72" selected>72 fps cap</option>
<option value="60">60 fps cap</option>
<option value="45">45 fps cap</option>
<option value="30">30 fps cap</option>
</select>
</div>
<br><br>
<table> <table>
<tr> <tr>
<td>FIRE</td> <th>FIRE</th>
<td>left mouse</td> <td>left mouse</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>FIELD</td> <th>FIELD</th>
<td>right mouse / spacebar</td> <td>right mouse / spacebar</td>
</tr> </tr>
<tr> <tr>
<td>MOVE</td> <th>MOVE</th>
<td>WASD / arrows</td> <td>WASD / arrows</td>
</tr> </tr>
<tr> <tr>
<td>GUNS</td> <th>GUNS</th>
<td>Q / E / mouse wheel</td> <td>Q / E / mouse wheel</td>
</tr> </tr>
<tr> <tr>
<td>ZOOM</td> <th>ZOOM</th>
<td>+ / -</td> <td>+ / -</td>
</tr> </tr>
<tr> <tr>
<td>PAUSE</td> <th>PAUSE</th>
<td>P</td> <td>P</td>
</tr> </tr>
<!-- <tr> <!-- <tr>
@@ -140,35 +187,9 @@
<a href="https://github.com/landgreen/n-gon">Github</a> hosts the source code for n-gon.<br> It's written in JavaScript, CSS, and HTML. <a href="https://github.com/landgreen/n-gon">Github</a> hosts the source code for n-gon.<br> It's written in JavaScript, CSS, and HTML.
<br> <br>
<br> <br>
N-gon is also on <a href="https://lilgreenland.itch.io/n-gon">itch.io</a>. n-gon is also hosted at <a href="https://lilgreenland.itch.io/n-gon">itch.io</a>.
<br>
<br> <br>
</div>
</details>
</div>
<div id="settings">
<details>
<summary>settings</summary>
<div id="details-div">
<label for="body-damage" title="allow damage from heavy, fast moving blocks">block collision damage:</label>
<input type="checkbox" id="body-damage" name="body-damage" checked>
<br><br>
<label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed">combat difficulty:</label>
<select name="difficulty-select" id="difficulty-select">
<option value="easy">easy</option>
<option value="0" selected>normal</option>
<option value="4">hard</option>
<option value="8">why...</option>
</select>
<br><br>
<label for="fps-select" title="use this to slow the game down">FPS cap:</label>
<select name="fps-select" id="fps-select">
<option value="max">no fps cap</option>
<option value="72" selected>72 fps cap</option>
<option value="60">60 fps cap</option>
<option value="45">45 fps cap</option>
<option value="30">30 fps cap</option>
</select>
</div> </div>
</details> </details>
</div> </div>

View File

@@ -19,7 +19,12 @@ const b = {
modExtraDmg: null, modExtraDmg: null,
annihilation: null, annihilation: null,
fullHeal: null, fullHeal: null,
modSquirrelFx: 1, modSquirrelFx: null,
modIsCrit: null,
modMoreDrops: null,
isModLowHealthDmg: null,
isModFarAwayDmg: null,
isModMonogamy: null,
setModDefaults() { setModDefaults() {
b.modCount = 0; b.modCount = 0;
b.modFireRate = 1; b.modFireRate = 1;
@@ -37,6 +42,11 @@ const b = {
b.modAnnihilation = false; b.modAnnihilation = false;
b.isModFullHeal = false; b.isModFullHeal = false;
b.modSquirrelFx = 1; b.modSquirrelFx = 1;
b.modIsCrit = false;
b.modMoreDrops = 0;
b.isModLowHealthDmg = false;
b.isModFarAwayDmg = false;
b.isModMonogamy = false;
mech.Fx = 0.015; mech.Fx = 0.015;
mech.jumpForce = 0.38; mech.jumpForce = 0.38;
mech.throwChargeRate = 2; mech.throwChargeRate = 2;
@@ -47,17 +57,17 @@ const b = {
}, },
mods: [{ mods: [{
name: "depleted uranium rounds", name: "depleted uranium rounds",
description: "your <strong class='color-b'>bullets</strong> are larger and do more physical <span class='color-d'>damage</span>", description: "your <strong>bullets</strong> are 10% larger<br>increased momentum and physical <strong class='color-d'>damage</strong>",
have: false, //0 have: false, //0
effect: () => { effect: () => {
//good for guns that do mostly projectile damage: //good for guns that do mostly projectile damage:
//testing at 1.08: spray(point blank)(+0.25), one shot(+0.16), wave beam(point blank)(+0.14) //testing at 1.08: spray(point blank)(+0.25), one shot(+0.16), wave beam(point blank)(+0.14)
b.modBulletSize = 1.07; b.modBulletSize = 1.1;
} }
}, },
{ {
name: "auto-loading heuristics", name: "auto-loading heuristics",
description: "your rate of fire is 15% higher", description: "your <strong>rate of fire</strong> is 15% higher",
have: false, //1 have: false, //1
effect: () => { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls effect: () => { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls
b.modFireRate = 0.85 b.modFireRate = 0.85
@@ -65,7 +75,7 @@ const b = {
}, },
{ {
name: "desublimated ammunition", name: "desublimated ammunition",
description: "use 50% less <strong class='color-b'>ammo</strong> when <strong>crouching</strong>", description: "use 50% less <strong>ammo</strong> when <strong>crouching</strong>",
have: false, //2 have: false, //2
effect: () => { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray effect: () => { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray
b.modNoAmmo = 1 b.modNoAmmo = 1
@@ -73,7 +83,7 @@ const b = {
}, },
{ {
name: "Lorentzian topology", name: "Lorentzian topology",
description: "your <strong class='color-b'>bullets</strong> last 40% longer", description: "your <strong>bullets</strong> last 40% <strong>longer</strong>",
have: false, //3 have: false, //3
effect: () => { //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range) effect: () => { //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range)
b.isModBulletsLastLonger = 1.40 b.isModBulletsLastLonger = 1.40
@@ -81,7 +91,7 @@ const b = {
}, },
{ {
name: "anti-matter cores", name: "anti-matter cores",
description: "the radius of your <strong class='color-e'>explosions</strong> is doubled<br><span style='opacity:0.3;'>be careful</span>", description: "the <strong>radius</strong> of your <strong class='color-e'>explosions</strong> is doubled<br><strong style='opacity:0.3;'>be careful</strong>",
have: false, //4 have: false, //4
effect: () => { //at 1.4 gives a flat 40% increase, and increased range, balanced by limited guns and self damage effect: () => { //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 //testing at 1.3: grenade(+0.3), missiles, flak, M80
@@ -90,7 +100,7 @@ const b = {
}, },
{ {
name: "ceramic plating", name: "ceramic plating",
description: "you take no damage from area effects<br>immune to <strong class='color-e'>explosions</strong> and enemy fields", description: "<strong>immune</strong> to <strong class='color-e'>explosions</strong> and enemy fields",
have: false, //5 have: false, //5
effect: () => { effect: () => {
b.isModAoEImmunity = true; //good for guns with explosions b.isModAoEImmunity = true; //good for guns with explosions
@@ -98,7 +108,7 @@ const b = {
}, },
{ {
name: "ablative synthesis", name: "ablative synthesis",
description: "after taking <span class='color-d'>damage</span>, there is a chance that your damaged parts will be rebuilt as <strong class='color-b'>drones</strong>", description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after taking <strong class='color-d'>damage</strong>",
have: false, //6 have: false, //6
effect: () => { //makes dangerous situations more survivable effect: () => { //makes dangerous situations more survivable
b.isModDroneOnDamage = true; b.isModDroneOnDamage = true;
@@ -106,7 +116,7 @@ const b = {
}, },
{ {
name: "zoospore vector", name: "zoospore vector",
description: "when an enemy <span style='color: #888;'>dies</span> it has a 20% chance to release <strong class='color-s'>spores</strong>", description: "enemies can discharge <strong class='color-s'>spores</strong> on <strong>death</strong><br><strong class='color-s'>spores</strong> seek out enemies",
have: false, //7 have: false, //7
effect: () => { //good late game maybe? effect: () => { //good late game maybe?
b.modSpores = 0.20; b.modSpores = 0.20;
@@ -114,16 +124,15 @@ const b = {
}, },
{ {
name: "field siphon", name: "field siphon",
description: "regenerate <span class='color-f'>field energy</span> proportional to your <span class='color-d'>damage</span> done", description: "gain <strong class='color-f'>energy</strong> proportional to <strong class='color-d'>damage</strong> done",
have: false, //8 have: false, //8
effect: () => { //good with laser, and all fields effect: () => { //good with laser, and all fields
b.modEnergySiphon = 0.15;
b.modEnergySiphon = 0.2;
} }
}, },
{ {
name: "entropy transfer", name: "entropy transfer",
description: "<span class='color-h'>heal</span> proportional to your <span class='color-d'>damage</span> done", description: "<strong class='color-h'>heal</strong> proportional to <strong class='color-d'>damage</strong> done",
have: false, //9 have: false, //9
effect: () => { //good with guns that overkill: one shot, grenade effect: () => { //good with guns that overkill: one shot, grenade
b.modHealthDrain = 0.01; b.modHealthDrain = 0.01;
@@ -131,7 +140,7 @@ const b = {
}, },
{ {
name: "quantum immortality", name: "quantum immortality",
description: "after you <strong style='color: #606;'>die</strong> continue in an <em>alternate reality</em><br>guns, ammo, and field are randomized", description: "after <strong>dying</strong>, continue in an <em>alternate reality</em><br>guns, ammo, and field are randomized",
have: false, //10 have: false, //10
effect: () => { effect: () => {
b.modIsImmortal = true; b.modIsImmortal = true;
@@ -139,7 +148,7 @@ const b = {
}, },
{ {
name: "fluoroantimonic acid", name: "fluoroantimonic acid",
description: "your bullets do extra chemical <span class='color-d'>damage</span> each time they make contact", description: "each bullet does extra chemical <strong class='color-d'>damage</strong>",
have: false, //11 have: false, //11
effect: () => { //good with guns that fire many bullets at low speeds, minigun, drones, junk-bots, shotgun, superballs, wavebeam effect: () => { //good with guns that fire many bullets at low speeds, minigun, drones, junk-bots, shotgun, superballs, wavebeam
b.modExtraDmg = 0.1 b.modExtraDmg = 0.1
@@ -147,7 +156,7 @@ const b = {
}, },
{ {
name: "annihilation", name: "annihilation",
description: "after you touch any enemy, they are <strong class='color-l'>annihilated</strong><br><em>touching enemies <span class='color-d'>damages</span> you, but <span class='color-d'>destroys</span> them</em>", description: "after <strong>touching</strong> enemies, they are annihilated",
have: false, //12 have: false, //12
effect: () => { //good with mods that heal: superconductive healing, entropy transfer effect: () => { //good with mods that heal: superconductive healing, entropy transfer
b.modAnnihilation = true b.modAnnihilation = true
@@ -155,17 +164,16 @@ const b = {
}, },
{ {
name: "recursive healing", name: "recursive healing",
description: "<span class='color-h'>heals</span> bring you to full health", description: "<strong class='color-h'>healing</strong> power ups bring you to <strong>full health</strong>",
have: false, //13 have: false, //13
effect: () => { // good with ablative synthesis, electrostatic field effect: () => { // good with ablative synthesis, melee builds
b.isModFullHeal = true
} }
}, },
{ {
name: "Gauss rifle", name: "Gauss rifle",
description: "<span style='color:#f0f;'>magnetically</span> <strong>launch blocks</strong> at much higher speeds<br>carry more massive blocks<br><em>hold right click to charge up a throw and release to fire</em>", description: "<strong>launch blocks</strong> at much higher speeds<br>carry more massive blocks",
have: false, //14 have: false, //14
effect: () => { // good with ablative synthesis, electrostatic field effect: () => { // good with guns that run out of ammo
b.isModFullHeal = true b.isModFullHeal = true
mech.throwChargeRate = 4; mech.throwChargeRate = 4;
mech.throwChargeMax = 150; mech.throwChargeMax = 150;
@@ -174,15 +182,54 @@ const b = {
}, },
{ {
name: "squirrel-cage rotor", name: "squirrel-cage rotor",
description: "jump higher and move faster", description: "your legs produce 20% more force<br><strong>jump</strong> higher and <strong>move</strong> faster",
have: false, //15 have: false, //15
effect: () => { // effect: () => { // good with melee builds, content skipping builds
b.modSquirrelFx = 1.2; b.modSquirrelFx = 1.2;
mech.Fx = 0.015 * b.modSquirrelFx; mech.Fx = 0.015 * b.modSquirrelFx;
mech.jumpForce = 0.38 * 1.1; mech.jumpForce = 0.38 * 1.1;
} }
}, },
{
name: "fracture analysis",
description: "<strong>6x</strong> physical <strong class='color-d'>damage</strong> to unaware enemies<br><em>enemies aware of you have a health bar</em>",
have: false, //16
effect: () => { // good with high damage guns that strike from a distance: rail gun, drones, flechettes, spores, grenade, vacuum bomb
b.modIsCrit = true;
}
},
{
name: "kinetic bombardment",
description: "do extra <strong class='color-d'>damage</strong> from farther away<br><em>up to 50% increase at about 30 steps away</em>",
have: false, //17
effect: () => { // good with annihilation, melee builds
b.isModFarAwayDmg = true; //used in mob.damage()
}
},
{
name: "quasistatic equilibrium",
description: "do extra <strong class='color-d'>damage</strong> at low health<br><em>up to 50% increase when near death</em>",
have: false, //18
effect: () => { // good with annihilation, melee builds
b.isModLowHealthDmg = true; //used in mob.damage()
}
},
{
name: "Bayesian inference",
description: "<strong>20%</strong> chance for double <strong>power ups</strong> to drop",
have: false, //19
effect: () => { // good with long term planning
b.modMoreDrops = 0.20;
}
},
{
name: "monogamy",
description: "equipping your first gun reduces <strong class='color-d'>damage</strong> taken<br>scales by <strong>7%</strong> for each gun in your inventory",
have: false, //20
effect: () => { // good with long term planning
b.isModMonogamy = true
}
},
], ],
giveMod(i) { giveMod(i) {
b.mods[i].effect(); //give specific mod b.mods[i].effect(); //give specific mod
@@ -226,7 +273,7 @@ const b = {
} }
} else { } else {
mech.fireCDcycle = mech.cycle + 30; //cooldown mech.fireCDcycle = mech.cycle + 30; //cooldown
// game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div><span class = 'box'>E</span> / <span class = 'box'>Q</span>", 200); // game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div><strong class = 'box'>E</strong> / <strong class = 'box'>Q</strong>", 200);
game.replaceTextLog = true; game.replaceTextLog = true;
game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div> <p style='font-size:90%;'><strong>Q</strong>, <strong>E</strong>, and <strong>mouse wheel</strong> change weapons</p>", 200); game.makeTextLog("<div style='font-size:140%;'>NO AMMO</div> <p style='font-size:90%;'><strong>Q</strong>, <strong>E</strong>, and <strong>mouse wheel</strong> change weapons</p>", 200);
} }
@@ -496,7 +543,7 @@ const b = {
}, },
guns: [{ guns: [{
name: "laser", //0 name: "laser", //0
description: "fire a <span style='color:#f00;'>beam</span> of coherent light<br>reflects off walls at 75% intensity<br>uses <span class='color-f'>energy</span> instead of ammunition", description: "emit a beam of <strong class='color-d'>damaging</strong> coherent light<br>uses <strong class='color-f'>energy</strong> instead of ammunition",
ammo: 0, ammo: 0,
// ammoPack: 350, // ammoPack: 350,
ammoPack: Infinity, ammoPack: Infinity,
@@ -658,17 +705,18 @@ const b = {
}, },
{ {
name: "rail gun", //1 name: "rail gun", //1
description: "<strong>hold left mouse</strong> to charge and release to fire<br>charging repels small enemies<br><em>crouching charges quicker and reduces recoil</em>", description: "magnetically launch a dense rod<br><strong>hold left mouse</strong> to charge and <strong>repel</strong> enemies",
ammo: 0, ammo: 0,
ammoPack: 12, ammoPack: 12,
have: false, have: false,
isStarterGun: false, isStarterGun: false,
fire() { fire() {
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.rectangle(9, -90, 0.01 * b.modBulletSize, 0.0017 * b.modBulletSize, { bullet[me] = Bodies.rectangle(0, 0, 0.012 * b.modBulletSize, 0.0022 * b.modBulletSize, {
// density: 0.0015, //frictionAir: 0.01, //restitution: 0, density: 0.002, //0.001 is normal
angle: 0, //frictionAir: 0.01, //restitution: 0,
friction: 0.5, // angle: 0,
// friction: 0.5,
frictionAir: 0, frictionAir: 0,
dmg: 3 + b.modExtraDmg, //damage done in addition to the damage from momentum dmg: 3 + b.modExtraDmg, //damage done in addition to the damage from momentum
classType: "bullet", classType: "bullet",
@@ -698,7 +746,7 @@ const b = {
y: mech.pos.y y: mech.pos.y
}) })
Matter.Body.setAngle(this, mech.angle) Matter.Body.setAngle(this, mech.angle)
const speed = 80 const speed = 85
Matter.Body.setVelocity(this, { Matter.Body.setVelocity(this, {
x: mech.Vx / 2 + speed * this.charge * Math.cos(mech.angle), x: mech.Vx / 2 + speed * this.charge * Math.cos(mech.angle),
y: mech.Vy / 2 + speed * this.charge * Math.sin(mech.angle) y: mech.Vy / 2 + speed * this.charge * Math.sin(mech.angle)
@@ -714,6 +762,7 @@ const b = {
for (let i = 0, len = body.length; i < len; ++i) { for (let i = 0, len = body.length; i < len; ++i) {
const SUB = Matter.Vector.sub(body[i].position, mech.pos) const SUB = Matter.Vector.sub(body[i].position, mech.pos)
const DISTANCE = Matter.Vector.magnitude(SUB) const DISTANCE = Matter.Vector.magnitude(SUB)
if (DISTANCE < RANGE) { if (DISTANCE < RANGE) {
const DEPTH = Math.max(RANGE - DISTANCE, 100) const DEPTH = Math.max(RANGE - DISTANCE, 100)
const FORCE = Matter.Vector.mult(Matter.Vector.normalise(SUB), 0.005 * Math.sqrt(DEPTH) * Math.sqrt(body[i].mass)) const FORCE = Matter.Vector.mult(Matter.Vector.normalise(SUB), 0.005 * Math.sqrt(DEPTH) * Math.sqrt(body[i].mass))
@@ -732,8 +781,6 @@ const b = {
// mob[i].force.y += FORCE.y // mob[i].force.y += FORCE.y
// } // }
// } // }
} else { // charging on mouse down } else { // charging on mouse down
mech.fireCDcycle = Infinity //can't fire until mouse is released mech.fireCDcycle = Infinity //can't fire until mouse is released
if (mech.crouch) { if (mech.crouch) {
@@ -750,7 +797,9 @@ const b = {
// if (DISTANCE < RANGE) { // if (DISTANCE < RANGE) {
// Matter.Body.setVelocity(mob[i], Matter.Vector.rotate(mob[i].velocity, 0.1)) // Matter.Body.setVelocity(mob[i], Matter.Vector.rotate(mob[i].velocity, 0.1))
// } // }
// const DRAIN = 0.0002 //&& mech.fieldMeter > DRAIN
if (DISTANCE < RANGE) { if (DISTANCE < RANGE) {
// mech.fieldMeter -= DRAIN + mech.fieldRegen;
const DEPTH = RANGE - DISTANCE const DEPTH = RANGE - DISTANCE
const FORCE = Matter.Vector.mult(Matter.Vector.normalise(SUB), 0.000000001 * DEPTH * DEPTH * DEPTH * Math.sqrt(mob[i].mass)) const FORCE = Matter.Vector.mult(Matter.Vector.normalise(SUB), 0.000000001 * DEPTH * DEPTH * DEPTH * Math.sqrt(mob[i].mass))
mob[i].force.x += FORCE.x mob[i].force.x += FORCE.x
@@ -894,7 +943,7 @@ const b = {
} }
}, { }, {
name: "wave beam", //3 name: "wave beam", //3
description: "fire a stream of oscillating particles<br><strong style='opacity: 0.4;'>propagates through solids</strong>", description: "fire a stream of oscillating particles<br>bullets <strong>propagate</strong> through solids",
ammo: 0, ammo: 0,
ammoPack: 85, ammoPack: 85,
have: false, have: false,
@@ -947,7 +996,7 @@ const b = {
} }
}, { }, {
name: "super balls", //4 name: "super balls", //4
description: "fire 3 very <strong>bouncy</strong> balls", description: "fire balls that <strong>bounce</strong> with no momentum loss",
ammo: 0, ammo: 0,
ammoPack: 11, ammoPack: 11,
have: false, have: false,
@@ -975,7 +1024,7 @@ const b = {
} }
}, { }, {
name: "shotgun", //5 name: "shotgun", //5
description: "fire a <strong>burst</strong> of bullets<br><em>crouch to reduce recoil</em>", description: "fire a <strong>burst</strong> of short range bullets<br><em>crouch to reduce recoil</em>",
ammo: 0, ammo: 0,
ammoPack: 8, ammoPack: 8,
have: false, have: false,
@@ -1003,7 +1052,7 @@ const b = {
} }
}, { }, {
name: "fléchettes", //6 name: "fléchettes", //6
description: "fire accurate high speed needles", description: "fire a flight of needles<br><strong>accurate</strong> at long range",
ammo: 0, ammo: 0,
ammoPack: 25, ammoPack: 25,
have: false, have: false,
@@ -1038,7 +1087,7 @@ const b = {
} }
}, { }, {
name: "missiles", //7 name: "missiles", //7
description: "fire a missile that accelerates towards nearby targets<br><span class='color-e'>explodes</span> when near target", description: "fire missiles that accelerate towards enemies<br><strong class='color-e'>explodes</strong> when near target",
ammo: 0, ammo: 0,
ammoPack: 8, ammoPack: 8,
have: false, have: false,
@@ -1143,7 +1192,7 @@ const b = {
} }
}, { }, {
name: "flak", //8 name: "flak", //8
description: "fire a cluster of short range projectiles<br><span class='color-e'>explode</span> on contact or after half a second", description: "fire a cluster of short range projectiles<br><strong class='color-e'>explode</strong> on contact or after half a second",
ammo: 0, ammo: 0,
ammoPack: 20, ammoPack: 20,
have: false, have: false,
@@ -1186,7 +1235,7 @@ const b = {
} }
}, { }, {
name: "grenades", //9 name: "grenades", //9
description: "fire a projectile that <span class='color-e'>explodes</span> on contact or after one second", description: "lob a single bouncy projectile<br><strong class='color-e'>explodes</strong> on contact or after one second",
ammo: 0, ammo: 0,
ammoPack: 9, ammoPack: 9,
have: false, have: false,
@@ -1214,7 +1263,7 @@ const b = {
} }
}, { }, {
name: "vacuum bomb", //10 name: "vacuum bomb", //10
description: "fire a huge <strong>bomb</strong> that sucks before it <span class='color-e'>explodes</span><br>click left mouse <strong>again</strong> to detonate", description: "fire a bomb that <strong>sucks</strong> before <strong class='color-e'>exploding</strong><br>click left mouse again to <strong>detonate</strong>",
ammo: 0, ammo: 0,
ammoPack: 5, ammoPack: 5,
have: false, have: false,
@@ -1323,7 +1372,7 @@ const b = {
} }
}, { }, {
name: "ferro frag", //11 name: "ferro frag", //11
description: "fire a <strong>grenade</strong> that ejects <strong class='color-m'>magnetized</strong> nails<br>nails are <strong class='color-m'>attracted</strong> to enemy targets", description: "fire a <strong>grenade</strong> that ejects magnetized nails<br>nails are <strong>attracted</strong> to enemies",
ammo: 0, ammo: 0,
ammoPack: 8, ammoPack: 8,
have: false, have: false,
@@ -1348,38 +1397,42 @@ const b = {
//target nearby mobs //target nearby mobs
const targets = [] const targets = []
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
const sub = Matter.Vector.sub(this.position, mob[i].position); if (mob[i].dropPowerUp) {
const dist = Matter.Vector.magnitude(sub); const sub = Matter.Vector.sub(this.position, mob[i].position);
if (dist < 1400 && const dist = Matter.Vector.magnitude(sub);
Matter.Query.ray(map, this.position, mob[i].position).length === 0 && if (dist < 1400 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0) { Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
targets.push(mob[i].position) Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
targets.push(
Matter.Vector.add(mob[i].position, Matter.Vector.mult(mob[i].velocity, dist / 60))
)
}
} }
} }
for (let i = 0; i < 14; i++) { for (let i = 0; i < 14; i++) {
const SPEED = 35 + 20 * Math.random() const speed = 55 + 10 * Math.random()
if (targets.length > 0) { // aim near a random target if (targets.length > 0) { // aim near a random target
const SPREAD = 100 const index = Math.floor(Math.random() * targets.length)
const INDEX = Math.floor(Math.random() * targets.length) const SPREAD = 150 / targets.length
const WHERE = { const WHERE = {
x: targets[INDEX].x + SPREAD * (Math.random() - 0.5), x: targets[index].x + SPREAD * (Math.random() - 0.5),
y: targets[INDEX].y + SPREAD * (Math.random() - 0.5) y: targets[index].y + SPREAD * (Math.random() - 0.5)
} }
needle(this.position, Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(WHERE, this.position)), SPEED)) needle(this.position, Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(WHERE, this.position)), speed))
} else { // aim in random direction } else { // aim in random direction
const ANGLE = 2 * Math.PI * Math.random() const ANGLE = 2 * Math.PI * Math.random()
needle(this.position, { needle(this.position, {
x: SPEED * Math.cos(ANGLE), x: speed * Math.cos(ANGLE),
y: SPEED * Math.sin(ANGLE) y: speed * Math.sin(ANGLE)
}) })
} }
function needle(pos, velocity) { function needle(pos, velocity) {
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.rectangle(pos.x, pos.y, 23 * b.modBulletSize, 2 * b.modBulletSize, b.fireAttributes(Math.atan2(velocity.y, velocity.x))); bullet[me] = Bodies.rectangle(pos.x, pos.y, 25 * b.modBulletSize, 2 * b.modBulletSize, b.fireAttributes(Math.atan2(velocity.y, velocity.x)));
Matter.Body.setVelocity(bullet[me], velocity); Matter.Body.setVelocity(bullet[me], velocity);
World.add(engine.world, bullet[me]); //add bullet to world World.add(engine.world, bullet[me]); //add bullet to world
bullet[me].endCycle = game.cycle + 60 + Math.floor(15 * Math.random()); bullet[me].endCycle = game.cycle + 60 + 15 * Math.random();
// bullet[me].dmg = 1.1+b.modExtraDmg; // bullet[me].dmg = 1.1+b.modExtraDmg;
bullet[me].do = function () {}; bullet[me].do = function () {};
} }
@@ -1390,7 +1443,7 @@ const b = {
} }
}, { }, {
name: "spores", //12 name: "spores", //12
description: "release an orb that discharges <span class='color-s'>spores</span> after 2 seconds<br>seeks out targets<br>passes through blocks", description: "fire orbs that discharge <strong class='color-s'>spores</strong><br><strong class='color-s'>spores</strong> seek out enemies",
ammo: 0, ammo: 0,
ammoPack: 5, ammoPack: 5,
have: false, have: false,
@@ -1491,9 +1544,10 @@ const b = {
} }
} }
}, { },
{
name: "drones", //13 name: "drones", //13
description: "release <strong>drones</strong> that seek out targets for 16 seconds<br>follows mouse if no targets are found", description: "fire <strong>drones</strong> that seek out enemies<br>follows mouse if no targets are found",
ammo: 0, ammo: 0,
ammoPack: 20, ammoPack: 20,
have: false, have: false,
@@ -1664,7 +1718,7 @@ const b = {
// }, // },
// { // {
// name: "kinetic slugs", //1 // name: "kinetic slugs", //1
// description: "fire a large <strong>rod</strong> that does excessive physical <span class='color-d'>damage</span><br><em>high recoil</em>", // description: "fire a large <strong>rod</strong> that does excessive physical <strong class='color-d'>damage</strong><br><em>high recoil</em>",
// ammo: 0, // ammo: 0,
// ammoPack: 5, // ammoPack: 5,
// have: false, // have: false,
@@ -1686,7 +1740,7 @@ const b = {
// player.force.x -= KNOCK * Math.cos(dir) // player.force.x -= KNOCK * Math.cos(dir)
// player.force.y -= KNOCK * Math.sin(dir) * 0.3 //reduce knock back in vertical direction to stop super jumps // player.force.y -= KNOCK * Math.sin(dir) * 0.3 //reduce knock back in vertical direction to stop super jumps
// }, // },
// { // {
// name: "triboelectricty", //14 // name: "triboelectricty", //14
// description: "release <strong>particles</strong> that quickly seek out targets", // description: "release <strong>particles</strong> that quickly seek out targets",
// ammo: 0, // ammo: 0,
@@ -1754,7 +1808,7 @@ const b = {
// { // {
// //draw a halo, since there will only be 1-3 balls // //draw a halo, since there will only be 1-3 balls
// name: "junk-bots", //14 // name: "junk-bots", //14
// description: "release unreliable <strong>drones</strong> that defend the space around the player<br><strong>collisions</strong> may cause <span class='color-d'>malfunction</span>", // description: "release unreliable <strong>drones</strong> that defend the space around the player<br><strong>collisions</strong> may cause <strong class='color-d'>malfunction</strong>",
// ammo: 0, // ammo: 0,
// ammoPack: 15, // ammoPack: 15,
// have: false, // have: false,

View File

@@ -177,9 +177,10 @@ function mobCollisionChecks(event) {
} }
//mob + bullet collisions //mob + bullet collisions
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) {
mob[k].foundPlayer();
// const dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity))); // const dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity)));
const dmg = b.dmgScale * (obj.dmg + b.modExtraDmg + 0.15 * obj.mass * Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity))) let dmg = b.dmgScale * (obj.dmg + b.modExtraDmg + 0.15 * obj.mass * Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity)))
if (b.modIsCrit && !mob[k].seePlayer.recall) dmg *= 6
mob[k].foundPlayer();
mob[k].damage(dmg); mob[k].damage(dmg);
obj.onDmg(); //some bullets do actions when they hits things, like despawn obj.onDmg(); //some bullets do actions when they hits things, like despawn
game.drawList.push({ game.drawList.push({

View File

@@ -454,7 +454,9 @@ const game = {
game.startGame(); game.startGame();
}; };
document.getElementById("controls").style.display = "inline"; document.getElementById("controls").style.display = "inline";
document.getElementById("settings").style.display = "inline"; document.getElementById("build-button").style.display = "inline"
isShowingBuilds = false
// document.getElementById("settings").style.display = "inline";
document.getElementById("splash").style.display = "inline"; document.getElementById("splash").style.display = "inline";
document.getElementById("dmg").style.display = "none"; document.getElementById("dmg").style.display = "none";
document.getElementById("health-bg").style.display = "none"; document.getElementById("health-bg").style.display = "none";
@@ -464,8 +466,10 @@ const game = {
then: null, then: null,
startGame() { startGame() {
game.onTitlePage = false; game.onTitlePage = false;
document.body.style.overflow = "hidden"
document.getElementById("build-grid").style.display = "none"
document.getElementById("controls").style.display = "none"; document.getElementById("controls").style.display = "none";
document.getElementById("settings").style.display = "none"; document.getElementById("build-button").style.display = "none";
document.getElementById("splash").onclick = null; //removes the onclick effect so the function only runs once document.getElementById("splash").onclick = null; //removes the onclick effect so the function only runs once
document.getElementById("splash").style.display = "none"; //hides the element that spawned the function document.getElementById("splash").style.display = "none"; //hides the element that spawned the function
document.getElementById("dmg").style.display = "inline"; document.getElementById("dmg").style.display = "inline";

View File

@@ -2,6 +2,15 @@
/* TODO: ******************************************* /* TODO: *******************************************
***************************************************** *****************************************************
add builds with combinations of gun, field and mobs
use the pull down menu
dynamically generate html about fields, guns and mods
add grid check to improve queries over large body arrays
something about broad phase
having trouble with this, might give up
gun: like drones, but fast moving and short lived gun: like drones, but fast moving and short lived
dies after doing damage dies after doing damage
@@ -12,31 +21,16 @@ gun: Spirit Bomb (singularity)
sucked in stuff increase size sucked in stuff increase size
uses energy uses energy
left and right click mouse icons for text displays
mod: auto pick up guns, heals, ammo mod: auto pick up guns, heals, ammo
use the same rule for drones use the same rule for drones
maybe give some other bonus too? maybe give some other bonus too?
mod: + move speed and jump height
will leg animations look strange?
that's OK for a mod
this could just slow the mobs down instead?
how?
rework junk bot rework junk bot
it's behavior is too unpredictable it's behavior is too unpredictable
range is unclear range is unclear
having the bullets last long after doing dmg isn't fun having the bullets last long after doing dmg isn't fun
we want a fun gun that acts like a melee weapon we want a fun gun that acts like a melee weapon
mouse can get suck as clicked if the user clicks off the window
can lead to gun lock up until player pressed mouse again
should I really need to fix this?
diegetic field meter
show as the player head filling with teal color
atmosphere levels atmosphere levels
large rotating fan that the player has to move through large rotating fan that the player has to move through
give the user a rest, between combat give the user a rest, between combat
@@ -55,17 +49,10 @@ Boss levels
add a key that player picks up and needs to set on the exit door to open it add a key that player picks up and needs to set on the exit door to open it
add modular difficulty settings
take reduced dmg
slower mob look / CD
more drops
fewer mobs
make a new var to scale number of mobs and stop using levels cleared var
make power ups keep moving to player if the pickup field is turned off before they get picked up make power ups keep moving to player if the pickup field is turned off before they get picked up
not sure how to do this without adding a constant check not sure how to do this without adding a constant check
levels spawn by having the map aspects randomly fly into place animate new level spawn by having the map aspects randomly fly into place
new map with repeating endlessness new map with repeating endlessness
get ideas from Manifold Garden game get ideas from Manifold Garden game
@@ -128,6 +115,37 @@ map: 0x000001 0x111111
*/ */
//build build grid display
let isShowingBuilds = false
document.getElementById("build-button").addEventListener("click", () => {
const el = document.getElementById("build-grid")
if (isShowingBuilds) {
el.style.display = "none"
isShowingBuilds = false
document.body.style.overflow = "hidden"
document.getElementById("controls").style.display = 'inline'
} else {
let text = ""
for (let i = 0, len = mech.fieldUpgrades.length; i < len; i++) {
text += `<div class="build-grid-module "><div class="circle-grid field"></div> &nbsp; <strong style='font-size:1.3em;'>${mech.fieldUpgrades[i].name}</strong><br> ${mech.fieldUpgrades[i].description}</div>`
}
for (let i = 0, len = b.guns.length; i < len; i++) {
text += `<div class="build-grid-module "><div class="circle-grid gun"></div> &nbsp; <strong style='font-size:1.3em;'>${b.guns[i].name}</strong><br> ${b.guns[i].description}</div>`
}
for (let i = 0, len = b.mods.length; i < len; i++) {
text += `<div class="build-grid-module "><div class="circle-grid mod"></div> &nbsp; <strong style='font-size:1.3em;'>${b.mods[i].name}</strong><br> ${b.mods[i].description}</div>`
}
el.innerHTML = text
el.style.display = "grid"
isShowingBuilds = true
document.body.style.overflowY = "scroll";
document.body.style.overflowX = "hidden";
document.getElementById("controls").style.display = 'none'
}
});
//set up canvas //set up canvas
var canvas = document.getElementById("canvas"); var canvas = document.getElementById("canvas");
//using "const" causes problems in safari when an ID shares the same name. //using "const" causes problems in safari when an ID shares the same name.

View File

@@ -14,9 +14,10 @@ const level = {
start() { start() {
if (level.levelsCleared === 0) { if (level.levelsCleared === 0) {
// game.difficulty = 6; //for testing to simulate possible mobs spawns // game.difficulty = 6; //for testing to simulate possible mobs spawns
// b.giveGuns(14) // level.startBuildRun(6)
// b.giveGuns(11)
// mech.fieldUpgrades[2].effect(); // mech.fieldUpgrades[2].effect();
// b.giveMod(15) // b.giveMod(20)
// spawn.pickList = ["ghoster", "ghoster"] // spawn.pickList = ["ghoster", "ghoster"]
this.intro(); //starting level this.intro(); //starting level
@@ -36,6 +37,77 @@ const level = {
level.addToWorld(); //add bodies to game engine level.addToWorld(); //add bodies to game engine
game.draw.setPaths(); game.draw.setPaths();
}, },
isBuildRun: false,
builds: [ // choose 5 total: guns, mods, and field
() => {
mech.fieldUpgrades[2].effect();
b.giveMod(6)
b.giveMod(8)
b.giveMod(9)
b.giveMod(15)
game.replaceTextLog = true;
game.makeTextLog("<h2>build: melee</h2>", 300);
},
() => {
b.giveGuns(13)
mech.fieldUpgrades[5].effect();
b.giveMod(8)
b.giveMod(3)
b.giveMod(11)
game.replaceTextLog = true;
game.makeTextLog("<h2>build: drones</h2>", 300);
},
() => {
b.giveGuns(8)
mech.fieldUpgrades[4].effect();
b.giveMod(4)
b.giveMod(5)
b.giveMod(16)
game.replaceTextLog = true;
game.makeTextLog("<h2>build: flak</h2>", 300);
},
() => {
b.giveMod(6)
b.giveMod(7)
b.giveMod(12)
b.giveMod(13)
b.giveMod(14)
game.replaceTextLog = true;
game.makeTextLog("<h2>build: block thrower</h2>", 300);
},
() => {
b.giveGuns(5)
mech.fieldUpgrades[6].effect();
b.giveMod(1)
b.giveMod(8)
b.giveMod(15)
game.replaceTextLog = true;
game.makeTextLog("<h2>build: stealth shotgun</h2>", 300);
},
() => {
b.giveGuns(2)
mech.fieldUpgrades[1].effect();
b.giveMod(8)
b.giveMod(9)
b.giveMod(11)
game.replaceTextLog = true;
game.makeTextLog("<h2>build: time out</h2>", 300);
},
() => {
b.giveGuns(0)
mech.fieldUpgrades[5].effect();
b.giveMod(7)
b.giveMod(5)
b.giveMod(18)
game.replaceTextLog = true;
game.makeTextLog("<h2>build: laser tag</h2>", 300);
},
],
startBuildRun(build) {
level.builds[build]()
game.difficulty = 6;
level.isBuildRun = true
},
difficultyIncrease(num = 1) { difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
game.dmgScale += 0.2; //damage done by mobs increases each level game.dmgScale += 0.2; //damage done by mobs increases each level

View File

@@ -898,6 +898,8 @@ const mobs = {
} }
}, },
damage(dmg) { damage(dmg) {
if (b.isModLowHealthDmg) dmg *= (3 / (2 + mech.health)) //up to 50% dmg at zero player health
if (b.isModFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(1000, Math.min(3500, this.distanceToPlayer())) - 1000) * 0.01 //up to 50% dmg at max range of 3500
this.health -= dmg / Math.sqrt(this.mass); this.health -= dmg / Math.sqrt(this.mass);
//this.fill = this.color + this.health + ')'; //this.fill = this.color + this.health + ')';
if (this.health < 0.1) this.death(); if (this.health < 0.1) this.death();
@@ -913,7 +915,7 @@ const mobs = {
}, },
onDeath() { onDeath() {
// a placeholder for custom effects on mob death // a placeholder for custom effects on mob death
//to use declare custom method in mob spawn // to use declare custom method in mob spawn
}, },
leaveBody: true, leaveBody: true,
dropPowerUp: true, dropPowerUp: true,

View File

@@ -68,15 +68,6 @@ const mech = {
FxNotHolding: 0.015, FxNotHolding: 0.015,
Fx: 0.015, //run Force on ground //this is reset in b.setModDefaults() Fx: 0.015, //run Force on ground //this is reset in b.setModDefaults()
FxAir: 0.015, //run Force in Air FxAir: 0.015, //run Force in Air
definePlayerMass(mass = mech.defaultMass) {
Matter.Body.setMass(player, mass);
//reduce air and ground move forces
this.Fx = 0.075 / mass * b.modSquirrelFx
this.FxAir = 0.375 / mass / mass
//make player stand a bit lower when holding heavy masses
this.yOffWhen.stand = Math.max(this.yOffWhen.crouch, Math.min(49, 49 - (mass - 5) * 6))
if (this.onGround && !this.crouch) this.yOffGoal = this.yOffWhen.stand;
},
yOff: 70, yOff: 70,
yOffGoal: 70, yOffGoal: 70,
onGround: false, //checks if on ground or in air onGround: false, //checks if on ground or in air
@@ -415,11 +406,6 @@ const mech = {
} }
}, },
health: 0, health: 0,
// regen() {
// if (this.health < 1 && mech.cycle % 15 === 0) {
// this.addHealth(0.01);
// }
// },
drawHealth() { drawHealth() {
if (this.health < 1) { if (this.health < 1) {
ctx.fillStyle = "rgba(100, 100, 100, 0.5)"; ctx.fillStyle = "rgba(100, 100, 100, 0.5)";
@@ -450,6 +436,12 @@ const mech = {
}, },
defaultFPSCycle: 0, //tracks when to return to normal fps defaultFPSCycle: 0, //tracks when to return to normal fps
damage(dmg) { damage(dmg) {
if (b.isModMonogamy && b.inventory[0] === b.activeGun) {
for (let i = 0, len = b.inventory.length; i < len; i++) {
dmg *= 0.93
}
}
console.log(dmg, "after")
this.health -= dmg; this.health -= dmg;
if (this.health < 0) { if (this.health < 0) {
this.health = 0; this.health = 0;
@@ -639,7 +631,6 @@ const mech = {
throwChargeRate: 0, throwChargeRate: 0,
throwChargeMax: 0, throwChargeMax: 0,
fieldFireCD: 0, fieldFireCD: 0,
fieldDamage: 0,
fieldShieldingScale: 0, fieldShieldingScale: 0,
grabRange: 0, grabRange: 0,
fieldArc: 0, fieldArc: 0,
@@ -656,7 +647,6 @@ const mech = {
player.collisionFilter.mask = 0x010011 //0x010011 is normal player.collisionFilter.mask = 0x010011 //0x010011 is normal
this.holdingMassScale = 0.5; this.holdingMassScale = 0.5;
this.fieldFireCD = 15; this.fieldFireCD = 15;
this.fieldDamage = 0; // a value of 1.0 kills a small mob in 2-3 hits on level 1
this.fieldShieldingScale = 1; //scale energy loss after collision with mob this.fieldShieldingScale = 1; //scale energy loss after collision with mob
this.grabRange = 175; this.grabRange = 175;
this.fieldArc = 0.2; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) this.fieldArc = 0.2; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
@@ -701,6 +691,15 @@ const mech = {
this.throwCharge = 0; this.throwCharge = 0;
} }
}, },
definePlayerMass(mass = mech.defaultMass) {
Matter.Body.setMass(player, mass);
//reduce air and ground move forces
this.Fx = 0.075 / mass * b.modSquirrelFx
this.FxAir = 0.375 / mass / mass
//make player stand a bit lower when holding heavy masses
this.yOffWhen.stand = Math.max(this.yOffWhen.crouch, Math.min(49, 49 - (mass - 5) * 6))
if (this.onGround && !this.crouch) this.yOffGoal = this.yOffWhen.stand;
},
drawHold(target, stroke = true) { drawHold(target, stroke = true) {
const eye = 15; const eye = 15;
const len = target.vertices.length - 1; const len = target.vertices.length - 1;
@@ -869,55 +868,70 @@ const mech = {
} }
} }
}, },
pushMobs() { // push all mobs in range and in direction looking pushMass(who) {
const fieldBlockCost = Math.max(0.02, who.mass * 0.012) //0.012
if (this.fieldMeter > fieldBlockCost) {
this.fieldMeter -= fieldBlockCost * this.fieldShieldingScale;
if (this.fieldMeter < 0) this.fieldMeter = 0;
this.drawHold(who);
//knock backs
const angle = Math.atan2(player.position.y - who.position.y, player.position.x - who.position.x);
const mass = Math.min(Math.sqrt(who.mass), 4);
Matter.Body.setVelocity(who, {
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
});
}
},
pushMobsFacing() { // find mobs in range and in direction looking
for (let i = 0, len = mob.length; i < len; ++i) { 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) { if (
const fieldBlockCost = Math.max(0.02, mob[i].mass * 0.012) //0.012 Matter.Vector.magnitude(Matter.Vector.sub(mob[i].position, this.pos)) < this.grabRange &&
if (this.fieldMeter > fieldBlockCost) { this.lookingAt(mob[i]) &&
this.fieldMeter -= fieldBlockCost * this.fieldShieldingScale; Matter.Query.ray(map, mob[i].position, this.pos).length === 0
if (this.fieldMeter < 0) this.fieldMeter = 0; ) {
if (this.fieldDamage) mob[i].damage(b.dmgScale * this.fieldDamage); mob[i].locatePlayer();
mob[i].locatePlayer(); mech.pushMass(mob[i]);
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);
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 in any direction pushMobs360(range = this.grabRange * 0.75) { // find mobs in range in any direction
for (let i = 0, len = mob.length; i < len; ++i) { 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) { if (
const fieldBlockCost = Math.max(0.02, mob[i].mass * 0.012) Matter.Vector.magnitude(Matter.Vector.sub(mob[i].position, this.pos)) < range &&
if (this.fieldMeter > fieldBlockCost) { Matter.Query.ray(map, mob[i].position, this.pos).length === 0
this.fieldMeter -= fieldBlockCost * this.fieldShieldingScale; ) {
if (this.fieldMeter < 0) this.fieldMeter = 0 mob[i].locatePlayer();
mech.pushMass(mob[i]);
if (this.fieldDamage) mob[i].damage(b.dmgScale * this.fieldDamage); }
mob[i].locatePlayer(); }
this.drawHold(mob[i]); },
//mob and player knock back pushBodyFacing() { // push all body in range and in direction looking
const angle = Math.atan2(player.position.y - mob[i].position.y, player.position.x - mob[i].position.x); for (let i = 0, len = body.length; i < len; ++i) {
const mass = Math.min(Math.sqrt(mob[i].mass), 4); if (
// console.log(mob[i].mass, Math.sqrt(mob[i].mass), mass) body[i].speed > 12 && body[i].mass > 2 &&
Matter.Body.setVelocity(mob[i], { Matter.Vector.magnitude(Matter.Vector.sub(body[i].position, this.pos)) < this.grabRange &&
x: player.velocity.x - (15 * Math.cos(angle)) / mass, this.lookingAt(body[i]) &&
y: player.velocity.y - (15 * Math.sin(angle)) / mass Matter.Query.ray(map, body[i].position, this.pos).length === 0
}); ) {
Matter.Body.setVelocity(player, { mech.pushMass(body[i]);
x: player.velocity.x + 5 * Math.cos(angle) * mass, }
y: player.velocity.y + 5 * Math.sin(angle) * mass }
}); },
} pushBody360(range = this.grabRange * 0.75) { // push all body in range and in direction looking
for (let i = 0, len = body.length; i < len; ++i) {
if (
body[i].speed > 12 && body[i].mass > 2 &&
Matter.Vector.magnitude(Matter.Vector.sub(body[i].position, this.pos)) < range &&
this.lookingAt(body[i]) &&
Matter.Query.ray(map, body[i].position, this.pos).length === 0 &&
body[i].collisionFilter.category === 0x010000
) {
mech.pushMass(body[i]);
} }
} }
}, },
@@ -1017,12 +1031,12 @@ const mech = {
}, },
fieldUpgrades: [{ fieldUpgrades: [{
name: "field emitter", name: "field emitter",
description: "<strong class='color-f'>shields</strong> you from <span class='color-d'>damage</span><br>lets you <strong>pick up</strong> and throw objects", description: "use <strong class='color-f'>energy</strong> to <strong>shield</strong> yourself from <strong class='color-d'>damage</strong><br>lets you <strong>pick up</strong> and <strong>throw</strong> objects",
effect: () => { effect: () => {
mech.fieldMode = 0; mech.fieldMode = 0;
mech.fieldText(); mech.fieldText();
game.replaceTextLog = true; //allow text over write game.replaceTextLog = true; //allow text over write
// game.makeTextLog("<strong style='font-size:30px;'></strong><br> <span class='faded'>(right click or space bar)</span><p></p>", 1200); // game.makeTextLog("<strong style='font-size:30px;'></strong><br> <strong class='faded'>(right click or space bar)</strong><p></p>", 1200);
mech.setHoldDefaults(); mech.setHoldDefaults();
mech.hold = function () { mech.hold = function () {
if (mech.isHolding) { if (mech.isHolding) {
@@ -1032,7 +1046,8 @@ const mech = {
} else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed } else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed
mech.drawField(); mech.drawField();
mech.grabPowerUp(); mech.grabPowerUp();
mech.pushMobs(); mech.pushMobsFacing();
mech.pushBodyFacing();
mech.lookForPickUp(); mech.lookForPickUp();
} else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
mech.pickUp(); mech.pickUp();
@@ -1045,7 +1060,7 @@ const mech = {
}, },
{ {
name: "time dilation field", name: "time dilation field",
description: "<strong style='letter-spacing: 3px;'>stop time</strong> while field is active<br> <em>can fire while field is active</em>", description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br><em>can fire bullets while field is active</em>",
effect: () => { effect: () => {
mech.fieldMode = 1; mech.fieldMode = 1;
mech.fieldText(); mech.fieldText();
@@ -1119,14 +1134,14 @@ const mech = {
}, },
{ {
name: "plasma torch", name: "plasma torch",
description: "field emits a beam of destructive <strong style='color:#d0d;'>ionized gas</strong><br><span style='color:#a00;'>decreased</span> <strong class='color-f'>shield</strong> range and efficiency", description: "use <strong class='color-f'>energy</strong> to emit <strong class='color-d'>damaging</strong> beam<br><strong>decreased</strong> <strong>shield</strong> range and efficiency",
effect: () => { effect: () => {
mech.fieldMode = 2; mech.fieldMode = 2;
mech.fieldText(); mech.fieldText();
mech.setHoldDefaults(); mech.setHoldDefaults();
// mech.fieldShieldingScale = 2; // mech.fieldShieldingScale = 2;
// mech.grabRange = 125; // mech.grabRange = 125;
mech.fieldArc = 0.05 //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.fieldArc = 0.1 //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
mech.hold = function () { mech.hold = function () {
if (mech.isHolding) { if (mech.isHolding) {
@@ -1269,7 +1284,8 @@ const mech = {
ctx.lineWidth = 2 * Math.random(); ctx.lineWidth = 2 * Math.random();
ctx.stroke(); ctx.stroke();
mech.pushMobs360(100); mech.pushMobs360(110);
// mech.pushBody360(100); //disabled because doesn't work at short range
mech.grabPowerUp(); mech.grabPowerUp();
mech.lookForPickUp(); mech.lookForPickUp();
} else { } else {
@@ -1286,7 +1302,7 @@ const mech = {
}, },
{ {
name: "negative mass field", name: "negative mass field",
description: "field nullifies &nbsp;<strong style='letter-spacing: 15px;'>gravity</strong><br><em>can fire while field is active</em>", description: "use <strong class='color-f'>energy</strong> to nullify &nbsp; <strong style='letter-spacing: 10px;'>gravity</strong><br><em>can fire bullets while active</em>",
effect: () => { effect: () => {
mech.fieldMode = 3; mech.fieldMode = 3;
mech.fieldText(); mech.fieldText();
@@ -1302,6 +1318,7 @@ const mech = {
const DRAIN = 0.0004 const DRAIN = 0.0004
if (mech.fieldMeter > DRAIN) { if (mech.fieldMeter > DRAIN) {
mech.pushMobs360(170); mech.pushMobs360(170);
mech.pushBody360(180);
mech.grabPowerUp(); mech.grabPowerUp();
mech.lookForPickUp(170); mech.lookForPickUp(170);
//look for nearby objects to make zero-g //look for nearby objects to make zero-g
@@ -1373,7 +1390,7 @@ const mech = {
}, },
{ {
name: "standing wave harmonics", name: "standing wave harmonics",
description: "you are surrounded by oscillating <strong class='color-f'>shields</strong><br> <span style='color:#a00;'>decreased</span> field regeneration", description: "oscillating <strong>shields</strong> surround you <strong>constantly</strong><br> <strong>decreased</strong> <strong class='color-f'>energy</strong> regeneration",
effect: () => { effect: () => {
mech.fieldMode = 4; mech.fieldMode = 4;
mech.fieldText(); mech.fieldText();
@@ -1409,6 +1426,7 @@ const mech = {
ctx.arc(mech.pos.x, mech.pos.y, grabRange3, 0, 2 * Math.PI); ctx.arc(mech.pos.x, mech.pos.y, grabRange3, 0, 2 * Math.PI);
ctx.fill(); ctx.fill();
mech.pushMobs360(netGrabRange); mech.pushMobs360(netGrabRange);
mech.pushBody360(netGrabRange);
} }
mech.drawFieldMeter() mech.drawFieldMeter()
} }
@@ -1416,16 +1434,16 @@ const mech = {
}, },
{ {
name: "nano-scale manufacturing", name: "nano-scale manufacturing",
description: "excess field <span class='color-f'>energy</span> used to build <strong class='color-b'>drones</strong><br> increased <span class='color-f'>energy</span> regeneration", description: "excess <strong class='color-f'>energy</strong> used to build <strong>drones</strong><br><strong>3x</strong> <strong class='color-f'>energy</strong> regeneration",
effect: () => { effect: () => {
let gunIndex = 13 //Math.random() < 0.5 ? 13 : 14 let gunIndex = 13 //Math.random() < 0.5 ? 13 : 14
mech.fieldMode = 5; mech.fieldMode = 5;
mech.fieldText(); mech.fieldText();
mech.setHoldDefaults(); mech.setHoldDefaults();
mech.fieldRegen *= 3.5; mech.fieldRegen *= 3;
mech.hold = function () { mech.hold = function () {
if (mech.fieldMeter === 1) { if (mech.fieldMeter === 1) {
mech.fieldMeter -= 0.5; mech.fieldMeter -= 0.43;
b.guns[gunIndex].fire() //spawn drone b.guns[gunIndex].fire() //spawn drone
} }
if (mech.isHolding) { if (mech.isHolding) {
@@ -1433,7 +1451,8 @@ const mech = {
mech.holding(); mech.holding();
mech.throw(); mech.throw();
} else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed } else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed
mech.pushMobs(); mech.pushMobsFacing();
mech.pushBodyFacing();
mech.drawField(); mech.drawField();
mech.grabPowerUp(); mech.grabPowerUp();
mech.lookForPickUp(); mech.lookForPickUp();
@@ -1448,7 +1467,7 @@ const mech = {
}, },
{ {
name: "phase decoherence field", name: "phase decoherence field",
description: "<strong>intangible</strong> while field is active<br><em style='opacity: 0.6;'>can't see or be seen outside field</em>", description: "use <strong class='color-f'>energy</strong> to to become <strong>intangible</strong><br><em style='opacity: 0.6;'>can't see or be seen outside field</em>",
effect: () => { effect: () => {
mech.fieldMode = 6; mech.fieldMode = 6;
mech.fieldText(); mech.fieldText();
@@ -1493,142 +1512,5 @@ const mech = {
} }
} }
}, },
// {
// name: "electrostatic field",
// description: "field does <strong class='color-d'>damage</strong> on contact<br> increased <span class='color-f'>field</span> regeneration",
// effect: () => {
// mech.fieldMode = 2;
// mech.fieldText();
// mech.setHoldDefaults();
// mech.grabRange = 225;
// mech.fieldShieldingScale = 2.5;
// mech.fieldRegen *= 2;
// mech.fieldDamage = 4; //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) {
// mech.drawHold(mech.holdingTarget);
// mech.holding();
// mech.throw();
// } else if ((keys[32] || game.mouseDownRight) && mech.fieldMeter > 0.15) { //not hold but field button is pressed
// //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.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.01 + mech.fieldMeter * (0.1 + 0.1 * Math.random())) + ")";
// } else {
// ctx.fillStyle = "rgba(255,50,150," + (0.02 + mech.fieldMeter * (0.18 + 0.18 * Math.random())) + ")";
// }
// // ctx.fillStyle = "rgba(110,170,200," + (0.02 + mech.fieldMeter * (0.08 + 0.1 * Math.random())) + ")";
// // ctx.fillStyle = "rgba(110,170,200," + (0.06 + mech.fieldMeter * (0.1 + 0.18 * Math.random())) + ")";
// 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();
// mech.grabPowerUp();
// mech.pushMobs();
// mech.lookForPickUp();
// } else if (mech.holdingTarget && mech.fireCDcycle < mech.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)
// }
// mech.drawFieldMeter()
// }
// }
// },
// () => {
// mech.fieldMode = 7;
// game.makeTextLog("<strong style='font-size:30px;'>Thermal Radiation Field</strong><br> <span class='faded'>(right click or space bar)</span> <p>field grows while active<br>damages all targets within range, <span style='color:#a00;'>including player</span><br> <span style='color:#a00;'>decreased</span> field shielding efficiency</p>", 1200);
// mech.setHoldDefaults();
// mech.fieldShieldingScale = 10;
// mech.rangeSmoothing = 0
// mech.hold = function () {
// if (mech.isHolding) {
// mech.drawHold(mech.holdingTarget);
// mech.holding();
// mech.throw();
// } else if ((keys[32] || game.mouseDownRight && mech.fieldCDcycle < mech.cycle)) { //not hold but field button is pressed
// mech.grabPowerUp();
// mech.lookForPickUp(Math.max(180, mech.grabRange));
// mech.pushMobs360(140);
// if (mech.health > 0.1) {
// const DRAIN = 0.0008
// if (mech.fieldMeter > DRAIN) {
// mech.fieldMeter -= DRAIN;
// mech.damage(0.00005 + 0.00000012 * mech.grabRange)
// //draw damage field
// mech.grabRange = mech.grabRange * 0.997 + (1350 + 150 * Math.cos(mech.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.7)');
// gradient.addColorStop(1, 'rgba(255,0,50,' + (0.6 + 0.2 * Math.random()) + ')');
// const angleOff = 2 * Math.PI * Math.random()
// ctx.beginPath();
// ctx.arc(this.pos.x, this.pos.y, mech.grabRange + Math.sqrt(mech.grabRange) * 0.7 * (Math.random() - 0.5), angleOff, 1.8 * Math.PI + angleOff);
// ctx.fillStyle = gradient //rgba(255,0,0,0.2)
// ctx.fill();
// //damage and push away mobs in range
// 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.grabRange) {
// mob[i].damage(0.01);
// mob[i].locatePlayer();
// mob[i].force = Matter.Vector.mult(Matter.Vector.normalise(sub), -0.0001 * mob[i].mass) //gently push mobs back
// }
// }
// }
// } else {
// mech.fieldCDcycle = mech.cycle + 120;
// }
// } else {
// mech.grabRange = 180;
// mech.drawField();
// mech.grabPowerUp();
// mech.lookForPickUp();
// }
// } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
// mech.grabRange = 0
// mech.pickUp();
// } else {
// mech.grabRange = 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()
// }
// },
], ],
}; };

View File

@@ -45,7 +45,8 @@ const powerUps = {
if (!game.lastLogTime) game.makeTextLog("<span style='font-size:115%;'><span class='color-f'>+energy</span></span>", 300); if (!game.lastLogTime) game.makeTextLog("<span style='font-size:115%;'><span class='color-f'>+energy</span></span>", 300);
} else { } else {
//ammo given scales as mobs take more hits to kill //ammo given scales as mobs take more hits to kill
const ammo = Math.ceil((target.ammoPack * (0.45 + 0.08 * Math.random())) / b.dmgScale); let ammo = Math.ceil((target.ammoPack * (0.4 + 0.05 * Math.random())) / b.dmgScale);
if (level.isBuildRun) ammo *= 2
target.ammo += ammo; target.ammo += ammo;
game.updateGunHUD(); game.updateGunHUD();
game.makeTextLog("<div class='circle gun'></div> &nbsp; <span style='font-size:110%;'>+" + ammo + " ammo for " + target.name + "</span>", 300); game.makeTextLog("<div class='circle gun'></div> &nbsp; <span style='font-size:110%;'>+" + ammo + " ammo for " + target.name + "</span>", 300);
@@ -143,38 +144,49 @@ const powerUps = {
spawnRandomPowerUp(x, y) { //mostly used after mob dies spawnRandomPowerUp(x, y) { //mostly used after mob dies
if (Math.random() * Math.random() - 0.25 > Math.sqrt(mech.health) || Math.random() < 0.04) { //spawn heal chance is higher at low health if (Math.random() * Math.random() - 0.25 > Math.sqrt(mech.health) || Math.random() < 0.04) { //spawn heal chance is higher at low health
powerUps.spawn(x, y, "heal"); powerUps.spawn(x, y, "heal");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "heal");
return; return;
} }
if (Math.random() < 0.2) { if (Math.random() < 0.2 && b.inventory.length > 0) {
if (b.inventory.length > 0) powerUps.spawn(x, y, "ammo"); powerUps.spawn(x, y, "ammo");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "ammo");
return; return;
} }
if (Math.random() < 0.004 * (5 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun to drop if (Math.random() < 0.004 * (5 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun to drop
powerUps.spawn(x, y, "gun"); powerUps.spawn(x, y, "gun");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun");
return; return;
} }
if (Math.random() < 0.004 * (8 - b.modCount)) { if (Math.random() < 0.004 * (8 - b.modCount)) {
powerUps.spawn(x, y, "mod"); powerUps.spawn(x, y, "mod");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod");
return; return;
} }
if (Math.random() < 0.005) { if (Math.random() < 0.005) {
powerUps.spawn(x, y, "field"); powerUps.spawn(x, y, "field");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field");
return; return;
} }
}, },
spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades
if (mech.fieldMode === 0) { if (mech.fieldMode === 0) {
powerUps.spawn(x, y, "field") powerUps.spawn(x, y, "field")
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field")
} else if (Math.random() < 0.042 * (b.mods.length - b.modCount)) { } else if (Math.random() < 0.042 * (b.mods.length - b.modCount)) {
powerUps.spawn(x, y, "mod") powerUps.spawn(x, y, "mod")
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod")
} else if (Math.random() < 0.3) { } else if (Math.random() < 0.3) {
powerUps.spawn(x, y, "field"); powerUps.spawn(x, y, "field");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field");
} else if (Math.random() < 0.05 * (7 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun to drop } else if (Math.random() < 0.05 * (7 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun to drop
powerUps.spawn(x, y, "gun") powerUps.spawn(x, y, "gun")
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun")
} else if (mech.health < 0.6) { } else if (mech.health < 0.6) {
powerUps.spawn(x, y, "heal"); powerUps.spawn(x, y, "heal");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "heal");
} else { } else {
powerUps.spawn(x, y, "ammo"); powerUps.spawn(x, y, "ammo");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "ammo");
} }
}, },
chooseRandomPowerUp(x, y) { //100% chance to drop a random power up //used in spawn.debris chooseRandomPowerUp(x, y) { //100% chance to drop a random power up //used in spawn.debris
@@ -195,31 +207,33 @@ const powerUps = {
} }
}, },
spawn(x, y, target, moving = true, mode = null) { spawn(x, y, target, moving = true, mode = null) {
let i = powerUp.length; if (!level.isBuildRun || target === "heal" || target === "ammo") {
target = powerUps[target]; let i = powerUp.length;
size = target.size(); target = powerUps[target];
powerUp[i] = Matter.Bodies.polygon(x, y, 0, size, { size = target.size();
density: 0.001, powerUp[i] = Matter.Bodies.polygon(x, y, 0, size, {
frictionAir: 0.01, density: 0.001,
restitution: 0.8, frictionAir: 0.01,
inertia: Infinity, //prevents rotation restitution: 0.8,
collisionFilter: { inertia: Infinity, //prevents rotation
group: 0, collisionFilter: {
category: 0x100000, group: 0,
mask: 0x100001 category: 0x100000,
}, mask: 0x100001
color: target.color, },
effect: target.effect, color: target.color,
mode: mode, effect: target.effect,
name: target.name, mode: mode,
size: size name: target.name,
}); size: size
if (moving) {
Matter.Body.setVelocity(powerUp[i], {
x: (Math.random() - 0.5) * 15,
y: Math.random() * -9 - 3
}); });
if (moving) {
Matter.Body.setVelocity(powerUp[i], {
x: (Math.random() - 0.5) * 15,
y: Math.random() * -9 - 3
});
}
World.add(engine.world, powerUp[i]); //add to world
} }
World.add(engine.world, powerUp[i]); //add to world
}, },
}; };

113
style.css
View File

@@ -1,7 +1,7 @@
body { body {
font-family: "Helvetica", "Arial", sans-serif; font-family: "Helvetica", "Arial", sans-serif;
margin: 0; margin: 0;
overflow: hidden; /* overflow: hidden; */
background-color: #fff; background-color: #fff;
user-select: none; user-select: none;
/*cursor: crosshair;*/ /*cursor: crosshair;*/
@@ -35,10 +35,78 @@ table {
/* background-color: #ddd; */ /* background-color: #ddd; */
} }
th {
text-align: left;
}
summary { summary {
font-size: 1.2em; font-size: 1.2em;
} }
#build-button {
position: absolute;
bottom: 0px;
right: 1px;
z-index: 12;
font-size: 1.3em;
}
#build-grid {
padding: 10px;
margin: 0px;
border: 0px;
/* border-radius: 8px; */
background-color: #b6bfca;
display: none;
/* display: grid; */
grid-template-columns: repeat(auto-fit, minmax(292px, 1fr));
grid-auto-rows: minmax(auto, auto);
grid-gap: 15px;
position: relative;
bottom: 0px;
/* left: 0px; */
z-index: 12;
font-size: 1.3em;
}
.build-grid-module {
/* box-shadow: 0px 1px 4px #234; */
padding: 7px;
/* margin: 4px; */
line-height: 150%;
border-radius: 6px;
background: #eee;
font-size: 0.65em;
/* display: flex; */
}
.build-grid-module:hover {
background-color: #fff;
}
.gun-module {
background: #d5dde5;
}
.field-module {
background: #bde;
}
.mod-module {
background: #fdf;
}
/* #build {
position: absolute;
bottom: 0px;
right: 1px;
z-index: 12;
font-size: 1.3em;
} */
#controls { #controls {
position: absolute; position: absolute;
bottom: 0px; bottom: 0px;
@@ -49,14 +117,6 @@ summary {
/* border-radius: 5px; */ /* border-radius: 5px; */
} }
#settings {
position: absolute;
bottom: 0px;
right: 1px;
z-index: 12;
font-size: 1.3em;
}
#details-div { #details-div {
padding: 10px; padding: 10px;
border-radius: 8px; border-radius: 8px;
@@ -214,36 +274,28 @@ em {
.color-f { .color-f {
color: #0cf; color: #0cf;
} letter-spacing: 1px;
.color-b {
color: #024;
} }
.color-d { .color-d {
color: #f05; color: #f03;
} letter-spacing: 1px;
.color-l {
color: #f0f;
} }
.color-h { .color-h {
color: #0d9; color: #0c8;
letter-spacing: 1px;
} }
.color-e { .color-e {
color: #a10; color: #e50;
} letter-spacing: 1px;
.color-m {
color: #536;
} }
.color-s { .color-s {
color: #066; color: #066;
font-weight: 900; font-weight: 900;
letter-spacing: 2px; letter-spacing: 1px;
} }
.faded { .faded {
@@ -256,6 +308,15 @@ em {
height: 20px; height: 20px;
border-radius: 50%; border-radius: 50%;
display: inline-block; display: inline-block;
margin-bottom: -2px;
}
.circle-grid {
width: 20px;
height: 20px;
border-radius: 50%;
display: inline-block;
margin-bottom: -4px;
} }
.field { .field {
@@ -268,12 +329,10 @@ em {
.gun { .gun {
background: #149; background: #149;
margin-bottom: -2px;
} }
.heal { .heal {
background: #0d9; background: #0d9;
margin-bottom: -2px;
} }
.box { .box {