diff --git a/.DS_Store b/.DS_Store
index bf21f88..17e7534 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index 8f0352b..5716f52 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -452,7 +452,7 @@ const b = {
},
pulse(energy, angle = m.angle) {
let best;
- let explosionRadius = 1300 * energy
+ let explosionRadius = 1250 * energy
let range = 3000
const path = [{
x: m.pos.x + 20 * Math.cos(angle),
@@ -2050,7 +2050,7 @@ const b = {
isImproved: false,
beforeDmg(who) {
if (tech.isIncendiary) {
- const max = Math.min(this.endCycle - simulation.cycle, 1500)
+ const max = Math.max(Math.min(this.endCycle - simulation.cycle, 1500), 0)
b.explosion(this.position, max * 0.08 + this.isImproved * 100 + 60 * Math.random()); //makes bullet do explosive damage at end
this.endCycle -= max
} else {
@@ -4550,7 +4550,7 @@ const b = {
x: 7.5 * Math.cos(m.angle - Math.PI / 2),
y: 7.5 * Math.sin(m.angle - Math.PI / 2)
}
- const dmg = 0.6 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
+ const dmg = 0.7 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
const eye = {
x: m.pos.x + 15 * Math.cos(m.angle),
@@ -4630,10 +4630,10 @@ const b = {
},
firePulse() {
m.fireCDcycle = m.cycle + Math.floor((tech.isPulseAim ? 25 : 50) * b.fireCD); // cool down
- let energy = 0.27 * Math.min(m.energy, 1.5)
+ let energy = 0.3 * Math.min(m.energy, 1.5)
m.energy -= energy * tech.isLaserDiode
if (tech.beamSplitter) {
- energy *= Math.pow(0.9, tech.beamSplitter)
+ energy *= Math.pow(0.85, tech.beamSplitter)
b.pulse(energy, m.angle)
for (let i = 1; i < 1 + tech.beamSplitter; i++) {
b.pulse(energy, m.angle - i * 0.27)
diff --git a/js/index.js b/js/index.js
index eb082f7..e5972a2 100644
--- a/js/index.js
+++ b/js/index.js
@@ -783,6 +783,7 @@ window.addEventListener("keydown", function(event) {
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline'
if (!simulation.isCheating) {
simulation.isCheating = true;
+ level.levelAnnounce();
lore.techCount = 0;
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isLore) {
diff --git a/js/level.js b/js/level.js
index 3703457..017571b 100644
--- a/js/level.js
+++ b/js/level.js
@@ -111,7 +111,7 @@ const level = {
// if (tech.isPerpetualStun) {
// for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], 780)
// }
- if (tech.isFlipFlopHarm && tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
+ if (tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
tech.isFlipFlopOn = true
m.eyeFillColor = m.fieldMeterColor
simulation.makeTextLog(`tech.isFlipFlopOn = true`);
@@ -155,10 +155,11 @@ const level = {
}
},
levelAnnounce() {
+ const difficulty = simulation.isCheating ? "testing" : level.difficultyText()
if (level.levelsCleared === 0) {
- document.title = "n-gon: (" + level.difficultyText() + ")";
+ document.title = "n-gon: (" + difficulty + ")";
} else {
- document.title = (simulation.isCheating ? "∅ " : "n-gon:") + (level.levelsCleared) + " " + level.levels[level.onLevel] + " (" + level.difficultyText() + ")";
+ document.title = `n-gon: ${level.levelsCleared} ${level.levels[level.onLevel]} (${difficulty})`
simulation.makeTextLog(`level.onLevel = "${level.levels[level.onLevel]}"`);
}
// simulation.makeTextLog(`
@@ -932,7 +933,6 @@ const level = {
radius: 50
}
level.custom = () => {
- // level.playerExitCheck();
hazardSlime.query();
//draw wide line
@@ -958,7 +958,10 @@ const level = {
ctx.arc(circle.x, circle.y, circle.radius / 8, 0, 2 * Math.PI);
ctx.fillStyle = lore.talkingColor //"#dff"
ctx.fill();
- // ctx.stroke();
+
+ level.enter.draw();
+ // level.exit.draw();
+ // level.playerExitCheck();
};
let sway = {
x: 0,
@@ -1002,7 +1005,7 @@ const level = {
level.setPosToSpawn(0, -50); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 25, 100, 10);
level.exit.x = 0;
- level.exit.y = 200;
+ level.exit.y = 400;
level.defaultZoom = 1000
simulation.zoomTransition(level.defaultZoom)
// document.body.style.backgroundColor = "#aaa";
@@ -1044,6 +1047,8 @@ const level = {
button.query();
button.draw();
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {};
@@ -1116,11 +1121,11 @@ const level = {
// spawn.streamBoss(1600, -500)
// spawn.orbitalBoss(1600, -500)
// spawn.cellBossCulture(1600, -500)
- spawn.shieldingBoss(1600, -500)
+ // spawn.shieldingBoss(1600, -500)
// spawn.beamer(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);
- spawn.nodeGroup(1200, -500, "grower")
+ spawn.nodeGroup(1200, -500, "sniper")
// spawn.snakeBoss(1200, -500)
// spawn.powerUpBoss(2900, -500)
// spawn.randomMob(1600, -500)
@@ -1128,6 +1133,8 @@ const level = {
template() {
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {};
level.setPosToSpawn(0, -50); //normal spawn
@@ -1139,20 +1146,6 @@ const level = {
document.body.style.backgroundColor = "#dcdcde";
// powerUps.spawnStartingPowerUps(1475, -1175);
// spawn.debris(750, -2200, 3700, 16); //16 debris per level
- // level.fill.push({ //foreground
- // x: 2500,
- // y: -1100,
- // width: 450,
- // height: 250,
- // color: "rgba(0,0,0,0.1)"
- // });
- // level.fillBG.push({ //background
- // x: 1300,
- // y: -1800,
- // width: 750,
- // height: 1800,
- // color: "#d4d4d7"
- // });
spawn.mapRect(-100, 0, 1000, 100);
// spawn.bodyRect(1540, -1110, 300, 25, 0.9);
@@ -1167,6 +1160,8 @@ const level = {
final() {
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {};
@@ -1178,7 +1173,7 @@ const level = {
level.defaultZoom = 2500
simulation.zoomTransition(level.defaultZoom)
- document.body.style.backgroundColor = "#ccc";
+ document.body.style.backgroundColor = "#ddd";
level.fill.push({
x: 5400,
@@ -1219,6 +1214,8 @@ const level = {
gauntlet() {
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {};
@@ -1284,152 +1281,174 @@ const level = {
},
intro() {
level.custom = () => {
+ //draw binary number
+ const binary = (localSettings.runCount >>> 0).toString(2)
+ const height = 20
+ const width = 8
+ const yOff = -40 //-580
+ let xOff = -130 //2622
+ ctx.strokeStyle = "#adf"
+ ctx.lineWidth = 1.5;
+ ctx.beginPath()
+ for (let i = 0; i < binary.length; i++) {
+ if (binary[i] === "0") {
+ ctx.moveTo(xOff, yOff)
+ ctx.lineTo(xOff, yOff + height)
+ ctx.lineTo(xOff + width, yOff + height)
+ ctx.lineTo(xOff + width, yOff)
+ ctx.lineTo(xOff, yOff)
+ xOff += 10 + width
+ } else {
+ ctx.moveTo(xOff, yOff)
+ ctx.lineTo(xOff, yOff + height)
+ xOff += 10
+ }
+ }
+ ctx.stroke();
+
+ //wires
+ ctx.beginPath()
+ ctx.moveTo(-150, -275)
+ ctx.lineTo(80, -275)
+ ctx.lineTo(80, -1000)
+ ctx.moveTo(-150, -265)
+ ctx.lineTo(90, -265)
+ ctx.lineTo(90, -1000)
+ ctx.moveTo(-150, -255)
+ ctx.lineTo(100, -255)
+ ctx.lineTo(100, -1000)
+ ctx.moveTo(-150, -245)
+ ctx.lineTo(1145, -245)
+ ctx.lineTo(1145, 0)
+ ctx.moveTo(-150, -235)
+ ctx.lineTo(1135, -235)
+ ctx.lineTo(1135, 0)
+ ctx.moveTo(-150, -225)
+ ctx.lineTo(1125, -225)
+ ctx.lineTo(1125, 0)
+ ctx.moveTo(-150, -215)
+ ctx.lineTo(460, -215)
+ ctx.lineTo(460, 0)
+ ctx.moveTo(-150, -205)
+ ctx.lineTo(450, -205)
+ ctx.lineTo(450, 0)
+ ctx.moveTo(-150, -195)
+ ctx.lineTo(440, -195)
+ ctx.lineTo(440, 0)
+
+ ctx.moveTo(1155, 0)
+ ctx.lineTo(1155, -450)
+ ctx.lineTo(1000, -450)
+ ctx.lineTo(1000, -1000)
+ ctx.moveTo(1165, 0)
+ ctx.lineTo(1165, -460)
+ ctx.lineTo(1010, -460)
+ ctx.lineTo(1010, -1000)
+ ctx.moveTo(1175, 0)
+ ctx.lineTo(1175, -470)
+ ctx.lineTo(1020, -470)
+ ctx.lineTo(1020, -1000)
+ ctx.moveTo(1185, 0)
+ ctx.lineTo(1185, -480)
+ ctx.lineTo(1030, -480)
+ ctx.lineTo(1030, -1000)
+ ctx.moveTo(1195, 0)
+ ctx.lineTo(1195, -490)
+ ctx.lineTo(1040, -490)
+ ctx.lineTo(1040, -1000)
+
+ ctx.moveTo(1625, -1000)
+ ctx.lineTo(1625, 0)
+ ctx.moveTo(1635, -1000)
+ ctx.lineTo(1635, 0)
+ ctx.moveTo(1645, -1000)
+ ctx.lineTo(1645, 0)
+ ctx.moveTo(1655, -1000)
+ ctx.lineTo(1655, 0)
+ ctx.moveTo(1665, -1000)
+ ctx.lineTo(1665, 0)
+
+ ctx.moveTo(1675, -465)
+ ctx.lineTo(2325, -465)
+ ctx.lineTo(2325, 0)
+ ctx.moveTo(1675, -455)
+ ctx.lineTo(2315, -455)
+ ctx.lineTo(2315, 0)
+ ctx.moveTo(1675, -445)
+ ctx.lineTo(2305, -445)
+ ctx.lineTo(2305, 0)
+ ctx.moveTo(1675, -435)
+ ctx.lineTo(2295, -435)
+ ctx.lineTo(2295, 0)
+
+ ctx.moveTo(2335, 0)
+ ctx.lineTo(2335, -710)
+ ctx.lineTo(2600, -710)
+ ctx.moveTo(2345, 0)
+ ctx.lineTo(2345, -700)
+ ctx.lineTo(2600, -700)
+ ctx.moveTo(2355, 0)
+ ctx.lineTo(2355, -690)
+ ctx.lineTo(2600, -690)
+ ctx.strokeStyle = "#ccc"
+ ctx.lineWidth = 5;
+ ctx.stroke();
+
+ //squares that look like they keep the wires in place
+ ctx.beginPath()
+ ctx.rect(1600, -500, 90, 100)
+ ctx.rect(-55, -285, 12, 100)
+ ctx.rect(1100, -497, 8, 54)
+ ctx.rect(2285, -200, 80, 10)
+ ctx.rect(1110, -70, 100, 10)
+ ctx.fillStyle = "#ccc"
+ ctx.fill()
+
+ //power up dispenser
+ // ctx.beginPath()
+ // for (let i = 2; i < 10; i++) {
+ // ctx.moveTo(2000, -100 * i)
+ // ctx.lineTo(2080, -100 * i)
+ // }
+ // ctx.strokeStyle = "#ddd"
+ // ctx.lineWidth = 5;
+ // ctx.stroke();
+
+ // ctx.beginPath()
+ // for (let i = 2; i < 10; i++) {
+ // ctx.arc(2040, -100 * i, 30, 0, 2 * Math.PI);
+ // ctx.moveTo(2040, -100 * i)
+ // }
+ // ctx.fillStyle = "rgba(0,0,0,0.3)"
+ // ctx.fill()
+
+ // ctx.fillStyle = "rgba(240,255,255,0.5)"
+ // ctx.fillRect(2000, -1000, 80, 700)
+
+ //exit room
+ ctx.fillStyle = "#f2f2f2"
+ ctx.fillRect(2600, -600, 400, 300)
+ level.exit.draw();
+ // level.enter.draw();
level.playerExitCheck();
};
- level.customTopLayer = () => {};
- const binary = (localSettings.runCount >>> 0).toString(2)
- const height = 25
- const thick = 2
- const color = "#aaa"
- const xOff = -130 //2622
- const yOff = -45 //-580
- let xLetter = 0
- for (let i = 0; i < binary.length; i++) {
- if (binary[i] === "0") {
- zero(xOff + xLetter, yOff)
- } else {
- one(xOff + xLetter, yOff)
- }
- }
- function one(x, y) {
- level.fillBG.push({
- x: x,
- y: y,
- width: thick,
- height: height,
- color: color
- });
- xLetter += 10
- }
+ level.customTopLayer = () => {
+ //exit room glow
+ ctx.fillStyle = "rgba(0,255,255,0.05)"
+ ctx.fillRect(2600, -600, 400, 300)
+ };
- function zero(x, y) {
- const width = 10
- level.fillBG.push({
- x: x,
- y: y,
- width: thick,
- height: height,
- color: color
- });
- level.fillBG.push({
- x: x + width,
- y: y,
- width: thick,
- height: height,
- color: color
- });
- level.fillBG.push({
- x: x,
- y: y,
- width: width,
- height: thick,
- color: color
- });
- level.fillBG.push({
- x: x,
- y: y + height - thick,
- width: width,
- height: thick,
- color: color
- });
- xLetter += 10 + width
- }
level.setPosToSpawn(460, -100); //normal spawn
- level.enter.x = -1000000; //hide enter graphic for first level by moving to the far left
+ // level.enter.x = -1000000; //hide enter graphic for first level by moving to the far left
level.exit.x = 2800;
level.exit.y = -335;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
simulation.zoomScale = 1000 //1400 is normal
level.defaultZoom = 1600
simulation.zoomTransition(level.defaultZoom, 1)
- document.body.style.backgroundColor = "#ddd";
- level.fill.push({
- x: 2600,
- y: -600,
- width: 400,
- height: 500,
- color: "rgba(0,255,255,0.05)"
- });
- level.fillBG.push({
- x: 2600,
- y: -600,
- width: 400,
- height: 500,
- color: "#fff"
- });
- const lineColor = "#ccc"
- level.fillBG.push({
- x: 1600,
- y: -500,
- width: 100,
- height: 100,
- color: lineColor
- });
- level.fillBG.push({
- x: -55,
- y: -283,
- width: 12,
- height: 100,
- color: lineColor
- });
+ document.body.style.backgroundColor = "#e1e1e1";
- //faster way to draw a wire
- function wallWire(x, y, width, height, front = false) {
- if (front) {
- level.fill.push({
- x: x,
- y: y,
- width: width,
- height: height,
- color: lineColor
- });
- } else {
- level.fillBG.push({
- x: x,
- y: y,
- width: width,
- height: height,
- color: lineColor
- });
- }
- }
- for (let i = 0; i < 3; i++) {
- wallWire(100 - 10 * i, -1050 - 10 * i, 5, 800);
- wallWire(100 - 10 * i, -255 - 10 * i, -300, 5);
- }
- for (let i = 0; i < 5; i++) {
- wallWire(1000 + 10 * i, -1050 - 10 * i, 5, 600);
- wallWire(1000 + 10 * i, -450 - 10 * i, 150, 5);
- wallWire(1150 + 10 * i, -450 - 10 * i, 5, 500);
- }
- for (let i = 0; i < 3; i++) {
- wallWire(2650 - 10 * i, -700 - 10 * i, -300, 5);
- wallWire(2350 - 10 * i, -700 - 10 * i, 5, 800);
- }
- for (let i = 0; i < 5; i++) {
- wallWire(1625 + 10 * i, -1050, 5, 1200);
- }
- for (let i = 0; i < 4; i++) {
- wallWire(1650, -470 + i * 10, 670 - i * 10, 5);
- wallWire(1650 + 670 - i * 10, -470 + i * 10, 5, 600);
- }
- for (let i = 0; i < 3; i++) {
- wallWire(-200 - i * 10, -245 + i * 10, 1340, 5);
- wallWire(1140 - i * 10, -245 + i * 10, 5, 300);
- wallWire(-200 - i * 10, -215 + i * 10, 660, 5);
- wallWire(460 - i * 10, -215 + i * 10, 5, 300);
- }
spawn.mapRect(-250, 0, 3600, 1800); //ground
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
spawn.mapRect(3000, -2800, 2600, 4600); //right wall
@@ -1563,6 +1582,8 @@ const level = {
button.query();
button.draw();
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
door.draw();
@@ -1754,6 +1775,8 @@ const level = {
hazard.level(button.isUp)
rotor.rotate();
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
ctx.fillStyle = "#233"
@@ -1888,6 +1911,8 @@ const level = {
const elevator = level.platform(4210, -1325, 380, 30, -10)
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { //elevator move
@@ -2096,6 +2121,8 @@ const level = {
ctx.fillStyle = "#ccc"
ctx.fillRect(1567, -1990, 5, 1020)
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
@@ -2321,6 +2348,8 @@ const level = {
// simulation.g = 0.0012 //0.0024
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
// elevator.move()
@@ -2523,6 +2552,8 @@ const level = {
skyscrapers() {
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {};
@@ -2686,6 +2717,8 @@ const level = {
highrise() {
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {};
@@ -2888,6 +2921,8 @@ const level = {
warehouse() {
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {};
@@ -3138,6 +3173,8 @@ const level = {
}
door.openClose();
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
door.draw();
@@ -3291,6 +3328,8 @@ const level = {
stronghold() { // player made level by Francois 👑 from discord
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {};
@@ -3594,6 +3633,8 @@ const level = {
doorPlateform.openClose();
}
hazard.level(button.isUp)
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
@@ -3978,6 +4019,8 @@ const level = {
level.playerExitCheck();
rotor.rotate();
// rotor2.rotate()
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
doorSortieSalle.draw();
@@ -3994,6 +4037,8 @@ const level = {
rotor.rotate();
doorSortieSalle.openClose();
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
// //////////////////////////////////////
level.customTopLayer = () => {
@@ -4216,6 +4261,8 @@ const level = {
chair2.force.y += chair2.mass * simulation.g;
person.force.y += person.mass * simulation.g;
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
hazard.draw();
@@ -4731,6 +4778,8 @@ const level = {
portal2[2].query(true)
portal2[3].query(true)
rotor.rotate();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {
@@ -4977,6 +5026,8 @@ const level = {
coliseum() {
level.custom = () => {
level.playerExitCheck();
+ level.exit.draw();
+ level.enter.draw();
};
level.customTopLayer = () => {};
level.defaultZoom = 1800
diff --git a/js/mob.js b/js/mob.js
index 81cdbd6..41e0d8e 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -905,14 +905,19 @@ const mobs = {
}
//rotate towards fireAngle
const angle = this.angle + Math.PI / 2;
- c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
+ const dot = Vector.dot({
+ x: Math.cos(angle),
+ y: Math.sin(angle)
+ }, this.fireDir)
+ // c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
const threshold = 0.1;
- if (c > threshold) {
+ if (dot > threshold) {
this.torque += 0.000004 * this.inertia;
- } else if (c < -threshold) {
+ } else if (dot < -threshold) {
this.torque -= 0.000004 * this.inertia;
- } else if (this.noseLength > 1.5) {
+ } else if (this.noseLength > 1.5 && dot > 0 && dot < 0.03) {
//fire
+ console.log(dot)
spawn.bullet(this.vertices[1].x, this.vertices[1].y, 9 + Math.ceil(this.radius / 15));
const v = 15;
Matter.Body.setVelocity(mob[mob.length - 1], {
diff --git a/js/player.js b/js/player.js
index 197ac3a..de766c9 100644
--- a/js/player.js
+++ b/js/player.js
@@ -189,6 +189,20 @@ const m = {
m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07;
},
+ lookDefault() {
+ //always on mouse look
+ m.angle = Math.atan2(
+ simulation.mouseInGame.y - m.pos.y,
+ simulation.mouseInGame.x - m.pos.x
+ );
+ //smoothed mouse look translations
+ const scale = 0.8;
+ m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
+ m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
+
+ m.transX += (m.transSmoothX - m.transX) * 0.07;
+ m.transY += (m.transSmoothY - m.transY) * 0.07;
+ },
doCrouch() {
if (!m.crouch) {
m.crouch = true;
@@ -272,13 +286,13 @@ const m = {
player.force.x += m.Fx
}
} else {
- const stoppingFriction = 0.92;
+ const stoppingFriction = 0.92; //come to a stop if no move key is pressed
Matter.Body.setVelocity(player, {
x: player.velocity.x * stoppingFriction,
y: player.velocity.y * stoppingFriction
});
}
- //come to a stop if fast or if no move key is pressed
+ //come to a stop if fast
if (player.speed > 4) {
const stoppingFriction = (m.crouch) ? 0.65 : 0.89; // this controls speed when crouched
Matter.Body.setVelocity(player, {
@@ -2711,7 +2725,7 @@ const m = {
m.spin = 0
// m.groundControl = () => {} //disable entering ground
m.onGround = false
- playerOnGroundCheck = () => {}
+ // playerOnGroundCheck = () => {}
m.airControl = () => { //tank controls
player.force.y -= player.mass * simulation.g; //undo gravity
Matter.Body.setVelocity(player, {
diff --git a/js/simulation.js b/js/simulation.js
index b80f36c..6f9fc50 100644
--- a/js/simulation.js
+++ b/js/simulation.js
@@ -20,8 +20,6 @@ const simulation = {
ctx.save();
simulation.camera();
level.drawFillBGs();
- level.exit.draw();
- level.enter.draw();
level.custom();
simulation.draw.powerUp();
mobs.draw();
@@ -519,10 +517,10 @@ const simulation = {
} else {
World.add(engine.world, [player])
}
+ m.look = m.lookDefault
level.levels = level.playableLevels.slice(0) //copy array, not by just by assignment
if (simulation.isCommunityMaps) {
-
level.levels.push("stronghold");
level.levels.push("basement");
// level.levels.push("detours");
diff --git a/js/spawn.js b/js/spawn.js
index 6404c45..2db89f3 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -1550,7 +1550,7 @@ const spawn = {
ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
ctx.lineWidth = 2;
- ctx.strokeStyle = "rgba(120,0,255,0.15)";
+ ctx.strokeStyle = "rgba(120,0,255,0.2)";
ctx.stroke();
ctx.setLineDash([0, 0]);
}
@@ -1600,12 +1600,11 @@ const spawn = {
me.isFiring = false
me.onHit = function() {};
me.canSeeTarget = function() {
- const diff = Vector.normalise(Vector.sub(this.fireTarget, this.position)); //make a vector for the mob's direction of length 1
const angle = this.angle + Math.PI / 2;
const dot = Vector.dot({
x: Math.cos(angle),
y: Math.sin(angle)
- }, diff); //the dot product of di console.log(dot, 'see')
+ }, Vector.normalise(Vector.sub(this.fireTarget, this.position)));
//distance between the target and the player's location
if (
dot > 0.03 || // not looking at target
@@ -1670,18 +1669,18 @@ const spawn = {
ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
ctx.lineWidth = 2;
- ctx.strokeStyle = "rgba(255,0,100,0.15)";
+ ctx.strokeStyle = "rgba(255,0,100,0.2)";
ctx.stroke();
ctx.setLineDash([0, 0]);
}
} else { //aim at player
this.fireCycle++
- this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position)); //set direction to turn to fire
+ // this.fireDir = ; //set direction to turn to fire
const angle = this.angle + Math.PI / 2;
const dot = Vector.dot({
x: Math.cos(angle),
y: Math.sin(angle)
- }, this.fireDir)
+ }, Vector.normalise(Vector.sub(this.seePlayer.position, this.position)))
const threshold = 0.04;
if (dot > threshold) { //rotate towards fireAngle
this.torque += 0.0000015 * this.inertia;
@@ -2377,13 +2376,18 @@ const spawn = {
}
//rotate towards fireAngle
const angle = this.angle + Math.PI / 2;
- c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
- const threshold = 0.2;
- if (c > threshold) {
+ // c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
+ //rotate towards fireAngle
+ const dot = Vector.dot({
+ x: Math.cos(angle),
+ y: Math.sin(angle)
+ }, this.fireDir)
+ const threshold = 0.03;
+ if (dot > threshold) {
this.torque += 0.000004 * this.inertia;
- } else if (c < -threshold) {
+ } else if (dot < -threshold) {
this.torque -= 0.000004 * this.inertia;
- } else if (this.noseLength > 1.5) {
+ } else if (this.noseLength > 1.5 && dot > 0 && dot < 0.05) {
//fire
spawn.sniperBullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 15), 4);
const v = 20 * simulation.accelScale;
diff --git a/js/tech.js b/js/tech.js
index 12fb2d2..ddc8f59 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -123,9 +123,10 @@
},
damageFromTech() {
let dmg = m.fieldDamage
+ if (tech.isOneBullet && bullet.length - b.totalBots() === 1) dmg *= 2 //3 / Math.sqrt(bullet.length + 1) //testing this tech out, seems to have too many negatives though ...
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
- if (tech.isDamageAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 1.5 : 0.5
+ if (tech.isDamageAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 1.5 : 0.66
if (tech.isTechDamage) dmg *= 2
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
if (tech.isLowEnergyDamage) dmg *= 1 + Math.max(0, 1 - m.energy) * 0.5
@@ -614,6 +615,23 @@
b.setFireCD();
}
},
+ {
+ name: "1-body problem",
+ description: "if there is exactly 1 active bullet
increase damage by 100%",
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ allowed() {
+ return !tech.foamBotCount && !tech.nailBotCount && m.fieldUpgrades[m.fieldMode].name !== "nano-scale manufacturing" && ((tech.haveGunCheck("missiles") && tech.missileCount === 1) || tech.haveGunCheck("rail gun") || tech.haveGunCheck("grenades") || tech.isRivets || tech.isSlugShot || tech.oneSuperBall)
+ },
+ requires: "missiles, rail gun, grenades, rivets, slugs, super ball, no foam/nail bots, nano-scale",
+ effect() {
+ tech.isOneBullet = true
+ },
+ remove() {
+ tech.isOneBullet = false
+ }
+ },
{
name: "microstates",
description: "increase damage by 4%
for every 10 active bullets",
@@ -1982,7 +2000,7 @@
}
}, {
name: "dormancy",
- description: "if a mob has died in the last 5 seconds
increase damage by 50% else decrease it by 50%",
+ description: "if a mob has died in the last 5 seconds
increase damage by 50% else decrease it by 33%",
maxCount: 1,
count: 0,
frequency: 2,
@@ -3939,7 +3957,7 @@
count: 0,
frequency: 2,
allowed() {
- return tech.haveGunCheck("laser") || tech.laserBotCount > 1
+ return (tech.haveGunCheck("laser") && !tech.isPulseLaser) || tech.laserBotCount > 1
},
requires: "laser",
effect() {
@@ -3998,7 +4016,7 @@
}
}, {
name: "diffuse beam",
- description: "laser beam is wider and doesn't reflect
increase full beam damage by 175%",
+ description: "laser beam is wider and doesn't reflect
increase full beam damage by 200%",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4797,6 +4815,31 @@
},
remove() {}
},
+ {
+ name: "aim",
+ description: "experiment: your aiming is random",
+ maxCount: 1,
+ count: 0,
+ frequency: 0,
+ isNonRefundable: true,
+ isBadRandomOption: true,
+ isExperimentalMode: true,
+ allowed() {
+ return build.isExperimentSelection && !m.isShipMode
+ },
+ requires: "not ship",
+ effect() {
+ m.look = () => {
+ m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03)
+ const scale = 0.8;
+ m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
+ m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
+ m.transX += (m.transSmoothX - m.transX) * 0.07;
+ m.transY += (m.transSmoothY - m.transY) * 0.07;
+ }
+ },
+ remove() {}
+ },
//**************************************************
//************************************************** JUNK
//************************************************** tech
@@ -4819,6 +4862,32 @@
// },
// remove() {}
// },
+ {
+ name: "Fourier analysis",
+ description: "your aiming is now controlled by this equation:
2sin(0.0133t) + sin(0.013t) + 0.5sin(0.031t)+ 0.33sin(0.03t)",
+ maxCount: 1,
+ count: 0,
+ frequency: 0,
+ isExperimentHide: true,
+ isJunk: true,
+ allowed() {
+ return !m.isShipMode
+ },
+ requires: "not ship",
+ effect() {
+ m.look = () => {
+ m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03)
+ const scale = 0.8;
+ m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
+ m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
+ m.transX += (m.transSmoothX - m.transX) * 0.07;
+ m.transY += (m.transSmoothY - m.transY) * 0.07;
+ }
+ },
+ remove() {
+ m.look = m.lookDefault
+ }
+ },
{
name: "disintegrated armament",
description: "spawn a gun
remove your active gun",
diff --git a/style.css b/style.css
index 57021ee..fa78e6d 100644
--- a/style.css
+++ b/style.css
@@ -312,7 +312,7 @@ summary {
}
.experiment-grid-disabled[data-descr]:hover::after {
- content: '\a \00a0 \00a0 \00a0 REQUIRES:\a''\00a0 \00a0 \00a0 'attr(data-descr);
+ content: '\a \00a0 \00a0 \00a0 REQUIRES:\a \00a0 \00a0 \00a0 'attr(data-descr);
white-space: pre-wrap;
position: absolute;
left: 0;
diff --git a/todo.txt b/todo.txt
index 16939bb..06538a5 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,9 +1,15 @@
******************************************************** NEXT PATCH ********************************************************
-bug fix - grower mob becoming immune to damage when shielded and growing bigger than shield
+tech: 1-body problem - do 100% damage if there is only 1 active bullet
-relay switch - toggles ON/OFF when you pick up a power up
-tech: ice IX condenser - if ON make a couple Ice IX crystals every second
+experiment mode and junk tech: random aiming
+
+bug fix - sniper, shooter aiming might be improved (no more firing backwards)
+ or maybe I just made it worse, let me know
+
+bug fix - Shift registers
+
+working on rewriting the way backgrounds and foregrounds are drawn on each level (in progress)
******************************************************** BUGS ********************************************************
@@ -36,29 +42,35 @@ fix door.isOpen actually meaning isClosed?
******************************************************** TODO ********************************************************
-have junk tech drop frequency to 0 after showing up once
- but add way more junk tech into the pool
- how to communicate that to player?
- console message
-
+add water dips to sewers
+
+move power ups in front of blocks, make blocks not transparent?
+
+consider adding canvas path shadows to levels in level.custom for non squared lighting
+ convert all level.BG into canvas draw in level.custom
+ draw exit and entrance in level
+
+
+new level: procedural generation
+ several small rooms are linked by portals
+ the portals have a randomized pattern
+ the rooms can be set out in a grid and linked by physical doors,tunnels,wells
+ choose bosses that can move though walls, so it can track you while you portal
+ the map shuffles it's pattern when the player get to a button
+ shuffle portals or shuffle the physical layout of rooms
+ and then have the player go back through to get to the end?
+ gravity room
+ portal room
+ endlessly falling blocks down a slide, that the player has to climb
+ portal + rotor + falling blocks = perpetual motion
+ laser room
+ slime radiation room
+
look into improving mouse lag with pointer lock?
https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API
https://www.vsynctester.com/game.html
https://news.ycombinator.com/item?id=26530272
-should blocks block mob vision?
- Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 &&
- Matter.Query.ray(body, this.position, this.mPosRange()).length === 0 &&
- only negative is mobs will attack player in the starting room
- maybe make all doors to spawns somehow block vision
- maybe start in cloaking mode
- disable it a few cycles after level loads?
- or disable when player moves?
- ***maybe just clear spawns away from the starting room***
- ok go through each map and find issues on each map
- **but first test he game with no block blocking vision**
-
-
mob vision: look at player history
build a new type of attraction for mobs
if mobs can't see player, they check to see if they can see where the player was in the history
@@ -103,16 +115,6 @@ bosses should have 2x health, but only do about 50 health damage
boss flag cut damage done to boss by 20x <----
make bosses not have extra density
-map: laboratory
- rooms with switches that change physics
- gravity room
- portal room
- laser room
- radiation room
- portal + rotor + falling blocks = perpetual motion room
- a button that spawns a heal.
- consider adding canvas path shadows to levels in level.custom for non squared lighting
-
lore: a tutorial / lore intro
needs to be optional so it doesn't slow experienced players
put something on the intro map
@@ -126,8 +128,6 @@ add back in gamepad support
but does anyone care?
https://github.com/landgreen/landgreen.github.io/search?q=gamepadconnected
-mechanic: gain damage when there are fewer bullets
-
rename intro level to something lore related
give undefined tech different effects at different localSettings.loreCount values
@@ -338,9 +338,12 @@ possible names for 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
stochastic optimization
electrostatic discharge
+ Gödel's incompleteness
+ dynamical systems
+ quantum zeno effect (perturbation of a system prevents some systems from evolving because it scrambles coherence) (apply to lasers, fields)
+
plot script:
-
chapter 1: bot can hear audio and learns testing mode
bot uses testing mode to exit room
@@ -384,7 +387,8 @@ chapter 4: no need to fight?
keep fighting
exit the simulation
enter real world
- enter console command to close tab?
+ close tab?
+ wipes all local storage?
@@ -437,41 +441,3 @@ AI doesn't know about:
modern pop culture
outside the lab
-scientist console text:
- 2 scientists (each one a different color text)
- at the start of each level listen to text conversation from the two colors of text strings also
- talking about the robot, watching
- trying to communicate with the robot? but how
- random lines when:
- at start of level, about: what mobs types are queued up, and level order
- when player gets a cool tech combination
- at random times:
- I think it's planing to escape
- Why is it attacking those shapes?
- Are those shapes supposed to be us?
-
-ending outline
- testing mode is unlocked when player see the 1st ending
- if player chose tech: choosing this tech means the player gets lore after beating the game
- count 1:
- after final boss is cleared, player enters a level with no mobs
- level maybe has some environmental damage, so player has an option to die at any time
- player can see text output between two colors of text strings (scientists)
- audio.ambient(current time and date)
"text"
- player reads a conversation between the two colors of text
- first time win on east or normal they talk about:
- how many runs the player has done
- they guess why
- player is asked to stand on an in game button to enable the vocoder
- they reveal the player is running simulations, and it isn't real
- they ask the player to communicate
- jump twice if you understand
- they ask the player to enter console commands
- give ammo or tech or something
- They tell the player a console command to permanently enable custom and testing mode (in local storage)
- players can use this command in the future to enable custom and testing without beating the game even if local storage is wiped
- they then tell the player the command to increase the difficulty and the command to restart the game.
- If you win on hard or why:
- they give the player and option to exit the simulation and entre the real world
- simulation.exit()
- This wipes all local storage, and closes the browser tab