From 4848cc4e73d350005fd53a2432ba8825a5fb659f Mon Sep 17 00:00:00 2001 From: landgreen Date: Tue, 30 Mar 2021 05:23:56 -0700 Subject: [PATCH] 1-body problem tech: 1-body problem - do 100% damage if there is only 1 active bullet 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) --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 10 +- js/index.js | 1 + js/level.js | 365 +++++++++++++++++++++++++++-------------------- js/mob.js | 13 +- js/player.js | 20 ++- js/simulation.js | 4 +- js/spawn.js | 26 ++-- js/tech.js | 77 +++++++++- style.css | 2 +- todo.txt | 112 +++++---------- 11 files changed, 369 insertions(+), 261 deletions(-) diff --git a/.DS_Store b/.DS_Store index bf21f88bd93cc9090d027da08a3e7f87fd026c4f..17e7534e44b57c508e0f98b1c9dad43fcff3fe4b 100644 GIT binary patch delta 22 dcmZoMXffEJ#muyM=VTpbUnUWT&DG4EA^=jh2B!c3 delta 22 dcmZoMXffEJ#muzKY_blsFO%?x&DG4EA^=eG2L=ED 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