diff --git a/index.html b/index.html
index 8086413..099c076 100644
--- a/index.html
+++ b/index.html
@@ -77,25 +77,6 @@
banned levels:
- classic n-gon:
-
- mech: 2014
- spacetime: 2015
- ballistics: 2015
- portal: 2016
- side scroller: 2016
- side scroller: 2016
- LandGame: 2017
- n-gon: 2018
- n-gon: summer-2019
- n-gon: fall-2019
- n-gon: summer-2020
- n-gon: spring-2021
- n-gon: fall-2022
- n-gon: summer-2024
- current version
-
-
randomization seed:
@@ -179,16 +160,70 @@
about
-
- 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
Github .
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+ 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 Github .
+ This is just my hobby project, but I try to fix bugs when reported .
+
+
+
+ classic n-gon:
+
+ mech: 2014
+ spacetime: 2015
+ ballistics: 2015
+ portal: 2016
+ side scroller: 2016
+ side scroller: 2016
+ LandGame: 2017
+ n-gon: 2018
+ n-gon: summer-2019
+ n-gon: fall-2019
+ n-gon: summer-2020
+ n-gon: spring-2021
+ n-gon: fall-2022
+ n-gon: summer-2024
+ old versions
+
+ community links:
+
+ n-commit loader
+ n-gon upgraded
+ n-gon enhanced
+ c-gon
+ n-gon portal gun
+ n-scythe
+ n-mobile
+ n-controller
+ n-stopwatch
+ n-qol
+ n-treasury
+ n-docs
+ n-wiki fandom
+ n-wiki n-gon
+ mods, forks, info
+
+
@@ -230,8 +265,9 @@
-
+
+
diff --git a/js/bullet.js b/js/bullet.js
index 80c0d09..dcca903 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -280,8 +280,8 @@ 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
},
@@ -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
},
@@ -2972,11 +2830,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;
@@ -3810,165 +3663,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 +3718,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 +3761,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 +3787,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;
@@ -4417,8 +4099,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
@@ -5928,8 +5610,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) {
@@ -6201,8 +5883,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) {
@@ -6333,8 +6015,8 @@ const b = {
return `emit wave packets that propagate through solids waves slow mobs${this.ammoPack.toFixed(0)} wave packets per ${powerUps.orb.ammo()}`
},
ammo: 0,
- ammoPack: 52,
- defaultAmmoPack: 52,
+ ammoPack: 60,
+ defaultAmmoPack: 60,
have: false,
wavePacketCycle: 0,
delay: 40,
@@ -6655,12 +6337,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
@@ -7083,10 +6765,13 @@ 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)
+ // this.applyKnock(velocity)
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
},
doCharges() {
@@ -7105,15 +6790,15 @@ 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),
y: m.pos.y + 30 * Math.sin(m.angle)
}
b.foam(position, Vector.rotate(velocity, spread), radius)
- this.applyKnock(velocity)
+ // this.applyKnock(velocity)
this.charge -= 0.75
m.fireCDcycle = m.cycle + 2; //disable firing and adding more charge until empty
} else if (!input.fire) {
@@ -7135,31 +6820,13 @@ 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)
+ // this.applyKnock(velocity)
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
this.charge += 1 + tech.isCapacitor
},
diff --git a/js/index.js b/js/index.js
index 59f6379..ec4aaa9 100644
--- a/js/index.js
+++ b/js/index.js
@@ -643,7 +643,7 @@ ${simulation.difficultyMode > 4 ? ` { document.getElementById("sort-input").focus(); });
+ // requestAnimationFrame(() => { document.getElementById("sort-input").focus(); });
},
sortTech(find, isExperiment = false) {
const sortKeyword = (a, b) => {
@@ -730,6 +730,8 @@ ${simulation.difficultyMode > 4 ? `${powerUps.orb.fieldTech()}
damage
dmg taken
- heal
- energy
+ heal
+ energy
sort
@@ -1416,11 +1418,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()
@@ -1542,7 +1546,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);
diff --git a/js/level.js b/js/level.js
index 90a790f..1308368 100644
--- a/js/level.js
+++ b/js/level.js
@@ -10,7 +10,7 @@ const level = {
levelsCleared: 0,
isFlipped: false,
uniqueLevels: ["initial", "reservoir", "factory", "interferometer", "reactor", "subway", "final"], //see level.populateLevels: (initial, ... , (reservoir, factory, or interferometer), reactor, ... , subway, final) added later
- playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers", "flocculation", "gravitron", "substructure"],
+ playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers", "flocculation", "gravitron", "substructure", "corridor"],
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo", "arena", "soft", "flappyGon", "rings", "trial"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [],
@@ -23,7 +23,7 @@ const level = {
// level.levelsCleared = 10
// level.updateDifficulty()
// tech.giveTech("performance")
- // m.maxHealth = m.health = 1//00000000
+ // m.maxHealth = m.health = 100000000
// m.maxEnergy = m.energy = 10000000
// tech.isRerollDamage = true
// powerUps.research.changeRerolls(99999)
@@ -48,24 +48,24 @@ const level = {
// requestAnimationFrame(() => { tech.giveTech("non-renewables") });
// tech.giveTech("dark matter")
// tech.addJunkTechToPool(0.5)
- // for (let i = 0; i < 1; ++i) tech.giveTech("nail-bot")
- // for (let i = 0; i < 1; ++i) tech.giveTech("quantum immortality")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("pigeonhole principle")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("generalist")
// m.skin.egg();
// for (let i = 0; i < 1; ++i) tech.giveTech("many-worlds")
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("quasiparticles") });
- // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("field coupling") });
+ // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("interest") });
// for (let i = 0; i < 1; i++) tech.giveTech("interest")
// m.lastKillCycle = m.cycle
// for (let i = 0; i < 1; i++) powerUps.directSpawn(450, -50, "warp");
// for (let i = 0; i < 7; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 250, "research", false);
// spawn.bodyRect(575, -700, 150, 150); //block mob line of site on testing
- // level.cocoon();
+ // level.corridor();
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
- // for (let i = 0; i < 1; ++i) spawn.shieldingBoss(1900, -500)
+ // for (let i = 0; i < 1; ++i) spawn.powerUpBossBaby(1900, -500)
// for (let i = 0; i < 1; i++) spawn.mantisBoss(1900, -500)
// for (let i = 0; i < 1; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "entanglement");
@@ -168,14 +168,14 @@ const level = {
tech.tokamakHealCount = 0
tech.buffedGun++
if (tech.buffedGun > b.inventory.length - 1) tech.buffedGun = 0;
- if (tech.isGunCycle && (b.activeGun !== null && b.activeGun !== undefined) && b.inventory.length) {
+ if ((tech.isGunCycle || tech.isGunChoice) && (b.activeGun !== null && b.activeGun !== undefined) && b.inventory.length) {
b.inventoryGun = tech.buffedGun;
simulation.switchGun();
}
- if (tech.isGunChoice && Number.isInteger(tech.buffedGun) && b.inventory.length) {
- var gun = b.guns[b.inventory[tech.buffedGun]].name
- simulation.inGameConsole(`pigeonhole principle: ${(1.3 * Math.max(0, b.inventory.length)).toFixed(2)}x damage for ${gun} `, 600);
- }
+ // if (tech.isGunChoice && Number.isInteger(tech.buffedGun) && b.inventory.length) {
+ // var gun = b.guns[b.inventory[tech.buffedGun]].name
+ // simulation.inGameConsole(`pigeonhole principle: ${(1 + 0.4 * Math.max(0, b.inventory.length)).toFixed(2)}x damage for ${gun} `, 600);
+ // }
if (tech.isSwitchReality && level.levelsCleared !== 0) {
simulation.inGameConsole(`simulation.amplitude = ${Math.random()}`);
m.switchWorlds("many-worlds")
@@ -187,7 +187,12 @@ const level = {
for (let i = 0; i < len; i++) powerUps.spawn(player.position.x + 90 * (Math.random() - 0.5), player.position.y + 90 * (Math.random() - 0.5), "heal", false);
}
if (tech.interestRate > 0) {
- const rate = ((level[level.levels[level.onLevel]].name === "final" || level[level.levels[level.onLevel]].name === "subway") ? 1 / 3 : 1) * tech.interestRate //this effect triggers extra times on these final levels
+ // const rate = ((level[level.levels[level.onLevel]].name === "final" || level[level.levels[level.onLevel]].name === "subway") ? 1 / 3 : 1) * tech.interestRate //this effect triggers extra times on these final levels
+ let rate = tech.interestRate
+ if (level.onLevel < level.levels.length - 1) {//make sure it's not on the lore level which has an undefined name
+ const levelName = level.levels[level.onLevel]
+ if (levelName === "final" || levelName === "subway") rate *= 1 / 3
+ }
let ammoSum = 0
for (let i = 0; i < b.inventory.length; i++) {
@@ -315,10 +320,13 @@ const level = {
}
//update HUD with constraints
let text = `${level.constraintDescription1}`
+ if (level.constraintDescription1) simulation.inGameConsole(`constraint : ${level.constraintDescription1}`)
if (simulation.difficultyMode > 6 && level.constraintDescription2) {
text += ` ${level.constraintDescription2}`
+ if (level.constraintDescription2) simulation.inGameConsole(`constraint : ${level.constraintDescription2}`)
}
document.getElementById("right-HUD-constraint").innerHTML = text
+
if (level.constraintDescription1) {
if (level.constraintDescription2) {
document.getElementById("right-HUD").style.top = "80px";
@@ -2290,6 +2298,55 @@ const level = {
},
}
},
+ fizzler(p1, p2) {
+ return {
+ isOn: true,
+ position: p1,
+ look: p2,
+ color: color,
+ query() {
+ if (!m.isTimeDilated) {
+ // let best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }
+ // best = vertexCollision(this.position, this.look, [body]);
+
+ const hits = Matter.Query.ray(body, this.position, this.look, 25)
+ for (let i = hits.length - 1; i > -1; i--) {
+ // console.log(what)
+ const what = hits[i].bodyA
+ simulation.drawList.push({ x: what.position.x, y: what.position.y, radius: 11, color: "rgba(0,160,255,0.7)", time: 10 });
+ if (what === m.holdingTarget) m.drop()
+ for (let i = 0; i < body.length; i++) {
+ if (body[i] === what) {
+ body.splice(i, 1);
+ break
+ }
+ }
+ Matter.Composite.remove(engine.world, what);
+ }
+ //draw
+ ctx.beginPath();
+ ctx.moveTo(this.position.x, this.position.y);
+ ctx.lineTo(this.look.x, this.look.y);
+ // ctx.strokeStyle = "rgba(50,200,255,0.3)";
+ // ctx.lineWidth = 2 + 5 * Math.random()
+ // ctx.stroke();
+ ctx.strokeStyle = "rgba(50,160,255,0.17)";
+ ctx.lineWidth = 35 + 25 * Math.random() * Math.random();
+ ctx.stroke();
+
+ //draw random dots in the path
+ if (Math.random() < 0.05) {
+ const r = Math.random();
+ const where = {
+ x: this.position.x + r * (this.look.x - this.position.x) + 60 * (Math.random() - 0.5),
+ y: this.position.y + r * (this.look.y - this.position.y) + 60 * (Math.random() - 0.5)
+ };
+ simulation.drawList.push({ x: where.x, y: where.y, radius: 6, color: "rgba(0,160,255,0.7)", time: 5 });
+ }
+ }
+ },
+ }
+ },
isHazardRise: false,
hazard(x, y, width, height, damage = 0.002) {
return {
@@ -2474,6 +2531,19 @@ const level = {
ctx.lineDashOffset = (-simulation.cycle * this.VxGoal) % 80;
ctx.stroke();
ctx.setLineDash([0, 0]);
+ },
+ drawFast() {
+ ctx.beginPath();
+ const v = this.vertices;
+ ctx.moveTo(v[0].x + 2, v[0].y);
+ // for (let i = 1; i < v.length; ++i) ctx.lineTo(v[i].x, v[i].y);
+ ctx.lineTo(v[1].x - 2, v[1].y);
+ ctx.strokeStyle = "#000"
+ ctx.lineWidth = 4;
+ ctx.setLineDash([60, 60]);
+ ctx.lineDashOffset = (-simulation.cycle * this.VxGoal) % 120;
+ ctx.stroke();
+ ctx.setLineDash([0, 0]);
}
});
Matter.Body.setStatic(rect, true); //make static
@@ -5410,7 +5480,7 @@ const level = {
if (badBlocks[j] === body[i]) index = i
}
//remove block
- console.log(index, j)
+ // console.log(index, j)
if (index) {
Matter.Composite.remove(engine.world, badBlocks[j]);
body.splice(index, 1);
@@ -7199,7 +7269,7 @@ const level = {
let buildMapOutline = function () {
//boxes center on zero,zero with deep walls to hide background
- spawn.mapRect(2000, -2000, 2000, 4000); //right map wall
+ spawn.mapRect(2025, -2000, 1975, 4000); //right map wall
spawn.mapRect(-4000, -2000, 2000, 4000); //left map wall
spawn.mapRect(-4000, -5000, 8000, 3000); //map ceiling
spawn.mapRect(-4000, 2000, 8000, 3000); //floor
@@ -7233,7 +7303,7 @@ const level = {
balance.push(level.rotor(-750, 1755, 400, 25, 0.01, Math.PI / 2, 0.5))
balance.push(level.rotor(-275, 1675, 550, 32, 0.01, 0, 0.5))
- lasers.push(level.laser({ x: -1625, y: -850 }, { x: 1980, y: -850 })) ////x, y, width, height, damage = 0.002)
+ lasers.push(level.laser({ x: 1610, y: -850 }, { x: -1625, y: -850 })) ////x, y, width, height, damage = 0.002)
// spawn.mapRect(1980, -862, 25, 25); //laser entrance
// balance.push(level.rotor(1000, -910, 550, 32, 0.01, 0, 0.5))
@@ -7263,9 +7333,9 @@ const level = {
spawn.mapRect(1925, 800, 200, 200);
spawn.mapRect(1925, 1300, 200, 200);
- spawn.mapRect(1400, 1650, 200, 25);
- spawn.mapRect(1400, 1125, 200, 25);
- spawn.mapRect(1400, 600, 200, 25);
+ spawn.mapRect(1250, 1650, 500, 25);
+ spawn.mapRect(1300, 1125, 400, 25);
+ spawn.mapRect(1350, 600, 300, 25);
spawn.mapRect(1400, 75, 200, 25);
spawn.mapRect(650, 1287, 475, 50);
@@ -7273,9 +7343,9 @@ const level = {
spawn.mapRect(650, 150, 500, 225);
spawn.mapRect(350, 1300, 800, 375);
spawn.mapRect(350, 950, 150, 400);
- spawn.mapRect(175, 950, 325, 100);
- spawn.mapRect(150, 525, 350, 200);
- spawn.mapRect(150, 75, 350, 200);
+ spawn.mapRect(-25, 950, 525, 100);
+ spawn.mapRect(-75, 525, 575, 200);
+ spawn.mapRect(-75, 75, 575, 200);
spawn.mapRect(475, 1987, 550, 50);
//ceiling zone
@@ -7315,7 +7385,7 @@ const level = {
balance.push(level.rotor(-750, -1755 - 25, 400, 25, 0.01, Math.PI / 2, 0.5))
balance.push(level.rotor(-250, -1675 - 32, 500, 32, 0.01, 0, 0.5))
- lasers.push(level.laser({ x: -1625, y: 850 }, { x: 1980, y: 850 })) ////x, y, width, height, damage = 0.002)
+ lasers.push(level.laser({ x: 1610, y: 850 }, { x: -1625, y: 850 })) ////x, y, width, height, damage = 0.002)
// spawn.mapRect(1980, 862 - 25, 25, 25); //laser entrance
// balance.push(level.rotor(1000, 910 - 32, 550, 32, 0.01, 0, 0.5))
@@ -7340,9 +7410,9 @@ const level = {
spawn.mapRect(1925, -800 - 200, 200, 200);
spawn.mapRect(1925, -1300 - 200, 200, 200);
- spawn.mapRect(1400, -1650 - 25, 200, 25);
- spawn.mapRect(1400, -1125 - 25, 200, 25);
- spawn.mapRect(1400, -600 - 25, 200, 25);
+ spawn.mapRect(1250, -1650 - 25, 500, 25);
+ spawn.mapRect(1300, -1125 - 25, 400, 25);
+ spawn.mapRect(1350, -600 - 25, 300, 25);
spawn.mapRect(1400, -75 - 25, 200, 25);
spawn.mapRect(650, -1287 - 50, 475, 50);
@@ -7350,11 +7420,10 @@ const level = {
spawn.mapRect(650, -150 - 225, 500, 225);
spawn.mapRect(350, -1300 - 375, 800, 375);
spawn.mapRect(350, -950 - 400, 150, 400);
- spawn.mapRect(175, -950 - 100, 325, 100);
- spawn.mapRect(150, -525 - 200, 350, 200);
- spawn.mapRect(150, -75 - 200, 350, 200);
+ spawn.mapRect(-25, -950 - 100, 525, 100);
+ spawn.mapRect(-75, -525 - 200, 575, 200);
+ spawn.mapRect(-75, -75 - 200, 575, 200);
spawn.mapRect(475, -1987 - 50, 550, 50);
-
//ceiling zone
spawn.mapRect(1200, 1575, 400, 25);
spawn.mapRect(-75, 1700, 1075, 25);
@@ -7463,16 +7532,16 @@ const level = {
//spawn second wave of flipped mobs only once
spawn.randomMob(-1500, -1425, 0);
spawn.randomMob(-950, -1425, 0);
- spawn.randomMob(-800, -1475, 0.1);
- spawn.randomMob(-425, -1425, 0.1);
- spawn.randomMob(850, -1750, 0.2);
- spawn.randomMob(325, -850, 0.2);
- spawn.randomMob(400, -400, 0.3);
- spawn.randomMob(825, -475, 0.3);
- spawn.randomMob(875, -1050, 0.4);
- spawn.randomMob(1425, 1425, 0.5);
- spawn.randomMob(675, 1450, 0.7);
- spawn.randomMob(225, 1475, 0.9);
+ spawn.randomMob(-800, -1475, 0);
+ spawn.randomMob(-425, -1425, 0);
+ spawn.randomMob(850, -1750, 0.1);
+ spawn.randomMob(325, -850, 0.1);
+ spawn.randomMob(400, -400, 0.2);
+ spawn.randomMob(825, -475, 0.2);
+ spawn.randomMob(875, -1050, 0.3);
+ spawn.randomMob(1425, 1425, 0.4);
+ spawn.randomMob(675, 1450, 0.5);
+ spawn.randomMob(225, 1475, 0.6);
spawn.randomMob(-275, 1425, 1);
spawn.randomMob(-800, 1375, 1);
@@ -7551,7 +7620,7 @@ const level = {
ctx.fillRect(-1075, -2025, 450, 725);
ctx.fillRect(-575, -2025, 450, 725);
- ctx.fillRect(175, -250 - 725, 325, 725);
+ ctx.fillRect(-25, -250 - 725, 525, 725);
ctx.fillRect(650, -350 - 975, 475, 975);
ctx.fillRect(375, -1650 - 400, 750, 400);
//ceiling
@@ -7569,7 +7638,7 @@ const level = {
ctx.fillRect(-1075, 1300, 450, 725);
ctx.fillRect(-575, 1300, 450, 725);
- ctx.fillRect(175, 250, 325, 725);
+ ctx.fillRect(-25, 250, 525, 725);
ctx.fillRect(650, 350, 475, 975);
ctx.fillRect(375, 1650, 750, 400);
//ceiling
@@ -7581,6 +7650,9 @@ const level = {
ctx.fillRect(-1625, -2025, 475, 450);
}
};
+ spawn.bodyRect(1325, -1775, 175, 175);
+ spawn.bodyRect(-375, -1725, 100, 75, 0.5);
+ spawn.bodyRect(-900, -1625, 125, 200, 0.5);
spawn.bodyRect(-1662, 1325, 25, 175);
spawn.bodyRect(-1662, 1825, 25, 175);
@@ -7601,24 +7673,24 @@ const level = {
spawn.randomMob(-1350, -1750, 0);
spawn.randomMob(-875, -1575, 0);
spawn.randomMob(500, -1875, 0);
- spawn.randomMob(350, 825, 0.1);
- spawn.randomMob(375, 400, 0.1);
- spawn.randomMob(1500, -25, 0.2);
- spawn.randomMob(650, -1950, 0.3);
- spawn.randomMob(775, 700, 0.3);
- spawn.randomMob(275, -50, 0.4);
- spawn.randomMob(75, -1750, 0.5);
- spawn.randomMob(1750, -1425, 0.5);
- spawn.randomMob(950, 50, 0.6);
- spawn.randomMob(-1375, 175, 0.6);
- spawn.randomMob(-350, 175, 0.7);
- spawn.randomMob(725, 1175, 0.7);
- spawn.randomMob(-850, -1950, 0.8);
- spawn.randomMob(-1400, -1725, 0.9);
- spawn.randomMob(1400, -1700, 0.9);
- spawn.randomMob(-800, 200, 0.9);
- spawn.randomMob(1475, 1550, 1);
- spawn.randomMob(1475, 500, 1);
+ spawn.randomMob(350, 825, 0);
+ spawn.randomMob(375, 400, 0);
+ spawn.randomMob(1500, -25, 0.1);
+ spawn.randomMob(650, -1950, 0.2);
+ spawn.randomMob(775, 700, 0.2);
+ spawn.randomMob(275, -50, 0.3);
+ spawn.randomMob(75, -1750, 0.3);
+ spawn.randomMob(1750, -1425, 0.4);
+ spawn.randomMob(950, 50, 0.4);
+ spawn.randomMob(-1375, 175, 0.4);
+ spawn.randomMob(-350, 175, 0.5);
+ spawn.randomMob(725, 1175, 0.5);
+ spawn.randomMob(-850, -1950, 0.6);
+ spawn.randomMob(-1400, -1725, 0.7);
+ spawn.randomMob(1400, -1700, 0.7);
+ spawn.randomMob(-800, 200, 0.7);
+ spawn.randomMob(1475, 1550, 0.8);
+ spawn.randomMob(1475, 500, 0.8);
powerUps.spawnStartingPowerUps(-875, -1925);
spawn.randomLevelBoss(-875, -200);
@@ -8155,45 +8227,256 @@ const level = {
powerUps.directSpawn(2100, 925, "heal");
powerUps.directSpawn(625, -100, "heal");
},
- cocoon() {
+ corridor() {
// simulation.fallHeight = 4000
level.announceMobTypes()
- level.setPosToSpawn(-3800, 950);
- level.exit.x = 3750
- level.exit.y = -625
- level.defaultZoom = 2000
+ level.defaultZoom = 2400
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#d0d5d5";
color.map = "#444"
+ // level.isHorizontalFlipped = true
+ if (level.isHorizontalFlipped) {
+ level.setPosToSpawn(14075, -625);
+ level.exit.x = -350
+ level.exit.y = 505
+ spawn.bodyRect(13525, -675, 50, 100);
+ var color1 = "rgba(0,20,60,0.09)"
+ var color2 = "rgba(0,255,255,0.1)"
+ } else {
+ level.setPosToSpawn(-350, 475);
+ level.exit.x = 14025
+ level.exit.y = -600
+ spawn.bodyRect(-225, 475, 50, 50);
+ var color1 = "rgba(0,255,255,0.1)"
+ var color2 = "rgba(0,20,60,0.09)"
+ }
+ spawn.mapRect(14015, -585, 120, 75); //exit/entrance platform
+ const buttonLeft = level.button(-4100, 991)
+ const buttonRight = level.button(4050, 991)
+ buttonLeft.isUp = true
+ // const buttonCamera = level.button(940, -1545)
+ // buttonRight.isUp = false
+ const boosts = []
+ boosts.push(level.boost(-3650, 990, 2700, 1.45))
+ boosts.push(level.boost(3325, 990, 1600, 1.4))
+ boosts.push(level.boost(7960, -1110, 1650, 2.3))
+ boosts.push(level.boost(13345, -460, 2070, 2.35))
+ const fizzlers = []
+ fizzlers.push(level.fizzler({ x: -135, y: 265 }, { x: -135, y: 535 }))
+ fizzlers.push(level.fizzler({ x: -3850, y: 650 }, { x: -3850, y: 1025 }))
+ fizzlers.push(level.fizzler({ x: 3875, y: 675 }, { x: 3875, y: 1025 }))
+ fizzlers.push(level.fizzler({ x: 13425, y: -1275 }, { x: 13425, y: -550 }))
+ const movers = []
+ const baseMoverSpeed = 15
+ movers.push(level.mover(-3550, 995, 6875, 150, -baseMoverSpeed))
+ movers.push(level.mover(225, -1190, 2450, 50, -baseMoverSpeed))
+ movers.push(level.mover(-3000, -1190, 3000, 50, baseMoverSpeed))
+ movers.push(level.mover(4000, -2025, 2000, 150, -23))
+ movers.push(level.mover(8000, -1125, 2000, 150, -23))
+ movers.push(level.mover(3775, -425, 1650, 150, 20))
+ movers.push(level.mover(5425, -425, 1925, 150, 40))
+ movers.push(level.mover(7350, -425, 6000, 150, 60))
+ function setMoverDirection(index, VxGoal, force) {
+ movers[index].VxGoal = VxGoal
+ movers[index].force = force
+ }
level.custom = () => {
+ // buttonCamera.query()
+ // if (!buttonCamera.isUp) {
+ // simulation.setCameraPosition(100, -1000, 0.29)
+ // //block spawner
+ // spawn.mapRect(0, -2375, 200, 100);
+ // if (!(simulation.cycle % 10) && !m.isTimeDilated && body.length < 200) {
+ // const where = { x: 112, y: -3800 }
+ // // simulation.drawList.push({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 100 * (Math.random() - 0.5), radius: 11, color: "rgba(0,160,255,0.5)", time: 10 });
+
+ // let makeBlock = function (where, size) {
+ // const sides = Math.floor(4 + 6 * Math.random() * Math.random())
+ // body[body.length] = Matter.Bodies.polygon(where.x, where.y, sides, size, {
+ // friction: 0.05,
+ // frictionAir: 0.001,
+ // collisionFilter: {
+ // category: cat.body,
+ // mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet
+ // },
+ // classType: "body",
+ // density: 0.001,
+ // });
+ // const who = body[body.length - 1]
+ // Composite.add(engine.world, who); //add to world
+ // }
+ // makeBlock({ x: where.x, y: where.y }, Math.floor(20 + 35 * Math.random() * Math.random()))
+ // }
+ // }
+ ctx.fillStyle = "#c8cccc"//background color is "#d0d5d5"
+ ctx.fillRect(-2150, 675, 500, 400);
+ ctx.fillRect(-1050, 675, 500, 400);
+ ctx.fillRect(750, 675, 500, 400);
+ ctx.fillRect(1850, 675, 500, 400);
+ ctx.fillRect(-2250, -2425, 700, 1325);
+ ctx.fillRect(-1150, -2400, 700, 1300);
+ ctx.fillRect(650, -2375, 700, 1325);
+ ctx.fillRect(1750, -2375, 700, 1350);
+ ctx.fillRect(8000, -2425, 2000, 2225);
+ ctx.fillRect(4000, -2375, 2000, 2100);
+ ctx.fillRect(11125, -2425, 1000, 2150)
level.exit.drawAndCheck();
level.enter.draw();
+ if (buttonRight.isUp) {
+ buttonRight.query();
+ if (!buttonRight.isUp) {
+ requestAnimationFrame(() => buttonLeft.isUp = true);
+ setMoverDirection(0, -baseMoverSpeed, -0.0005)
+ const list = Matter.Query.region(body, buttonLeft) //are any blocks colliding with this
+ if (list.length > 0) Matter.Body.setVelocity(list[0], { x: baseMoverSpeed, y: -20 });
+ }
+ } else if (buttonLeft.isUp) {
+ buttonLeft.query();
+ if (!buttonLeft.isUp) {
+ requestAnimationFrame(() => buttonRight.isUp = true);
+ setMoverDirection(0, 20, 0.0005)
+ const list = Matter.Query.region(body, buttonRight) //are any blocks colliding with this
+ if (list.length > 0) Matter.Body.setVelocity(list[0], { x: -15, y: -20 });
+ }
+ }
+ buttonRight.draw();
+ buttonLeft.draw();
+ for (let i = 0; i < movers.length; i++) movers[i].push();
+ for (let i = 0; i < boosts.length; i++) boosts[i].query();
};
level.customTopLayer = () => {
- ctx.fillStyle = "rgba(0,255,255,0.1)" //"#d4f4f4" //exit
- ctx.fillRect(3535, -1050, 500, 475);
-
+ for (let i = 0; i < fizzlers.length; i++) fizzlers[i].query();
+ ctx.fillStyle = color1 //exit
+ ctx.fillRect(13400, -1325, 1000, 825);
//shadows
- ctx.fillStyle = "rgba(0,20,60,0.09)"
- // ctx.fillRect(-4025, -1050, 1750, 2275);
+ ctx.fillStyle = color2
+ ctx.fillRect(-500, 225, 494, 350);
+ ctx.fillStyle = "rgba(0,5,10,0.06)"
+ ctx.beginPath();
+ ctx.moveTo(0, -1180)
+ ctx.lineTo(225, -1180)
+ ctx.lineTo(3220, 669)
+ ctx.lineTo(3180, 1010)
+ ctx.lineTo(-2960, 1010)
+ ctx.lineTo(-2995, 674)
+ ctx.fill()
+ ctx.beginPath();
+ //right button room
+ ctx.beginPath();
+ ctx.moveTo(3780, 720)
+ ctx.lineTo(4325, 720)
+ ctx.lineTo(4325, 1010)
+ ctx.lineTo(3810, 1010)
+ ctx.fill()
+ //left button room
+ ctx.beginPath();
+ ctx.moveTo(-3755, 675)
+ ctx.lineTo(-3785, 1010)
+ ctx.lineTo(-4250, 1010)
+ ctx.lineTo(-4250, 675)
+ ctx.fill()
+ ctx.fillStyle = "rgba(68, 68, 68,0.9)"
+ ctx.fillRect(-50, -4300, 325, 1950);
+ for (let i = 0; i < movers.length; i++) movers[i].draw();
};
- //boxes center on zero,zero with deep walls to hide background
- spawn.mapRect(4000, -2000, 2000, 4000); //right map wall
- spawn.mapRect(-6000, -2000, 2000, 4000); //left map wall
- spawn.mapRect(-6000, -4000, 12000, 3000); //map ceiling
spawn.mapRect(-6000, 1000, 12000, 3000); //floor
+ spawn.mapRect(-6000, -4300, 6020, 1950);
+ spawn.mapRect(205, -4300, 15120, 1950);
+ spawn.mapVertex(-250, 602.5, "-200 0 235 0 400 50 400 150 -200 150");
+ spawn.mapVertex(-3675, -2275, "0 0 500 0 0 500");
+ spawn.mapVertex(13275, -2275, "0 0 -500 0 0 500");
+ spawn.mapRect(-525, -1175, 525, 1450);
+ spawn.mapRect(225, -1175, 3000, 1850);
+ spawn.mapRect(-3000, -1175, 2525, 1850);
+ spawn.mapRect(-4350, -2500, 600, 3175);
+ spawn.mapRect(-6000, -2350, 1775, 3350);
+ spawn.mapVertex(-1900, 675, "-350 0 -250 100 250 100 350 0");
+ spawn.mapVertex(-800, 675, "-350 0 -250 100 250 100 350 0");
+ spawn.mapVertex(1000, 675, "-350 0 -250 100 250 100 350 0");
+ spawn.mapVertex(2100, 675, "-350 0 -250 100 250 100 350 0");
+
+ spawn.mapVertex(-1900, -1450, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
+ spawn.mapVertex(-800, -1450, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
+ spawn.mapVertex(1000, -1450, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
+ spawn.mapVertex(2100, -1450, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
+
+ spawn.mapVertex(-1900, -2350, "-450 0 -350 100 350 100 450 0");
+ spawn.mapVertex(-800, -2350, "-450 0 -350 100 350 100 450 0");
+ spawn.mapVertex(1000, -2350, "-450 0 -350 100 350 100 450 0");
+ spawn.mapVertex(2100, -2350, "-450 0 -350 100 350 100 450 0");
+ spawn.mapRect(-1500, 840, 300, 20);
+ spawn.mapRect(1400, 840, 300, 20);
+ //ramp to catch blocks
+ spawn.mapVertex(3001, -1260, "0 0 400 -200 550 -200 550 75 0 75");
+ spawn.mapVertex(4100, -1100, "-625 0 -600 -60 600 -60 625 0 600 60 -600 60");
+ spawn.mapVertex(5550, -750, "-625 0 -600 -60 600 -60 625 0 600 60 -600 60");
+ spawn.mapVertex(11625, -900, "-525 0 -500 -50 500 -50 525 0 500 50 -500 50");
+ //base for mover
+ spawn.mapVertex(5000, -1935, "-1050 0 -1000 -90 1000 -90 1050 0 1000 90 -1000 90");
+ spawn.mapVertex(9000, -1035, "-1050 0 -1000 -90 1000 -90 1050 0 1000 90 -1000 90");
+ spawn.mapVertex(5000, -2370, "-1200 0 -1000 100 1000 100 1200 0");
+ spawn.mapVertex(9000, -2310, "-1200 0 -1000 100 1000 100 1200 0");
+ spawn.mapVertex(11625, -2310, "-600 0 -500 100 500 100 600 0");
+ spawn.mapRect(3775, -400, 675, 1125);
+ spawn.mapRect(4300, -400, 11025, 4400);
+ //exit
+ spawn.mapRect(13400, -575, 1925, 300);
+ spawn.mapRect(14275, -2375, 1050, 2050);
+ spawn.mapRect(13400, -2375, 900, 1125);
- // spawn.randomMob(2825, 75, 0.9);
- // spawn.randomLevelBoss(2400, 600);
- // spawn.secondaryBossChance(800, -300)
- // powerUps.spawnStartingPowerUps(600, 375);
- // powerUps.addResearchToLevel() //needs to run after mobs are spawned
+ //blocks on movers
+ spawn.bodyRect(-200, 950, 50, 50);
+ spawn.bodyRect(-1100, 925, 65, 75);
+ spawn.bodyRect(-2275, 975, 70, 25);
+ spawn.bodyRect(-3325, 925, 75, 75);
+ spawn.bodyRect(-2950, -1225, 90, 25);
+ spawn.bodyRect(-1425, -1275, 45, 75);
+ spawn.bodyRect(600, -1275, 70, 75);
+ spawn.bodyRect(1900, -1225, 90, 50);
+ spawn.bodyRect(4250, -2100, 115, 50);
+ spawn.bodyRect(2175, 900, 100, 65);
+ spawn.bodyRect(4075, -450, 75, 20);
+ spawn.bodyRect(8350, -1175, 90, 50);
+ spawn.bodyRect(6525, -525, 70, 100);
+ spawn.bodyRect(12025, -475, 130, 50);
+ spawn.bodyRect(625, 950, 55, 45);
+ spawn.bodyRect(6250, -450, 55, 25);
+ spawn.bodyRect(3950, -475, 46, 53);
+ //other blocks
+ spawn.bodyRect(3525, -1300, 100, 125, 0.6);
+ spawn.bodyRect(11550, -1150, 100, 200, 0.4);
+
+ spawn.randomMob(-1775, -1650, 0);
+ spawn.randomMob(950, -1775, 0);
+ spawn.randomMob(1550, 775, 0);
+ spawn.randomMob(4500, -1250, 0);
+ spawn.randomMob(11400, -1300, 0);
+ spawn.randomMob(-800, -1675, 0);
+ spawn.randomMob(-1325, 775, 0.1);
+ spawn.randomMob(2050, -1625, 0.1);
+ spawn.randomMob(3100, -1475, 0.2);
+ spawn.randomMob(5400, -900, 0.2);
+ spawn.randomMob(11950, -1025, 0.3);
+ spawn.randomMob(-925, -1700, 0.3);
+ spawn.randomMob(2025, -1725, 0.4);
+ spawn.randomMob(1575, 775, 0.4);
+ spawn.randomMob(-1350, 775, 0.6);
+ spawn.randomMob(11925, -1275, 0.6);
+ spawn.randomMob(4325, -1425, 0.6);
+ spawn.randomMob(5425, -950, 0.6);
+ spawn.randomMob(3575, 375, 0.6);
+ spawn.randomGroup(5300, -1400, 1.3);
+
+ spawn.randomLevelBoss(2025, -1825);
+ spawn.secondaryBossChance(-1900, -1800);
+ powerUps.spawnStartingPowerUps(11750, -1000);
+ powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
lock() {
level.announceMobTypes()
@@ -8930,9 +9213,9 @@ const level = {
simulation.zoomTransition(level.defaultZoom)
powerUps.spawnStartingPowerUps(4900, -500); //1 per level
- spawn.debris(1000, 20, 1800, 3); //16 debris per level //but less here because a few mobs die from laser
- spawn.debris(4830, -1330, 850, 3); //16 debris per level
- spawn.debris(3035, -3900, 1500, 3); //16 debris per level
+ spawn.debris(1000, 20, 1800, 6); //16 debris per level
+ // spawn.debris(4830, -1330, 850, 3); //16 debris per level
+ // spawn.debris(3035, -3900, 1500, 3); //16 debris per level
document.body.style.backgroundColor = "#dbdcde";
@@ -8998,6 +9281,11 @@ const level = {
spawn.mapRect(4100, -3450, 100, 850); //left top shelf
spawn.mapRect(4600, -3450, 100, 1850);
+ //steps up and down
+ spawn.mapVertex(4525, 250, "-650 0 -625 -20 625 -20 650 0");
+ spawn.mapVertex(4525, 237, "-550 0 -525 -20 525 -20 550 0");
+ // spawn.mapVertex(4525, 225, "-400 0 -375 -20 375 -20 400 0");
+
spawn.randomSmallMob(4400, -3500);
spawn.randomSmallMob(4800, -800);
spawn.randomMob(800, -2600);
@@ -36987,6 +37275,19 @@ const level = {
level.enter.draw();
level.exit.drawAndCheck();
+
+ //check if blocks are in the exit zone and destroy them
+ for (let i = 0; i < body.length; i++) {
+ if (body[i].position.x > 1675) {
+ Matter.Composite.remove(engine.world, body[i]);
+ body.splice(i, 1);
+ break
+ }
+ }
+ //if no blocks left make a new one
+ if (body.length < 2) { //< 2 because the door is a body
+ spawn.bodyRect(1025, -550, 50, 50);
+ }
};
level.customTopLayer = () => {
buttonDoor.query();
@@ -37076,6 +37377,18 @@ const level = {
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(1600, -400, 400, 400)
+ //check if blocks are in the exit zone and destroy them
+ for (let i = 0; i < body.length; i++) {
+ if (body[i].position.x > 1675 && body[i].position.y > -350) {
+ Matter.Composite.remove(engine.world, body[i]);
+ body.splice(i, 1);
+ break
+ }
+ }
+ //if no blocks left make a new one
+ if (body.length < 2) { //< 2 because the door is a body
+ spawn.bodyRect(1025, -550, 50, 50);
+ }
};
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
@@ -37136,6 +37449,19 @@ const level = {
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(1600, -400, 400, 400)
+
+ //check if blocks are in the exit zone and destroy them
+ for (let i = 0; i < body.length; i++) {
+ if (body[i].position.x > 1675 && body[i].position.y > -350) {
+ Matter.Composite.remove(engine.world, body[i]);
+ body.splice(i, 1);
+ break
+ }
+ }
+ //if no blocks left make a new one
+ if (body.length < 2) { //< 2 because the door is a body
+ spawn.bodyRect(1025, -550, 50, 50);
+ }
};
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
diff --git a/js/mob.js b/js/mob.js
index 1c3af8a..30197db 100644
--- a/js/mob.js
+++ b/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
@@ -1384,7 +1376,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 +1389,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 +1400,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 +1425,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()
diff --git a/js/player.js b/js/player.js
index d4502b1..83d4a47 100644
--- a/js/player.js
+++ b/js/player.js
@@ -782,7 +782,7 @@ const m = {
defense() {
let dmg = 1
if (powerUps.boost.isDefense && powerUps.boost.endCycle > simulation.cycle) dmg *= 0.3
- if (tech.isMaxHealthDefense && m.health === m.maxHealth) dmg *= 0.3
+ if (tech.isMaxHealthDefense && m.health === m.maxHealth) dmg *= 0.2
if (tech.isDiaphragm) dmg *= 0.55 + 0.35 * Math.sin(m.cycle * 0.0075);
if (tech.isZeno) dmg *= 0.15
if (tech.isFieldHarmReduction) dmg *= 0.6
@@ -1773,7 +1773,7 @@ const m = {
tungsten() {
m.hardLandCDScale = 2
m.hardLanding = 60
- m.coyoteCycles = 0
+ // m.coyoteCycles = 0
m.isAltSkin = true
m.color = {
hue: 210,
diff --git a/js/powerup.js b/js/powerup.js
index 55f057e..213eb8d 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -785,7 +785,7 @@ const powerUps = {
m.addHealth(heal);
if (healOutput > 0) simulation.inGameConsole(`
m .health += ${(healOutput).toFixed(3)}`) // ${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(`
m .maxHealth += ${(0.3 * overHeal).toFixed(3)}`)
simulation.drawList.push({ //add dmg to draw queue
diff --git a/js/simulation.js b/js/simulation.js
index 55f696c..df22584 100644
--- a/js/simulation.js
+++ b/js/simulation.js
@@ -558,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();
@@ -768,7 +768,7 @@ const simulation = {
}
},
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;
@@ -794,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
diff --git a/js/spawn.js b/js/spawn.js
index b2eb361..9b9f2a8 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -1015,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 = Infinite `);
@@ -2704,7 +2704,10 @@ const spawn = {
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) {
@@ -6022,7 +6025,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
});
diff --git a/js/tech.js b/js/tech.js
index ce794fd..778fa1b 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -67,7 +67,7 @@ const tech = {
tech.junkChance += percent
if (tech.junkChance < 0.001 || tech.junkChance === undefined) tech.junkChance = 0
if (tech.junkChance > 1) tech.junkChance = 1
- simulation.inGameConsole(`+${(100 * percent).toFixed(0)}% JUNK tech chance (${(100 * tech.junkChance).toFixed(0)} total chance)`)
+ simulation.inGameConsole(`+${(100 * percent).toFixed(0)}% JUNK tech chance (${(100 * tech.junkChance).toFixed(0)}% total chance)`)
// tech.junkChance += (1 - tech.junkChance) * percent
return percent
@@ -266,7 +266,7 @@ const tech = {
damageFromTech() {
let dmg = tech.damage * m.fieldDamage
if (level.isNoDamage && (m.cycle - 180 < level.noDamageCycle)) dmg *= 0.3
- if (tech.isMaxHealthDamage && m.health === m.maxHealth) dmg *= 1.5
+ if (tech.isMaxHealthDamage && m.health === m.maxHealth) dmg *= 2
if (tech.noDefenseSettingDamage && m.defense() === 1) dmg *= 2.5
if (tech.isImmunityDamage && m.immuneCycle > m.cycle) dmg *= 3
if (tech.isPowerUpDamage) dmg *= 1 + 0.07 * powerUp.length
@@ -275,7 +275,7 @@ const tech = {
if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.9
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.9 : 2
if (tech.isDilate) dmg *= 1.9 + 1.1 * Math.sin(m.cycle * 0.01)
- if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.3 * b.inventory.length
+ if (tech.isGunChoice) dmg *= 1 + 0.4 * b.inventory.length
if (powerUps.boost.endCycle > simulation.cycle) dmg *= 1 + powerUps.boost.damage
if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.025 * m.coupling
if (tech.isVerlet) dmg *= 3
@@ -781,13 +781,16 @@ const tech = {
{
name: "pigeonhole principle",
descriptionFunction() {
- let info = ""
- if (this.count > 0 && Number.isInteger(tech.buffedGun) && b.inventory.length) {
- let gun = b.guns[b.inventory[tech.buffedGun]].name
- info = ` this level: ${(1.3 * Math.max(0, b.inventory.length)).toFixed(2)}x damage for ${gun} `
- }
- return `a new ${powerUps.orb.gun()} in your inventory is chosen each level if it's equipped, 1.3x damage per ${powerUps.orb.gun()} in your inventory${info} `
+ return `1.4x damage per ${powerUps.orb.gun()}, but your equipped ${powerUps.orb.gun()} cycles each level and you can't switch `
},
+ // descriptionFunction() {
+ // let info = ""
+ // if (this.count > 0 && Number.isInteger(tech.buffedGun) && b.inventory.length) {
+ // let gun = b.guns[b.inventory[tech.buffedGun]].name
+ // info = ` this level: ${(1.3 * Math.max(0, b.inventory.length)).toFixed(2)}x damage for ${gun} `
+ // }
+ // return `a new ${powerUps.orb.gun()} in your inventory is chosen each level if it's equipped, 1.3x damage per ${powerUps.orb.gun()} in your inventory${info} `
+ // },
maxCount: 1,
count: 0,
frequency: 1,
@@ -807,7 +810,7 @@ const tech = {
},
{
name: "generalist",
- description: `spawn 7 ${powerUps.orb.gun()}, but you can't switch ${powerUps.orb.gun()} your equipped ${powerUps.orb.gun()} cycles after each level`,
+ description: `spawn 7 ${powerUps.orb.gun()}, but your equipped ${powerUps.orb.gun()} cycles each level and you can't switch `,
maxCount: 1,
count: 0,
frequency: 1,
@@ -815,9 +818,9 @@ const tech = {
isInstant: true,
isBadRandomOption: true,
allowed() {
- return (b.inventory.length < b.guns.length - 5) && (b.inventory.length > 1)
+ return (b.inventory.length < b.guns.length - 5) && b.inventory.length > 1
},
- requires: "at least 2 guns, at least 5 unclaimed guns",
+ requires: "you have at least 2 guns and 5 unclaimed guns",
effect() {
tech.isGunCycle = true;
for (let i = 0; i < 7; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun");
@@ -982,7 +985,7 @@ const tech = {
if (this.count === 0) this.gun = Math.floor(Math.random() * (b.guns.length - 1)) //don't pick laser
return `2x ammo per ${powerUps.orb.ammo(1)} for ${b.guns[this.gun].name} `
},
- maxCount: 9,
+ maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
@@ -1432,7 +1435,7 @@ const tech = {
name: "zoospore vector",
link: `zoospore vector `,
descriptionFunction() {
- return `after mobs die there is a 10% chance they grow ${b.guns[6].nameString('s')}`
+ return `after mobs die there is a 13% chance they grow ${b.guns[6].nameString('s')}`
},
// description: "after mobs die they have a +10% chance to grow spores ",
maxCount: 9,
@@ -1444,7 +1447,7 @@ const tech = {
},
requires: "no other mob death tech",
effect() {
- tech.sporesOnDeath += 0.1;
+ tech.sporesOnDeath += 0.13;
// if (tech.isSporeWorm) {
// for (let i = 0; i < 4; i++) b.worm(m.pos)
// } else {
@@ -2890,7 +2893,7 @@ const tech = {
},
{
name: "overcharge",
- description: "+88 maximum energy +4% JUNK ch oi ces ",
+ description: "+100 maximum energy +5% JUNK ch oi ces ",
maxCount: 9,
count: 0,
frequency: 1,
@@ -2900,9 +2903,9 @@ const tech = {
},
requires: "",
effect() {
- tech.bonusEnergy += 0.88
+ tech.bonusEnergy += 1
m.setMaxEnergy()
- this.refundAmount += tech.addJunkTechToPool(0.04)
+ this.refundAmount += tech.addJunkTechToPool(0.05)
},
refundAmount: 0,
remove() {
@@ -3063,7 +3066,7 @@ const tech = {
{
name: "stability",
descriptionFunction() {
- return `0.3x damage taken while your health is at maximum`
+ return `0.2x damage taken while your health is at maximum`
},
maxCount: 1,
count: 0,
@@ -3103,7 +3106,7 @@ const tech = {
{
name: "control theory",
descriptionFunction() {
- return `1.5x damage while your health is at maximum`
+ return `2x damage while your health is at maximum`
},
maxCount: 1,
count: 0,
@@ -3329,7 +3332,7 @@ const tech = {
{
name: "quenching",
descriptionFunction() {
- return `0.4x of ${powerUps.orb.heal()} overhealing is added to maximum health `
+ return `0.5x of ${powerUps.orb.heal()} overhealing is added to maximum health `
},
maxCount: 1,
count: 0,
@@ -3455,7 +3458,7 @@ const tech = {
return true
},
requires: "",
- rate: 0.06,
+ rate: 0.05,
effect() {
tech.interestRate += this.rate;
},
@@ -4318,7 +4321,7 @@ const tech = {
},
{
name: "replication",
- description: "+10% chance to duplicate spawned power ups +15% JUNK ch oi ces ",
+ description: "+10% chance to duplicate spawned power ups +10% JUNK ch oi ces ",
maxCount: 9,
count: 0,
frequency: 1,
@@ -4331,7 +4334,7 @@ const tech = {
tech.duplicateChance += 0.1
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.1);
- this.refundAmount += tech.addJunkTechToPool(0.15)
+ this.refundAmount += tech.addJunkTechToPool(0.10)
},
refundAmount: 0,
remove() {
@@ -5532,7 +5535,7 @@ const tech = {
},
{
name: "phase velocity",
- description: "wave particles propagate faster as solids 1.4x wave damage ",
+ description: "wave particles propagate faster as solids 1.5x wave damage ",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5584,11 +5587,11 @@ const tech = {
requires: "wave",
effect() {
tech.waveBeamSpeed *= 0.75;
- tech.waveBeamDamage += 0.3 * 0.4 //this sets base wave damage
+ tech.waveBeamDamage *= 1.4 //this sets base wave damage
},
remove() {
tech.waveBeamSpeed = 11;
- tech.waveBeamDamage = 0.3 //this sets base wave damage
+ tech.waveBeamDamage = 0.4 //this sets base wave damage
}
},
{
diff --git a/style.css b/style.css
index 2feb1f4..9b15685 100644
--- a/style.css
+++ b/style.css
@@ -1568,9 +1568,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;
}
diff --git a/todo.txt b/todo.txt
index 4f149f2..7d47bf9 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,17 +1,45 @@
******************************************************** NEXT PATCH **************************************************
-reworked focuser mobs to fire blue energy draining laser instead of charging player
+new level corridor
+ new level element fizzler - it removes blocks
+interferometer has wider platforms, a few helpful blocks, and fewer mobs
+level constraints are announced in console
+
+foam gun no longer pushes the player back when firing
+wave gun buffs
+ 1.2x base damage
+ 1.1x base ammo
+ 0.1->0.13x speed in map
+ 0.25->0.30x speed in blocks
+ tech: phase velocity 1.4->1.5x damage
+pigeonhole principle gives 1.3->1.4 damage per gun
+ you can no longer switch guns, your gun cycles each level
+quenching 0.4->0.5x overheal converts into max health
+tungsten carbide no longer has reduced coyote cycles
+control theory 1.5->2x damage at max health
+stability 0.3->0.2 damage taken at max health
+overcharge +88->100 max energy, 4->5% JUNK
+zoospore vector 10->13% chance for spores on mob death
+replication 15->10% JUNK
+interest 6->5% of your power ups spawn each level
+
+updated "about" details menu
+ moved classic n-gon to here from settings
+ added links to community content in "about"
+ Are there more links I should add?
+ added an n-gon SVG head image
+
+bugs
+ fixed outline on splash screen doesn't sync right on safari browser
+ fixed possible lock out on training levels: "hold", "throw", "throwAt"
+ from losing block behind a door
+ shortcut sort buttons in experiment mode properly order tech without clicking sort
+ fixed/increased the horizontal velocity contribution for some guns
+ this makes bullets shot on moving platforms more realistic
+ nail gun, super balls, foam, harpoon
******************************************************** 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?
@@ -27,32 +55,17 @@ figure out why seeded random isn't making runs the same:
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
*********************************************************** TODO *****************************************************
-new level - something with movers, rubber band blocks
-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: demineralization - 0.2x damage taken, but it slowly reduces effect
+ increase to full:
+ at start of level?
+ when you get the tech
+ decrease:
+ over time
+ at start of new level
!!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)
@@ -288,16 +301,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?
@@ -311,23 +314,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
@@ -1242,6 +1230,7 @@ possible names for 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?
******************************************************* DESIGN ******************************************************
@@ -1277,12 +1266,13 @@ n-gon fork
kgurchiek.github.io/n-gon-portal-gun
3xiondev.github.io/n-gon-upgraded
coaldeficit.github.io/c-gon
- c-rxxp-y.github.io/n-gon-enhanced
+ n-gon-enhanced.vercel.app
bookmarlet
github.com/Whyisthisnotavalable/n-scythe
github.com/kgurchiek/n-gon-mobile
github.com/kgurchiek/n-gon-controller
+
text
ngon.fandom.com/wiki/N-gon
github.com/3xionDev/n-docs
\ No newline at end of file