Compare commits
10 Commits
8bb8222b73
...
7142943b71
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7142943b71 | ||
|
|
b2426cd7be | ||
|
|
77e484c3d2 | ||
|
|
c9a5ab91b8 | ||
|
|
1040d1ff7e | ||
|
|
2daeae1ff4 | ||
|
|
1966173f88 | ||
|
|
97c5509278 | ||
|
|
f1a6713f68 | ||
|
|
1fde74d65a |
BIN
img/Bells theorem.webp
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
img/collimator.webp
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
img/demineralization.webp
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
img/equivalence principle.webp
Normal file
|
After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 52 KiB |
BIN
img/principle of locality.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
img/remineralization.webp
Normal file
|
After Width: | Height: | Size: 60 KiB |
108
index.html
@@ -39,20 +39,22 @@
|
||||
<div style="position: absolute; top:0;right:0;">
|
||||
<div id="pause-grid-right" class="pause-grid"></div>
|
||||
</div>
|
||||
<svg class="SVG-button" id="experiment-button" width="170" height="45" style="border: 2px #333 solid;">
|
||||
<g stroke='none' fill='#333' stroke-width="2" font-size="30px" font-family="Arial, sans-serif">
|
||||
<text x="10" y="33">experiment</text>
|
||||
</g>
|
||||
<svg class="SVG-button SVG-button-splash" id="start-button" width="82" height="45" stroke='none' fill='#333' font-size="30px" font-family="Arial, sans-serif" onclick="simulation.startGame()">
|
||||
<text x="10" y="32">start</text>
|
||||
</svg>
|
||||
<svg class="SVG-button" id="training-button" width="120" height="45" style="border: 2px #333 solid;" stroke='none' fill='#333' font-size="30px" font-family="Arial, sans-serif" onclick="simulation.startGame(false, true)">
|
||||
<text x="10" y="33">training</text>
|
||||
<svg class="SVG-button SVG-button-splash" id="training-button" width="120" height="45" stroke='none' fill='#333' font-size="30px" font-family="Arial, sans-serif" onclick="simulation.startGame(false, true)">
|
||||
<text x="10" y="32">training</text>
|
||||
</svg>
|
||||
<svg class="SVG-button SVG-button-splash" id="experiment-button" width="170" height="45">
|
||||
<text stroke='none' fill='#333' stroke-width="2" font-size="30px" font-family="Arial, sans-serif" x="10" y="32">experiment</text>
|
||||
</svg>
|
||||
|
||||
|
||||
<div id='info'>
|
||||
<div id="settings" >
|
||||
<details id = 'settings-details'>
|
||||
<div>
|
||||
<details id='settings-details'>
|
||||
<summary>settings</summary>
|
||||
<div style="line-height: 150%;" class="details-div">
|
||||
<div class="details-div" style="max-width: 24rem; line-height: 150%;">
|
||||
<input onclick="build.showImages('settings')" type="checkbox" id="hide-images" name="hide-images" style="width:17px; height:17px;">
|
||||
<label for="hide-images" title="hide images for fields, guns, and tech">hide images</label>
|
||||
<br>
|
||||
@@ -75,25 +77,6 @@
|
||||
<label for="banned" title="type banned levels with a space between them. Example: run temple biohazard">banned levels:</label>
|
||||
<input id="banned" name="banned" placeholder="list levels by name" autocomplete="off" spellcheck="false" style="width: 182px;" />
|
||||
<br>
|
||||
<label for="classic-select" title="play older versions of n-gon">classic n-gon:</label>
|
||||
<select name="classic-select" id="classic-select" onChange="window.location.href=this.value">
|
||||
<option value="https://scratch.mit.edu/projects/14005697/fullscreen/">mech: 2014</option>
|
||||
<option value="https://scratch.mit.edu/projects/22573757/fullscreen/">spacetime: 2015</option>
|
||||
<option value="https://scratch.mit.edu/projects/41429974/fullscreen/">ballistics: 2015</option>
|
||||
<option value="https://scratch.mit.edu/projects/43690666/fullscreen/">portal: 2016</option>
|
||||
<option value="https://codepen.io/lilgreenland/full/ozXNWZ">side scroller: 2016</option>
|
||||
<option value="https://codepen.io/lilgreenland/full/wzARJY">side scroller: 2016</option>
|
||||
<option value="classic/7-1-2017/">LandGame: 2017</option>
|
||||
<option value="classic/4-15-2018/">n-gon: 2018</option>
|
||||
<option value="classic/7-11-2019/">n-gon: summer-2019</option>
|
||||
<option value="classic/9-8-2019/">n-gon: fall-2019</option>
|
||||
<option value="classic/7-15-2020/">n-gon: summer-2020</option>
|
||||
<option value="classic/6-1-2021/">n-gon: spring-2021</option>
|
||||
<option value="classic/11-1-2022/">n-gon: fall-2022</option>
|
||||
<option value="classic/7-29-2024/">n-gon: summer-2024</option>
|
||||
<option value="" selected>current version</option>
|
||||
</select>
|
||||
<br>
|
||||
<label for="seed" title="the randoms seed determines level order, tech choices, and mob types">randomization seed:</label>
|
||||
<input type="text" id="seed" name="seed" autocomplete="off" spellcheck="false" minlength="1" style="width: 120px;">
|
||||
<br><span id="previous-seed" style="color:#bbb"></span>
|
||||
@@ -103,7 +86,7 @@
|
||||
<div>
|
||||
<details id="control-details">
|
||||
<summary>controls</summary>
|
||||
<div class="details-div">
|
||||
<div class="details-div" style="max-width: 24rem;">
|
||||
To change controls click a box
|
||||
<br>and press an unused key.
|
||||
<br><br>
|
||||
@@ -171,22 +154,76 @@
|
||||
<div>
|
||||
<details id="updates">
|
||||
<summary>updates</summary>
|
||||
<div id="updates-div" class="details-div" style="font-size: 70%;height: 400px;overflow: scroll;max-width: 800px;"></div>
|
||||
<div id="updates-div" class="details-div" style="font-size: 70%;height: 400px;overflow: scroll;max-width: 50rem;"></div>
|
||||
</details>
|
||||
</div>
|
||||
<div>
|
||||
<details>
|
||||
<summary>about</summary>
|
||||
<div class="details-div" style="max-width: 450px;">
|
||||
n-gon is a solo project written in JavaScript, CSS, and HTML using the matter.js 2-D physics library. It's free and open source on <a href="https://github.com/landgreen/n-gon">Github</a>.
|
||||
<div class="details-div" style="max-width: 24rem;padding:0.6em;font-size: 1.3rem;">
|
||||
<a id="github" href="https://github.com/landgreen/n-gon" aria-label="github">
|
||||
<svg viewBox="0 0 100 16" xmlns="http://www.w3.org/2000/svg" fill="#1B1F23">
|
||||
<!-- <svg viewBox="0 0 100 16" xmlns="http://www.w3.org/2000/svg" fill="#1B1F23">
|
||||
<path d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" />
|
||||
<g stroke='none' font-size="8px" font-family="Arial Black, sans-serif">
|
||||
<text x="19" y="11">Github</text>
|
||||
</g>
|
||||
</svg> -->
|
||||
<svg viewBox="-19 -8 40 16" xmlns="http://www.w3.org/2000/svg" stroke="#333" stroke-width="0.4" >
|
||||
<defs>
|
||||
<linearGradient id="horizontalGradient" x1="-8" y1="0" x2="8" y2="0" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="#e0e3e6" />
|
||||
<stop offset="100%" stop-color="#fff" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="0" cy="0" r="7" fill="url(#horizontalGradient)" />
|
||||
<circle cx="4" cy="0" r="1.1" fill="none" />
|
||||
<path d="M5.3 0 h1.7" stroke="#1B1F23" />
|
||||
</svg>
|
||||
</a>
|
||||
</a>
|
||||
<p>
|
||||
I wrote n-gon in JavaScript, CSS, and HTML using the matter.js 2-D physics library.
|
||||
The code is free and open source on <a id="github" href="https://github.com/landgreen/n-gon" aria-label="github">Github</a>.
|
||||
This is just my hobby project, but I try to fix bugs when <a id="github" href="https://github.com/landgreen/n-gon/issues" aria-label="github">reported</a>.
|
||||
</p>
|
||||
|
||||
<span style="max-width: 25rem; line-height: 180%;">
|
||||
<label for="classic-select" title="play older versions of n-gon">classic n-gon:</label>
|
||||
<select name="classic-select" id="classic-select" onChange="window.location.href=this.value">
|
||||
<option value="https://scratch.mit.edu/projects/14005697/fullscreen/">mech: 2014</option>
|
||||
<option value="https://scratch.mit.edu/projects/22573757/fullscreen/">spacetime: 2015</option>
|
||||
<option value="https://scratch.mit.edu/projects/41429974/fullscreen/">ballistics: 2015</option>
|
||||
<option value="https://scratch.mit.edu/projects/43690666/fullscreen/">portal: 2016</option>
|
||||
<option value="https://codepen.io/lilgreenland/full/ozXNWZ">side scroller: 2016</option>
|
||||
<option value="https://codepen.io/lilgreenland/full/wzARJY">side scroller: 2016</option>
|
||||
<option value="classic/7-1-2017/">LandGame: 2017</option>
|
||||
<option value="classic/4-15-2018/">n-gon: 2018</option>
|
||||
<option value="classic/7-11-2019/">n-gon: summer-2019</option>
|
||||
<option value="classic/9-8-2019/">n-gon: fall-2019</option>
|
||||
<option value="classic/7-15-2020/">n-gon: summer-2020</option>
|
||||
<option value="classic/6-1-2021/">n-gon: spring-2021</option>
|
||||
<option value="classic/11-1-2022/">n-gon: fall-2022</option>
|
||||
<option value="classic/7-29-2024/">n-gon: summer-2024</option>
|
||||
<option value="" selected>old versions</option>
|
||||
</select>
|
||||
<br><label for="classic-select" title="community links">community links:</label>
|
||||
<select name="classic-select" id="classic-select" onChange="window.location.href=this.value">
|
||||
<option value="https://www.cornbread2100.com/n-gon-loader">n-commit loader</option>
|
||||
<option value="https://3xiondev.github.io/n-gon-upgraded">n-gon upgraded</option>
|
||||
<option value="https://n-gon-enhanced.vercel.app">n-gon enhanced</option>
|
||||
<option value="https://coaldeficit.github.io/c-gon">c-gon</option>
|
||||
<option value="https://kgurchiek.github.io/n-gon-portal-gun">n-gon portal gun</option>
|
||||
<option value="https://github.com/Whyisthisnotavalable/n-scythe">n-scythe</option>
|
||||
<option value="https://github.com/kgurchiek/n-gon-mobile">n-mobile</option>
|
||||
<option value="https://github.com/kgurchiek/n-gon-controller">n-controller</option>
|
||||
<option value="https://github.com/kgurchiek/n-gon-stopwatch">n-stopwatch</option>
|
||||
<option value="https://github.com/Ant-Throw-Pology/n-qol">n-qol</option>
|
||||
<option value="https://github.com/c-rxxp-y/n-gon-treasury">n-treasury</option>
|
||||
<option value="https://github.com/3xionDev/n-docs">n-docs</option>
|
||||
<option value="https://ngon.fandom.com/wiki/N-gon">n-wiki fandom</option>
|
||||
<option value="https://n-gon.wiki/">n-wiki n-gon</option>
|
||||
<option value="" selected>mods, forks, info</option>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
@@ -228,8 +265,9 @@
|
||||
<path d="M70 70 h60 v60 h-60 v-60" class="draw-lines-box-2" />
|
||||
<path d="M140 70 h60 v60 h-60 v-60" class="draw-lines-box-3" />
|
||||
</g>
|
||||
<g fill='none' stroke='#333' stroke-width="3.5" stroke-linejoin="round" stroke-linecap="round">
|
||||
<g fill='none' stroke='#333' stroke-width="3" stroke-linejoin="round" stroke-linecap="round">
|
||||
<path d="M0 60 h60 v-60 h-60 v60" class="draw-lines-box-1" />
|
||||
<!-- <rect x="0" y="0" width="60" height="60" rx="10" ry="10" class="draw-lines-box-1" /> -->
|
||||
<path d="M70 60 h60 v-60 h-60 v60" class="draw-lines-box-2" />
|
||||
<path d="M140 60 h60 v-60 h-60 v60" class="draw-lines-box-3" />
|
||||
<path d="M0 70 h60 v60 h-60 v-60" class="draw-lines-box-1" />
|
||||
|
||||
583
js/bullet.js
@@ -23,7 +23,7 @@ const b = {
|
||||
},
|
||||
fire() { },
|
||||
fireNormal() {
|
||||
if (b.inventory.length && b.activeGun !== null) {
|
||||
if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) {
|
||||
if (input.fire && m.fireCDcycle < m.cycle && (!input.field || m.fieldFire)) {
|
||||
if (b.guns[b.activeGun].ammo > 0) {
|
||||
b.fireWithAmmo()
|
||||
@@ -36,7 +36,7 @@ const b = {
|
||||
}
|
||||
},
|
||||
fireNotMove() { //added && player.speed < 0.5 && m.onGround
|
||||
if (b.inventory.length && b.activeGun !== null) {
|
||||
if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) {
|
||||
if (input.fire && m.fireCDcycle < m.cycle && (!input.field || m.fieldFire) && player.speed < 2.5 && m.onGround && Math.abs(m.yOff - m.yOffGoal) < 1) {
|
||||
if (b.guns[b.activeGun].ammo > 0) {
|
||||
b.fireWithAmmo()
|
||||
@@ -49,7 +49,7 @@ const b = {
|
||||
}
|
||||
},
|
||||
fireAlwaysFire() { //added && player.speed < 0.5 && m.onGround //removed input.fire && (!input.field || m.fieldFire)
|
||||
if (b.inventory.length && b.activeGun !== null) {
|
||||
if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) {
|
||||
if (m.fireCDcycle < m.cycle && player.speed < 0.5 && m.onGround && Math.abs(m.yOff - m.yOffGoal) < 1) {
|
||||
if (b.guns[b.activeGun].ammo > 0) {
|
||||
b.fireWithAmmo()
|
||||
@@ -60,7 +60,7 @@ const b = {
|
||||
}
|
||||
},
|
||||
fireFloat() { //added && player.speed < 0.5 && m.onGround
|
||||
if (b.inventory.length && b.activeGun !== null) {
|
||||
if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) {
|
||||
if (input.fire && (!input.field || m.fieldFire)) {
|
||||
if (m.fireCDcycle < m.cycle) {
|
||||
if (b.guns[b.activeGun].ammo > 0) {
|
||||
@@ -116,7 +116,7 @@ const b = {
|
||||
}
|
||||
},
|
||||
refundAmmo() { //triggers after firing when you removed ammo for a gun, but didn't need to
|
||||
if (tech.crouchAmmoCount && m.crouch && b.activeGun !== null) {
|
||||
if (tech.crouchAmmoCount && m.crouch && (b.activeGun !== null && b.activeGun !== undefined)) {
|
||||
tech.crouchAmmoCount--
|
||||
if ((tech.crouchAmmoCount) % 2) {
|
||||
b.guns[b.activeGun].ammo++;
|
||||
@@ -280,14 +280,14 @@ const b = {
|
||||
fireProps(cd, speed, dir, me) {
|
||||
m.fireCDcycle = m.cycle + Math.floor(cd * b.fireCDscale); // cool down
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: m.Vx / 2 + speed * Math.cos(dir),
|
||||
y: m.Vy / 2 + speed * Math.sin(dir)
|
||||
x: 0.5 * player.velocity.x + speed * Math.cos(dir),
|
||||
y: 0.5 * player.velocity.y + speed * Math.sin(dir)
|
||||
});
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
},
|
||||
fireCDscale: 1,
|
||||
setFireCD() {
|
||||
b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage
|
||||
b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.slowFireDamage
|
||||
if (m.fieldMode === 6) b.fireCDscale *= 0.8
|
||||
if (tech.isFastTime) b.fireCDscale *= 0.666
|
||||
if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.76923, Math.max(0, b.inventory.length - 1))
|
||||
@@ -377,7 +377,7 @@ const b = {
|
||||
explosion(where, radius, color = "rgba(255,25,0,0.6)", reducedKnock = 1) { // typically explode is used for some bullets with .onEnd
|
||||
radius *= tech.explosiveRadius
|
||||
|
||||
let dist, sub, knock;
|
||||
let knock;
|
||||
let dmg = radius * 0.019
|
||||
if (tech.isExplosionHarm) radius *= 1.7 // 1/sqrt(2) radius -> area
|
||||
if (tech.isSmallExplosion) {
|
||||
@@ -385,10 +385,13 @@ const b = {
|
||||
radius *= 0.7
|
||||
dmg *= 1.7
|
||||
}
|
||||
let sub = Vector.sub(where, player.position);
|
||||
let dist = Vector.magnitude(sub);
|
||||
if (tech.isSmartRadius && radius > dist - 50) radius = Math.max(dist - 50, 1)
|
||||
|
||||
if (tech.isExplodeRadio) { //radiation explosion
|
||||
radius *= 1.25; //alert range
|
||||
if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
|
||||
// if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
|
||||
color = "rgba(25,139,170,0.25)"
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: where.x,
|
||||
@@ -425,7 +428,7 @@ const b = {
|
||||
}
|
||||
}
|
||||
} else { //normal explosions
|
||||
if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
|
||||
// if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: where.x,
|
||||
y: where.y,
|
||||
@@ -444,9 +447,6 @@ const b = {
|
||||
|
||||
//player damage and knock back
|
||||
if (m.immuneCycle < m.cycle) {
|
||||
sub = Vector.sub(where, player.position);
|
||||
dist = Vector.magnitude(sub);
|
||||
|
||||
if (dist < radius) {
|
||||
if (simulation.dmgScale) {
|
||||
const harm = tech.isExplosionHarm ? 0.067 : 0.05
|
||||
@@ -624,7 +624,7 @@ const b = {
|
||||
clusterExplode(where, size) { //can occur after grenades detonate
|
||||
const cycle = () => {
|
||||
if (m.alive) {
|
||||
if (simulation.paused || m.isBodiesAsleep) {
|
||||
if (simulation.paused || m.isTimeDilated) {
|
||||
requestAnimationFrame(cycle)
|
||||
} else {
|
||||
count++
|
||||
@@ -643,7 +643,7 @@ const b = {
|
||||
const color = `hsla(${360 * Math.random()},100%,66%,0.6)`
|
||||
const cycle = () => {
|
||||
if (m.alive) {
|
||||
if (simulation.paused || m.isBodiesAsleep) {
|
||||
if (simulation.paused || m.isTimeDilated) {
|
||||
requestAnimationFrame(cycle)
|
||||
} else {
|
||||
count++
|
||||
@@ -668,7 +668,7 @@ const b = {
|
||||
const range = size * Math.sqrt(b.explosionRange())
|
||||
const cycle = () => {
|
||||
if (m.alive) {
|
||||
if (simulation.paused || m.isBodiesAsleep) {
|
||||
if (simulation.paused || m.isTimeDilated) {
|
||||
requestAnimationFrame(cycle)
|
||||
} else {
|
||||
if (count < 30 && m.alive) requestAnimationFrame(cycle);
|
||||
@@ -734,8 +734,8 @@ const b = {
|
||||
};
|
||||
speed = m.crouch ? 43 : 32
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: m.Vx / 2 + speed * Math.cos(angle),
|
||||
y: m.Vy / 2 + speed * Math.sin(angle)
|
||||
x: 0.5 * player.velocity.x + speed * Math.cos(angle),
|
||||
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
|
||||
});
|
||||
bullet[me].endCycle = simulation.cycle + Math.floor(m.crouch ? 120 : 80) * tech.bulletsLastLonger;
|
||||
bullet[me].restitution = 0.4;
|
||||
@@ -759,8 +759,8 @@ const b = {
|
||||
};
|
||||
speed = m.crouch ? 46 : 32
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: m.Vx / 2 + speed * Math.cos(angle),
|
||||
y: m.Vy / 2 + speed * Math.sin(angle)
|
||||
x: 0.8 * player.velocity.x + speed * Math.cos(angle),
|
||||
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
|
||||
});
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
|
||||
@@ -794,8 +794,8 @@ const b = {
|
||||
};
|
||||
speed = m.crouch ? 46 : 32
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: m.Vx / 2 + speed * Math.cos(angle),
|
||||
y: m.Vy / 2 + speed * Math.sin(angle)
|
||||
x: 0.8 * player.velocity.x + speed * Math.cos(angle),
|
||||
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
|
||||
});
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
bullet[me].endCycle = simulation.cycle + 70 * tech.bulletsLastLonger;
|
||||
@@ -924,8 +924,8 @@ const b = {
|
||||
bullet[me].endCycle += 20;
|
||||
}
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: m.Vx / 2 + speed * Math.cos(angle),
|
||||
y: m.Vy / 2 + speed * Math.sin(angle)
|
||||
x: 0.5 * player.velocity.x + speed * Math.cos(angle),
|
||||
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
|
||||
});
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
}
|
||||
@@ -951,7 +951,7 @@ const b = {
|
||||
Matter.Body.scale(bullet[me], SCALE, SCALE);
|
||||
speed = m.crouch ? 25 : 15
|
||||
// speed = m.crouch ? 43 : 32
|
||||
Matter.Body.setVelocity(bullet[me], { x: m.Vx / 2 + speed * Math.cos(angle), y: m.Vy / 2 + speed * Math.sin(angle) });
|
||||
Matter.Body.setVelocity(bullet[me], { x: 0.5 * player.velocity.x + speed * Math.cos(angle), y: 0.5 * player.velocity.y + speed * Math.sin(angle) });
|
||||
const MAG = 0.005
|
||||
bullet[me].thrust = { x: bullet[me].mass * MAG * Math.cos(angle), y: bullet[me].mass * MAG * Math.sin(angle) }
|
||||
}
|
||||
@@ -1140,148 +1140,6 @@ const b = {
|
||||
}
|
||||
}
|
||||
},
|
||||
// dart(where, angle = m.angle, size = 0.8) {
|
||||
// //find a target
|
||||
// const closest = {
|
||||
// score: 10000,
|
||||
// position: null
|
||||
// }
|
||||
// for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
// if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, where, mob[i].position).length === 0) {
|
||||
// const dot = Vector.dot({ x: Math.cos(angle), y: Math.sin(angle) }, Vector.normalise(Vector.sub(mob[i].position, where))) //the dot product of diff and dir will return how much over lap between the vectors
|
||||
// const dist = Vector.magnitude(Vector.sub(where, mob[i].position))
|
||||
// // if (dist < closest.score && ((dist > 500 && dot > 0) || (dot > 0.9))) { //target closest mob that player is looking at and isn't too close to target
|
||||
// if (dist < closest.score && dot > 0.9 - 0.0004 * dist) { //target closest mob that player is looking at and isn't too close to target
|
||||
// closest.score = dist
|
||||
// closest.position = mob[i].position
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (!closest.position) {
|
||||
// // const unit = Vector.mult(sub(simulation.mouseInGame, where), 10000)
|
||||
// closest.position = Vector.mult(Vector.sub(simulation.mouseInGame, where), 10000)
|
||||
// }
|
||||
// const me = bullet.length;
|
||||
// bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -20 * size, y: 2 * size, index: 0, isInternal: false }, { x: -20 * size, y: -2 * size, index: 1, isInternal: false }, { x: 5 * size, y: -2 * size, index: 4, isInternal: false }, { x: 20 * size, y: 0, index: 3, isInternal: false }, { x: 5 * size, y: 2 * size, index: 4, isInternal: false }], {
|
||||
// cycle: 0,
|
||||
// angle: angle,
|
||||
// friction: 1,
|
||||
// frictionAir: 0.15,
|
||||
// thrustMag: 0.03,
|
||||
// turnRate: 0.15, //0.015
|
||||
// drawStringControlMagnitude: 3000 + 5000 * Math.random(),
|
||||
// drawStringFlip: (Math.round(Math.random()) ? 1 : -1),
|
||||
// dmg: 7, //damage done in addition to the damage from momentum
|
||||
// classType: "bullet",
|
||||
// endCycle: simulation.cycle + 120,
|
||||
// collisionFilter: {
|
||||
// category: cat.bullet,
|
||||
// mask: tech.isShieldPierce ? cat.body | cat.mob | cat.mobBullet : cat.body | cat.mob | cat.mobBullet | cat.mobShield,
|
||||
// },
|
||||
// minDmgSpeed: 0,
|
||||
// lookFrequency: Math.floor(7 + Math.random() * 3),
|
||||
// density: 0.001, //0.001 is normal for blocks, 0.008 is normal for harpoon, 0.008*6 when buffed
|
||||
// beforeDmg(who) {
|
||||
// if (tech.isShieldPierce && who.isShielded) { //disable shields
|
||||
// who.isShielded = false
|
||||
// requestAnimationFrame(() => { who.isShielded = true });
|
||||
// }
|
||||
// if (tech.fragments) {
|
||||
// b.targetedNail(this.vertices[2], tech.fragments * Math.floor(2 + 1.5 * Math.random()))
|
||||
// this.endCycle = 0;
|
||||
// }
|
||||
// if (!who.isBadTarget) {
|
||||
// this.frictionAir = 0.01
|
||||
// this.do = this.doNoTargeting
|
||||
// }
|
||||
// },
|
||||
// onEnd() {},
|
||||
// doNoTargeting: function() {
|
||||
// // this.force.y += this.mass * 0.001;
|
||||
// if (Matter.Query.collides(this, map).length) { //stick in walls
|
||||
// this.collisionFilter.mask = 0;
|
||||
// Matter.Body.setAngularVelocity(this, 0)
|
||||
// Matter.Body.setVelocity(this, {
|
||||
// x: 0,
|
||||
// y: 0
|
||||
// });
|
||||
// this.do = () => {
|
||||
// // if (!Matter.Query.collides(this, map).length) this.force.y += this.mass * 0.001;
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// do() {
|
||||
// this.cycle++
|
||||
// // if (this.cycle > 40) {
|
||||
// // this.frictionAir = 0.003
|
||||
// // this.do = this.doNoTargeting
|
||||
// // }
|
||||
// // if (closest.target) { //rotate towards the target
|
||||
// const face = { x: Math.cos(this.angle), y: Math.sin(this.angle) };
|
||||
// const vectorGoal = Vector.normalise(Vector.sub(this.position, closest.position));
|
||||
// const cross = Vector.cross(vectorGoal, face)
|
||||
// if (cross > 0.01) {
|
||||
// Matter.Body.rotate(this, this.turnRate * Math.sqrt(cross));
|
||||
// } else if (cross < 0.01) {
|
||||
// Matter.Body.rotate(this, -this.turnRate * Math.sqrt(Math.abs(cross)));
|
||||
// }
|
||||
// this.force.x += this.thrustMag * this.mass * Math.cos(this.angle);
|
||||
// this.force.y += this.thrustMag * this.mass * Math.sin(this.angle);
|
||||
// // }
|
||||
// if (Matter.Query.collides(this, map).length) { //stick in walls
|
||||
// this.collisionFilter.mask = 0;
|
||||
// Matter.Body.setAngularVelocity(this, 0)
|
||||
// Matter.Body.setVelocity(this, {
|
||||
// x: 0,
|
||||
// y: 0
|
||||
// });
|
||||
// this.do = this.doNoTargeting
|
||||
// }
|
||||
// // else if (!(this.cycle % 2)) { //look for a target if you don't have one
|
||||
// // simulation.drawList.push({ //add dmg to draw queue
|
||||
// // x: this.position.x,
|
||||
// // y: this.position.y,
|
||||
// // radius: 10,
|
||||
// // color: simulation.mobDmgColor,
|
||||
// // time: simulation.drawTime
|
||||
// // });
|
||||
// // let closest = {
|
||||
// // distance: 2000,
|
||||
// // target: null
|
||||
// // }
|
||||
// // const dir = Vector.normalise(this.velocity) //make a vector for direction of length 1
|
||||
// // for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
// // if (
|
||||
// // mob[i].alive && !mob[i].isBadTarget &&
|
||||
// // Matter.Query.ray(map, this.position, mob[i].position).length === 0 && //check for map in Line of sight
|
||||
// // Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, this.position))) > 0.55 //the dot product of diff and dir will return how much over lap between the vectors
|
||||
// // ) {
|
||||
// // const dist = Vector.magnitude(Vector.sub(this.position, mob[i].position))
|
||||
// // if (dist < closest.distance) {
|
||||
// // closest.distance = dist
|
||||
// // closest.target = mob[i]
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
// // if (closest.target) {
|
||||
// // target = closest.target
|
||||
// // this.turnRate = 0.05
|
||||
// // this.frictionAir = 0.8
|
||||
// // }
|
||||
// // }
|
||||
// },
|
||||
// });
|
||||
// Matter.Body.setVelocity(bullet[me], {
|
||||
// x: m.Vx / 2 + 40 * Math.cos(bullet[me].angle),
|
||||
// y: m.Vy / 2 + 40 * Math.sin(bullet[me].angle)
|
||||
// });
|
||||
// // if (!closest.target) {
|
||||
// // bullet[me].frictionAir = 0.002
|
||||
// // bullet[me].do = bullet[me].doNoTargeting
|
||||
// // }
|
||||
// Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
|
||||
// },
|
||||
grapple(where, angle = m.angle) {
|
||||
const me = bullet.length;
|
||||
const returnRadius = 100
|
||||
@@ -1962,8 +1820,8 @@ const b = {
|
||||
});
|
||||
if (!isReturn && !target) {
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: m.Vx / 2 + 600 * thrust * Math.cos(bullet[me].angle),
|
||||
y: m.Vy / 2 + 600 * thrust * Math.sin(bullet[me].angle)
|
||||
x: 0.7 * player.velocity.x + 600 * thrust * Math.cos(bullet[me].angle),
|
||||
y: 0.5 * player.velocity.x + 600 * thrust * Math.sin(bullet[me].angle)
|
||||
});
|
||||
bullet[me].frictionAir = 0.002
|
||||
bullet[me].do = function () {
|
||||
@@ -2084,8 +1942,8 @@ const b = {
|
||||
});
|
||||
const thrust = 0.0066 * bullet[me].mass * (tech.isMissileBig ? (tech.isMissileBiggest ? 0.3 : 0.7) : 1);
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: m.Vx / 2 + speed * Math.cos(angle),
|
||||
y: m.Vy / 2 + speed * Math.sin(angle)
|
||||
x: 0.5 * player.velocity.x + speed * Math.cos(angle),
|
||||
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
|
||||
});
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
},
|
||||
@@ -2322,7 +2180,7 @@ const b = {
|
||||
const d = Vector.sub(path[path.length - 1], path[path.length - 2]);
|
||||
const nn = Vector.mult(n, 2 * Vector.dot(d, n));
|
||||
const r = Vector.normalise(Vector.sub(d, nn));
|
||||
path[path.length] = Vector.add(Vector.mult(r, 3000), path[path.length - 1]);
|
||||
path[path.length] = Vector.add(Vector.mult(r, 5000), path[path.length - 1]);
|
||||
};
|
||||
|
||||
checkForCollisions();
|
||||
@@ -2761,14 +2619,14 @@ const b = {
|
||||
}
|
||||
}
|
||||
},
|
||||
spore(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death()
|
||||
spore(where, velocity = null) { //used with the tech upgrade in mob.death()
|
||||
const bIndex = bullet.length;
|
||||
const size = 4
|
||||
if (bIndex < 500) { //can't make over 500 spores
|
||||
bullet[bIndex] = Bodies.polygon(where.x, where.y, size, size, {
|
||||
// density: 0.0015, //frictionAir: 0.01,
|
||||
inertia: Infinity,
|
||||
isFreeze: isFreeze,
|
||||
isFreeze: tech.isSporeFreeze,
|
||||
restitution: 0.5,
|
||||
angle: Math.random() * 2 * Math.PI,
|
||||
friction: 0,
|
||||
@@ -2835,57 +2693,19 @@ const b = {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if (!this.lockedOn && !(simulation.cycle % this.lookFrequency)) { //find mob targets
|
||||
// this.closestTarget = null;
|
||||
// this.lockedOn = null;
|
||||
// let closeDist = Infinity;
|
||||
// for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
// if (mob[i].isDropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
|
||||
// // Matter.Query.ray(body, this.position, mob[i].position).length === 0
|
||||
// const targetVector = Vector.sub(this.position, mob[i].position)
|
||||
// const dist = Vector.magnitude(targetVector);
|
||||
// if (dist < closeDist) {
|
||||
// this.closestTarget = mob[i].position;
|
||||
// closeDist = dist;
|
||||
// this.lockedOn = mob[i] //Vector.normalise(targetVector);
|
||||
// if (0.3 > Math.random()) break //doesn't always target the closest mob
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (this.lockedOn && this.lockedOn.alive) { //accelerate towards mobs
|
||||
// this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
|
||||
// } else if (tech.isSporeFollow && this.lockedOn !== undefined) { //move towards player
|
||||
// //checking for undefined means that the spores don't go after the player until it has looked and not found a target
|
||||
// const dx = this.position.x - m.pos.x;
|
||||
// const dy = this.position.y - m.pos.y;
|
||||
// if (dx * dx + dy * dy > 10000) {
|
||||
// this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
|
||||
// }
|
||||
// // this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), this.mass * this.thrust)
|
||||
// } else {
|
||||
// this.force.y += this.mass * 0.0001; //gravity
|
||||
// }
|
||||
|
||||
// if (this.nextPortCycle < simulation.cycle) { //teleport around if you have tech.isBulletTeleport
|
||||
// this.nextPortCycle = simulation.cycle + this.portFrequency
|
||||
// const range = 50 * Math.random()
|
||||
// Matter.Body.setPosition(this, Vector.add(this.position, Vector.rotate({ x: range, y: 0 }, 2 * Math.PI * Math.random())))
|
||||
// }
|
||||
},
|
||||
});
|
||||
// if (tech.isBulletTeleport) {
|
||||
// bullet[bIndex].portFrequency = 10 + Math.floor(5 * Math.random())
|
||||
// bullet[bIndex].nextPortCycle = simulation.cycle + bullet[bIndex].portFrequency
|
||||
// }
|
||||
if (velocity) {
|
||||
Matter.Body.setVelocity(bullet[bIndex], velocity);
|
||||
} else {
|
||||
const SPEED = 4 + 8 * Math.random();
|
||||
const ANGLE = 2 * Math.PI * Math.random()
|
||||
Matter.Body.setVelocity(bullet[bIndex], {
|
||||
x: SPEED * Math.cos(ANGLE),
|
||||
y: SPEED * Math.sin(ANGLE)
|
||||
});
|
||||
}
|
||||
|
||||
const SPEED = 4 + 8 * Math.random();
|
||||
const ANGLE = 2 * Math.PI * Math.random()
|
||||
Matter.Body.setVelocity(bullet[bIndex], {
|
||||
x: SPEED * Math.cos(ANGLE),
|
||||
y: SPEED * Math.sin(ANGLE)
|
||||
});
|
||||
Composite.add(engine.world, bullet[bIndex]); //add bullet to world
|
||||
|
||||
if (tech.isMutualism && m.health > 0.01) {
|
||||
@@ -2972,11 +2792,6 @@ const b = {
|
||||
y: speed * Math.sin(dir)
|
||||
});
|
||||
Matter.Body.setAngularVelocity(bullet[me], 3000 * bullet[me].spin);
|
||||
|
||||
// Matter.Body.setVelocity(bullet[me], {
|
||||
// x: m.Vx / 2 + speed * Math.cos(dir),
|
||||
// y: m.Vy / 2 + speed * Math.sin(dir)
|
||||
// });
|
||||
},
|
||||
flea(where, velocity, radius = 6 + 3 * Math.random() + 10 * tech.wormSize * Math.random()) {
|
||||
const me = bullet.length;
|
||||
@@ -3307,7 +3122,7 @@ const b = {
|
||||
if (
|
||||
Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 &&
|
||||
!(
|
||||
(m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
|
||||
(m.health > 0.94 * m.maxHealth && !tech.isOverHeal && !tech.isDroneGrab && powerUp[i].name === "heal") ||
|
||||
(tech.isSuperDeterminism && powerUp[i].name === "field") ||
|
||||
((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
|
||||
)
|
||||
@@ -3339,7 +3154,7 @@ const b = {
|
||||
let closeDist = Infinity;
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
if (!(
|
||||
(m.health > 0.93 * m.maxHealth && !tech.isDroneGrab && powerUp[i].name === "heal") ||
|
||||
(m.health > 0.94 * m.maxHealth && !tech.isOverHeal && !tech.isDroneGrab && powerUp[i].name === "heal") ||
|
||||
(tech.isSuperDeterminism && powerUp[i].name === "field") ||
|
||||
((tech.isEnergyNoAmmo || b.inventory.length === 0) && powerUp[i].name === "ammo")
|
||||
)) {
|
||||
@@ -3810,165 +3625,6 @@ const b = {
|
||||
}
|
||||
return shotsFired
|
||||
},
|
||||
// plasmaBall(position, velocity, radius) {
|
||||
// // radius *= Math.sqrt(tech.bulletSize)
|
||||
// const me = bullet.length;
|
||||
// bullet[me] = Bodies.polygon(position.x, position.y, 20, radius, {
|
||||
// density: 0.000001, // 0.001 is normal density
|
||||
// inertia: Infinity,
|
||||
// frictionAir: 0.003,
|
||||
// dmg: 0, //damage on impact
|
||||
// damage: 0, //damage done over time
|
||||
// scale: 1 - 0.006 / tech.bulletsLastLonger,
|
||||
// classType: "bullet",
|
||||
// collisionFilter: {
|
||||
// category: cat.bullet,
|
||||
// mask: 0 //cat.mob | cat.mobBullet // cat.map | cat.body | cat.mob | cat.mobShield
|
||||
// },
|
||||
// minDmgSpeed: 0,
|
||||
// endCycle: Infinity,
|
||||
// count: 0,
|
||||
// radius: radius,
|
||||
// portFrequency: 5 + Math.floor(5 * Math.random()),
|
||||
// nextPortCycle: Infinity, //disabled unless you have the teleport tech
|
||||
// beforeDmg(who) {
|
||||
// if (!this.target && who.alive) {
|
||||
// this.target = who;
|
||||
// if (who.radius < 20) {
|
||||
// this.targetRelativePosition = {
|
||||
// x: 0,
|
||||
// y: 0
|
||||
// } //find relative position vector for zero mob rotation
|
||||
// } else if (Matter.Query.collides(this, [who]).length > 0) {
|
||||
// const normal = Matter.Query.collides(this, [who])[0].normal
|
||||
// this.targetRelativePosition = Vector.rotate(Vector.sub(Vector.sub(this.position, who.position), Vector.mult(normal, -this.radius)), -who.angle) //find relative position vector for zero mob rotation
|
||||
// } else {
|
||||
// this.targetRelativePosition = Vector.rotate(Vector.sub(this.position, who.position), -who.angle) //find relative position vector for zero mob rotation
|
||||
// }
|
||||
// this.collisionFilter.category = cat.body;
|
||||
// this.collisionFilter.mask = null;
|
||||
|
||||
// let bestVertexDistance = Infinity
|
||||
// let bestVertex = null
|
||||
// for (let i = 0; i < this.target.vertices.length; i++) {
|
||||
// const dist = Vector.magnitude(Vector.sub(this.position, this.target.vertices[i]));
|
||||
// if (dist < bestVertexDistance) {
|
||||
// bestVertex = i
|
||||
// bestVertexDistance = dist
|
||||
// }
|
||||
// }
|
||||
// this.targetVertex = bestVertex
|
||||
// }
|
||||
// },
|
||||
// onEnd() {},
|
||||
// do() {
|
||||
// if (this.count < 20) {
|
||||
// this.count++
|
||||
// //grow
|
||||
// const SCALE = 1.06
|
||||
// Matter.Body.scale(this, SCALE, SCALE);
|
||||
// this.radius *= SCALE;
|
||||
// } else {
|
||||
// //shrink
|
||||
// Matter.Body.scale(this, this.scale, this.scale);
|
||||
// this.radius *= this.scale;
|
||||
// if (this.radius < 8) this.endCycle = 0;
|
||||
// }
|
||||
// if (this.target && this.target.alive) { //if stuck to a target
|
||||
// const rotate = Vector.rotate(this.targetRelativePosition, this.target.angle) //add in the mob's new angle to the relative position vector
|
||||
// if (this.target.isVerticesChange) {
|
||||
// Matter.Body.setPosition(this, this.target.vertices[this.targetVertex])
|
||||
// } else {
|
||||
// Matter.Body.setPosition(this, Vector.add(Vector.add(rotate, this.target.velocity), this.target.position))
|
||||
// }
|
||||
// if (this.target.isBoss) {
|
||||
// if (this.target.speed > 8) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.98))
|
||||
// } else {
|
||||
// if (this.target.speed > 4) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.95))
|
||||
// }
|
||||
|
||||
// Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9);
|
||||
// // Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9)
|
||||
// if (this.target.isShielded) {
|
||||
// this.target.damage(m.dmgScale * this.damage, true); //shield damage bypass
|
||||
// const SCALE = 1 - 0.004 / tech.bulletsLastLonger //shrink if mob is shielded
|
||||
// Matter.Body.scale(this, SCALE, SCALE);
|
||||
// this.radius *= SCALE;
|
||||
// } else {
|
||||
// this.target.damage(m.dmgScale * this.damage);
|
||||
// }
|
||||
// } else if (this.target !== null) { //look for a new target
|
||||
// this.collisionFilter.category = cat.bullet;
|
||||
// this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||
// if (tech.isSpawnBulletsOnDeath && bullet.length < 180 && !this.target.isMobBullet) {
|
||||
// let targets = []
|
||||
// for (let i = 0, len = mob.length; i < len; i++) {
|
||||
// const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
|
||||
// if (dist < 1000000) targets.push(mob[i])
|
||||
// }
|
||||
// const radius = Math.min(this.radius * 0.5, 9)
|
||||
// const len = bullet.length < 80 ? 2 : 1
|
||||
// for (let i = 0; i < len; i++) {
|
||||
// if (targets.length - i > 0) {
|
||||
// const index = Math.floor(Math.random() * targets.length)
|
||||
// const speed = 6 + 6 * Math.random()
|
||||
// const velocity = Vector.mult(Vector.normalise(Vector.sub(targets[index].position, this.position)), speed)
|
||||
// b.foam(this.position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius)
|
||||
// } else {
|
||||
// b.foam(this.position, Vector.rotate({
|
||||
// x: 15 + 10 * Math.random(),
|
||||
// y: 0
|
||||
// }, 2 * Math.PI * Math.random()), radius)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// this.target = null
|
||||
// } else if (Matter.Query.point(map, this.position).length > 0) { //slow when touching map or blocks
|
||||
// const slow = 0.85
|
||||
// Matter.Body.setVelocity(this, {
|
||||
// x: this.velocity.x * slow,
|
||||
// y: this.velocity.y * slow
|
||||
// });
|
||||
// const SCALE = 0.96
|
||||
// Matter.Body.scale(this, SCALE, SCALE);
|
||||
// this.radius *= SCALE;
|
||||
// // } else if (Matter.Query.collides(this, body).length > 0) {
|
||||
// } else if (Matter.Query.point(body, this.position).length > 0) {
|
||||
// const slow = 0.9
|
||||
// Matter.Body.setVelocity(this, {
|
||||
// x: this.velocity.x * slow,
|
||||
// y: this.velocity.y * slow
|
||||
// });
|
||||
// const SCALE = 0.96
|
||||
// Matter.Body.scale(this, SCALE, SCALE);
|
||||
// this.radius *= SCALE;
|
||||
// } else {
|
||||
// this.force.y += this.mass * tech.foamGravity; //gravity
|
||||
// if (tech.isFoamAttract) {
|
||||
// for (let i = 0, len = mob.length; i < len; i++) {
|
||||
// if (!mob[i].isBadTarget && Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 && mob[i].alive && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
|
||||
// this.force = Vector.mult(Vector.normalise(Vector.sub(mob[i].position, this.position)), this.mass * 0.004)
|
||||
// const slow = 0.9
|
||||
// Matter.Body.setVelocity(this, {
|
||||
// x: this.velocity.x * slow,
|
||||
// y: this.velocity.y * slow
|
||||
// });
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (this.nextPortCycle < simulation.cycle) { //teleport around if you have tech.isBulletTeleport
|
||||
// this.nextPortCycle = simulation.cycle + this.portFrequency
|
||||
// const range = 15 * Math.sqrt(this.radius) * Math.random()
|
||||
// Matter.Body.setPosition(this, Vector.add(this.position, Vector.rotate({ x: range, y: 0 }, 2 * Math.PI * Math.random())))
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// if (tech.isBulletTeleport) bullet[me].nextPortCycle = simulation.cycle + bullet[me].portFrequency
|
||||
// Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
// Matter.Body.setVelocity(bullet[me], velocity);
|
||||
// },
|
||||
foam(position, velocity, radius) {
|
||||
if (tech.isFoamCavitation && Math.random() < 0.25) {
|
||||
velocity = Vector.mult(velocity, 1.35)
|
||||
@@ -4024,10 +3680,7 @@ const b = {
|
||||
}
|
||||
}
|
||||
this.targetVertex = bestVertex
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: 0,
|
||||
y: 0
|
||||
});
|
||||
Matter.Body.setVelocity(this, { x: 0, y: 0 });
|
||||
}
|
||||
},
|
||||
onEnd() { },
|
||||
@@ -4070,10 +3723,7 @@ const b = {
|
||||
} else if (this.target !== null) { //look for a new target
|
||||
this.collisionFilter.category = cat.bullet;
|
||||
this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: this.target.velocity.x,
|
||||
y: this.target.velocity.y
|
||||
});
|
||||
Matter.Body.setVelocity(this, { x: this.target.velocity.x, y: this.target.velocity.y });
|
||||
if (tech.isSpawnBulletsOnDeath && bullet.length < 180 && !this.target.isMobBullet) {
|
||||
let targets = []
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
@@ -4099,20 +3749,14 @@ const b = {
|
||||
this.target = null
|
||||
} else if (Matter.Query.point(map, this.position).length > 0) { //slow when touching map
|
||||
const slow = 0.87
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: this.velocity.x * slow,
|
||||
y: this.velocity.y * slow
|
||||
});
|
||||
Matter.Body.setVelocity(this, { x: this.velocity.x * slow, y: this.velocity.y * slow });
|
||||
const SCALE = 0.97
|
||||
Matter.Body.scale(this, SCALE, SCALE);
|
||||
this.radius *= SCALE;
|
||||
// } else if (Matter.Query.collides(this, body).length > 0) {
|
||||
} else if (Matter.Query.point(body, this.position).length > 0) { //slow when touching blocks
|
||||
const slow = 0.94
|
||||
Matter.Body.setVelocity(this, {
|
||||
x: this.velocity.x * slow,
|
||||
y: this.velocity.y * slow
|
||||
});
|
||||
Matter.Body.setVelocity(this, { x: this.velocity.x * slow, y: this.velocity.y * slow });
|
||||
const SCALE = 0.99
|
||||
Matter.Body.scale(this, SCALE, SCALE);
|
||||
this.radius *= SCALE;
|
||||
@@ -4247,7 +3891,7 @@ const b = {
|
||||
bullet[me] = Bodies.rectangle(pos.x, pos.y, 25 * tech.bulletSize, 2 * tech.bulletSize, b.fireAttributes(Math.atan2(velocity.y, velocity.x)));
|
||||
Matter.Body.setVelocity(bullet[me], velocity);
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
bullet[me].endCycle = simulation.cycle + 60 + 18 * Math.random();
|
||||
bullet[me].endCycle = simulation.cycle + 80 + 18 * Math.random();
|
||||
bullet[me].dmg = tech.isNailRadiation ? 0 : dmg
|
||||
bullet[me].beforeDmg = function (who) { //beforeDmg is rewritten with ice crystal tech
|
||||
if (tech.isNailRadiation) mobs.statusDoT(who, dmg * (tech.isFastRadiation ? 1.3 : 0.44), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles
|
||||
@@ -4417,8 +4061,8 @@ const b = {
|
||||
}
|
||||
const SPEED = 90
|
||||
Matter.Body.setVelocity(bullet[me], {
|
||||
x: m.Vx / 2 + SPEED * Math.cos(angle),
|
||||
y: m.Vy / 2 + SPEED * Math.sin(angle)
|
||||
x: 0.5 * player.velocity.x + SPEED * Math.cos(angle),
|
||||
y: 0.5 * player.velocity.y + SPEED * Math.sin(angle)
|
||||
});
|
||||
// Matter.Body.setDensity(bullet[me], 0.00001);
|
||||
Composite.add(engine.world, bullet[me]); //add bullet to world
|
||||
@@ -4505,14 +4149,15 @@ const b = {
|
||||
}
|
||||
},
|
||||
zeroBotCount() { //remove all bots
|
||||
tech.dynamoBotCount = 0
|
||||
tech.laserBotCount = 0
|
||||
tech.nailBotCount = 0
|
||||
tech.foamBotCount = 0
|
||||
tech.soundBotCount = 0
|
||||
tech.boomBotCount = 0
|
||||
tech.orbitBotCount = 0
|
||||
tech.missileBotCount = 0
|
||||
tech.dynamoBotCount = 0;
|
||||
tech.nailBotCount = 0;
|
||||
tech.laserBotCount = 0;
|
||||
tech.orbitBotCount = 0;
|
||||
tech.foamBotCount = 0;
|
||||
tech.soundBotCount = 0;
|
||||
tech.boomBotCount = 0;
|
||||
tech.plasmaBotCount = 0;
|
||||
tech.missileBotCount = 0;
|
||||
},
|
||||
respawnBots() {
|
||||
for (let i = 0; i < tech.dynamoBotCount; i++) b.dynamoBot({
|
||||
@@ -5032,7 +4677,7 @@ const b = {
|
||||
} else { //fire mode: quickly fire at targets and doesn't follow player
|
||||
this.fire()
|
||||
}
|
||||
if (!m.isBodiesAsleep) { //update current waves
|
||||
if (!m.isTimeDilated) { //update current waves
|
||||
ctx.strokeStyle = "rgba(0,0,0,0.6)" //"000";
|
||||
ctx.lineWidth = 2 * tech.wavePacketDamage
|
||||
ctx.beginPath();
|
||||
@@ -5713,7 +5358,7 @@ const b = {
|
||||
b.needle()
|
||||
|
||||
function cycle() {
|
||||
if (simulation.paused || m.isBodiesAsleep) {
|
||||
if (simulation.paused || m.isTimeDilated) {
|
||||
requestAnimationFrame(cycle)
|
||||
} else {
|
||||
count++
|
||||
@@ -5728,7 +5373,7 @@ const b = {
|
||||
b.needle()
|
||||
|
||||
function cycle() {
|
||||
if (simulation.paused || m.isBodiesAsleep) {
|
||||
if (simulation.paused || m.isTimeDilated) {
|
||||
requestAnimationFrame(cycle)
|
||||
} else {
|
||||
count++
|
||||
@@ -5927,8 +5572,8 @@ const b = {
|
||||
x: m.pos.x + 30 * Math.cos(m.angle),
|
||||
y: m.pos.y + 30 * Math.sin(m.angle)
|
||||
}, {
|
||||
x: m.Vx / 2 + speed * Math.cos(angle),
|
||||
y: m.Vy / 2 + speed * Math.sin(angle)
|
||||
x: 0.8 * player.velocity.x + speed * Math.cos(angle),
|
||||
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
|
||||
}) //position, velocity, damage
|
||||
if (tech.isIceCrystals) {
|
||||
bullet[bullet.length - 1].beforeDmg = function (who) {
|
||||
@@ -6200,8 +5845,8 @@ const b = {
|
||||
const SPEED = 13 + 4 * Math.random();
|
||||
const angle = m.angle + spread * (Math.random() - 0.5)
|
||||
b.foam(where, {
|
||||
x: SPEED * Math.cos(angle),
|
||||
y: SPEED * Math.sin(angle)
|
||||
x: 0.6 * player.velocity.x + SPEED * Math.cos(angle),
|
||||
y: 0.5 * player.velocity.y + SPEED * Math.sin(angle)
|
||||
}, 8 + 7 * Math.random())
|
||||
}
|
||||
} else if (tech.isNeedles) {
|
||||
@@ -6332,8 +5977,8 @@ const b = {
|
||||
return `emit <strong>wave packets</strong> that propagate through <strong>solids</strong><br>waves <strong class='color-s'>slow</strong> mobs<br><strong>${this.ammoPack.toFixed(0)}</strong> wave packets per ${powerUps.orb.ammo()}`
|
||||
},
|
||||
ammo: 0,
|
||||
ammoPack: 52,
|
||||
defaultAmmoPack: 52,
|
||||
ammoPack: 60,
|
||||
defaultAmmoPack: 60,
|
||||
have: false,
|
||||
wavePacketCycle: 0,
|
||||
delay: 40,
|
||||
@@ -6356,7 +6001,7 @@ const b = {
|
||||
},
|
||||
do() { },
|
||||
do360Longitudinal() {
|
||||
if (!m.isBodiesAsleep) {
|
||||
if (!m.isTimeDilated) {
|
||||
ctx.strokeStyle = "rgba(0,0,0,0.6)" //"000";
|
||||
ctx.lineWidth = 2 * tech.wavePacketDamage
|
||||
ctx.beginPath();
|
||||
@@ -6453,7 +6098,7 @@ const b = {
|
||||
})
|
||||
},
|
||||
doLongitudinal() {
|
||||
if (!m.isBodiesAsleep) {
|
||||
if (!m.isTimeDilated) {
|
||||
ctx.strokeStyle = "rgba(0,0,0,0.6)" //"000";
|
||||
ctx.lineWidth = 2 * tech.wavePacketDamage
|
||||
ctx.beginPath();
|
||||
@@ -6654,12 +6299,12 @@ const b = {
|
||||
}
|
||||
}
|
||||
}
|
||||
let waveSpeedMap = 0.1
|
||||
let waveSpeedBody = 0.25
|
||||
let waveSpeedMap = 0.13
|
||||
let waveSpeedBody = 0.3
|
||||
if (tech.isPhaseVelocity) {
|
||||
waveSpeedMap = 3.5
|
||||
waveSpeedBody = 2
|
||||
bullet[me].dmg *= 1.4
|
||||
bullet[me].dmg *= 1.5
|
||||
}
|
||||
if (tech.waveReflections) {
|
||||
bullet[me].reflectCycle = totalCycles / tech.waveReflections //tech.waveLengthRange
|
||||
@@ -7061,8 +6706,12 @@ const b = {
|
||||
isDischarge: false,
|
||||
knockBack: 0.0005, //set in tech: cavitation
|
||||
applyKnock(velocity) {
|
||||
player.force.x -= this.knockBack * velocity.x
|
||||
player.force.y -= 2 * this.knockBack * velocity.y
|
||||
player.force.x -= 0.7 * this.knockBack * velocity.x
|
||||
if (velocity.y > 0) {
|
||||
player.force.y -= 4.3 * this.knockBack * velocity.y
|
||||
} else {
|
||||
player.force.y -= this.knockBack * velocity.y
|
||||
}
|
||||
},
|
||||
chooseFireMethod() {
|
||||
if (tech.isFoamPressure) {
|
||||
@@ -7082,7 +6731,10 @@ const b = {
|
||||
const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12
|
||||
const SPEED = (m.crouch ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25)
|
||||
const dir = m.angle + 0.15 * (Math.random() - 0.5)
|
||||
const velocity = { x: SPEED * Math.cos(dir), y: SPEED * Math.sin(dir) }
|
||||
const velocity = {
|
||||
x: 0.7 * player.velocity.x + SPEED * Math.cos(dir),
|
||||
y: 0.5 * player.velocity.y + SPEED * Math.sin(dir)
|
||||
}
|
||||
const position = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
|
||||
b.foam(position, Vector.rotate(velocity, spread), radius)
|
||||
this.applyKnock(velocity)
|
||||
@@ -7104,8 +6756,8 @@ const b = {
|
||||
const SPEED = (m.crouch ? 1.2 : 1) * 10 - radius * 0.4 + Math.min(5, Math.sqrt(this.charge));
|
||||
const dir = m.angle + 0.15 * (Math.random() - 0.5)
|
||||
const velocity = {
|
||||
x: SPEED * Math.cos(dir),
|
||||
y: SPEED * Math.sin(dir)
|
||||
x: 0.7 * player.velocity.x + SPEED * Math.cos(dir),
|
||||
y: 0.5 * player.velocity.y + SPEED * Math.sin(dir)
|
||||
}
|
||||
const position = {
|
||||
x: m.pos.x + 30 * Math.cos(m.angle),
|
||||
@@ -7134,29 +6786,11 @@ const b = {
|
||||
const SPEED = (m.crouch ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25)
|
||||
const dir = m.angle + 0.15 * (Math.random() - 0.5)
|
||||
const velocity = {
|
||||
x: SPEED * Math.cos(dir),
|
||||
y: SPEED * Math.sin(dir)
|
||||
x: 0.7 * player.velocity.x + SPEED * Math.cos(dir),
|
||||
y: 0.5 * player.velocity.y + SPEED * Math.sin(dir)
|
||||
}
|
||||
const position = {
|
||||
x: m.pos.x + 30 * Math.cos(m.angle),
|
||||
y: m.pos.y + 30 * Math.sin(m.angle)
|
||||
}
|
||||
// if (tech.foamFutureFire) {
|
||||
// simulation.drawList.push({ //add dmg to draw queue
|
||||
// x: position.x,
|
||||
// y: position.y,
|
||||
// radius: 5,
|
||||
// color: "rgba(0,50,50,0.3)",
|
||||
// time: 15 * tech.foamFutureFire
|
||||
// });
|
||||
// setTimeout(() => {
|
||||
// if (!simulation.paused) {
|
||||
// b.foam(position, Vector.rotate(velocity, spread), radius)
|
||||
// bullet[bullet.length - 1].damage *= (1 + 0.7 * tech.foamFutureFire)
|
||||
// }
|
||||
// }, 210 * tech.foamFutureFire);
|
||||
// } else {
|
||||
// }
|
||||
const position = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
|
||||
|
||||
b.foam(position, Vector.rotate(velocity, spread), radius)
|
||||
this.applyKnock(velocity)
|
||||
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
|
||||
@@ -7698,6 +7332,8 @@ const b = {
|
||||
};
|
||||
}
|
||||
|
||||
} else if (tech.beamCollimator) {
|
||||
this.fire = this.fireSplitCollimator
|
||||
} else if (tech.beamSplitter) {
|
||||
this.fire = this.fireSplit
|
||||
} else if (tech.historyLaser) {
|
||||
@@ -7716,16 +7352,14 @@ const b = {
|
||||
} else {
|
||||
m.fireCDcycle = m.cycle
|
||||
m.energy -= drain
|
||||
const where = {
|
||||
x: m.pos.x + 20 * Math.cos(m.angle),
|
||||
y: m.pos.y + 20 * Math.sin(m.angle)
|
||||
}
|
||||
const where = { x: m.pos.x + 20 * Math.cos(m.angle), y: m.pos.y + 20 * Math.sin(m.angle) }
|
||||
b.laser(where, {
|
||||
x: where.x + 3000 * Math.cos(m.angle),
|
||||
y: where.y + 3000 * Math.sin(m.angle)
|
||||
x: where.x + 5000 * Math.cos(m.angle),
|
||||
y: where.y + 5000 * Math.sin(m.angle)
|
||||
}, tech.laserDamage / b.fireCDscale * this.lensDamage);
|
||||
}
|
||||
},
|
||||
|
||||
firePulse() { },
|
||||
fireSplit() {
|
||||
const drain = tech.laserDrain / b.fireCDscale
|
||||
@@ -7749,6 +7383,29 @@ const b = {
|
||||
}
|
||||
}
|
||||
},
|
||||
fireSplitCollimator() {
|
||||
const drain = tech.laserDrain / b.fireCDscale
|
||||
if (m.energy < drain) {
|
||||
m.fireCDcycle = m.cycle + 100; // cool down if out of energy
|
||||
} else {
|
||||
m.fireCDcycle = m.cycle
|
||||
m.energy -= drain
|
||||
const freq = 0.037
|
||||
const len = tech.beamSplitter + 1
|
||||
const phase = 2 * Math.PI / len
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (Math.sin(m.cycle * freq + phase * (i) + Math.PI / 2) > 0 || !(m.cycle % 3)) ctx.globalAlpha = 0.35
|
||||
|
||||
const whereSweep = m.angle + (m.crouch ? 0.4 : 1) * (Math.sin(m.cycle * freq + phase * (i)))
|
||||
const where = { x: m.pos.x + 30 * Math.cos(whereSweep), y: m.pos.y + 30 * Math.sin(whereSweep) }
|
||||
b.laser(where, {
|
||||
x: where.x + 5000 * Math.cos(m.angle),
|
||||
y: where.y + 5000 * Math.sin(m.angle)
|
||||
}, tech.laserDamage / b.fireCDscale * this.lensDamage);
|
||||
ctx.globalAlpha = 1
|
||||
}
|
||||
}
|
||||
},
|
||||
fireWideBeam() {
|
||||
const drain = tech.laserDrain / b.fireCDscale
|
||||
if (m.energy < drain) {
|
||||
|
||||
@@ -116,7 +116,7 @@ function collisionChecks(event) {
|
||||
m.damage(dmg); //normal damage
|
||||
|
||||
if (tech.isCollisionRealitySwitch && m.alive) {
|
||||
m.switchWorlds()
|
||||
m.switchWorlds("Hilbert space")
|
||||
simulation.trails(90)
|
||||
simulation.inGameConsole(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
|
||||
}
|
||||
@@ -177,8 +177,8 @@ function collisionChecks(event) {
|
||||
let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
|
||||
Matter.Body.setVelocity(player, { x: player.velocity.x + 8 * Math.cos(angle), y: player.velocity.y + 8 * Math.sin(angle) });
|
||||
Matter.Body.setVelocity(mob[k], { x: mob[k].velocity.x - 8 * Math.cos(angle), y: mob[k].velocity.y - 8 * Math.sin(angle) });
|
||||
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.1 && mob[k].damageReduction > 0) {
|
||||
m.energy -= 0.1 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
|
||||
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.08 && mob[k].damageReduction > 0) {
|
||||
m.energy -= 0.08 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
|
||||
if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage
|
||||
mob[k].death();
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
|
||||
105
js/index.js
@@ -1,5 +1,14 @@
|
||||
"use strict";
|
||||
|
||||
//list of the recent github hashes, shortened to the first 7 digits of the full hash.
|
||||
//the last element of the array is the most recent commit
|
||||
// const commitHashes = ['6472d6d', 'c8bf77d', 'eb8f4b0', 'f556371', '74f569b', 'c9f355b', '6814c10', '9402cf2', 'f8b4b6f', '82c0ea8', 'f9849d4', 'd00a94a', '3654198', '9bcf4d3', 'eecf763', 'be109bb', 'e2bf9aa', '3ea8bfd', 'c614451', '1752453', '34e05c7', '07af7a7', '2e76b5c', '1b23dec', '0b728fb', 'e6e5058', '4f87444', 'e418b93', 'b3fa1bf', '09c9e93', 'd8e978f', 'da559f4', '1d4b0c4', '4415942', '6cd2502', '8a211e8', '3d423a5', '4933ef5', '77cafe3', 'bffaeed', '99bd1c8', '8a3ac11', 'bf5f866', 'b14f2c1', 'ff613dc', '1129b9d', '3844d00', 'e9d2262', 'ce74f42', 'ad33cf6', '2d12f1d', 'c47d860', '4e6acdd', '778a2c9', '68f9269', '17f65cf', 'b5e4b0d', '38d9931', '64f2a9f', '64c81cd', '254ec00', '38ef45a', '1728b53', 'fde3a58', '6c3d97a', '951806d', '2b99e59', '3ce6bec', '773ee5c', '4c6b480', 'a1164ed', '507b060', '63bfaba', 'eabd146', '438c166', '1903b9e', '5e12cea', 'f43a5e3', '022e2fa', '20f9b79', 'fc70dfe', '5eae070', '8dacb02', '52046ca', '220a6b4', 'ebd2274', 'cea1c64', 'a47ef97', 'a8c6c0e', '9c2c9be', '8bb8222', '1fde74d', 'f1a6713', '97c5509', '1966173', '2daeae1', '1040d1f', 'c9a5ab9', '77e484c', 'b2426cd']
|
||||
// const lastShortHash = 'b2426cd'
|
||||
//Landgreen needs to update the commitHashes array with the most recent commit hash on each new upload, but the array will always be missing the current hash since it is generated with each new commit
|
||||
//write code to check the 2nd most recent hash and see if it match an element in the commitHashes array. Use that to calculate how many commits have been made since the last update
|
||||
|
||||
|
||||
|
||||
//convert text into numbers for seed
|
||||
Math.hash = s => {
|
||||
for (var i = 0, h = 9; i < s.length;) h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
|
||||
@@ -13,7 +22,9 @@ Math.hash = s => {
|
||||
// document.getElementById("seed").placeholder = Math.initialSeed = Math.floor(Date.now() % 100000) //random every time: just the time in milliseconds UTC
|
||||
|
||||
window.addEventListener('error', error => {
|
||||
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${error.message} <u>${error.filename}:${error.lineno}</u>`)
|
||||
// simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${error.message} <u>${error.filename}:${error.lineno}</u>`)
|
||||
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
|
||||
|
||||
});
|
||||
|
||||
document.getElementById("seed").placeholder = Math.initialSeed = String(Math.floor(Date.now() % 100000))
|
||||
@@ -26,11 +37,11 @@ Math.seededRandom = function (min = 0, max = 1) { // in order to work 'Math.seed
|
||||
// console.log(Math.seed)
|
||||
|
||||
|
||||
function shuffle(array) {
|
||||
function seededShuffle(array) {
|
||||
var currentIndex = array.length,
|
||||
temporaryValue,
|
||||
randomIndex;
|
||||
// While there remain elements to shuffle...
|
||||
// While there remain elements
|
||||
while (0 !== currentIndex) {
|
||||
// Pick a remaining element...
|
||||
// randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
@@ -495,7 +506,7 @@ const build = {
|
||||
<span style="float: right;"><strong class='color-d'>level</strong> ${((m.dmgScale)).toPrecision(4)}x</span>
|
||||
<br><strong class='color-defense'>damage taken</strong> ${(m.defense()).toPrecision(4)}x
|
||||
<span style="float: right;"><strong class='color-defense'>level</strong> ${(simulation.dmgScale).toPrecision(4)}x</span>
|
||||
<br><strong class='color-h'>health</strong> (${(m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)})
|
||||
<br><strong class='color-h'>health</strong> (${level.isHideHealth ? "null" : (m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)})
|
||||
<span style="float: right;">${powerUps.research.count} ${powerUps.orb.research()}</span>
|
||||
<br><strong class='color-f'>energy</strong> (${(m.energy * 100).toFixed(0)} / ${(m.maxEnergy * 100).toFixed(0)}) + (${(m.fieldRegen * 6000 * level.isReducedRegen).toFixed(0)}/s)
|
||||
<span style="float: right;">${tech.totalCount} ${powerUps.orb.tech()}</span>
|
||||
@@ -512,7 +523,7 @@ ${botText}
|
||||
<span style="float: right;">mouse (${simulation.mouseInGame.x.toFixed(0)}, ${simulation.mouseInGame.y.toFixed(0)})</span>
|
||||
<br>cycles ${m.cycle}
|
||||
<span style="float: right;">velocity (${player.velocity.x.toFixed(2)}, ${player.velocity.y.toFixed(2)})</span>
|
||||
<br>mobs ${mob.length} (${spawn.pickList[0]}, ${spawn.pickList[0]})
|
||||
<br>mobs ${mob.length} (${spawn.pickList[0]}, ${spawn.pickList[1]})
|
||||
<span style="float: right;">blocks ${body.length}</span>
|
||||
<br>bullets ${bullet.length}
|
||||
<span style="float: right;">power ups ${powerUp.length}</span>
|
||||
@@ -540,7 +551,7 @@ ${simulation.difficultyMode > 4 ? `<details id="constraints-details" style="padd
|
||||
<details id = "console-log-details" style="padding: 0 8px;">
|
||||
<summary>console log</summary>
|
||||
<div class="pause-details">
|
||||
<div class="pause-grid-module" style="background-color: rgba(255,255,255,0.3);font-size: 0.8em;">${document.getElementById("text-log").innerHTML}</div>
|
||||
<div class="pause-grid-module" style=" background-color: #e2e9ec;font-size: 0.8em;">${document.getElementById("text-log").innerHTML}</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>`
|
||||
@@ -641,7 +652,7 @@ ${simulation.difficultyMode > 4 ? `<details id="constraints-details" style="padd
|
||||
}
|
||||
}
|
||||
document.getElementById("sort-input").addEventListener('keydown', pressEnterSort);
|
||||
requestAnimationFrame(() => { document.getElementById("sort-input").focus(); });
|
||||
// requestAnimationFrame(() => { document.getElementById("sort-input").focus(); });
|
||||
},
|
||||
sortTech(find, isExperiment = false) {
|
||||
const sortKeyword = (a, b) => {
|
||||
@@ -728,6 +739,8 @@ ${simulation.difficultyMode > 4 ? `<details id="constraints-details" style="padd
|
||||
});
|
||||
} else if (find === 'damage') {
|
||||
tech.tech.sort(sortKeyword);
|
||||
} else if (find === 'damage taken') {
|
||||
tech.tech.sort(sortKeyword);
|
||||
} else if (find === 'defense') {
|
||||
tech.tech.sort(sortKeyword);
|
||||
} else if (find === 'energy') {
|
||||
@@ -952,8 +965,8 @@ ${simulation.difficultyMode > 4 ? `<details id="constraints-details" style="padd
|
||||
<button onclick="build.sortTech('fieldtech', true)" class='sort-button'>${powerUps.orb.fieldTech()}</button>
|
||||
<button onclick="build.sortTech('damage', true)" class='sort-button'><strong class='color-d'>damage</strong></button>
|
||||
<button onclick="build.sortTech('damage taken', true)" class='sort-button'><strong style="letter-spacing: 1px;font-weight: 100;">dmg taken</strong></button>
|
||||
<button onclick="build.sortTech('heal')" class='sort-button'><strong class='color-h'>heal</strong></button>
|
||||
<button onclick="build.sortTech('energy')" class='sort-button'><strong class='color-f'>energy</strong></button>
|
||||
<button onclick="build.sortTech('heal', true)" class='sort-button'><strong class='color-h'>heal</strong></button>
|
||||
<button onclick="build.sortTech('energy', true)" class='sort-button'><strong class='color-f'>energy</strong></button>
|
||||
<input type="search" id="sort-input" style="width: 7.5em;font-size: 0.6em;color:#000;" placeholder="sort by" />
|
||||
<button onclick="build.sortTech('input', true)" class='sort-button' style="border-radius: 0em;border: 1.5px #000 solid;font-size: 0.6em;" value="damage">sort</button>
|
||||
</div>
|
||||
@@ -1064,8 +1077,7 @@ ${simulation.difficultyMode > 4 ? `<details id="constraints-details" style="padd
|
||||
b.activeGun = null;
|
||||
b.inventoryGun = 0;
|
||||
simulation.makeGunHUD();
|
||||
tech.setupAllTech();
|
||||
m.resetSkin();
|
||||
tech.resetAllTech();
|
||||
build.populateGrid();
|
||||
document.getElementById("field-0").classList.add("build-field-selected");
|
||||
document.getElementById("experiment-grid").style.display = "grid"
|
||||
@@ -1166,12 +1178,14 @@ ${simulation.difficultyMode > 4 ? `<details id="constraints-details" style="padd
|
||||
function openExperimentMenu() {
|
||||
document.getElementById("experiment-button").style.display = "none";
|
||||
document.getElementById("training-button").style.display = "none";
|
||||
document.getElementById("start-button").style.display = "none";
|
||||
const el = document.getElementById("experiment-grid")
|
||||
el.style.display = "grid"
|
||||
document.body.style.overflowY = "scroll";
|
||||
document.body.style.overflowX = "hidden";
|
||||
document.getElementById("info").style.display = 'none'
|
||||
build.reset();
|
||||
|
||||
}
|
||||
|
||||
//record settings so they can be reproduced in the experimental menu
|
||||
@@ -1201,6 +1215,8 @@ const input = {
|
||||
left: false,
|
||||
right: false,
|
||||
isPauseKeyReady: true,
|
||||
// isMouseInside: true,
|
||||
// lastDown: null,
|
||||
key: {
|
||||
fire: "KeyF",
|
||||
field: "Space",
|
||||
@@ -1375,6 +1391,7 @@ window.addEventListener("keyup", function (event) {
|
||||
});
|
||||
|
||||
window.addEventListener("keydown", function (event) {
|
||||
// input.lastDown = event.code
|
||||
// console.log(event.code)
|
||||
switch (event.code) {
|
||||
case input.key.right:
|
||||
@@ -1414,11 +1431,13 @@ window.addEventListener("keydown", function (event) {
|
||||
build.pauseGrid()
|
||||
|
||||
} else if (simulation.paused) {
|
||||
build.unPauseGrid()
|
||||
simulation.paused = false;
|
||||
// level.levelAnnounce();
|
||||
document.body.style.cursor = "none";
|
||||
requestAnimationFrame(cycle);
|
||||
if (document.activeElement !== document.getElementById('sort-input')) {
|
||||
build.unPauseGrid()
|
||||
simulation.paused = false;
|
||||
// level.levelAnnounce();
|
||||
document.body.style.cursor = "none";
|
||||
requestAnimationFrame(cycle);
|
||||
}
|
||||
} else { //if (!tech.isNoDraftPause)
|
||||
simulation.paused = true;
|
||||
build.pauseGrid()
|
||||
@@ -1540,7 +1559,7 @@ window.addEventListener("keydown", function (event) {
|
||||
}
|
||||
break
|
||||
}
|
||||
if (b.inventory.length > 1 && !simulation.testing && !tech.isGunCycle) {
|
||||
if (b.inventory.length > 1 && !simulation.testing && !(tech.isGunChoice || tech.isGunCycle)) {
|
||||
switch (event.code) {
|
||||
case "Digit1":
|
||||
simulation.switchToGunInInventory(0);
|
||||
@@ -1727,11 +1746,12 @@ document.body.addEventListener("mouseenter", (e) => { //prevents mouse getting s
|
||||
input.fire = false;
|
||||
}
|
||||
|
||||
if (e.button === 3) {
|
||||
input.field = true;
|
||||
} else {
|
||||
input.field = false;
|
||||
}
|
||||
// if (e.button === 3) {
|
||||
// input.field = true;
|
||||
// } else {
|
||||
// input.field = false;
|
||||
// }
|
||||
// input.isMouseInside = true
|
||||
});
|
||||
document.body.addEventListener("mouseleave", (e) => { //prevents mouse getting stuck when leaving the window
|
||||
if (e.button === 1) {
|
||||
@@ -1740,11 +1760,12 @@ document.body.addEventListener("mouseleave", (e) => { //prevents mouse getting s
|
||||
input.fire = false;
|
||||
}
|
||||
|
||||
if (e.button === 3) {
|
||||
input.field = true;
|
||||
} else {
|
||||
input.field = false;
|
||||
}
|
||||
// if (e.button === 3) {
|
||||
// input.field = true;
|
||||
// } else {
|
||||
// input.field = false;
|
||||
// }
|
||||
// input.isMouseInside = false
|
||||
});
|
||||
|
||||
document.body.addEventListener("wheel", (e) => {
|
||||
@@ -1941,13 +1962,41 @@ document.getElementById("updates").addEventListener("toggle", function () {
|
||||
xhr.open("GET", path, true);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
// fetch(`https://api.github.com/repos/landgreen/n-gon/commits?per_page=100`)
|
||||
// .then(response => {
|
||||
// if (!response.ok) {
|
||||
// throw new Error(`GitHub API responded with status ${response.status}`);
|
||||
// }
|
||||
// return response.json();
|
||||
// })
|
||||
// .then(commits => {
|
||||
// // console.log(commits.sha)
|
||||
// const array = []
|
||||
// commits.forEach(commitData => {
|
||||
// const shortHash = commitData.sha.substr(0, 7);
|
||||
// array.push(shortHash)
|
||||
// });
|
||||
// console.log(array)
|
||||
// })
|
||||
// .catch(error => {
|
||||
// console.error('Error fetching commits:', error);
|
||||
// });
|
||||
|
||||
|
||||
|
||||
let text = `<pre><strong>n-gon</strong>: <a href="https://github.com/landgreen/n-gon/blob/master/todo.txt">todo list</a> and complete <a href="https://github.com/landgreen/n-gon/commits/master">change-log</a><hr>`
|
||||
document.getElementById("updates-div").innerHTML = text
|
||||
|
||||
/// https://api.github.com/repos/landgreen/n-gon/stats/commit_activity
|
||||
loadJSON('https://api.github.com/repos/landgreen/n-gon/commits',
|
||||
function (data) {
|
||||
// console.log(data[0].sha) //unique code for most recent commit
|
||||
// console.log(data[0].sha, lastShortHash)
|
||||
// if (data[0].sha.substr(0, 7) === lastShortHash) {
|
||||
// text += "<br><em>https://github.com/landgreen/n-gon/</em>: hash matches latest version<hr>"
|
||||
// } else {
|
||||
// text += "<br><em>https://github.com/landgreen/n-gon/</em>: hash does <strong>not</strong> match latest version<br><hr>"
|
||||
// }
|
||||
for (let i = 0, len = 20; i < len; i++) {
|
||||
text += "<strong>" + data[i].commit.author.date.substr(0, 10) + "</strong> - "; //+ "<br>"
|
||||
text += data[i].commit.message
|
||||
|
||||
2222
js/level.js
@@ -1088,7 +1088,7 @@ const lore = {
|
||||
|
||||
() => {
|
||||
setTimeout(() => {
|
||||
lore.anand.text("How ever it thinks it can learn, and I think we showed it that nonviolence is an option,")
|
||||
lore.anand.text("How ever it thinks, it can learn, and I think we showed it that violence isn't the only option,")
|
||||
}, 1000);
|
||||
},
|
||||
() => {
|
||||
|
||||
73
js/mob.js
@@ -41,23 +41,15 @@ const mobs = {
|
||||
ctx.fillRect(x, y, w, h);
|
||||
ctx.fillStyle = "rgba(255,0,0,0.7)";
|
||||
ctx.fillRect(x, y, w * mob[i].health, h);
|
||||
// if (mob[i].isInvulnerable) {
|
||||
// ctx.strokeStyle = "rgba(255,255,255,1)";
|
||||
// ctx.lineWidth = 5
|
||||
// ctx.strokeRect(x, y, w, h);
|
||||
// }
|
||||
}
|
||||
}
|
||||
},
|
||||
healthBar() {
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
if (mob[i].seePlayer.recall && mob[i].showHealthBar) {
|
||||
const h = mob[i].radius * 0.3;
|
||||
const w = mob[i].radius * 2;
|
||||
const x = mob[i].position.x - w / 2;
|
||||
const y = mob[i].position.y - w * 0.7;
|
||||
ctx.fillStyle = "rgba(100, 100, 100, 0.3)";
|
||||
ctx.fillRect(x, y, w, h);
|
||||
ctx.fillStyle = "rgba(255,0,0,0.7)";
|
||||
ctx.fillRect(x, y, w * mob[i].health, h);
|
||||
}
|
||||
}
|
||||
},
|
||||
healthBar() { },
|
||||
statusSlow(who, cycles = 60) {
|
||||
applySlow(who)
|
||||
//look for mobs near the target
|
||||
@@ -989,7 +981,7 @@ const mobs = {
|
||||
},
|
||||
explode(mass = this.mass) {
|
||||
if (m.immuneCycle < m.cycle) {
|
||||
m.damage(Math.min(Math.max(0.02 * Math.sqrt(mass), 0.01), 0.35) * simulation.dmgScale);
|
||||
m.damage(Math.min(Math.max(0.03 * Math.sqrt(mass), 0.01), 0.4) * simulation.dmgScale);
|
||||
this.isDropPowerUp = false;
|
||||
this.death(); //death with no power up or body
|
||||
}
|
||||
@@ -1077,7 +1069,11 @@ const mobs = {
|
||||
if (tech.isFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 33% dmg at max range of 3000
|
||||
dmg *= this.damageReduction
|
||||
//energy and heal drain should be calculated after damage boosts
|
||||
if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp && m.immuneCycle < m.cycle) m.energy += Math.min(this.health, dmg) * tech.energySiphon * level.isReducedRegen
|
||||
if (tech.energySiphon && this.isDropPowerUp && m.immuneCycle < m.cycle) {
|
||||
//dmg !== Infinity &&
|
||||
const regen = Math.min(this.health, dmg) * tech.energySiphon * level.isReducedRegen
|
||||
if (!isNaN(regen) && regen !== Infinity) m.energy += regen
|
||||
}
|
||||
dmg /= Math.sqrt(this.mass)
|
||||
}
|
||||
|
||||
@@ -1137,7 +1133,7 @@ const mobs = {
|
||||
for (let i = 0; i < mob.length; i++) {
|
||||
if (Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) < 500000 && mob[i].alive) { //700
|
||||
if (mob[i].health < 1) {
|
||||
mob[i].health += 0.33 + this.isBoss
|
||||
mob[i].health += 0.33
|
||||
if (mob[i].health > 1) mob[i].health = 1
|
||||
simulation.drawList.push({
|
||||
x: mob[i].position.x,
|
||||
@@ -1232,7 +1228,7 @@ const mobs = {
|
||||
});
|
||||
}
|
||||
|
||||
if (tech.isVerlet && !m.isBodiesAsleep) {
|
||||
if (tech.isVerlet && !m.isTimeDilated) {
|
||||
requestAnimationFrame(() => {
|
||||
simulation.timePlayerSkip(this.isBoss ? 60 : 30)
|
||||
simulation.loop(); //ending with a wipe and normal loop fixes some very minor graphical issues where things are draw in the wrong locations
|
||||
@@ -1242,6 +1238,30 @@ const mobs = {
|
||||
m.energy -= 0.05;
|
||||
if (m.energy < 0) m.energy = 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (tech.isRemineralize) {
|
||||
//reduce mineral percent based on time since last check
|
||||
const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
|
||||
tech.mineralLastCheck = simulation.cycle
|
||||
tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
|
||||
tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
|
||||
//apply mineral damage reduction
|
||||
tech.mineralDamageReduction *= 0.85
|
||||
}
|
||||
if (tech.isDemineralize) {
|
||||
//reduce mineral percent based on time since last check
|
||||
const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
|
||||
tech.mineralLastCheck = simulation.cycle
|
||||
tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
|
||||
tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
|
||||
//apply mineral damage
|
||||
tech.mineralDamage *= 1.08
|
||||
}
|
||||
|
||||
|
||||
|
||||
powerUps.spawnRandomPowerUp(this.position.x, this.position.y);
|
||||
m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks()
|
||||
mobs.mobDeaths++
|
||||
@@ -1261,9 +1281,11 @@ const mobs = {
|
||||
} else {
|
||||
for (let i = 0; i < amount; i++) b.spore(this.position)
|
||||
}
|
||||
} else if (tech.isExplodeMob) {
|
||||
}
|
||||
if (tech.isExplodeMob) {
|
||||
b.explosion(this.position, Math.min(700, Math.sqrt(this.mass + 6) * (30 + 60 * Math.random())))
|
||||
} else if (tech.nailsDeathMob) {
|
||||
}
|
||||
if (tech.nailsDeathMob) {
|
||||
b.targetedNail(this.position, tech.nailsDeathMob, 39 + 6 * Math.random())
|
||||
}
|
||||
if (tech.isBotSpawnerReset) {
|
||||
@@ -1277,7 +1299,7 @@ const mobs = {
|
||||
this.leaveBody = false; // no body since it turned into the bot
|
||||
}
|
||||
if (tech.isMobDeathImmunity) {
|
||||
const immuneTime = 360
|
||||
const immuneTime = 300
|
||||
if (m.immuneCycle < m.cycle + immuneTime) m.immuneCycle = m.cycle + immuneTime; //player is immune to damage
|
||||
}
|
||||
if (tech.isAddRemoveMaxHealth) {
|
||||
@@ -1384,7 +1406,7 @@ const mobs = {
|
||||
//replace dead mob with a regular body
|
||||
replace(i) {
|
||||
//if there are too many bodies don't turn into blocks to help performance
|
||||
if (this.leaveBody && body.length < mobs.maxMobBody && this.mass < 200 && this.radius > 18) {
|
||||
if (this.leaveBody && body.length < mobs.maxMobBody && this.mass < 200 && this.mass > 2 && this.radius > 18) {
|
||||
let v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure
|
||||
if (v.length > 5 && body.length < 35 && Math.random() < 0.25) {
|
||||
const cutPoint = 3 + Math.floor((v.length - 6) * Math.random()) //Math.floor(v.length / 2)
|
||||
@@ -1397,6 +1419,8 @@ const mobs = {
|
||||
body[len].collisionFilter.category = cat.body;
|
||||
body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
|
||||
body[len].classType = "body";
|
||||
body[len].frictionAir = 0.001
|
||||
body[len].friction = 0.05
|
||||
Composite.add(engine.world, body[len]); //add to world
|
||||
|
||||
const len2 = body.length;
|
||||
@@ -1406,6 +1430,8 @@ const mobs = {
|
||||
body[len2].collisionFilter.category = cat.body;
|
||||
body[len2].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
|
||||
body[len2].classType = "body";
|
||||
body[len2].frictionAir = 0.001
|
||||
body[len2].friction = 0.05
|
||||
Composite.add(engine.world, body[len2]); //add to world
|
||||
|
||||
//large mobs shrink so they don't block paths
|
||||
@@ -1429,8 +1455,9 @@ const mobs = {
|
||||
body[len].collisionFilter.category = cat.body;
|
||||
body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
|
||||
body[len].classType = "body";
|
||||
body[len].frictionAir = 0.001
|
||||
body[len].friction = 0.05
|
||||
Composite.add(engine.world, body[len]); //add to world
|
||||
|
||||
//large mobs shrink so they don't block paths
|
||||
if (body[len].mass > 9) {
|
||||
const massLimit = 7 + 4 * Math.random()
|
||||
|
||||
4775
js/player.js
@@ -212,7 +212,7 @@ const powerUps = {
|
||||
dupExplode() {
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
if (powerUp[i].isDuplicated) {
|
||||
if (Math.random() < 0.003 && !m.isBodiesAsleep) { // (1-0.003)^240 = chance to be removed after 4 seconds, 240 = 4 seconds * 60 cycles per second
|
||||
if (Math.random() < 0.003 && !m.isTimeDilated) { // (1-0.003)^240 = chance to be removed after 4 seconds, 240 = 4 seconds * 60 cycles per second
|
||||
b.explosion(powerUp[i].position, 175 + (11 + 3 * Math.random()) * powerUp[i].size);
|
||||
if (powerUp[i]) {
|
||||
Matter.Composite.remove(engine.world, powerUp[i]);
|
||||
@@ -256,6 +256,8 @@ const powerUps = {
|
||||
powerUps.endDraft(type);
|
||||
},
|
||||
showDraft() {
|
||||
simulation.isChoosing = true; //stops p from un pausing on key down
|
||||
|
||||
//disable clicking for 1/2 a second to prevent mistake clicks
|
||||
document.getElementById("choose-grid").style.pointerEvents = "none";
|
||||
document.body.style.cursor = "none";
|
||||
@@ -264,7 +266,6 @@ const powerUps = {
|
||||
document.getElementById("choose-grid").style.pointerEvents = "auto";
|
||||
document.getElementById("choose-grid").style.transitionDuration = "0s";
|
||||
}, 400);
|
||||
simulation.isChoosing = true; //stops p from un pausing on key down
|
||||
|
||||
if (!simulation.paused) {
|
||||
if (tech.isNoDraftPause || level.isNoPause) {
|
||||
@@ -285,7 +286,7 @@ const powerUps = {
|
||||
endDraft(type, isCanceled = false) { //type should be a gun, tech, or field
|
||||
if (isCanceled) {
|
||||
if (tech.isCancelDuplication) {
|
||||
const value = 0.05
|
||||
const value = 0.06
|
||||
tech.duplication += value
|
||||
simulation.inGameConsole(`tech.duplicationChance() <span class='color-symbol'>+=</span> ${value}`)
|
||||
simulation.circleFlare(value);
|
||||
@@ -708,7 +709,7 @@ const powerUps = {
|
||||
if (amount !== 0) powerUps.research.count += amount
|
||||
if (tech.isRerollBots && !this.isMakingBots) {
|
||||
let cycle = () => {
|
||||
const cost = 2 + Math.floor(0.25 * b.totalBots())
|
||||
const cost = 2 + Math.floor(b.totalBots() / 3)
|
||||
if (m.alive && powerUps.research.count >= cost) {
|
||||
requestAnimationFrame(cycle);
|
||||
this.isMakingBots = true
|
||||
@@ -762,7 +763,7 @@ const powerUps = {
|
||||
}
|
||||
powerUps.research.currentRerollCount++
|
||||
if (tech.isResearchReality) {
|
||||
m.switchWorlds()
|
||||
m.switchWorlds("Ψ(t) collapse")
|
||||
simulation.trails()
|
||||
simulation.inGameConsole(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
|
||||
}
|
||||
@@ -785,7 +786,7 @@ const powerUps = {
|
||||
m.addHealth(heal);
|
||||
if (healOutput > 0) simulation.inGameConsole(`<div class="circle-grid heal"></div> <span class='color-var'>m</span>.health <span class='color-symbol'>+=</span> ${(healOutput).toFixed(3)}`) // <br>${m.health.toFixed(3)}
|
||||
if (tech.isOverHeal && overHeal > 0) { //tech quenching
|
||||
tech.extraMaxHealth += 0.4 * overHeal //increase max health
|
||||
tech.extraMaxHealth += 0.5 * overHeal //increase max health
|
||||
m.setMaxHealth();
|
||||
simulation.inGameConsole(`<div class="circle-grid heal"></div> <span class='color-var'>m</span>.maxHealth <span class='color-symbol'>+=</span> ${(0.3 * overHeal).toFixed(3)}`)
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
@@ -812,7 +813,7 @@ const powerUps = {
|
||||
// color: simulation.mobDmgColor,
|
||||
// time: simulation.drawTime
|
||||
// });
|
||||
} else if (overHeal > 0.13) { //if leftover heals spawn a new spammer heal power up
|
||||
} else if (overHeal > 0.2) { //if leftover heals spawn a new spammer heal power up
|
||||
requestAnimationFrame(() => {
|
||||
powerUps.directSpawn(this.position.x, this.position.y, "heal", true, Math.min(1, overHeal) * 40 * (simulation.healScale ** 0.25))// directSpawn(x, y, name, moving = true, mode = null, size = powerUps[name].size()) {
|
||||
});
|
||||
@@ -883,7 +884,7 @@ const powerUps = {
|
||||
const couplingExtraAmmo = (m.fieldMode === 10 || m.fieldMode === 0) ? 1 + 0.04 * m.coupling : 1
|
||||
if (b.inventory.length > 0) {
|
||||
powerUps.animatePowerUpGrab('rgba(68, 102, 119,0.25)')
|
||||
if (tech.isAmmoForGun && b.activeGun !== null) { //give extra ammo to one gun only with tech logistics
|
||||
if (tech.isAmmoForGun && (b.activeGun !== null && b.activeGun !== undefined)) { //give extra ammo to one gun only with tech logistics
|
||||
const name = b.guns[b.activeGun]
|
||||
if (name.ammo !== Infinity) {
|
||||
if (tech.ammoCap) {
|
||||
@@ -909,7 +910,7 @@ const powerUps = {
|
||||
}
|
||||
},
|
||||
cancelText(type) {
|
||||
if (tech.isSuperDeterminism) {
|
||||
if (tech.isSuperDeterminism || type === "constraint") {
|
||||
return `<div></div>`
|
||||
} else if (tech.isCancelTech && tech.cancelTechCount === 0) {
|
||||
return `<div class='cancel-card sticky' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;"><span class="color-randomize">randomize</span></div>`
|
||||
@@ -940,7 +941,9 @@ const powerUps = {
|
||||
},
|
||||
researchAndCancelText(type) {
|
||||
let text = `<div class='research-cancel'>`
|
||||
if (type === "entanglement") {
|
||||
if (type === "constraint") {
|
||||
return
|
||||
} else if (type === "entanglement") {
|
||||
text += `<span class='research-card entanglement flipX' style="width: 275px;" onclick='powerUps.endDraft("${type}",true)'><span style="letter-spacing: 6px;">entanglement</span></span>`
|
||||
} else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) {
|
||||
text += `<span onclick="powerUps.research.use('${type}')" class='research-card' style="width: 275px;float: left;">` // style = "margin-left: 192px; margin-right: -192px;"
|
||||
@@ -1008,6 +1011,12 @@ const powerUps = {
|
||||
return text
|
||||
},
|
||||
hideStyle: `style="height:auto; border: none; background-color: transparent;"`,
|
||||
constraintText(choose, click) {
|
||||
return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${powerUps.hideStyle}>
|
||||
<div class="card-text">
|
||||
<div class="grid-title"><div class="circle-grid field"></div> ${m.fieldUpgrades[choose].name}</div>
|
||||
${m.fieldUpgrades[choose].description}</div></div>`
|
||||
},
|
||||
gunText(choose, click) {
|
||||
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/gun/${b.guns[choose].name}.webp');"`
|
||||
return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}" ${style}>
|
||||
@@ -1129,7 +1138,7 @@ const powerUps = {
|
||||
}
|
||||
// console.log(options.length)
|
||||
if (options.length > 0 || !tech.isSuperDeterminism) {
|
||||
let totalChoices = 2 + tech.extraChoices + 3 * (m.fieldMode === 8) - level.fewerChoices
|
||||
let totalChoices = 2 + tech.extraChoices + (tech.isInPilot ? 1 : 3) * (m.fieldMode === 8) - level.fewerChoices
|
||||
if (tech.isCancelTech && tech.cancelTechCount === 1) {
|
||||
totalChoices *= 3
|
||||
tech.cancelTechCount++
|
||||
@@ -1196,7 +1205,7 @@ const powerUps = {
|
||||
for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter
|
||||
if (i !== m.fieldMode) options.push(i);
|
||||
}
|
||||
let totalChoices = 2 + tech.extraChoices + 3 * (m.fieldMode === 8) - level.fewerChoices
|
||||
let totalChoices = 2 + tech.extraChoices + (tech.isInPilot ? 1 : 3) * (m.fieldMode === 8) - level.fewerChoices
|
||||
if (tech.isCancelTech && tech.cancelTechCount === 1) {
|
||||
totalChoices *= 3
|
||||
tech.cancelTechCount++
|
||||
@@ -1276,7 +1285,7 @@ const powerUps = {
|
||||
}
|
||||
}
|
||||
//set total choices
|
||||
let totalChoices = 3 + tech.extraChoices + 3 * (m.fieldMode === 8) - level.fewerChoices
|
||||
let totalChoices = 3 + tech.extraChoices + (tech.isInPilot ? 1 : 3) * (m.fieldMode === 8) - level.fewerChoices
|
||||
if (tech.isCancelTech && tech.cancelTechCount === 1) {
|
||||
totalChoices *= 3
|
||||
tech.cancelTechCount++
|
||||
@@ -1607,6 +1616,8 @@ const powerUps = {
|
||||
}
|
||||
}
|
||||
}
|
||||
powerUps.spawn(x + 25, y - 25, "ammo", false);
|
||||
if (simulation.difficultyMode > 5) powerUps.spawn(x - 25, y - 50, "ammo", false);
|
||||
if (tech.isAddRemoveMaxHealth) {
|
||||
powerUps.spawn(x + 20, y, "tech", false)
|
||||
powerUps.spawn(x - 20, y, "research", false)
|
||||
@@ -1618,7 +1629,7 @@ const powerUps = {
|
||||
powerUps.spawn(x, y - 40, "heal", false)
|
||||
}
|
||||
if (tech.isResearchReality) powerUps.spawnDelay("research", 6)
|
||||
if (tech.isBanish) powerUps.spawnDelay("research", 2)
|
||||
if (tech.isBanish) powerUps.spawnDelay("research", 3)
|
||||
if (tech.isCouplingNoHit) powerUps.spawnDelay("coupling", 9)
|
||||
// if (tech.isRerollDamage) powerUps.spawnDelay("research", 1)
|
||||
}
|
||||
@@ -1642,6 +1653,7 @@ const powerUps = {
|
||||
if (b.inventory.length === 0) {
|
||||
powerUps.spawn(x, y, "gun", false); //first gun
|
||||
} else if (tech.totalCount === 0) { //first tech
|
||||
powerUps.spawn(x - 22, y - 50, "ammo", false); //some ammo
|
||||
powerUps.spawn(x, y, "tech", false);
|
||||
} else if (b.inventory.length === 1) { //second gun or extra ammo
|
||||
if (Math.random() < 0.4) {
|
||||
@@ -1735,9 +1747,10 @@ const powerUps = {
|
||||
}
|
||||
|
||||
//count big power ups and small power ups
|
||||
let options = ["heal", "research", "ammo"]
|
||||
let options = ["heal", "research", tech.isBoostReplaceAmmo ? "boost" : "ammo"]
|
||||
if (m.coupling) options.push("coupling")
|
||||
if (tech.isBoostPowerUps) options.push("boost")
|
||||
|
||||
let bigIndexes = []
|
||||
let smallIndexes = []
|
||||
for (let i = 0; i < powerUp.length; i++) {
|
||||
|
||||
378
js/simulation.js
@@ -2,152 +2,152 @@
|
||||
//*********************************************************************
|
||||
const simulation = {
|
||||
loop() { }, //main game loop, gets set to normal or testing loop
|
||||
normalLoop() {
|
||||
try {
|
||||
simulation.gravity();
|
||||
Engine.update(engine, simulation.delta);
|
||||
simulation.wipe();
|
||||
simulation.textLog();
|
||||
if (m.onGround) {
|
||||
m.groundControl()
|
||||
} else {
|
||||
m.airControl()
|
||||
}
|
||||
m.move();
|
||||
m.look();
|
||||
simulation.camera();
|
||||
level.custom();
|
||||
powerUps.do();
|
||||
mobs.draw();
|
||||
simulation.draw.cons();
|
||||
simulation.draw.body();
|
||||
if (!m.isBodiesAsleep) mobs.loop();
|
||||
mobs.healthBar();
|
||||
m.draw();
|
||||
m.hold();
|
||||
level.customTopLayer();
|
||||
simulation.draw.drawMapPath();
|
||||
b.fire();
|
||||
b.bulletRemove();
|
||||
b.bulletDraw();
|
||||
if (!m.isBodiesAsleep) b.bulletDo();
|
||||
simulation.drawCircle();
|
||||
simulation.runEphemera();
|
||||
ctx.restore();
|
||||
} catch (error) {
|
||||
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
|
||||
} finally {
|
||||
simulation.drawCursor();
|
||||
}
|
||||
},
|
||||
testingLoop() {
|
||||
try {
|
||||
simulation.gravity();
|
||||
Engine.update(engine, simulation.delta);
|
||||
simulation.wipe();
|
||||
simulation.textLog();
|
||||
if (m.onGround) {
|
||||
m.groundControl()
|
||||
} else {
|
||||
m.airControl()
|
||||
}
|
||||
m.move();
|
||||
m.look();
|
||||
simulation.camera();
|
||||
level.custom();
|
||||
m.draw();
|
||||
m.hold();
|
||||
level.customTopLayer();
|
||||
simulation.draw.wireFrame();
|
||||
if (input.fire && m.fireCDcycle < m.cycle) {
|
||||
m.fireCDcycle = m.cycle + 15; //fire cooldown
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
|
||||
console.log(mob[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
simulation.draw.cons();
|
||||
simulation.draw.testing();
|
||||
simulation.drawCircle();
|
||||
simulation.runEphemera();
|
||||
simulation.constructCycle()
|
||||
} catch (error) {
|
||||
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
|
||||
} finally {
|
||||
ctx.restore();
|
||||
simulation.testingOutput();
|
||||
simulation.drawCursor();
|
||||
}
|
||||
},
|
||||
// normalLoop() {
|
||||
// simulation.gravity();
|
||||
// Engine.update(engine, simulation.delta);
|
||||
// simulation.wipe();
|
||||
// simulation.textLog();
|
||||
// if (m.onGround) {
|
||||
// m.groundControl()
|
||||
// } else {
|
||||
// m.airControl()
|
||||
// try {
|
||||
// simulation.gravity();
|
||||
// Engine.update(engine, simulation.delta);
|
||||
// simulation.wipe();
|
||||
// simulation.textLog();
|
||||
// if (m.onGround) {
|
||||
// m.groundControl()
|
||||
// } else {
|
||||
// m.airControl()
|
||||
// }
|
||||
// m.move();
|
||||
// m.look();
|
||||
// simulation.camera();
|
||||
// level.custom();
|
||||
// powerUps.do();
|
||||
// mobs.draw();
|
||||
// simulation.draw.cons();
|
||||
// simulation.draw.body();
|
||||
// if (!m.isTimeDilated) mobs.loop();
|
||||
// mobs.healthBar();
|
||||
// m.draw();
|
||||
// m.hold();
|
||||
// level.customTopLayer();
|
||||
// simulation.draw.drawMapPath();
|
||||
// b.fire();
|
||||
// b.bulletRemove();
|
||||
// b.bulletDraw();
|
||||
// if (!m.isTimeDilated) b.bulletDo();
|
||||
// simulation.drawCircle();
|
||||
// simulation.runEphemera();
|
||||
// ctx.restore();
|
||||
// } catch (error) {
|
||||
// simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
|
||||
// } finally {
|
||||
// simulation.drawCursor();
|
||||
// }
|
||||
// m.move();
|
||||
// m.look();
|
||||
// simulation.camera();
|
||||
// level.custom();
|
||||
// powerUps.do();
|
||||
// mobs.draw();
|
||||
// simulation.draw.cons();
|
||||
// simulation.draw.body();
|
||||
// if (!m.isBodiesAsleep) mobs.loop();
|
||||
// mobs.healthBar();
|
||||
// m.draw();
|
||||
// m.hold();
|
||||
// level.customTopLayer();
|
||||
// simulation.draw.drawMapPath();
|
||||
// b.fire();
|
||||
// b.bulletRemove();
|
||||
// b.bulletDraw();
|
||||
// if (!m.isBodiesAsleep) b.bulletDo();
|
||||
// simulation.drawCircle();
|
||||
// simulation.runEphemera();
|
||||
// ctx.restore();
|
||||
// simulation.drawCursor();
|
||||
// },
|
||||
// testingLoop() {
|
||||
// simulation.gravity();
|
||||
// Engine.update(engine, simulation.delta);
|
||||
// simulation.wipe();
|
||||
// simulation.textLog();
|
||||
// if (m.onGround) {
|
||||
// m.groundControl()
|
||||
// } else {
|
||||
// m.airControl()
|
||||
// }
|
||||
// m.move();
|
||||
// m.look();
|
||||
// simulation.camera();
|
||||
// level.custom();
|
||||
// m.draw();
|
||||
// m.hold();
|
||||
// level.customTopLayer();
|
||||
// simulation.draw.wireFrame();
|
||||
// if (input.fire && m.fireCDcycle < m.cycle) {
|
||||
// m.fireCDcycle = m.cycle + 15; //fire cooldown
|
||||
// for (let i = 0, len = mob.length; i < len; i++) {
|
||||
// if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
|
||||
// console.log(mob[i])
|
||||
// try {
|
||||
// simulation.gravity();
|
||||
// Engine.update(engine, simulation.delta);
|
||||
// simulation.wipe();
|
||||
// simulation.textLog();
|
||||
// if (m.onGround) {
|
||||
// m.groundControl()
|
||||
// } else {
|
||||
// m.airControl()
|
||||
// }
|
||||
// m.move();
|
||||
// m.look();
|
||||
// simulation.camera();
|
||||
// level.custom();
|
||||
// m.draw();
|
||||
// m.hold();
|
||||
// level.customTopLayer();
|
||||
// simulation.draw.wireFrame();
|
||||
// if (input.fire && m.fireCDcycle < m.cycle) {
|
||||
// m.fireCDcycle = m.cycle + 15; //fire cooldown
|
||||
// for (let i = 0, len = mob.length; i < len; i++) {
|
||||
// if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
|
||||
// console.log(mob[i])
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// simulation.draw.cons();
|
||||
// simulation.draw.testing();
|
||||
// simulation.drawCircle();
|
||||
// simulation.runEphemera();
|
||||
// simulation.constructCycle()
|
||||
// } catch (error) {
|
||||
// simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
|
||||
// } finally {
|
||||
// ctx.restore();
|
||||
// simulation.testingOutput();
|
||||
// simulation.drawCursor();
|
||||
// }
|
||||
// simulation.draw.cons();
|
||||
// simulation.draw.testing();
|
||||
// simulation.drawCircle();
|
||||
// simulation.runEphemera();
|
||||
// simulation.constructCycle()
|
||||
// ctx.restore();
|
||||
// simulation.testingOutput();
|
||||
// simulation.drawCursor();
|
||||
// },
|
||||
normalLoop() {
|
||||
simulation.gravity();
|
||||
Engine.update(engine, simulation.delta);
|
||||
simulation.wipe();
|
||||
simulation.textLog();
|
||||
if (m.onGround) {
|
||||
m.groundControl()
|
||||
} else {
|
||||
m.airControl()
|
||||
}
|
||||
m.move();
|
||||
m.look();
|
||||
simulation.camera();
|
||||
level.custom();
|
||||
powerUps.do();
|
||||
mobs.draw();
|
||||
simulation.draw.cons();
|
||||
simulation.draw.body();
|
||||
if (!m.isTimeDilated) mobs.loop();
|
||||
mobs.healthBar();
|
||||
m.draw();
|
||||
m.hold();
|
||||
level.customTopLayer();
|
||||
simulation.draw.drawMapPath();
|
||||
b.fire();
|
||||
b.bulletRemove();
|
||||
b.bulletDraw();
|
||||
if (!m.isTimeDilated) b.bulletDo();
|
||||
simulation.drawCircle();
|
||||
simulation.runEphemera();
|
||||
ctx.restore();
|
||||
simulation.drawCursor();
|
||||
},
|
||||
testingLoop() {
|
||||
simulation.gravity();
|
||||
Engine.update(engine, simulation.delta);
|
||||
simulation.wipe();
|
||||
simulation.textLog();
|
||||
if (m.onGround) {
|
||||
m.groundControl()
|
||||
} else {
|
||||
m.airControl()
|
||||
}
|
||||
m.move();
|
||||
m.look();
|
||||
simulation.camera();
|
||||
level.custom();
|
||||
m.draw();
|
||||
m.hold();
|
||||
level.customTopLayer();
|
||||
simulation.draw.wireFrame();
|
||||
if (input.fire && m.fireCDcycle < m.cycle) {
|
||||
m.fireCDcycle = m.cycle + 15; //fire cooldown
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
|
||||
console.log(mob[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
simulation.draw.cons();
|
||||
simulation.draw.testing();
|
||||
simulation.drawCircle();
|
||||
simulation.runEphemera();
|
||||
simulation.constructCycle()
|
||||
ctx.restore();
|
||||
simulation.testingOutput();
|
||||
simulation.drawCursor();
|
||||
},
|
||||
isTimeSkipping: false,
|
||||
timeSkip(cycles = 60) {
|
||||
simulation.isTimeSkipping = true;
|
||||
@@ -183,10 +183,10 @@ const simulation = {
|
||||
Engine.update(engine, simulation.delta);
|
||||
// level.custom();
|
||||
// level.customTopLayer();
|
||||
if (!m.isBodiesAsleep) mobs.loop();
|
||||
if (!m.isTimeDilated) mobs.loop();
|
||||
if (m.fieldMode !== 7) m.hold();
|
||||
b.bulletRemove();
|
||||
if (!m.isBodiesAsleep) b.bulletDo();
|
||||
if (!m.isTimeDilated) b.bulletDo();
|
||||
simulation.runEphemera();
|
||||
}
|
||||
simulation.isTimeSkipping = false;
|
||||
@@ -223,7 +223,7 @@ const simulation = {
|
||||
// mobs.draw();
|
||||
// simulation.draw.cons();
|
||||
// simulation.draw.body();
|
||||
// if (!m.isBodiesAsleep) {
|
||||
// if (!m.isTimeDilated) {
|
||||
// // mobs.loop();
|
||||
// }
|
||||
// mobs.healthBar();
|
||||
@@ -235,7 +235,7 @@ const simulation = {
|
||||
// b.fire();
|
||||
// b.bulletRemove();
|
||||
// b.bulletDraw();
|
||||
// if (!m.isBodiesAsleep) b.bulletDo();
|
||||
// if (!m.isTimeDilated) b.bulletDo();
|
||||
// simulation.drawCircle();
|
||||
// // simulation.clip();
|
||||
// ctx.restore();
|
||||
@@ -425,7 +425,7 @@ const simulation = {
|
||||
if (simulation.drawList[i].time) {
|
||||
simulation.drawList[i].time--;
|
||||
} else {
|
||||
if (!m.isBodiesAsleep) simulation.drawList.splice(i, 1); //remove when timer runs out
|
||||
if (!m.isTimeDilated) simulation.drawList.splice(i, 1); //remove when timer runs out
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -496,6 +496,32 @@ const simulation = {
|
||||
}
|
||||
simulation.boldActiveGunHUD();
|
||||
},
|
||||
// updateTechHUD() {
|
||||
// let text = ""
|
||||
// for (let i = 0, len = tech.tech.length; i < len; i++) { //add tech
|
||||
// if (tech.tech[i].isLost) {
|
||||
// if (text) text += "<br>" //add a new line, but not on the first line
|
||||
// text += `<span style="text-decoration: line-through;">${tech.tech[i].name}</span>`
|
||||
// } else if (tech.tech[i].count > 0 && !tech.tech[i].isInstant) {
|
||||
// if (text) text += "<br>" //add a new line, but not on the first line
|
||||
// text += `<span id = "${tech.tech[i].name}">${tech.tech[i].name}${tech.tech[i].count > 1 ? ` (${tech.tech[i].count}x)` : ""}</span>`
|
||||
|
||||
// // document.getElementById(tech.tech[i].name).style.fontWeight = 'bold';
|
||||
// // simulation.ephemera.push({
|
||||
// // name: "bold",
|
||||
// // count: 180,
|
||||
// // do() {
|
||||
// // this.count--
|
||||
// // if (this.count < 0) {
|
||||
// // simulation.removeEphemera(this.name)
|
||||
// // if (document.getElementById(tech.tech[i].name)) document.getElementById(tech.tech[i].name).style.fontWeight = 'normal';
|
||||
// // }
|
||||
// // }
|
||||
// // })
|
||||
// }
|
||||
// }
|
||||
// document.getElementById("right-HUD").innerHTML = text
|
||||
// },
|
||||
updateTechHUD() {
|
||||
let text = ""
|
||||
for (let i = 0, len = tech.tech.length; i < len; i++) { //add tech
|
||||
@@ -532,14 +558,14 @@ const simulation = {
|
||||
}
|
||||
},
|
||||
nextGun() {
|
||||
if (b.inventory.length > 1 && !tech.isGunCycle) {
|
||||
if (b.inventory.length > 1 && !(tech.isGunCycle || tech.isGunChoice)) {
|
||||
b.inventoryGun++;
|
||||
if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0;
|
||||
simulation.switchGun();
|
||||
}
|
||||
},
|
||||
previousGun() {
|
||||
if (b.inventory.length > 1 && !tech.isGunCycle) {
|
||||
if (b.inventory.length > 1 && !(tech.isGunCycle || tech.isGunChoice)) {
|
||||
b.inventoryGun--;
|
||||
if (b.inventoryGun < 0) b.inventoryGun = b.inventory.length - 1;
|
||||
simulation.switchGun();
|
||||
@@ -712,7 +738,7 @@ const simulation = {
|
||||
mouseMove = mouseMoveDefault
|
||||
}
|
||||
},
|
||||
translatePlayerAndCamera(where) {
|
||||
translatePlayerAndCamera(where, isTranslateBots = true) {
|
||||
//infinite falling. teleport to sky after falling
|
||||
const before = { x: player.position.x, y: player.position.y, }
|
||||
Matter.Body.setPosition(player, { x: where.x, y: where.y });
|
||||
@@ -728,20 +754,21 @@ const simulation = {
|
||||
//is there a reason to update m.pos here?
|
||||
// m.pos.x = player.position.x;
|
||||
// m.pos.y = playerBody.position.y - m.yOff;
|
||||
|
||||
for (let i = 0; i < bullet.length; i++) {
|
||||
if (bullet[i].botType) {
|
||||
if (Vector.magnitudeSquared(Vector.sub(bullet[i].position, player.position)) > 1000000) { //far away bots teleport to player
|
||||
Matter.Body.setPosition(bullet[i], Vector.add(player.position, { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) }));
|
||||
Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 });
|
||||
} else { //close bots maintain relative distance to player on teleport
|
||||
Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
|
||||
if (isTranslateBots) {
|
||||
for (let i = 0; i < bullet.length; i++) {
|
||||
if (bullet[i].botType) {
|
||||
if (Vector.magnitudeSquared(Vector.sub(bullet[i].position, player.position)) > 1000000) { //far away bots teleport to player
|
||||
Matter.Body.setPosition(bullet[i], Vector.add(player.position, { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) }));
|
||||
Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 });
|
||||
} else { //close bots maintain relative distance to player on teleport
|
||||
Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
setupCamera() { //makes the camera not scroll after changing locations
|
||||
// //only works if velocity is zero
|
||||
// only works if velocity is zero
|
||||
m.pos.x = player.position.x;
|
||||
m.pos.y = playerBody.position.y - m.yOff;
|
||||
const scale = 0.8;
|
||||
@@ -767,6 +794,20 @@ const simulation = {
|
||||
simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX;
|
||||
simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY;
|
||||
},
|
||||
//for moving camera away from player
|
||||
setCameraPosition(x, y, zoom = 1) {
|
||||
ctx.restore();
|
||||
ctx.save();
|
||||
ctx.translate(canvas.width2, canvas.height2); //center
|
||||
ctx.scale(zoom, zoom); //zoom in once centered
|
||||
ctx.translate(- x, - y); //center
|
||||
|
||||
// ctx.scale(simulation.zoom / simulation.edgeZoomOutSmooth, simulation.zoom / simulation.edgeZoomOutSmooth); //zoom in once centered
|
||||
// ctx.translate(-canvas.width2, -canvas.height2); //translate
|
||||
//calculate in game mouse position by undoing the zoom and translations
|
||||
simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX;
|
||||
simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY;
|
||||
},
|
||||
cameraNoLook() {
|
||||
ctx.save();
|
||||
ctx.translate(canvas.width2, canvas.height2); //center
|
||||
@@ -836,7 +877,7 @@ const simulation = {
|
||||
bodies[i].force.y += bodies[i].mass * magnitude;
|
||||
}
|
||||
}
|
||||
if (!m.isBodiesAsleep) {
|
||||
if (!m.isTimeDilated) {
|
||||
addGravity(powerUp, simulation.g);
|
||||
addGravity(body, simulation.g);
|
||||
}
|
||||
@@ -864,6 +905,8 @@ const simulation = {
|
||||
document.getElementById("experiment-button").style.opacity = "0";
|
||||
document.getElementById("training-button").style.display = "inline"
|
||||
document.getElementById("training-button").style.opacity = "0";
|
||||
document.getElementById("start-button").style.display = "inline"
|
||||
document.getElementById("start-button").style.opacity = "0";
|
||||
document.getElementById("experiment-grid").style.display = "none"
|
||||
document.getElementById("pause-grid-left").style.display = "none"
|
||||
document.getElementById("pause-grid-right").style.display = "none"
|
||||
@@ -877,6 +920,7 @@ const simulation = {
|
||||
setTimeout(() => {
|
||||
document.getElementById("experiment-button").style.opacity = "1";
|
||||
document.getElementById("training-button").style.opacity = "1";
|
||||
document.getElementById("start-button").style.opacity = "1";
|
||||
document.getElementById("info").style.opacity = "1";
|
||||
document.getElementById("splash").style.opacity = "1";
|
||||
}, 200);
|
||||
@@ -903,6 +947,7 @@ const simulation = {
|
||||
document.getElementById("info").style.display = "none";
|
||||
document.getElementById("experiment-button").style.display = "none";
|
||||
document.getElementById("training-button").style.display = "none";
|
||||
document.getElementById("start-button").style.display = "none";
|
||||
// document.getElementById("experiment-button").style.opacity = "0";
|
||||
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
|
||||
@@ -942,14 +987,13 @@ const simulation = {
|
||||
} else {
|
||||
Composite.add(engine.world, [player])
|
||||
}
|
||||
shuffle(level.constraint)
|
||||
seededShuffle(level.constraint)
|
||||
level.populateLevels()
|
||||
input.endKeySensing();
|
||||
simulation.ephemera = []
|
||||
powerUps.powerUpStorage = []
|
||||
tech.setupAllTech(); //sets tech to default values
|
||||
tech.resetAllTech(); //sets tech to default values
|
||||
b.resetAllGuns();
|
||||
tech.duplication = 0;
|
||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||
if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod()
|
||||
if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
|
||||
@@ -957,15 +1001,7 @@ const simulation = {
|
||||
if (b.guns[i].name === "harpoon") b.guns[i].chooseFireMethod()
|
||||
if (b.guns[i].name === "foam") b.guns[i].chooseFireMethod()
|
||||
}
|
||||
tech.dynamoBotCount = 0;
|
||||
tech.nailBotCount = 0;
|
||||
tech.laserBotCount = 0;
|
||||
tech.orbitBotCount = 0;
|
||||
tech.foamBotCount = 0;
|
||||
tech.soundBotCount = 0;
|
||||
tech.boomBotCount = 0;
|
||||
tech.plasmaBotCount = 0;
|
||||
tech.missileBotCount = 0;
|
||||
b.zeroBotCount()
|
||||
|
||||
m.isSwitchingWorlds = false
|
||||
simulation.isChoosing = false;
|
||||
@@ -996,7 +1032,7 @@ const simulation = {
|
||||
simulation.makeGunHUD();
|
||||
simulation.lastLogTime = 0;
|
||||
mobs.mobDeaths = 0
|
||||
|
||||
level.isFlipped = false
|
||||
level.onLevel = 0;
|
||||
level.levelsCleared = 0;
|
||||
level.updateDifficulty()
|
||||
@@ -1043,12 +1079,12 @@ const simulation = {
|
||||
simulation.ephemera.push({
|
||||
name: "dmgDefBars", count: 0, do() {
|
||||
if (!(m.cycle % 15)) { //4 times a second
|
||||
const defense = m.defense() //update defense bar
|
||||
const defense = m.defense() //* simulation.dmgScale //update defense bar
|
||||
if (m.lastCalculatedDefense !== defense) {
|
||||
document.getElementById("defense-bar").style.width = Math.floor(300 * m.maxHealth * (1 - defense)) + "px";
|
||||
m.lastCalculatedDefense = defense
|
||||
}
|
||||
const damage = tech.damageFromTech() //update damage bar
|
||||
const damage = tech.damageFromTech() //* m.dmgScale //update damage bar
|
||||
if (m.lastCalculatedDamage !== damage) {
|
||||
document.getElementById("damage-bar").style.height = Math.floor((Math.atan(0.25 * damage - 0.25) + 0.25) * 0.53 * canvas.height) + "px";
|
||||
m.lastCalculatedDamage = damage
|
||||
|
||||
252
js/spawn.js
@@ -1,6 +1,6 @@
|
||||
//main object for spawning things in a level
|
||||
const spawn = {
|
||||
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture"],
|
||||
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture", "snakeBoss"],
|
||||
// other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss, mineBoss, hopMotherBoss //these need a particular level to work so they are not included in the random pool
|
||||
randomBossList: [
|
||||
"orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
|
||||
@@ -42,6 +42,7 @@ const spawn = {
|
||||
spawn.pickList.splice(0, 1);
|
||||
const push = spawn.mobTypeSpawnOrder[spawn.mobTypeSpawnIndex++ % spawn.mobTypeSpawnOrder.length]
|
||||
spawn.pickList.push(push);
|
||||
|
||||
// if (spawn.mobTypeSpawnIndex > spawn.mobTypeSpawnOrder.length) spawn.mobTypeSpawnIndex = 0
|
||||
//each level has 2 mobs: one new mob and one from the last level
|
||||
// spawn.pickList.splice(0, 1);
|
||||
@@ -113,11 +114,11 @@ const spawn = {
|
||||
}
|
||||
}
|
||||
},
|
||||
secondaryBossChance(x, y) {
|
||||
secondaryBossChance(x, y, options = []) {
|
||||
if (simulation.difficultyMode > 2 && level.levelsCleared > 1) {
|
||||
spawn.randomLevelBoss(x, y);
|
||||
powerUps.directSpawn(x - 30, y, "ammo");
|
||||
powerUps.directSpawn(x + 30, y, "ammo");
|
||||
spawn.randomLevelBoss(x, y, options);
|
||||
powerUps.spawn(x - 30, y, "ammo");
|
||||
powerUps.spawn(x + 30, y, "ammo");
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
@@ -194,7 +195,7 @@ const spawn = {
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
if (tech.isDarkStar && !m.isCloak) { //&& !m.isBodiesAsleep
|
||||
if (tech.isDarkStar && !m.isCloak) { //&& !m.isTimeDilated
|
||||
ctx.fillStyle = "rgba(10,0,40,0.4)"
|
||||
ctx.fill()
|
||||
//damage mobs
|
||||
@@ -744,7 +745,7 @@ const spawn = {
|
||||
// exit() { },
|
||||
// },
|
||||
]
|
||||
shuffle(me.mode); //THIS SHOULD NOT BE COMMENTED OUT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
me.mode.sort(() => Math.random() - 0.5);
|
||||
me.do = function () {
|
||||
this.fill = `hsl(${360 * Math.sin(this.cycle * 0.011)},${80 + 20 * Math.sin(this.cycle * 0.004)}%,${60 + 20 * Math.sin(this.cycle * 0.009)}%)`
|
||||
if (this.health < 1) {
|
||||
@@ -1014,7 +1015,7 @@ const spawn = {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (simulation.testing || simulation.difficultyMode > 5) {
|
||||
if (simulation.testing || simulation.difficultyMode > 6) {
|
||||
unlockExit()
|
||||
setTimeout(function () {
|
||||
simulation.inGameConsole(`level.levels.length <span class='color-symbol'>=</span> <strong>Infinite</strong>`);
|
||||
@@ -1497,7 +1498,7 @@ const spawn = {
|
||||
for (let i = 0; i < num; i++) spawn.spawnerBoss(x, y, radius, spawnID)
|
||||
},
|
||||
spawnerBoss(x, y, radius, spawnID) {
|
||||
mobs.spawn(x + Math.random(), y + Math.random(), 4, radius, "rgba(255,60,0,0.3)") //);
|
||||
mobs.spawn(x + Math.random(), y + Math.random(), 4, radius, "rgba(255,0,70,1)") //);
|
||||
let me = mob[mob.length - 1];
|
||||
me.isBoss = true;
|
||||
|
||||
@@ -1517,10 +1518,24 @@ const spawn = {
|
||||
// spawn.shield(me, x, y, 1);
|
||||
|
||||
me.onHit = function () { //run this function on hitting player
|
||||
this.explode();
|
||||
this.explode(2 * this.mass);
|
||||
};
|
||||
me.damageReduction = 0.14
|
||||
me.doAwake = function () {
|
||||
//draw aura
|
||||
ctx.beginPath();
|
||||
const vertices = this.vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
ctx.strokeStyle = `rgba(255,0,70,${0.2 + 0.4 * Math.random()})`
|
||||
ctx.lineWidth = Math.floor(5 + 30 * this.health)
|
||||
ctx.stroke();
|
||||
// ctx.strokeStyle = "rgba(255,60,0,0.1)"
|
||||
// ctx.lineWidth = 70
|
||||
// ctx.stroke();
|
||||
// this.fill = `rgba(255,0,70,${0.1 + 0.1 * Math.random()})`
|
||||
|
||||
this.alwaysSeePlayer();
|
||||
this.checkStatus();
|
||||
this.attraction();
|
||||
@@ -1545,6 +1560,7 @@ const spawn = {
|
||||
this.checkStatus();
|
||||
if (this.seePlayer.recall) {
|
||||
this.do = this.doAwake
|
||||
this.fill = `transparent`
|
||||
//awaken other spawnBosses
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
if (mob[i].isSpawnBoss && mob[i].spawnID === this.spawnID) mob[i].seePlayer.recall = 1
|
||||
@@ -1600,7 +1616,7 @@ const spawn = {
|
||||
me.seePlayerFreq = Math.floor(11 + 7 * Math.random())
|
||||
me.seeAtDistance2 = 200000 //1400000;
|
||||
me.stroke = "transparent"
|
||||
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body //| cat.map //"rgba(255,60,0,0.3)"
|
||||
me.collisionFilter.mask = cat.player | cat.bullet | cat.body //| cat.map //"rgba(255,60,0,0.3)"
|
||||
|
||||
me.buffCount = 0
|
||||
me.accelMag = 0.00005 //* simulation.accelScale;
|
||||
@@ -1770,6 +1786,7 @@ const spawn = {
|
||||
powerUps.spawn(me.position.x, me.position.y, "heal");
|
||||
powerUps.spawn(me.position.x, me.position.y, "ammo");
|
||||
powerUps.spawn(me.position.x, me.position.y, "ammo");
|
||||
powerUps.spawn(me.position.x, me.position.y, "ammo");
|
||||
} else if (!m.isCloak) {
|
||||
me.foundPlayer();
|
||||
}
|
||||
@@ -2028,7 +2045,7 @@ const spawn = {
|
||||
// Matter.Body.setStatic(me, true); //make static (disables taking damage)
|
||||
me.frictionAir = 1
|
||||
me.damageReduction = 2
|
||||
me.collisionFilter.mask = cat.bullet //| cat.body
|
||||
me.collisionFilter.mask = cat.bullet | cat.body
|
||||
// me.collisionFilter.category = cat.mobBullet;
|
||||
// me.collisionFilter.mask = cat.bullet | cat.body // | cat.player
|
||||
me.isMine = true
|
||||
@@ -2682,32 +2699,37 @@ const spawn = {
|
||||
this.seePlayerByHistory()
|
||||
this.invulnerabilityCountDown--
|
||||
if (this.isInvulnerable) {
|
||||
ctx.beginPath();
|
||||
let vertices = this.vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
for (let i = 0; i < this.babyList.length; i++) {
|
||||
if (this.babyList[i].alive) {
|
||||
let vertices = this.babyList[i].vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
if (this.invulnerabilityCountDown > 90 || this.invulnerabilityCountDown % 20 > 10) {
|
||||
ctx.beginPath();
|
||||
let vertices = this.vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
for (let i = 0; i < this.babyList.length; i++) {
|
||||
if (this.babyList[i].alive) {
|
||||
let vertices = this.babyList[i].vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
}
|
||||
}
|
||||
ctx.lineWidth = 3 + 0.2 * Math.min(this.invulnerabilityCountDown, 90) + 5 * Math.random()
|
||||
ctx.strokeStyle = `rgba(255,255,255,${0.4 + 0.4 * Math.random()})`;
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.lineWidth = 13 + 5 * Math.random();
|
||||
ctx.strokeStyle = `rgba(255,255,255,${0.5 + 0.2 * Math.random()})`;
|
||||
ctx.stroke();
|
||||
if (this.invulnerabilityCountDown < 0) {
|
||||
this.invulnerabilityCountDown = 110
|
||||
this.isInvulnerable = false
|
||||
this.damageReduction = this.startingDamageReduction
|
||||
for (let i = 0; i < this.babyList.length; i++) {
|
||||
if (this.babyList[i].alive) this.babyList[i].damageReduction = this.startingDamageReduction
|
||||
if (this.babyList[i].alive) {
|
||||
this.babyList[i].isInvulnerable = false
|
||||
this.babyList[i].damageReduction = this.startingDamageReduction
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (this.invulnerabilityCountDown < 0) {
|
||||
this.invulnerabilityCountDown = 120 + 9 * simulation.difficulty
|
||||
this.invulnerabilityCountDown = 240 + 5 * simulation.difficulty
|
||||
this.isInvulnerable = true
|
||||
if (this.damageReduction) this.startingDamageReduction = this.damageReduction
|
||||
this.damageReduction = 0
|
||||
@@ -3088,28 +3110,32 @@ const spawn = {
|
||||
if (this.seePlayer.yes && dist2 < 4000000) {
|
||||
const rangeWidth = 2000; //this is sqrt of 4000000 from above if()
|
||||
//targeting laser will slowly move from the mob to the player's position
|
||||
this.laserPos = Vector.add(this.laserPos, Vector.mult(Vector.sub(player.position, this.laserPos), 0.1));
|
||||
this.laserPos = Vector.add(this.laserPos, Vector.mult(Vector.sub(player.position, this.laserPos), 0.03));
|
||||
let targetDist = Vector.magnitude(Vector.sub(this.laserPos, m.pos));
|
||||
const r = 12;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.position.x, this.position.y);
|
||||
if (targetDist < r + 16) {
|
||||
targetDist = r + 10;
|
||||
//charge at player
|
||||
const forceMag = this.accelMag * 40 * this.mass;
|
||||
const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
|
||||
this.force.x += forceMag * Math.cos(angle);
|
||||
this.force.y += forceMag * Math.sin(angle);
|
||||
}
|
||||
// else {
|
||||
//high friction if can't lock onto player
|
||||
// Matter.Body.setVelocity(this, {
|
||||
// x: this.velocity.x * 0.98,
|
||||
// y: this.velocity.y * 0.98
|
||||
// });
|
||||
// }
|
||||
if (dist2 > 80000) {
|
||||
const laserWidth = 0.002;
|
||||
if (m.immuneCycle < m.cycle) {
|
||||
m.damage(0.0003 * simulation.dmgScale);
|
||||
if (m.energy > 0.1) m.energy -= 0.003
|
||||
}
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.position.x, this.position.y);
|
||||
ctx.lineTo(m.pos.x, m.pos.y);
|
||||
ctx.lineTo(m.pos.x + (Math.random() - 0.5) * 3000, m.pos.y + (Math.random() - 0.5) * 3000);
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = "rgb(0,0,255)";
|
||||
ctx.setLineDash([125 * Math.random(), 125 * Math.random()]);
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
ctx.beginPath();
|
||||
ctx.arc(m.pos.x, m.pos.y, 40, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = "rgba(0,0,255,0.1)";
|
||||
ctx.fill();
|
||||
} else {
|
||||
const laserWidth = 0.0005;
|
||||
let laserOffR = Vector.rotateAbout(this.laserPos, (targetDist - r) * laserWidth, this.position);
|
||||
let sub = Vector.normalise(Vector.sub(laserOffR, this.position));
|
||||
laserOffR = Vector.add(laserOffR, Vector.mult(sub, rangeWidth));
|
||||
@@ -3119,7 +3145,7 @@ const spawn = {
|
||||
sub = Vector.normalise(Vector.sub(laserOffL, this.position));
|
||||
laserOffL = Vector.add(laserOffL, Vector.mult(sub, rangeWidth));
|
||||
ctx.lineTo(laserOffL.x, laserOffL.y);
|
||||
ctx.fillStyle = `rgba(0,0,255,${Math.max(0, 0.3 * r / targetDist)})`
|
||||
ctx.fillStyle = `rgba(0,0,255,${Math.max(0, 0.6 * r / targetDist)})`
|
||||
ctx.fill();
|
||||
}
|
||||
} else {
|
||||
@@ -3127,6 +3153,69 @@ const spawn = {
|
||||
}
|
||||
}
|
||||
},
|
||||
// focuser(x, y, radius = 30 + Math.ceil(Math.random() * 10)) {
|
||||
// radius = Math.ceil(radius * 0.7);
|
||||
// mobs.spawn(x, y, 4, radius, "rgb(0,0,255)");
|
||||
// let me = mob[mob.length - 1];
|
||||
// Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001
|
||||
// me.restitution = 0;
|
||||
// me.laserPos = me.position; //required for laserTracking
|
||||
// me.repulsionRange = 1200000; //squared
|
||||
// me.accelMag = 0.00009 * simulation.accelScale;
|
||||
// me.frictionStatic = 0;
|
||||
// me.friction = 0;
|
||||
// me.onDamage = function () {
|
||||
// this.laserPos = this.position;
|
||||
// };
|
||||
// spawn.shield(me, x, y);
|
||||
// me.do = function () {
|
||||
// this.seePlayerByLookingAt();
|
||||
// this.checkStatus();
|
||||
// this.attraction();
|
||||
// const dist2 = this.distanceToPlayer2();
|
||||
// //laser Tracking
|
||||
// if (this.seePlayer.yes && dist2 < 4000000) {
|
||||
// const rangeWidth = 2000; //this is sqrt of 4000000 from above if()
|
||||
// //targeting laser will slowly move from the mob to the player's position
|
||||
// this.laserPos = Vector.add(this.laserPos, Vector.mult(Vector.sub(player.position, this.laserPos), 0.1));
|
||||
// let targetDist = Vector.magnitude(Vector.sub(this.laserPos, m.pos));
|
||||
// const r = 12;
|
||||
// ctx.beginPath();
|
||||
// ctx.moveTo(this.position.x, this.position.y);
|
||||
// if (targetDist < r + 16) {
|
||||
// targetDist = r + 10;
|
||||
// //charge at player
|
||||
// const forceMag = this.accelMag * 40 * this.mass;
|
||||
// const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
|
||||
// this.force.x += forceMag * Math.cos(angle);
|
||||
// this.force.y += forceMag * Math.sin(angle);
|
||||
// }
|
||||
// // else {
|
||||
// //high friction if can't lock onto player
|
||||
// // Matter.Body.setVelocity(this, {
|
||||
// // x: this.velocity.x * 0.98,
|
||||
// // y: this.velocity.y * 0.98
|
||||
// // });
|
||||
// // }
|
||||
// if (dist2 > 80000) {
|
||||
// const laserWidth = 0.002;
|
||||
// let laserOffR = Vector.rotateAbout(this.laserPos, (targetDist - r) * laserWidth, this.position);
|
||||
// let sub = Vector.normalise(Vector.sub(laserOffR, this.position));
|
||||
// laserOffR = Vector.add(laserOffR, Vector.mult(sub, rangeWidth));
|
||||
// ctx.lineTo(laserOffR.x, laserOffR.y);
|
||||
|
||||
// let laserOffL = Vector.rotateAbout(this.laserPos, (targetDist - r) * -laserWidth, this.position);
|
||||
// sub = Vector.normalise(Vector.sub(laserOffL, this.position));
|
||||
// laserOffL = Vector.add(laserOffL, Vector.mult(sub, rangeWidth));
|
||||
// ctx.lineTo(laserOffL.x, laserOffL.y);
|
||||
// ctx.fillStyle = `rgba(0,0,255,${Math.max(0, 0.3 * r / targetDist)})`
|
||||
// ctx.fill();
|
||||
// }
|
||||
// } else {
|
||||
// this.laserPos = this.position;
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
flutter(x, y, radius = 20 + 6 * Math.random()) {
|
||||
mobs.spawn(x, y, 7, radius, '#16576b');
|
||||
let me = mob[mob.length - 1];
|
||||
@@ -3850,13 +3939,13 @@ const spawn = {
|
||||
}
|
||||
me.frictionStatic = 0;
|
||||
me.friction = 0;
|
||||
me.memory = 240
|
||||
me.seePlayerFreq = 55
|
||||
me.memory = 900;
|
||||
me.seePlayerFreq = 41
|
||||
me.delay = 5 + 2 * simulation.CDScale;//8 + 3 * simulation.CDScale;
|
||||
me.nextBlinkCycle = me.delay;
|
||||
me.JumpDistance = 0//set in redMode()
|
||||
// spawn.shield(me, x, y, 1);
|
||||
me.collisionFilter.mask = cat.bullet | cat.map //| cat.body //cat.player |
|
||||
me.collisionFilter.mask = cat.bullet | cat.map | cat.body //cat.player |
|
||||
me.powerUpNames = []
|
||||
me.redMode = function () {
|
||||
this.color = `rgba(255,0,200,`
|
||||
@@ -3895,7 +3984,7 @@ const spawn = {
|
||||
if (this.health < this.nextHealthThreshold) {
|
||||
this.health = this.nextHealthThreshold - 0.01
|
||||
this.nextHealthThreshold = Math.floor(this.health * 4) / 4 //0.75,0.5,0.25
|
||||
this.invulnerableCount = 300
|
||||
this.invulnerableCount = 240
|
||||
this.isInvulnerable = true
|
||||
this.damageReduction = 0
|
||||
if (this.history.length < 200) for (let i = 0; i < 11; i++) this.history.unshift(this.history[0])
|
||||
@@ -4011,21 +4100,18 @@ const spawn = {
|
||||
move()
|
||||
} else if (this.seePlayer.recall) { //chase player's history
|
||||
this.lostPlayer();
|
||||
if (!m.isCloak) {
|
||||
for (let i = 0; i < 50; i++) { //if lost player lock onto a player location in history
|
||||
if (m.isCloak) {
|
||||
move(this.seePlayer.position) //go after where you last saw the player
|
||||
} else {
|
||||
for (let i = 0; i < 55; i++) { //if lost player lock onto a player location in history
|
||||
let history = m.history[(m.cycle - 10 * i) % 600]
|
||||
if (Matter.Query.ray(map, this.position, history.position).length === 0) {
|
||||
this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //cycles before mob falls a sleep
|
||||
this.seePlayer.position.x = history.position.x;
|
||||
this.seePlayer.position.y = history.position.y;
|
||||
this.seePlayer.yes = true;
|
||||
move()
|
||||
move(history.position) //go after where you last saw the player
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
this.checkStatus();
|
||||
if (this.isInvulnerable) {
|
||||
@@ -4099,7 +4185,7 @@ const spawn = {
|
||||
me.fire = function () {
|
||||
// this.armor();
|
||||
this.checkStatus();
|
||||
if (!m.isCloak && !this.isStunned) {
|
||||
if (!this.isStunned) {
|
||||
if (this.isFiring) {
|
||||
if (this.fireCycle > this.fireDelay) { //fire
|
||||
this.isFiring = false
|
||||
@@ -4150,7 +4236,9 @@ const spawn = {
|
||||
}
|
||||
} else { //aim at player
|
||||
this.fireCycle++
|
||||
this.fireDir = Vector.normalise(Vector.sub(m.pos, this.position)); //set direction to turn to fire
|
||||
//if cloaked, aim at player's history from 3 seconds ago
|
||||
const whereIsPlayer = m.isCloak ? m.history[(m.cycle - 180) % 600].position : m.pos
|
||||
this.fireDir = Vector.normalise(Vector.sub(whereIsPlayer, this.position)); //set direction to turn to fire
|
||||
//rotate towards fireAngle
|
||||
const angle = this.angle + Math.PI / 2;
|
||||
const c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
|
||||
@@ -4162,7 +4250,7 @@ const spawn = {
|
||||
} else if (this.fireCycle > 45) { //fire
|
||||
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
|
||||
this.fireTarget = Vector.add(this.vertices[1], unit)
|
||||
if (Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur
|
||||
if (Vector.magnitude(Vector.sub(whereIsPlayer, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur
|
||||
Matter.Body.setAngularVelocity(this, 0)
|
||||
this.fireLockCount = 0
|
||||
this.isFiring = true
|
||||
@@ -4206,7 +4294,7 @@ const spawn = {
|
||||
}, Vector.normalise(Vector.sub(this.fireTarget, this.position)));
|
||||
//distance between the target and the player's location
|
||||
if (
|
||||
m.isCloak ||
|
||||
// m.isCloak ||
|
||||
dot > 0.03 || // not looking at target
|
||||
Matter.Query.ray(map, this.fireTarget, this.position).length || Matter.Query.ray(body, this.fireTarget, this.position).length || //something blocking line of sight
|
||||
Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) > 1000 // distance from player to target is very far, (this is because dot product can't tell if facing 180 degrees away)
|
||||
@@ -4638,10 +4726,11 @@ const spawn = {
|
||||
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
|
||||
me.accelMag = 0.0001 * simulation.accelScale;
|
||||
me.laserInterval = 100
|
||||
Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
spawn.shield(me, x, y);
|
||||
me.onHit = function () {
|
||||
//run this function on hitting player
|
||||
this.explode();
|
||||
// this.explode();
|
||||
};
|
||||
me.do = function () {
|
||||
this.torque = this.lookTorque * this.inertia * 0.5;
|
||||
@@ -4985,7 +5074,7 @@ const spawn = {
|
||||
me.laserSword = function (where, angle, length) {
|
||||
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
|
||||
const look = { x: where.x + length * Math.cos(angle), y: where.y + length * Math.sin(angle) };
|
||||
best = vertexCollision(where, look, m.isCloak ? [map] : [map, [playerBody, playerHead]]);
|
||||
best = vertexCollision(where, look, [map, [playerBody, playerHead]]);
|
||||
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
|
||||
m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for an extra second
|
||||
m.damage(this.swordDamage);
|
||||
@@ -5592,7 +5681,7 @@ const spawn = {
|
||||
|
||||
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
|
||||
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
|
||||
best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
|
||||
best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
|
||||
|
||||
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
|
||||
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
|
||||
@@ -5691,7 +5780,7 @@ const spawn = {
|
||||
me.laserSword = function (where, angle) {
|
||||
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
|
||||
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
|
||||
best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
|
||||
best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
|
||||
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
|
||||
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
|
||||
m.damage(this.swordDamage);
|
||||
@@ -5783,7 +5872,7 @@ const spawn = {
|
||||
me.laserSword = function (where, angle) {
|
||||
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
|
||||
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
|
||||
best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
|
||||
best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
|
||||
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
|
||||
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
|
||||
m.damage(this.swordDamage);
|
||||
@@ -5893,7 +5982,7 @@ const spawn = {
|
||||
me.laserSpear = function (where, angle) {
|
||||
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
|
||||
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
|
||||
best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
|
||||
best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
|
||||
|
||||
if (best.who && (best.who === playerBody || best.who === playerHead)) {
|
||||
this.swordRadiusGrowRate = 1 / this.swordRadiusGrowRateInitial //!!!! this retracts the sword if it hits the player
|
||||
@@ -5954,7 +6043,7 @@ const spawn = {
|
||||
simulation.drawList.push({
|
||||
x: this.position.x,
|
||||
y: this.position.y,
|
||||
radius: 3000,
|
||||
radius: 5000,
|
||||
color: `rgba(0, 0, 0,${1 - 0.1 * i})`,
|
||||
time: (i + 2) * 4
|
||||
});
|
||||
@@ -6109,9 +6198,9 @@ const spawn = {
|
||||
mobs.spawn(x, y, 7, radius, "transparent");
|
||||
let me = mob[mob.length - 1];
|
||||
me.seeAtDistance2 = 500000;
|
||||
me.accelMag = 0.00007 + 0.0001 * simulation.accelScale;
|
||||
me.accelMag = 0.0002 + 0.0001 * simulation.accelScale;
|
||||
if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
|
||||
Matter.Body.setDensity(me, 0.0002); //normal is 0.001
|
||||
Matter.Body.setDensity(me, 0.00015); //normal is 0.001
|
||||
me.damageReduction = 0.1
|
||||
me.stroke = "transparent"; //used for drawGhost
|
||||
me.alpha = 1; //used in drawGhost
|
||||
@@ -6151,7 +6240,7 @@ const spawn = {
|
||||
if (this.health < 0.8) me.seeAtDistance2 = 2000000;
|
||||
}
|
||||
me.do = function () {
|
||||
if (this.speed > 7) Matter.Body.setVelocity(this, { x: this.velocity.x * 0.8, y: this.velocity.y * 0.8 }); //cap max speed to avoid getting launched by deflection, explosion
|
||||
if (this.speed > 6) Matter.Body.setVelocity(this, { x: this.velocity.x * 0.8, y: this.velocity.y * 0.8 }); //cap max speed to avoid getting launched by deflection, explosion
|
||||
this.seePlayerCheckByDistance();
|
||||
this.checkStatus();
|
||||
this.attraction();
|
||||
@@ -6251,7 +6340,7 @@ const spawn = {
|
||||
me.friction = 0;
|
||||
me.frictionAir = 0.01;
|
||||
me.memory = Infinity;
|
||||
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
|
||||
me.collisionFilter.mask = cat.player | cat.bullet | cat.body
|
||||
spawn.shield(me, x, y, 1);
|
||||
|
||||
const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty)))
|
||||
@@ -7144,6 +7233,7 @@ const spawn = {
|
||||
me.do = function () {
|
||||
this.seePlayerByHistory(60);
|
||||
this.attraction();
|
||||
if (this.distanceToPlayer2() > 9000000) this.attraction(); //extra attraction if far away
|
||||
this.checkStatus();
|
||||
this.eventHorizon = 950 + 250 * Math.sin(simulation.cycle * 0.005)
|
||||
if (!simulation.isTimeSkipping) {
|
||||
@@ -7355,13 +7445,27 @@ const spawn = {
|
||||
exploder(x, y, radius = 40 + Math.ceil(Math.random() * 50)) {
|
||||
mobs.spawn(x, y, 4, radius, "rgb(255,0,0)");
|
||||
let me = mob[mob.length - 1];
|
||||
Matter.Body.setDensity(me, 0.0013); //normal is 0.001
|
||||
me.onHit = function () {
|
||||
//run this function on hitting player
|
||||
this.explode();
|
||||
this.explode(2.5 * this.mass);
|
||||
};
|
||||
me.g = 0.0004; //required if using this.gravity
|
||||
spawn.shield(me, x, y);
|
||||
// spawn.shield(me, x, y);
|
||||
me.do = function () {
|
||||
//draw aura
|
||||
ctx.beginPath();
|
||||
const vertices = this.vertices;
|
||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||
for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||
ctx.strokeStyle = `rgba(255,0,50,${0.13 + 0.45 * Math.random()})`
|
||||
ctx.lineWidth = 30
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = "rgba(255,0,50,0.1)"
|
||||
ctx.lineWidth = 70
|
||||
ctx.stroke();
|
||||
|
||||
this.gravity();
|
||||
this.seePlayerCheck();
|
||||
this.checkStatus();
|
||||
|
||||
679
js/tech.js
101
style.css
@@ -9,6 +9,7 @@ body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
cursor: auto;
|
||||
background-color: #f00;
|
||||
/* filter: grayscale(1); */
|
||||
/* transition: background-color 0.2s ease-in-out; */
|
||||
}
|
||||
@@ -124,21 +125,45 @@ summary {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.SVG-button-splash {
|
||||
border: 2px #333 solid;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
transition: opacity 5s ease-in;
|
||||
}
|
||||
|
||||
.SVG-button-splash:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#start-button {
|
||||
position: absolute;
|
||||
bottom: 108px;
|
||||
right: 4px;
|
||||
z-index: 12;
|
||||
/* top-left | top-right | bottom-right | bottom-left */
|
||||
/* border-radius: 8px 8px 0 0; */
|
||||
}
|
||||
|
||||
#training-button {
|
||||
position: absolute;
|
||||
bottom: 56px;
|
||||
right: 4px;
|
||||
z-index: 12;
|
||||
/* border-radius: 8px 0px 0 0; */
|
||||
}
|
||||
|
||||
#experiment-button {
|
||||
position: absolute;
|
||||
bottom: 4px;
|
||||
right: 4px;
|
||||
z-index: 12;
|
||||
transition: opacity 5s ease-in;
|
||||
/* border-radius: 8px 0 8px 8px; */
|
||||
}
|
||||
|
||||
#training-button {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
z-index: 12;
|
||||
transition: opacity 5s ease-in;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#construct {
|
||||
display: none;
|
||||
@@ -567,9 +592,10 @@ summary {
|
||||
position: absolute;
|
||||
bottom: 3px;
|
||||
left: 3px;
|
||||
z-index: 12;
|
||||
z-index: 10;
|
||||
font-size: 1.5em;
|
||||
transition: opacity 5s ease-in;
|
||||
width: 100%;
|
||||
|
||||
/* border: 1.5px #333 solid; */
|
||||
/* border-radius: 8px; */
|
||||
@@ -721,6 +747,18 @@ summary {
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.constraint-module {
|
||||
line-height: 160%;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
font-size: 1.2em;
|
||||
font-family: monospace;
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
color: #624;
|
||||
background-color: rgba(255, 240, 250, 1);
|
||||
}
|
||||
|
||||
#right-HUD-constraint {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
@@ -743,6 +781,39 @@ summary {
|
||||
transition: all 0.5s linear;
|
||||
}
|
||||
|
||||
.constraint {
|
||||
color: rgb(141, 23, 88);
|
||||
}
|
||||
|
||||
.metallic-sparkle {
|
||||
background: linear-gradient(90deg,
|
||||
#c38aa6,
|
||||
#e6c0d9,
|
||||
#dca4c6,
|
||||
#c38aa6,
|
||||
#e6c0d9,
|
||||
#dca4c6,
|
||||
#c38aa6);
|
||||
background-size: 200% 100%;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
animation: shimmer 4s infinite linear;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
#text-log {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
@@ -758,12 +829,6 @@ summary {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.constraint {
|
||||
color: rgb(141, 23, 88);
|
||||
/* font-weight: 100; */
|
||||
/* text-decoration: underline; */
|
||||
}
|
||||
|
||||
.color-text {
|
||||
color: #000;
|
||||
}
|
||||
@@ -1543,9 +1608,9 @@ summary {
|
||||
}
|
||||
|
||||
.draw-lines4 {
|
||||
stroke-dasharray: 300;
|
||||
stroke-dashoffset: 300;
|
||||
animation: dash 2.5s ease-in forwards;
|
||||
stroke-dasharray: 500;
|
||||
stroke-dashoffset: 500;
|
||||
animation: dash 3.5s ease-in forwards;
|
||||
}
|
||||
|
||||
|
||||
|
||||
278
todo.txt
@@ -1,85 +1,116 @@
|
||||
******************************************************** NEXT PATCH **************************************************
|
||||
|
||||
tech: Halbach array - throwing a block will also throw other nearby blocks
|
||||
pilot wave tech: Bells theorem - field is always on for no energy cost
|
||||
pilot wave tech: principle of locality - 0.9x damage taken while inside pilot wave field, -2 choices
|
||||
|
||||
tech non-renewables now spawns ammo, but ammo can't be picked up
|
||||
grenade tech that cause multiple explosions have less knock back for mobs
|
||||
constraint: 0->0.5x healing
|
||||
wormhole 7->8% duplication
|
||||
many worlds takes a few frames between each tech given
|
||||
hidden-variable theory 1.2->1.3 damage per field tech
|
||||
WIMPS spawn 4->5 research per level
|
||||
|
||||
bug fixes
|
||||
harpoon ammo gain on autonomous defense fixed
|
||||
constraints are properly randomized again
|
||||
fixed exploit with final tech power up on subway level
|
||||
|
||||
|
||||
******************************************************** BUGS ********************************************************
|
||||
|
||||
couple reports of crashes from many-worlds
|
||||
around level 5-7
|
||||
for me crash on factory level 7
|
||||
might be linked to having all the guns?
|
||||
the crash was in matter.js something about collisions and undefined
|
||||
maybe too many things were spawned in the same spot?
|
||||
also occurs when you just gain many random tech in testing mode
|
||||
|
||||
figure out why seeded random isn't making runs the same:
|
||||
shuffle is being used for a wide variety of things that don't need a seeded random
|
||||
make two shuffle functions?
|
||||
check which of these is working
|
||||
level order
|
||||
is flipped
|
||||
constraint order
|
||||
mob type order
|
||||
boss order
|
||||
gun, field, tech options
|
||||
make field options offered precalculated so it doesn't depend on player choices?
|
||||
generate all constraints at the start of the game
|
||||
doesn't seem to be determined by the seed...
|
||||
display future constraints in pause menu?
|
||||
|
||||
at start of level game go stuck in pause state
|
||||
no crash or bug report
|
||||
occur level 8
|
||||
after 2 levels of sending power ups to next level
|
||||
auto drones grabbed a power up and game froze while in power up mode
|
||||
running code to exit pause kinda worked
|
||||
|
||||
ants marching outline on splash screen doesn't sync right on safari
|
||||
|
||||
player can become crouched while not touching the ground if they exit the ground while crouched
|
||||
graphical bug - player can become crouched while not touching the ground if they exit the ground while crouched
|
||||
|
||||
*********************************************************** TODO *****************************************************
|
||||
|
||||
make a text orb for JUNK text to make JUNK more clear
|
||||
tech - benefit if you haven't killed any mobs on this level
|
||||
have to clean up mobs that die on level spawn from falling blocks
|
||||
tech - benefit in the first 20 seconds of the level
|
||||
|
||||
extended vertical flip to edge cases:
|
||||
!!stored circular graphics simulation.drawList.push
|
||||
plasma globe - it should not explode on map contact, but instead shrink?
|
||||
only explode on mouse release
|
||||
use pilot wave code?
|
||||
|
||||
new level based laser element
|
||||
!!update new version into other levels
|
||||
rework JUNK
|
||||
example: +5 JUNK adds a frequency of (1? 6?) to a random JUNK tech
|
||||
if you see that JUNK tech again it's frequency drops down to 0 again
|
||||
have to rework constraints and a few other tech...
|
||||
|
||||
mob - moves around, but then stops and makes porcupine spikes for 2 seconds, then moves again.
|
||||
maybe use hopper movement?
|
||||
|
||||
soft body boss?
|
||||
search softBody(x, y, angle = 0, isAttached = true, len = 15, radius = 20, stiffness = 1, damping = 1) {
|
||||
|
||||
use ←↑→↓↖↗↘↙ combos to allow fields to have special actions
|
||||
how to limit spam?
|
||||
on cooldown
|
||||
timer or once per level
|
||||
energy cost
|
||||
research cost
|
||||
toggle modes
|
||||
combos are listed in white text in field description, and console message when getting field
|
||||
shows up on highlight, and mouse over in experiment mode
|
||||
field ideas:
|
||||
standing wave
|
||||
push mobs away are any distance
|
||||
pull mobs towards you
|
||||
perfect diamagnetism
|
||||
negative mass
|
||||
molecular assembler - done
|
||||
plasma torch
|
||||
move around like you have recoil, move kinda fast so it's hard to control
|
||||
like form recoil but fast
|
||||
time dilation
|
||||
metamaterial cloaking
|
||||
pilot wave - done
|
||||
wormhole
|
||||
toggle bullets entering with wormholes
|
||||
and player??
|
||||
shoot out all the blocks that were sucked in this level (maybe cap at like 10?, cap with energy spent to fire)
|
||||
are block sizes stored properly? because they shrink before they get eaten...
|
||||
store vertices on the body object if one does already exists
|
||||
after eating store the saved vertices
|
||||
where to fire blocks from and in what direction?
|
||||
target mobs?
|
||||
fire from player (and draw a wormhole looking graphic)
|
||||
grappling hook
|
||||
|
||||
new level idea: large map sized blocks that can't be destroyed that the player walks on as a part of the level
|
||||
eventually the blocks fall
|
||||
after fall level progresses to a phase 2 to clean up the blocks or leave them
|
||||
should bosses be killed by falling blocks??
|
||||
how to avoid the large block vibrating/dancing on tiny block issue
|
||||
|
||||
new level idea: escort mission
|
||||
player has to stay near something that moves slowly through the level
|
||||
maybe only a zone around the escort is safe
|
||||
safe from?
|
||||
lasers
|
||||
slime
|
||||
radiation
|
||||
use line of site vision?
|
||||
is it going to feel too slow?
|
||||
where to put in level order?
|
||||
random option instead of reactor?
|
||||
normal level?
|
||||
4th hard level?
|
||||
already too many hard options
|
||||
you could put in 2 hard levels in the level list
|
||||
make the style look like substructure, that level looks great
|
||||
use the motion sense lasers
|
||||
|
||||
|
||||
tech: - remove the research costs of all tech
|
||||
there's about 15 tech with a research cost
|
||||
!!conformal - similar rules for small and big scales linked to holographic principle
|
||||
!!holonomy - parallel transport of a vector leads to movement (applies to curved space)
|
||||
when far away from your wormhole regenerate 1% of your max energy per second
|
||||
when far away from your wormhole reduce damage taken
|
||||
heal last hit damage after enter wormhole
|
||||
!!quasar - plasma torch from both ends of wormhole
|
||||
only after wormhole eats a block fire?
|
||||
or just increase plasma length after eating block?
|
||||
|
||||
procedural animation
|
||||
https://www.youtube.com/watch?v=qlfh_rv6khY
|
||||
|
||||
not implemented random constraint ideas________________________
|
||||
mob death spawns something
|
||||
mob bullets
|
||||
bosses heals nearby mobs
|
||||
ammo power ups give 0.7x ammo
|
||||
2x research costs
|
||||
mobs slowly regen health
|
||||
exit door takes 10x time to open,
|
||||
and while door is opening (ghosters, suckers) attack?
|
||||
can't have more then 15 bullets
|
||||
how to code?
|
||||
remove 2 random tech and return them next level
|
||||
|
||||
tech: ice-VII - 1.5x duration for ice-IX
|
||||
|
||||
tech: - freezing grenades/explosions
|
||||
|
||||
tech: - when you get a bot, get a second bot
|
||||
|
||||
tech: - after killing a Boss
|
||||
heal to full
|
||||
gain 3x damage for the rest of the level
|
||||
@@ -117,12 +148,6 @@ tech: atomic pile - lose 1 health if you are above the maximum energy
|
||||
do damage?
|
||||
plasma torch tech?
|
||||
|
||||
figure out how to put instructions for controls in background on initial level
|
||||
mouse smooth makes the text position jitter when it moves sub pixels
|
||||
hide the jitter with artificial jitter to make it seem intentional
|
||||
make it look like the instructions are on a fuzzy TV screen
|
||||
when player presses move buttons highlight the box/letter for those buttons
|
||||
|
||||
make player mass an adjustable var in the skin
|
||||
does this mess with jump height or air control?
|
||||
increase mass and movement speed at the same time
|
||||
@@ -132,10 +157,6 @@ increase mass and movement speed at the same time
|
||||
possible player.mass bad interactions
|
||||
grapple
|
||||
|
||||
rework energy and health HUD
|
||||
make both diegetic?
|
||||
how? not sure there is a good way to do this...
|
||||
|
||||
tech - after a power up is duplicated
|
||||
update text to random effect after choosing tech, or after each trigger, or on first display of tech
|
||||
pick 1 effect at random
|
||||
@@ -143,7 +164,7 @@ tech - after a power up is duplicated
|
||||
summon JUNK bots for 10 seconds
|
||||
2x current energy
|
||||
gain 1.01x damage permanently
|
||||
cool name:
|
||||
cool name:
|
||||
|
||||
after picking up heals gain ____
|
||||
0.1x damage taken for 12s
|
||||
@@ -159,43 +180,9 @@ tech - getting caught in an explosion gives you _____
|
||||
damage for 10 seconds?
|
||||
heals
|
||||
|
||||
tech - limit total number of tech to like 10?
|
||||
|
||||
tech - destroying blocks gives _____
|
||||
|
||||
removeJunkTechFromPool doesn't seem to remove the correct amount
|
||||
|
||||
wormholes that end inside wall check to see if the space before the wall is safe and end there instead
|
||||
can use laser code
|
||||
|
||||
tech: - (1 + 0.01)x for each tech, gun, field you've picked up
|
||||
scales with born rule, duplication, remove tech
|
||||
|
||||
explosions have a chance to spawn spores
|
||||
infinite feedback loop with spores that explode?
|
||||
|
||||
make sure healing isn't effected by simulation.healScale
|
||||
instead heal orb size should be scaled
|
||||
but the ratio between size and heal shouldn't be effected
|
||||
|
||||
boss - tracks the position, velocity, angle of power ups, blocks, and bullets it fires
|
||||
reactor only?
|
||||
will rewind time
|
||||
after damage threshold?
|
||||
does it track player bullets?
|
||||
|
||||
button/switch input ideas from Cocoon game
|
||||
pick up blocks that have a rubber band attached to a sliding switch
|
||||
as player moves the vector direction of the rubber band will move the slider left or right
|
||||
use this to open doors, move larger blocks, ...
|
||||
switches that toggle left, right when player presses input.field while standing nearby
|
||||
replace laser off on switch?
|
||||
platform that rises up when player presses input.field while standing
|
||||
How to instruct player to use field on these?
|
||||
color with field #0ff
|
||||
draw field effect
|
||||
make it still functional without the field button
|
||||
|
||||
tech - getting a new gun also gives you 2 random tech for that gun
|
||||
or a field?
|
||||
can these guntech tech be converted into a player choice?
|
||||
@@ -219,6 +206,31 @@ improve new player experience
|
||||
When foam is in an explosion it also explodes with size proportional to the size of the foam bubble
|
||||
Requires foam, explosion source, not aerogel
|
||||
|
||||
new level similar to ash tray maze
|
||||
!!not sure how this works with theme (most levels are locations that have industrial stuff)
|
||||
this might work as another line of sight level?
|
||||
could be fine without line of sight if rooms don't exist until they open up?
|
||||
where to put in game sequence?
|
||||
watch a run through https://www.youtube.com/watch?v=nudSXUMBEV4
|
||||
close off doors as player gets close
|
||||
open up doors as player gets close
|
||||
holes in the floor
|
||||
slide large walls back to open up levels below
|
||||
show a zone, then close it off, but eventually reveal it later
|
||||
rise up pillars during combat
|
||||
small maze rooms, 1-2 really huge rooms, long corridors, medium combat rooms
|
||||
triggers for changes
|
||||
clearing mobs in a zone
|
||||
or time based if player is too slow
|
||||
player gets close to a zone
|
||||
make map elements shift around as player moves through the game
|
||||
start with map elements filling everywhere and slow open up new zones
|
||||
need a cool way to animate adding and removing map elements
|
||||
maybe for the entire level redraw the map every 15 cycles?
|
||||
simulation.draw.setPaths() //update map graphics
|
||||
slide map around
|
||||
small map squares that each add in sequentially
|
||||
|
||||
Cosmological natural selection: do something with black holes
|
||||
spawn black hole mobs
|
||||
after bosses die?
|
||||
@@ -341,16 +353,6 @@ make a lemming that walks until it hits a wall and then turns around robotically
|
||||
body or mob?
|
||||
can't be killed?
|
||||
|
||||
use ephemera to replace some bad code
|
||||
JUNK?
|
||||
request animation stuff
|
||||
simulation checks
|
||||
damage and defense bars
|
||||
disable and enable ephemera with settings
|
||||
|
||||
perfect diamagnatism - invulnerable while field is active?
|
||||
also drain energy while field is active?
|
||||
|
||||
mobs attack mines
|
||||
mines periodically set all mobs to have player location to be the mine
|
||||
is this going to work with all mob vision types?
|
||||
@@ -364,23 +366,8 @@ Tech: relativity
|
||||
wormhole tech - teleport away mobs with mass below 3 when they get too near the player
|
||||
short CD, small energy cost, only mobs below a mass
|
||||
|
||||
extend brainstorming animation timers to fps cap?
|
||||
will it be smoother or choppier?
|
||||
anything else needs to hit limited fps on a high fps monitor?
|
||||
|
||||
perfect diamagnatism could bounce on mobs, or even map elements?
|
||||
could work like a rocket jump?
|
||||
|
||||
tech: Bose Einstein condensate - freezes enemies in pilot wave, and drains some energy?
|
||||
|
||||
make super balls with Zectron deflectable with field
|
||||
but is there a simple way to do this?
|
||||
|
||||
set mob health bar colors based on status effects?
|
||||
make mob damage immunity a mob status effect?
|
||||
|
||||
tech: rail gun area damage effect, but for all harpoon mode
|
||||
|
||||
mob status effect - vulnerability
|
||||
mobs take 4x damage for __ time
|
||||
afterwards mobs go back to normal damage taken
|
||||
@@ -839,9 +826,6 @@ mob/boss that fires a laser at player, but give player time to avoid
|
||||
they target where player was 1 second ago
|
||||
they turn to face player?
|
||||
|
||||
tech rocket jump - jumping produces an explosion at your feet that lets you jump extra high, but does some damage
|
||||
require electric reactive armor?
|
||||
|
||||
Plasma Burner: upgrade for plasma torch, basically just a jet engine. does high damage, but short range, mostly for player movement.
|
||||
maybe reduce gravity to really low then apply a vector away from mouse direction
|
||||
|
||||
@@ -851,17 +835,6 @@ auto-gon - auto battler with n-gon mob AI and tech
|
||||
similar research and tech system to n-gon
|
||||
some mobs can fire player weapons
|
||||
|
||||
tech: relativistic jets:
|
||||
small particles that shot out from front and back poles and end up in a wide variety of spirals
|
||||
slow trickle when charging and several more when firing
|
||||
|
||||
Tech: Make player smol
|
||||
|
||||
adapt the cloaking graphics to make a flashlight cone visual effect
|
||||
put code in level.do?
|
||||
|
||||
be nice if block throwing had a projected path
|
||||
|
||||
Pilot wave tech
|
||||
Energy use is increased, but you can now shape blocks using pressure
|
||||
Grouping blocks will merge them into a massive ball
|
||||
@@ -1234,11 +1207,8 @@ look up sci-fi science ideas here https://projectrho.com/public_html/rocket/
|
||||
|
||||
possible names for tech
|
||||
sidereal - with respect to the stars (an extra rotation for time keeping)
|
||||
holonomy - parallel transport of a vector leads to movement (applies to curved space)
|
||||
holographic - 2-D surface can predict the 3-D space behind it? I think
|
||||
entropic gravity - gravity is emergent in a holographic way
|
||||
(maybe a field tech for negative mass)
|
||||
conformal - similar rules for small and big scales linked to holographic principle
|
||||
hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other.
|
||||
swarm intelligence - for a drone tech
|
||||
metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity
|
||||
@@ -1292,7 +1262,6 @@ possible names for tech
|
||||
amalgam, amalgamation - the action, process, or result of combining or uniting.
|
||||
thermoplastic - the stuff in 3-D printers, use for molecular assembler tech
|
||||
ergosphere - region of a spinning black hole that might allow FTL or alternate realities.
|
||||
equivalence principle - gravity and acceleration are the same
|
||||
Casimir effect - attractive force between two close conductive plates
|
||||
difference engine - early calculator/computer
|
||||
cyanoacrylate - superglue use for a slowing effect?
|
||||
@@ -1307,8 +1276,13 @@ possible names for tech
|
||||
cork - used as a heat shield for rockets
|
||||
P = NP - something with speeding up calculation times
|
||||
transistivity - something where a>b and b>c -> a>c
|
||||
lenticular - looks different from different angles (lasers?)
|
||||
lenticular - looks different from different angles (lasers?, cloaking?)
|
||||
every few seconds pick a random skin tech?
|
||||
De Sitter space - simple model of universe related to general relativity (mass-energy?)
|
||||
active optics - something with lasers? maybe something with diffuse beam getting smaller
|
||||
Quintessence - related to dark energy
|
||||
biofilm - something defensive? related to spores?
|
||||
Thermogalvanic - makes things cold, for no energy
|
||||
|
||||
******************************************************* DESIGN ******************************************************
|
||||
|
||||
@@ -1332,4 +1306,4 @@ list of powerful synergies
|
||||
interest + coupling, research + (peer review? or Bayesian statistics)
|
||||
electronegativity and high energy?
|
||||
electronegativity + anyon + duplication + Maxwells demon + interest + pair production
|
||||
chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level
|
||||
chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level
|
||||