added 5 new mods, power up display, game balance
This commit is contained in:
93
index.html
93
index.html
@@ -30,7 +30,6 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- <body oncontextmenu="return false"> -->
|
||||
<div id='guns'></div>
|
||||
<div id='field'></div>
|
||||
@@ -77,34 +76,82 @@
|
||||
<canvas id="canvas"></canvas>
|
||||
<!-- ********** 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">
|
||||
<details>
|
||||
<summary>info</summary>
|
||||
<summary>about</summary>
|
||||
<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>
|
||||
<tr>
|
||||
<td>FIRE</td>
|
||||
<th>FIRE</th>
|
||||
<td>left mouse</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>FIELD</td>
|
||||
<th>FIELD</th>
|
||||
<td>right mouse / spacebar</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>MOVE</td>
|
||||
<th>MOVE</th>
|
||||
<td>WASD / arrows</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GUNS</td>
|
||||
<th>GUNS</th>
|
||||
<td>Q / E / mouse wheel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ZOOM</td>
|
||||
<th>ZOOM</th>
|
||||
<td>+ / -</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>PAUSE</td>
|
||||
<th>PAUSE</th>
|
||||
<td>P</td>
|
||||
</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.
|
||||
<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>
|
||||
</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>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
186
js/bullets.js
186
js/bullets.js
@@ -19,7 +19,12 @@ const b = {
|
||||
modExtraDmg: null,
|
||||
annihilation: null,
|
||||
fullHeal: null,
|
||||
modSquirrelFx: 1,
|
||||
modSquirrelFx: null,
|
||||
modIsCrit: null,
|
||||
modMoreDrops: null,
|
||||
isModLowHealthDmg: null,
|
||||
isModFarAwayDmg: null,
|
||||
isModMonogamy: null,
|
||||
setModDefaults() {
|
||||
b.modCount = 0;
|
||||
b.modFireRate = 1;
|
||||
@@ -37,6 +42,11 @@ const b = {
|
||||
b.modAnnihilation = false;
|
||||
b.isModFullHeal = false;
|
||||
b.modSquirrelFx = 1;
|
||||
b.modIsCrit = false;
|
||||
b.modMoreDrops = 0;
|
||||
b.isModLowHealthDmg = false;
|
||||
b.isModFarAwayDmg = false;
|
||||
b.isModMonogamy = false;
|
||||
mech.Fx = 0.015;
|
||||
mech.jumpForce = 0.38;
|
||||
mech.throwChargeRate = 2;
|
||||
@@ -47,17 +57,17 @@ const b = {
|
||||
},
|
||||
mods: [{
|
||||
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
|
||||
effect: () => {
|
||||
//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)
|
||||
b.modBulletSize = 1.07;
|
||||
b.modBulletSize = 1.1;
|
||||
}
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls
|
||||
b.modFireRate = 0.85
|
||||
@@ -65,7 +75,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray
|
||||
b.modNoAmmo = 1
|
||||
@@ -73,7 +83,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range)
|
||||
b.isModBulletsLastLonger = 1.40
|
||||
@@ -81,7 +91,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
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
|
||||
@@ -90,7 +100,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => {
|
||||
b.isModAoEImmunity = true; //good for guns with explosions
|
||||
@@ -98,7 +108,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //makes dangerous situations more survivable
|
||||
b.isModDroneOnDamage = true;
|
||||
@@ -106,7 +116,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //good late game maybe?
|
||||
b.modSpores = 0.20;
|
||||
@@ -114,16 +124,15 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //good with laser, and all fields
|
||||
|
||||
b.modEnergySiphon = 0.2;
|
||||
b.modEnergySiphon = 0.15;
|
||||
}
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //good with guns that overkill: one shot, grenade
|
||||
b.modHealthDrain = 0.01;
|
||||
@@ -131,7 +140,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => {
|
||||
b.modIsImmortal = true;
|
||||
@@ -139,7 +148,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //good with guns that fire many bullets at low speeds, minigun, drones, junk-bots, shotgun, superballs, wavebeam
|
||||
b.modExtraDmg = 0.1
|
||||
@@ -147,7 +156,7 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //good with mods that heal: superconductive healing, entropy transfer
|
||||
b.modAnnihilation = true
|
||||
@@ -155,17 +164,16 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { // good with ablative synthesis, electrostatic field
|
||||
b.isModFullHeal = true
|
||||
effect: () => { // good with ablative synthesis, melee builds
|
||||
}
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { // good with ablative synthesis, electrostatic field
|
||||
effect: () => { // good with guns that run out of ammo
|
||||
b.isModFullHeal = true
|
||||
mech.throwChargeRate = 4;
|
||||
mech.throwChargeMax = 150;
|
||||
@@ -174,15 +182,54 @@ const b = {
|
||||
},
|
||||
{
|
||||
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
|
||||
effect: () => { //
|
||||
effect: () => { // good with melee builds, content skipping builds
|
||||
b.modSquirrelFx = 1.2;
|
||||
mech.Fx = 0.015 * b.modSquirrelFx;
|
||||
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) {
|
||||
b.mods[i].effect(); //give specific mod
|
||||
@@ -226,7 +273,7 @@ const b = {
|
||||
}
|
||||
} else {
|
||||
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.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: [{
|
||||
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,
|
||||
// ammoPack: 350,
|
||||
ammoPack: Infinity,
|
||||
@@ -658,17 +705,18 @@ const b = {
|
||||
},
|
||||
{
|
||||
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,
|
||||
ammoPack: 12,
|
||||
have: false,
|
||||
isStarterGun: false,
|
||||
fire() {
|
||||
const me = bullet.length;
|
||||
bullet[me] = Bodies.rectangle(9, -90, 0.01 * b.modBulletSize, 0.0017 * b.modBulletSize, {
|
||||
// density: 0.0015, //frictionAir: 0.01, //restitution: 0,
|
||||
angle: 0,
|
||||
friction: 0.5,
|
||||
bullet[me] = Bodies.rectangle(0, 0, 0.012 * b.modBulletSize, 0.0022 * b.modBulletSize, {
|
||||
density: 0.002, //0.001 is normal
|
||||
//frictionAir: 0.01, //restitution: 0,
|
||||
// angle: 0,
|
||||
// friction: 0.5,
|
||||
frictionAir: 0,
|
||||
dmg: 3 + b.modExtraDmg, //damage done in addition to the damage from momentum
|
||||
classType: "bullet",
|
||||
@@ -698,7 +746,7 @@ const b = {
|
||||
y: mech.pos.y
|
||||
})
|
||||
Matter.Body.setAngle(this, mech.angle)
|
||||
const speed = 80
|
||||
const speed = 85
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: mech.Vx / 2 + speed * this.charge * Math.cos(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) {
|
||||
const SUB = Matter.Vector.sub(body[i].position, mech.pos)
|
||||
const DISTANCE = Matter.Vector.magnitude(SUB)
|
||||
|
||||
if (DISTANCE < RANGE) {
|
||||
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))
|
||||
@@ -732,8 +781,6 @@ const b = {
|
||||
// mob[i].force.y += FORCE.y
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
} else { // charging on mouse down
|
||||
mech.fireCDcycle = Infinity //can't fire until mouse is released
|
||||
if (mech.crouch) {
|
||||
@@ -750,7 +797,9 @@ const b = {
|
||||
// if (DISTANCE < RANGE) {
|
||||
// Matter.Body.setVelocity(mob[i], Matter.Vector.rotate(mob[i].velocity, 0.1))
|
||||
// }
|
||||
// const DRAIN = 0.0002 //&& mech.fieldMeter > DRAIN
|
||||
if (DISTANCE < RANGE) {
|
||||
// mech.fieldMeter -= DRAIN + mech.fieldRegen;
|
||||
const DEPTH = RANGE - DISTANCE
|
||||
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
|
||||
@@ -894,7 +943,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 85,
|
||||
have: false,
|
||||
@@ -947,7 +996,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 11,
|
||||
have: false,
|
||||
@@ -975,7 +1024,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 8,
|
||||
have: false,
|
||||
@@ -1003,7 +1052,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 25,
|
||||
have: false,
|
||||
@@ -1038,7 +1087,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 8,
|
||||
have: false,
|
||||
@@ -1143,7 +1192,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 20,
|
||||
have: false,
|
||||
@@ -1186,7 +1235,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 9,
|
||||
have: false,
|
||||
@@ -1214,7 +1263,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 5,
|
||||
have: false,
|
||||
@@ -1323,7 +1372,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 8,
|
||||
have: false,
|
||||
@@ -1348,38 +1397,42 @@ const b = {
|
||||
//target nearby mobs
|
||||
const targets = []
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
const sub = Matter.Vector.sub(this.position, mob[i].position);
|
||||
const dist = Matter.Vector.magnitude(sub);
|
||||
if (dist < 1400 &&
|
||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||
Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
|
||||
targets.push(mob[i].position)
|
||||
if (mob[i].dropPowerUp) {
|
||||
const sub = Matter.Vector.sub(this.position, mob[i].position);
|
||||
const dist = Matter.Vector.magnitude(sub);
|
||||
if (dist < 1400 &&
|
||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
|
||||
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++) {
|
||||
const SPEED = 35 + 20 * Math.random()
|
||||
const speed = 55 + 10 * Math.random()
|
||||
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 = {
|
||||
x: targets[INDEX].x + SPREAD * (Math.random() - 0.5),
|
||||
y: targets[INDEX].y + SPREAD * (Math.random() - 0.5)
|
||||
x: targets[index].x + 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
|
||||
const ANGLE = 2 * Math.PI * Math.random()
|
||||
needle(this.position, {
|
||||
x: SPEED * Math.cos(ANGLE),
|
||||
y: SPEED * Math.sin(ANGLE)
|
||||
x: speed * Math.cos(ANGLE),
|
||||
y: speed * Math.sin(ANGLE)
|
||||
})
|
||||
}
|
||||
|
||||
function needle(pos, velocity) {
|
||||
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);
|
||||
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].do = function () {};
|
||||
}
|
||||
@@ -1390,7 +1443,7 @@ const b = {
|
||||
}
|
||||
}, {
|
||||
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,
|
||||
ammoPack: 5,
|
||||
have: false,
|
||||
@@ -1491,9 +1544,10 @@ const b = {
|
||||
}
|
||||
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
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,
|
||||
ammoPack: 20,
|
||||
have: false,
|
||||
@@ -1664,7 +1718,7 @@ const b = {
|
||||
// },
|
||||
// {
|
||||
// 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,
|
||||
// ammoPack: 5,
|
||||
// have: false,
|
||||
@@ -1686,7 +1740,7 @@ const b = {
|
||||
// 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
|
||||
// },
|
||||
// {
|
||||
// {
|
||||
// name: "triboelectricty", //14
|
||||
// description: "release <strong>particles</strong> that quickly seek out targets",
|
||||
// ammo: 0,
|
||||
@@ -1754,7 +1808,7 @@ const b = {
|
||||
// {
|
||||
// //draw a halo, since there will only be 1-3 balls
|
||||
// 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,
|
||||
// ammoPack: 15,
|
||||
// have: false,
|
||||
|
||||
@@ -177,9 +177,10 @@ function mobCollisionChecks(event) {
|
||||
}
|
||||
//mob + bullet collisions
|
||||
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 + 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);
|
||||
obj.onDmg(); //some bullets do actions when they hits things, like despawn
|
||||
game.drawList.push({
|
||||
|
||||
@@ -454,7 +454,9 @@ const game = {
|
||||
game.startGame();
|
||||
};
|
||||
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("dmg").style.display = "none";
|
||||
document.getElementById("health-bg").style.display = "none";
|
||||
@@ -464,8 +466,10 @@ const game = {
|
||||
then: null,
|
||||
startGame() {
|
||||
game.onTitlePage = false;
|
||||
document.body.style.overflow = "hidden"
|
||||
document.getElementById("build-grid").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").style.display = "none"; //hides the element that spawned the function
|
||||
document.getElementById("dmg").style.display = "inline";
|
||||
|
||||
64
js/index.js
64
js/index.js
@@ -2,6 +2,15 @@
|
||||
/* 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
|
||||
dies after doing damage
|
||||
|
||||
@@ -12,31 +21,16 @@ gun: Spirit Bomb (singularity)
|
||||
sucked in stuff increase size
|
||||
uses energy
|
||||
|
||||
left and right click mouse icons for text displays
|
||||
|
||||
mod: auto pick up guns, heals, ammo
|
||||
use the same rule for drones
|
||||
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
|
||||
it's behavior is too unpredictable
|
||||
range is unclear
|
||||
having the bullets last long after doing dmg isn't fun
|
||||
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
|
||||
large rotating fan that the player has to move through
|
||||
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 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
|
||||
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
|
||||
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> <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> <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> <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
|
||||
var canvas = document.getElementById("canvas");
|
||||
//using "const" causes problems in safari when an ID shares the same name.
|
||||
|
||||
76
js/level.js
76
js/level.js
@@ -14,9 +14,10 @@ const level = {
|
||||
start() {
|
||||
if (level.levelsCleared === 0) {
|
||||
// game.difficulty = 6; //for testing to simulate possible mobs spawns
|
||||
// b.giveGuns(14)
|
||||
// level.startBuildRun(6)
|
||||
// b.giveGuns(11)
|
||||
// mech.fieldUpgrades[2].effect();
|
||||
// b.giveMod(15)
|
||||
// b.giveMod(20)
|
||||
// spawn.pickList = ["ghoster", "ghoster"]
|
||||
|
||||
this.intro(); //starting level
|
||||
@@ -36,6 +37,77 @@ const level = {
|
||||
level.addToWorld(); //add bodies to game engine
|
||||
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) {
|
||||
for (let i = 0; i < num; i++) {
|
||||
game.dmgScale += 0.2; //damage done by mobs increases each level
|
||||
|
||||
@@ -898,6 +898,8 @@ const mobs = {
|
||||
}
|
||||
},
|
||||
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.fill = this.color + this.health + ')';
|
||||
if (this.health < 0.1) this.death();
|
||||
@@ -913,7 +915,7 @@ const mobs = {
|
||||
},
|
||||
onDeath() {
|
||||
// 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,
|
||||
dropPowerUp: true,
|
||||
|
||||
304
js/player.js
304
js/player.js
@@ -68,15 +68,6 @@ const mech = {
|
||||
FxNotHolding: 0.015,
|
||||
Fx: 0.015, //run Force on ground //this is reset in b.setModDefaults()
|
||||
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,
|
||||
yOffGoal: 70,
|
||||
onGround: false, //checks if on ground or in air
|
||||
@@ -415,11 +406,6 @@ const mech = {
|
||||
}
|
||||
},
|
||||
health: 0,
|
||||
// regen() {
|
||||
// if (this.health < 1 && mech.cycle % 15 === 0) {
|
||||
// this.addHealth(0.01);
|
||||
// }
|
||||
// },
|
||||
drawHealth() {
|
||||
if (this.health < 1) {
|
||||
ctx.fillStyle = "rgba(100, 100, 100, 0.5)";
|
||||
@@ -450,6 +436,12 @@ const mech = {
|
||||
},
|
||||
defaultFPSCycle: 0, //tracks when to return to normal fps
|
||||
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;
|
||||
if (this.health < 0) {
|
||||
this.health = 0;
|
||||
@@ -639,7 +631,6 @@ const mech = {
|
||||
throwChargeRate: 0,
|
||||
throwChargeMax: 0,
|
||||
fieldFireCD: 0,
|
||||
fieldDamage: 0,
|
||||
fieldShieldingScale: 0,
|
||||
grabRange: 0,
|
||||
fieldArc: 0,
|
||||
@@ -656,7 +647,6 @@ const mech = {
|
||||
player.collisionFilter.mask = 0x010011 //0x010011 is normal
|
||||
this.holdingMassScale = 0.5;
|
||||
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.grabRange = 175;
|
||||
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;
|
||||
}
|
||||
},
|
||||
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) {
|
||||
const eye = 15;
|
||||
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) {
|
||||
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.fieldShieldingScale;
|
||||
if (this.fieldMeter < 0) this.fieldMeter = 0;
|
||||
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);
|
||||
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
|
||||
});
|
||||
}
|
||||
if (
|
||||
Matter.Vector.magnitude(Matter.Vector.sub(mob[i].position, this.pos)) < this.grabRange &&
|
||||
this.lookingAt(mob[i]) &&
|
||||
Matter.Query.ray(map, mob[i].position, this.pos).length === 0
|
||||
) {
|
||||
mob[i].locatePlayer();
|
||||
mech.pushMass(mob[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
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) {
|
||||
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.fieldShieldingScale;
|
||||
if (this.fieldMeter < 0) this.fieldMeter = 0
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
if (
|
||||
Matter.Vector.magnitude(Matter.Vector.sub(mob[i].position, this.pos)) < range &&
|
||||
Matter.Query.ray(map, mob[i].position, this.pos).length === 0
|
||||
) {
|
||||
mob[i].locatePlayer();
|
||||
mech.pushMass(mob[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
pushBodyFacing() { // 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)) < this.grabRange &&
|
||||
this.lookingAt(body[i]) &&
|
||||
Matter.Query.ray(map, body[i].position, this.pos).length === 0
|
||||
) {
|
||||
mech.pushMass(body[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
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: [{
|
||||
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: () => {
|
||||
mech.fieldMode = 0;
|
||||
mech.fieldText();
|
||||
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.hold = function () {
|
||||
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
|
||||
mech.drawField();
|
||||
mech.grabPowerUp();
|
||||
mech.pushMobs();
|
||||
mech.pushMobsFacing();
|
||||
mech.pushBodyFacing();
|
||||
mech.lookForPickUp();
|
||||
} else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
|
||||
mech.pickUp();
|
||||
@@ -1045,7 +1060,7 @@ const mech = {
|
||||
},
|
||||
{
|
||||
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: () => {
|
||||
mech.fieldMode = 1;
|
||||
mech.fieldText();
|
||||
@@ -1119,14 +1134,14 @@ const mech = {
|
||||
},
|
||||
{
|
||||
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: () => {
|
||||
mech.fieldMode = 2;
|
||||
mech.fieldText();
|
||||
mech.setHoldDefaults();
|
||||
// mech.fieldShieldingScale = 2;
|
||||
// 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.hold = function () {
|
||||
if (mech.isHolding) {
|
||||
@@ -1269,7 +1284,8 @@ const mech = {
|
||||
ctx.lineWidth = 2 * Math.random();
|
||||
ctx.stroke();
|
||||
|
||||
mech.pushMobs360(100);
|
||||
mech.pushMobs360(110);
|
||||
// mech.pushBody360(100); //disabled because doesn't work at short range
|
||||
mech.grabPowerUp();
|
||||
mech.lookForPickUp();
|
||||
} else {
|
||||
@@ -1286,7 +1302,7 @@ const mech = {
|
||||
},
|
||||
{
|
||||
name: "negative mass field",
|
||||
description: "field nullifies <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 <strong style='letter-spacing: 10px;'>gravity</strong><br><em>can fire bullets while active</em>",
|
||||
effect: () => {
|
||||
mech.fieldMode = 3;
|
||||
mech.fieldText();
|
||||
@@ -1302,6 +1318,7 @@ const mech = {
|
||||
const DRAIN = 0.0004
|
||||
if (mech.fieldMeter > DRAIN) {
|
||||
mech.pushMobs360(170);
|
||||
mech.pushBody360(180);
|
||||
mech.grabPowerUp();
|
||||
mech.lookForPickUp(170);
|
||||
//look for nearby objects to make zero-g
|
||||
@@ -1373,7 +1390,7 @@ const mech = {
|
||||
},
|
||||
{
|
||||
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: () => {
|
||||
mech.fieldMode = 4;
|
||||
mech.fieldText();
|
||||
@@ -1409,6 +1426,7 @@ const mech = {
|
||||
ctx.arc(mech.pos.x, mech.pos.y, grabRange3, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
mech.pushMobs360(netGrabRange);
|
||||
mech.pushBody360(netGrabRange);
|
||||
}
|
||||
mech.drawFieldMeter()
|
||||
}
|
||||
@@ -1416,16 +1434,16 @@ const mech = {
|
||||
},
|
||||
{
|
||||
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: () => {
|
||||
let gunIndex = 13 //Math.random() < 0.5 ? 13 : 14
|
||||
mech.fieldMode = 5;
|
||||
mech.fieldText();
|
||||
mech.setHoldDefaults();
|
||||
mech.fieldRegen *= 3.5;
|
||||
mech.fieldRegen *= 3;
|
||||
mech.hold = function () {
|
||||
if (mech.fieldMeter === 1) {
|
||||
mech.fieldMeter -= 0.5;
|
||||
mech.fieldMeter -= 0.43;
|
||||
b.guns[gunIndex].fire() //spawn drone
|
||||
}
|
||||
if (mech.isHolding) {
|
||||
@@ -1433,7 +1451,8 @@ const mech = {
|
||||
mech.holding();
|
||||
mech.throw();
|
||||
} 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.grabPowerUp();
|
||||
mech.lookForPickUp();
|
||||
@@ -1448,7 +1467,7 @@ const mech = {
|
||||
},
|
||||
{
|
||||
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: () => {
|
||||
mech.fieldMode = 6;
|
||||
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()
|
||||
// }
|
||||
// },
|
||||
],
|
||||
};
|
||||
@@ -45,7 +45,8 @@ const powerUps = {
|
||||
if (!game.lastLogTime) game.makeTextLog("<span style='font-size:115%;'><span class='color-f'>+energy</span></span>", 300);
|
||||
} else {
|
||||
//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;
|
||||
game.updateGunHUD();
|
||||
game.makeTextLog("<div class='circle gun'></div> <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
|
||||
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");
|
||||
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "heal");
|
||||
return;
|
||||
}
|
||||
if (Math.random() < 0.2) {
|
||||
if (b.inventory.length > 0) powerUps.spawn(x, y, "ammo");
|
||||
if (Math.random() < 0.2 && b.inventory.length > 0) {
|
||||
powerUps.spawn(x, y, "ammo");
|
||||
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "ammo");
|
||||
return;
|
||||
}
|
||||
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");
|
||||
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun");
|
||||
return;
|
||||
}
|
||||
if (Math.random() < 0.004 * (8 - b.modCount)) {
|
||||
powerUps.spawn(x, y, "mod");
|
||||
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod");
|
||||
return;
|
||||
}
|
||||
if (Math.random() < 0.005) {
|
||||
powerUps.spawn(x, y, "field");
|
||||
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field");
|
||||
return;
|
||||
}
|
||||
},
|
||||
spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades
|
||||
if (mech.fieldMode === 0) {
|
||||
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)) {
|
||||
powerUps.spawn(x, y, "mod")
|
||||
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod")
|
||||
} else if (Math.random() < 0.3) {
|
||||
powerUps.spawn(x, y, "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
|
||||
powerUps.spawn(x, y, "gun")
|
||||
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun")
|
||||
} else if (mech.health < 0.6) {
|
||||
powerUps.spawn(x, y, "heal");
|
||||
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "heal");
|
||||
} else {
|
||||
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
|
||||
@@ -195,31 +207,33 @@ const powerUps = {
|
||||
}
|
||||
},
|
||||
spawn(x, y, target, moving = true, mode = null) {
|
||||
let i = powerUp.length;
|
||||
target = powerUps[target];
|
||||
size = target.size();
|
||||
powerUp[i] = Matter.Bodies.polygon(x, y, 0, size, {
|
||||
density: 0.001,
|
||||
frictionAir: 0.01,
|
||||
restitution: 0.8,
|
||||
inertia: Infinity, //prevents rotation
|
||||
collisionFilter: {
|
||||
group: 0,
|
||||
category: 0x100000,
|
||||
mask: 0x100001
|
||||
},
|
||||
color: target.color,
|
||||
effect: target.effect,
|
||||
mode: mode,
|
||||
name: target.name,
|
||||
size: size
|
||||
});
|
||||
if (moving) {
|
||||
Matter.Body.setVelocity(powerUp[i], {
|
||||
x: (Math.random() - 0.5) * 15,
|
||||
y: Math.random() * -9 - 3
|
||||
if (!level.isBuildRun || target === "heal" || target === "ammo") {
|
||||
let i = powerUp.length;
|
||||
target = powerUps[target];
|
||||
size = target.size();
|
||||
powerUp[i] = Matter.Bodies.polygon(x, y, 0, size, {
|
||||
density: 0.001,
|
||||
frictionAir: 0.01,
|
||||
restitution: 0.8,
|
||||
inertia: Infinity, //prevents rotation
|
||||
collisionFilter: {
|
||||
group: 0,
|
||||
category: 0x100000,
|
||||
mask: 0x100001
|
||||
},
|
||||
color: target.color,
|
||||
effect: target.effect,
|
||||
mode: mode,
|
||||
name: target.name,
|
||||
size: size
|
||||
});
|
||||
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
113
style.css
@@ -1,7 +1,7 @@
|
||||
body {
|
||||
font-family: "Helvetica", "Arial", sans-serif;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
/* overflow: hidden; */
|
||||
background-color: #fff;
|
||||
user-select: none;
|
||||
/*cursor: crosshair;*/
|
||||
@@ -35,10 +35,78 @@ table {
|
||||
/* background-color: #ddd; */
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
summary {
|
||||
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 {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
@@ -49,14 +117,6 @@ summary {
|
||||
/* border-radius: 5px; */
|
||||
}
|
||||
|
||||
#settings {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 1px;
|
||||
z-index: 12;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
#details-div {
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
@@ -214,36 +274,28 @@ em {
|
||||
|
||||
.color-f {
|
||||
color: #0cf;
|
||||
}
|
||||
|
||||
.color-b {
|
||||
color: #024;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.color-d {
|
||||
color: #f05;
|
||||
}
|
||||
|
||||
.color-l {
|
||||
color: #f0f;
|
||||
color: #f03;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.color-h {
|
||||
color: #0d9;
|
||||
color: #0c8;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.color-e {
|
||||
color: #a10;
|
||||
}
|
||||
|
||||
.color-m {
|
||||
color: #536;
|
||||
color: #e50;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.color-s {
|
||||
color: #066;
|
||||
font-weight: 900;
|
||||
letter-spacing: 2px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.faded {
|
||||
@@ -256,6 +308,15 @@ em {
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
.circle-grid {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
|
||||
.field {
|
||||
@@ -268,12 +329,10 @@ em {
|
||||
|
||||
.gun {
|
||||
background: #149;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
.heal {
|
||||
background: #0d9;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
.box {
|
||||
|
||||
Reference in New Issue
Block a user