From 5eae070238f49bbc0061443edbe291dcdf3a537d Mon Sep 17 00:00:00 2001 From: landgreen Date: Fri, 19 Jul 2024 16:34:01 -0700 Subject: [PATCH] new level - flocculation new level - flocculation snakeBoss does 40% less damage to player --- js/index.js | 12 +- js/level.js | 490 +++++++++++++++++++++++++++++++++++++---------- js/simulation.js | 11 ++ js/spawn.js | 4 +- js/tech.js | 12 +- todo.txt | 39 ++-- 6 files changed, 438 insertions(+), 130 deletions(-) diff --git a/js/index.js b/js/index.js index 9fc1ca2..86003be 100644 --- a/js/index.js +++ b/js/index.js @@ -1476,10 +1476,12 @@ window.addEventListener("keydown", function (event) { } else { simulation.testing = true; simulation.loop = simulation.testingLoop - if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline' if (simulation.testing) tech.setCheating(); - simulation.makeTextLog( - ` + if (simulation.isConstructionMode) { + document.getElementById("construct").style.display = 'inline' + } else { + simulation.makeTextLog( + `
@@ -1531,8 +1533,8 @@ window.addEventListener("keydown", function (event) { - -
T toggle testing
⇧X restart
`, Infinity); + `, Infinity); + } } } break diff --git a/js/level.js b/js/level.js index 4bc8273..3c7c368 100644 --- a/js/level.js +++ b/js/level.js @@ -9,7 +9,7 @@ const level = { onLevel: -1, levelsCleared: 0, //see level.populateLevels: (initial, ... , reservoir or factory, reactor, ... , subway, final) added later - playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers"], + playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers", "flocculation"], 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: [], @@ -17,6 +17,8 @@ const level = { if (level.levelsCleared === 0) { //this code only runs on the first level // simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode // simulation.isHorizontalFlipped = true + // level.levelsCleared = 4 + // level.updateDifficulty() // tech.giveTech("performance") // m.maxHealth = m.health = 1//00000000 // m.maxEnergy = m.energy = 10000000 @@ -45,33 +47,21 @@ const level = { // tech.giveTech("1st ionization energy") // for (let i = 0; i < 1; ++i) tech.giveTech("booby trap") // for (let i = 0; i < 1; ++i) tech.giveTech("obsolescence") - // for (let i = 0; i < 1; ++i) tech.giveTech("arsenal") + // for (let i = 0; i < 1; ++i) tech.giveTech("brainstorming") // requestAnimationFrame(() => { for (let i = 0; i < 3; i++) tech.giveTech("mechatronics") }); - // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("paradigm shift") }); - // for (let i = 0; i < 2; i++) tech.giveTech("nail-bot") + // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("eternalism") }); + // for (let i = 0; i < 2; i++) tech.giveTech("technical debt") // m.lastKillCycle = m.cycle - // for (let i = 0; i < 1; ++i) tech.giveTech("cross-disciplinary") + // for (let i = 0; i < 1; ++i) tech.giveTech("determinism") // for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech"); - // for (let i = 0; i < 1; i++) powerUps.directSpawn(-50, -70, "difficulty", false); + // for (let i = 0; i < 1; i++) powerUps.directSpawn(m.pos.x, m.pos.y - 50, "difficulty", false); // spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing - // level.testing(); - - // for (let i = 0; i < 1; ++i) spawn.snakeBoss(1400, -500) - // for (let i = 0; i < 20; i++) powerUps.directSpawn(0, 0, "coupling"); - // Matter.Body.setPosition(player, { x: -200, y: -3330 }); - // for (let i = 0; i < 4; ++i) spawn.sucker(1300, -500 + 100 * Math.random()) - // spawn.hopper(1900, -500) - // spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color) - // for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random()) - // tech.tech[322].frequency = 100 - // spawn.tetherBoss(1900, -500, { x: 1900, y: -500 }) - // for (let i = 0; i < 40; ++i) tech.giveTech() + // level.flocculation(); level[simulation.isTraining ? "walk" : "initial"]() //normal starting level ************************************************** - // for (let i = 0; i < 1; ++i) spawn.laserLayerBoss(1900, -500) + // for (let i = 0; i < 1; ++i) spawn.snakeBoss(1900, -500) // for (let i = 0; i < 2; i++) spawn.ghoster(level.exit.x, level.exit.y) //ghosters need to spawn after the map loads - // console.log(body[body.length - 1].mass) // simulation.isAutoZoom = false; //look in close // simulation.zoomScale *= 0.5; // simulation.setZoom(); @@ -922,10 +912,7 @@ const level = { return who } }, - elevator(x, y, width, height, maxHeight, force = 0.003, friction = { - up: 0.01, - down: 0.2 - }, isAtTop = false) { + elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }, isAtTop = false) { x += width / 2 y += height / 2 maxHeight += height / 2 @@ -934,7 +921,7 @@ const level = { const who = body[body.length] = Bodies.rectangle(x, isAtTop ? maxHeight : y, width, height, { collisionFilter: { category: cat.body, //cat.map, - mask: cat.map | cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + mask: cat.player | cat.body | cat.bullet | cat.mob | cat.mobBullet //| cat.powerUp }, inertia: Infinity, //prevents rotation isNotHoldable: true, @@ -990,17 +977,69 @@ const level = { x: this.holdX, y: this.position.y }); + }, + moveOnTouch() { + if (!m.isBodiesAsleep) { + if (this.isUp) { //moving up still with high air friction + this.force.y -= force * this.mass //hard force propels up, even with high friction + if (this.position.y < maxHeight) { //switch to down mode + this.isUp = false + this.frictionAir = friction.down + //adds a hard jerk at the top of vertical motion because it's fun + Matter.Body.setPosition(this, { x: this.holdX, y: maxHeight }); + Matter.Body.setVelocity(this, { x: 0, y: 0 }); + } + } else if (this.position.y + 10 * this.velocity.y > y) { //free falling down, with only air friction + //slow down early to avoid a jerky stop that can pass through blocks + Matter.Body.setVelocity(this, { x: 0, y: this.velocity.y * 0.7 }); + //switch to up mode + // if (this.position.y + this.velocity.y > y) { + // this.isUp = true + // this.frictionAir = friction.up + // } + } + Matter.Body.setVelocity(this, { x: 0, y: this.velocity.y }); + } + //draw line to show how far to will extend + ctx.beginPath(); + ctx.moveTo(x, y + height / 2); + ctx.lineTo(x, maxHeight - height / 2); + ctx.strokeStyle = `rgba(0,0,0,0.2)` + // ctx.lineWidth = "3" + ctx.stroke(); + + //draw body + ctx.beginPath(); + ctx.moveTo(this.vertices[0].x, this.vertices[0].y); + for (let j = 1; j < this.vertices.length; j++) { + ctx.lineTo(this.vertices[j].x, this.vertices[j].y); + } + ctx.lineTo(this.vertices[0].x, this.vertices[0].y); + ctx.lineWidth = "2" + ctx.strokeStyle = `#333` + ctx.fillStyle = `rgba(200,200,200,1)` + //edge limits + if (this.position.y < maxHeight) { + Matter.Body.setPosition(this, { x: this.holdX, y: maxHeight }); + } else if (this.position.y > y) { + ctx.fillStyle = `rgba(255,255,255,${0.5 + 0.15 * Math.random()})` + Matter.Body.setPosition(this, { x: this.holdX, y: y }); + //undoing force of gravity + this.force.y -= this.mass * simulation.g; + if (Matter.Query.collides(this, [player]).length) { + this.isUp = true + this.frictionAir = friction.up + } + } + ctx.fill(); + ctx.stroke(); + // hold horizontal position + Matter.Body.setPosition(this, { x: this.holdX, y: this.position.y }); }, off() { - Matter.Body.setPosition(this, { - x: this.holdX, - y: this.position.y - }); - Matter.Body.setVelocity(this, { - x: 0, - y: this.velocity.y - }); + Matter.Body.setPosition(this, { x: this.holdX, y: this.position.y }); + Matter.Body.setVelocity(this, { x: 0, y: this.velocity.y }); }, constraint: this.null, addConstraint() { @@ -1028,73 +1067,69 @@ const level = { who.classType = "body" return who }, - spring(x, y, v = "-100 0 100 0 70 40 0 50 -70 40", force = 0.01, distance = 300, angle = 0) { - const who = body[body.length] = Matter.Bodies.fromVertices(x, y, Vertices.fromPath(v), { - collisionFilter: { - category: cat.body, - mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet - }, - inertia: Infinity, //prevents rotation - isNotHoldable: true, - friction: 1, - frictionStatic: 1, - restitution: 0, - frictionAir: 1, - density: 0.1, - isReady: true, - isResetting: false, - query() { - if (this.isReady) { - if (Matter.Query.collides(this, [player]).length) { - this.isReady = false - this.constraint.stiffness = 0 - this.constraint.damping = 0 //0.3 - this.frictionAir = 0 - Matter.Body.setVelocity(this, { - x: 0, - y: 0 - }); - //show graphically being ready? - - } - } else { - if (this.isResetting) { - this.constraint.stiffness += 0.0005 - if (this.constraint.stiffness > 0.1) { - this.isResetting = false - this.isReady = true - } - } else { - if (Vector.magnitudeSquared(Vector.sub(this.position, { - x: x, - y: y - })) < distance * distance) { - this.force.y -= force * this.mass - } else { - this.constraint.damping = 1 - this.frictionAir = 1 - this.isResetting = true - Matter.Body.setVelocity(this, { - x: 0, - y: 0 - }); - } - } - } - } - }); - who.constraint = Constraint.create({ - pointA: { - x: who.position.x, - y: who.position.y - }, - bodyB: who, - stiffness: 1, - damping: 1 - }); - Composite.add(engine.world, who.constraint); - return who - }, + // spring(x, y, v = "-100 0 100 0 70 40 0 50 -70 40", force = 0.01, distance = 300, angle = 0) { + // const who = body[body.length] = Matter.Bodies.fromVertices(x, y, Vertices.fromPath(v), { + // collisionFilter: { + // category: cat.body, + // mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + // }, + // inertia: Infinity, //prevents rotation + // isNotHoldable: true, + // friction: 1, + // frictionStatic: 1, + // restitution: 0, + // frictionAir: 1, + // density: 0.1, + // isReady: true, + // isResetting: false, + // query() { + // if (this.isReady) { + // if (Matter.Query.collides(this, [player]).length) { + // this.isReady = false + // this.constraint.stiffness = 0 + // this.constraint.damping = 0 //0.3 + // this.frictionAir = 0 + // Matter.Body.setVelocity(this, { x: 0, y: 0 }); + // //show graphically being ready? + // } + // } else { + // if (this.isResetting) { + // this.constraint.stiffness += 0.0005 + // if (this.constraint.stiffness > 0.1) { + // this.isResetting = false + // this.isReady = true + // } + // } else { + // if (Vector.magnitudeSquared(Vector.sub(this.position, { + // x: x, + // y: y + // })) < distance * distance) { + // this.force.y -= force * this.mass + // } else { + // this.constraint.damping = 1 + // this.frictionAir = 1 + // this.isResetting = true + // Matter.Body.setVelocity(this, { + // x: 0, + // y: 0 + // }); + // } + // } + // } + // } + // }); + // who.constraint = Constraint.create({ + // pointA: { + // x: who.position.x, + // y: who.position.y + // }, + // bodyB: who, + // stiffness: 1, + // damping: 1 + // }); + // Composite.add(engine.world, who.constraint); + // return who + // }, // rotor(x, y, rotate = 0, radius = 800, width = 40, density = 0.0005) { // const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, { // density: density, @@ -4893,7 +4928,6 @@ const level = { balance1 = level.spinner(x + 200, y - 500, 30, 400, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) // spinner(x, y, width, height, density = 0.001, angle=0,frictionAir=0.001,angularVelocity=0) { balance2 = level.spinner(x + 200, y - 950, 30, 400, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) balance3 = level.spinner(x + 650, y - 750, 30, 400, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) - // balance4 = level.spinner(x + 750, y - 1050, 25, 350, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) balance4 = level.spinner(x + 1250, y - 1000, 30, 400, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) let isInRoom = false @@ -6760,6 +6794,260 @@ const level = { balance5 = level.rotor(2605, 1100, 390, 25, 0.001) //falling } + }, + flocculation() { + level.announceMobTypes() + const button0 = level.button(1125, 795) + const button1 = level.button(6538, 2670) + const button2 = level.button(1225, -100) + button0.isUp = true + button1.isUp = true + button2.isUp = true + // const hazard = level.hazard(4550, 2750, 4550, 150) + const hazard = level.hazard(simulation.isHorizontalFlipped ? -7200 : 675, 50, 7500, 3000) //1869 + // hazard.min.y = 3000 //REMOVE THIS IN LIVE VERSION!!!!! set slime to lowest level + let balance1, balance2, balance3, rotor1, rotor2 + + const drip1 = level.drip(6100, 1900, 2900, 100) // drip(x, yMin, yMax, period = 100, color = "hsla(160, 100%, 35%, 0.5)") { + const drip2 = level.drip(7300, 1900, 2900, 150) + const drip3 = level.drip(8750, 1900, 2900, 70) + + //up mode triggered by player contact + const elevator0 = level.elevator(700, 1865, 200, 490, 1400, 0.011, { up: 0.01, down: 0.7 }) + const elevator1 = level.elevator(3995, 2335, 210, 150, 1700, 0.011, { up: 0.01, down: 0.7 }) + + level.custom = () => { + drip1.draw(); + drip2.draw(); + drip3.draw(); + if (button0.isUp) { + button0.query(); + if (!button0.isUp) { //summon second set of mobs + //1 boss, 1-2 groups, 11 mobs (all on lower ground level, where the slime is leaving) + spawn.randomMob(918, 2695, 0.1); + spawn.randomMob(1818, 2719, 0.2); + spawn.randomMob(2530, 2460, 0.2); + spawn.randomMob(3109, 2665, 0.3); + spawn.randomMob(3909, 2191, 0.3); + spawn.randomMob(4705, 2711, 0.4); + spawn.randomMob(5800, 2796, 0.5); + spawn.randomMob(7287, 2757, 0.6); + spawn.randomMob(5759, 2691, 0.9); + spawn.randomMob(5675, 2225, 0.8); + spawn.randomMob(7450, 2775, 0.8); + + spawn.randomGroup(6600, 2400, 0.1); + if (simulation.difficulty > 1) spawn.randomLevelBoss(6076, 2341); + } + } + button0.draw(); + if (button1.isUp) button1.query(); + button1.draw(); + if (button2.isUp) button2.query(); + button2.draw(); + ctx.fillStyle = "hsl(175, 15%, 76%)" + ctx.fillRect(7625, 2625, 400, 300) + ctx.fillStyle = "rgba(0,0,0,0.03)" //shadows + ctx.fillRect(6250, 1875, 700, 875) + ctx.fillRect(900, 1200, 600, 1725) //900, 1350, 600, 1600); + ctx.fillRect(3000, 1200, 1000, 1750); + ctx.fillRect(2200, 625, 400, 2050); + + level.exit.drawAndCheck(); + level.enter.draw(); + }; + level.customTopLayer = () => { + elevator0.moveOnTouch() + elevator1.moveOnTouch() + rotor1.rotate(); + rotor2.rotate(); + + ctx.fillStyle = "#233" + ctx.beginPath(); + ctx.arc(balance1.center.x, balance1.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance2.center.x, balance2.center.y) + ctx.arc(balance2.center.x, balance2.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance3.center.x, balance3.center.y) + ctx.arc(balance3.center.x, balance3.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance5.center.x, balance5.center.y) + ctx.arc(balance5.center.x, balance5.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(rotor1.center.x, rotor1.center.y) + ctx.arc(rotor1.center.x, rotor1.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(rotor2.center.x, rotor2.center.y) + ctx.arc(rotor2.center.x, rotor2.center.y, 9, 0, 2 * Math.PI); + ctx.fill(); + hazard.query(); + const drainRate = Math.max(1, 4 - hazard.min.y / 800) + hazard.level( + (button2.isUp || hazard.height < 1150) && + (button0.isUp || hazard.height < 350) && + button1.isUp + , drainRate) //true = hold, false = lower + exitDoor.isClosing = hazard.min.y < 2900 + exitDoor.openClose(); + exitDoor.draw(); + }; + + level.setPosToSpawn(0, -50); //normal spawn + spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); + level.exit.x = 7800; + level.exit.y = 2865; + const exitDoor = level.door(7637, 2680, 25, 225, 195, 5) + + level.defaultZoom = 1800 + simulation.zoomTransition(level.defaultZoom) + document.body.style.backgroundColor = "hsl(138, 3%, 74%)"; + color.map = "#3d4240" + powerUps.spawnStartingPowerUps(3475, 1775); + spawn.debris(4575, 2550, 1600, 6); //16 debris per level + spawn.debris(750, 2550, 2250, 6); //16 debris per level + + spawn.mapRect(-500, -600, 200, 800); //left entrance wall + spawn.mapRect(-400, -600, 3550, 200); //ceiling + spawn.mapRect(-400, 0, 1400, 600); + + spawn.mapRect(575, 475, 250, 250); + Matter.Body.setAngle(map[map.length - 1], map[map.length - 1].angle - Math.PI / 4); + spawn.mapRect(4075, 75, 250, 250); + Matter.Body.setAngle(map[map.length - 1], map[map.length - 1].angle - Math.PI / 4); + spawn.mapRect(4259, 1559, 282.5, 282.5); + Matter.Body.setAngle(map[map.length - 1], map[map.length - 1].angle - Math.PI / 4); + + spawn.mapRect(3140, -600, 200, 800); //right down tube wall + spawn.mapRect(3150, 0, 1200, 200); //tube right exit ceiling + spawn.mapVertex(2400, 500, "-200 -100 -100 -200 100 -200 200 -100 200 200 -200 200"); + spawn.mapVertex(2400, 1200, "-200 -200 200 -200 200 100 100 200 -100 200 -200 100"); + spawn.mapVertex(1200, 2150, "-300 -300 300 -300 300 200 200 300 -200 300 -300 200"); + spawn.mapVertex(1200, 1100, "-300 -200 -200 -300 200 -300 300 -200 300 300 -300 300"); + spawn.mapVertex(3500, 950, "-500 -450 -400 -550 400 -550 500 -450 500 450 400 550 -400 550 -500 450"); + spawn.mapVertex(3500, 1990, "-300 -40 -230 -110 230 -110 300 -40 300 40 230 110 -230 110 -300 40"); + // spawn.mapVertex(2400, 1940, "-200 -40 -150 -90 150 -90 200 -40 200 40 150 90 -150 90 -200 40"); + spawn.mapRect(2200, 1850, 400, 200); + spawn.bodyRect(3825, 2240, 150, 75, 0.5); + + spawn.mapVertex(3500, 2452, "-500 -135 500 -135 500 35 400 135 -400 135 -500 35"); + spawn.mapVertex(1200, 2875, "-400 0 -300 -100 300 -100 400 0"); + spawn.mapVertex(1317, 275, "-500 0 -300 -200 300 -200 550 50 550 500 -500 500"); + spawn.mapVertex(1300, -357, "-300 0 -400 -100 400 -100 300 0"); + spawn.bodyRect(1550, -308, 50, 208, 0.5); + spawn.bodyRect(2000, 965, 525, 25, 0.5); + spawn.mapVertex(2400, 2850, "-350 -50 -300 -100 300 -100 350 -50 350 300 -350 300"); + spawn.mapVertex(6600, 1925, "-350 0 -450 -100 450 -100 350 0"); + spawn.mapVertex(6600, 2875, "-400 -50 -350 -100 350 -100 400 -50 400 300 -400 300"); + + spawn.bodyRect(2375, 300, 100, 100, 0.6); + spawn.bodyRect(1025, 1775, 100, 75, 0.6); + spawn.bodyRect(1250, 1825, 50, 25, 0.6); + spawn.bodyRect(3700, 275, 125, 125, 0.6); + spawn.bodyRect(5875, 2725, 200, 200, 0.6); + spawn.bodyRect(6900, 2590, 50, 50, 0.6); + spawn.mapRect(4200, 2325, 250, 625); + spawn.mapRect(-500, 50, 1200, 3050); + spawn.mapRect(-500, 2900, 9600, 775); + + spawn.mapRect(4400, 0, 4700, 1900); + spawn.mapRect(4200, 0, 200, 1700); + // spawn.mapRect(6250, 2675, 700, 325); + // spawn.mapRect(6250, 1875, 700, 150); + + //exit room + spawn.mapRect(8000, 1775, 1100, 1375); + spawn.mapRect(7625, 1825, 450, 825); + spawn.mapRect(7625, 2625, 50, 75); + spawn.mapRect(7625, 2890, 400, 25); + spawn.mapRect(7800, 2880, 100, 25); + + spawn.randomMob(2450, 250, 0.2); + spawn.randomMob(3250, 325, 0.2); + spawn.randomMob(3625, 350, 0.3); + spawn.randomMob(1750, -25, 0.4); + spawn.randomMob(1300, 1750, 0.5); + spawn.randomMob(2350, 1725, 0.6); + spawn.randomMob(3350, 1775, 0.7); + spawn.randomMob(1025, 750, 0.8); + spawn.randomMob(2400, 1775, 0.8); + spawn.randomMob(1250, 1725, 0.8); + spawn.randomMob(775, 1775, 0.9); + powerUps.addResearchToLevel() //needs to run after mobs are spawned + spawn.secondaryBossChance(1822, 1336) + + if (simulation.isHorizontalFlipped) { //flip the map horizontally + level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit + rotor1 = level.rotor(-5600, 2390, 850, 50, 0.001, 0, 0.01, 0, 0.001) //balance(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0, rotationForce = 0.0005) { + rotor2 = level.rotor(-2175, 1900, 650, 50, 0.001, 0, 0.01, 0, 0.0007) + + balance1 = level.rotor(-800 - 25, -395, 25, 390, 0.001) //entrance + balance2 = level.rotor(-2605 - 390, 500, 390, 25, 0.001) //falling + balance3 = level.rotor(-2608 - 584, 1950, 584, 25, 0.001) //falling + balance5 = level.rotor(-2605 - 390, 1020, 390, 25, 0.001) //falling + + button1.min.x = -button1.min.x - 126 + button1.max.x = -button1.max.x + 126 + button0.min.x = -button0.min.x - 126 + button0.max.x = -button0.max.x + 126 + button2.min.x = -button2.min.x - 126 + button2.max.x = -button2.max.x + 126 // flip the button horizontally + drip1.x *= -1 + drip2.x *= -1 + drip3.x *= -1 + elevator0.holdX *= -1 + elevator1.holdX *= -1 + // console.log(hazard) + hazard.min.x -= 840 + hazard.max.x -= 840 + + level.custom = () => { + drip1.draw(); + drip2.draw(); + drip3.draw(); + + if (button0.isUp) { + button0.query(); + if (!button0.isUp) { //summon second set of mobs + //1 boss, 1-2 groups, 11 mobs (all on lower ground level, where the slime is leaving) + spawn.randomMob(-7475, 2800, 0.1); + spawn.randomMob(-6475, 2500, 0.2); + spawn.randomMob(-4575, 2775, 0.3); + spawn.randomMob(-7575, 2850, 0.3); + spawn.randomMob(-6425, 2575, 0.3); + spawn.randomMob(-5750, 2775, 0.4); + spawn.randomMob(-4675, 2800, 0.5); + spawn.randomMob(-3425, 2800, 0.6); + spawn.randomMob(-2475, 2475, 0.7); + spawn.randomMob(-3350, 2250, 0.8); + spawn.randomMob(-1275, 2725, 0.9); + spawn.randomGroup(-6225, 2400, 0.1); + if (simulation.difficulty > 1) spawn.randomLevelBoss(-6250, 2350); + } + } + button0.draw(); + if (button1.isUp) button1.query(); + button1.draw(); + if (button2.isUp) button2.query(); + button2.draw(); + rotor1.rotate(); + rotor2.rotate(); + ctx.fillStyle = "hsl(175, 15%, 76%)" + ctx.fillRect(-8025, 2625, 400, 300) + ctx.fillStyle = "rgba(0,0,0,0.03)" //shadows + ctx.fillRect(-6950, 1875, 700, 875) + ctx.fillRect(-4000, 1400, 1000, 1550); + ctx.fillRect(-2600, 675, 400, 2025); + ctx.fillRect(-1500, 1375, 600, 1500); + + level.exit.drawAndCheck(); + level.enter.draw(); + }; + // level.customTopLayer = () => {}; + } else { + rotor1 = level.rotor(4700, 2390, 850, 50, 0.001, 0, 0.01, 0, -0.001) //balance(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0, rotationForce = 0.0005) { + rotor2 = level.rotor(1525, 1900, 650, 50, 0.001, 0, 0.01, 0, -0.0007) + balance1 = level.rotor(800, -395, 25, 390, 0.001) //entrance + balance2 = level.rotor(2605, 500, 390, 25, 0.001) //falling + balance3 = level.rotor(2608, 1950, 584, 25, 0.001) //falling + balance5 = level.rotor(2605, 1020, 390, 25, 0.001) //falling + } + }, satellite() { level.announceMobTypes() diff --git a/js/simulation.js b/js/simulation.js index f5298b2..99dbcf3 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -1928,6 +1928,17 @@ const simulation = { } }); + document.body.addEventListener("wheel", (e) => { + if (e.deltaY > 0) { + simulation.setZoom(simulation.zoomScale / 0.9) + } else { + simulation.setZoom(simulation.zoomScale * 0.9) + } + }); + + + + //undo last element added after you press z document.body.addEventListener("keydown", (event) => { // e.keyCode z=90 m=77 b=66 shift = 16 c = 67 if (simulation.testing && event.code === "KeyZ" && simulation.constructMapString.length) { diff --git a/js/spawn.js b/js/spawn.js index 850fec9..01ac8ea 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -7,7 +7,7 @@ const spawn = { "powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", "timeSkipBoss", "dragonFlyBoss", "beetleBoss", "sneakBoss", "mantisBoss", "laserLayerBoss", - "snakeBoss", + "snakeBoss" ], bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed bossTypeSpawnIndex: 0, //increases as the boss type cycles @@ -3963,7 +3963,7 @@ const spawn = { for (let i = 0; i < this.history.length - 1; i++) { if (Matter.Query.ray([player], this.history[i], this.history[i + 1], 10).length > 0) { m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60 - const dmg = 0.25 * simulation.dmgScale + const dmg = 0.15 * simulation.dmgScale m.damage(dmg); simulation.drawList.push({ //add dmg to draw queue x: m.pos.x, diff --git a/js/tech.js b/js/tech.js index 6ad991b..29fb786 100644 --- a/js/tech.js +++ b/js/tech.js @@ -3648,7 +3648,7 @@ const tech = { }, { name: "unified field theory", - description: `when paused you can switch ${powerUps.orb.field()} by clicking
2x ${powerUps.orb.fieldTech()} frequency`, + description: `when paused you can click to change your ${powerUps.orb.field()}
2x ${powerUps.orb.fieldTech()} frequency`, maxCount: 1, count: 0, frequency: 1, @@ -3787,7 +3787,7 @@ const tech = { }, { name: "determinism", - description: `spawn ${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}
only 1 choice for ${powerUps.orb.field()}, ${powerUps.orb.tech()}, and ${powerUps.orb.gun()}`, + description: `spawn ${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}
${powerUps.orb.field()}, ${powerUps.orb.tech()}, and ${powerUps.orb.gun()} have only 1 choice`, maxCount: 1, count: 0, frequency: 1, @@ -3832,7 +3832,7 @@ const tech = { { name: "technical debt", descriptionFunction() { - return `4x damage but lose 0.15x damage
for each ${powerUps.orb.tech()} you have (${(tech.totalCount > 20 ? (Math.pow(0.85, tech.totalCount - 20)) : (4 - 0.15 * tech.totalCount)).toFixed(2)}x)` + return `decrease damage by 0.15x for each ${powerUps.orb.tech()} you have
increase damage by 4x(${(tech.totalCount > 20 ? (Math.pow(0.85, tech.totalCount - 20)) : (4 - 0.15 * tech.totalCount)).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -6960,7 +6960,7 @@ const tech = { }, { name: "railgun", - description: `hold and release fire key to launch harpoons
but, harpoons can't retract`, + description: `hold and release fire to launch harpoons
but, harpoons can't retract`, // description: `+900% harpoon ammo, but it can't retract
+50% harpoon density and damage`, isGunTech: true, maxCount: 1, @@ -7914,7 +7914,7 @@ const tech = { // description: "molecular assembler prints one block
to jump off while midair", descriptionFunction() { const fieldName = m.fieldMode === 8 ? "pilot wave" : "molecular assembler" - return `pressing the jump key in midair
will print a block to jump off` + return `pressing jump in midair
will print a block to jump off` // return `${fieldName} prints a block
to jump off while midair` }, isFieldTech: true, @@ -8114,7 +8114,7 @@ const tech = { }, { name: "degenerate matter", - description: `if your ${powerUps.orb.field()} key is active
0.1x damage taken`, + description: `if your ${powerUps.orb.field()} is active
0.1x damage taken`, isFieldTech: true, maxCount: 1, count: 0, diff --git a/todo.txt b/todo.txt index 974162a..301e51b 100644 --- a/todo.txt +++ b/todo.txt @@ -1,19 +1,10 @@ ******************************************************** NEXT PATCH ************************************************** -replaced tech, field, and gun text with orbs - orbs length scale with px->em -cleaned up simulation variables text in pause menu -some minor tech description changes -total tech count no longer includes instant tech or removed tech +new level: flocculation -tech: planned obsolescence - at the start of each level eject your oldest tech and gain 1.1 damage +snakeBoss does 40% less damage to player -heuristics 1.3 -> between 1 and 1.5 fire rate -combinatorial optimization 1.35->1.4 damage -difficulty reduction per level - 0.85->0.87x damage done - 1.23->1.22 damage taken ******************************************************** BUGS ******************************************************** @@ -25,8 +16,28 @@ fix door.isClosing actually meaning isClosed? *********************************************************** TODO ***************************************************** -tech - at the start of each new level eject the oldest tech you have and gain 10% damage +new snakeBoss type that eats mobs + each time it eats: + heal? + get shield if full? + make boss longer (if snake) + get shield + get orbitals + spawn spawns (little red square mobs) + when boss dies + spawn eaten mobs? + spawn generic mobs? + nothing + make snake new colors, width +Boss mob - takes a snapshot of the positions of all mobs, player, blocks, power ups. Then 3 seconds later it teleports everything back to those spots. + after snap shot is stored draw outline of body positions for a second to show the change + immune after snapshot? or immune after teleport? +Boss mob - records the position of mobs every few cycles + makes a ghost copy of the mob that is delayed by a few seconds + ghost can damage player, but doesn't have a matter.js object + gives mobs short snake tails, like snakeBoss + brings 1 mob back to life every few seconds merge multiple power ups of the same type if nearby @@ -72,10 +83,6 @@ rework energy and health HUD how? not sure there is a good way to do this... should health be red or green? -Boss mob - takes a snapshot of the positions of all mobs, player, blocks, power ups. Then 3 seconds later it teleports everything back to those spots. - after snap shot is stored draw outline of body positions for a second to show the change - immune after snapshot? or immune after teleport? - flip player upside down how rotate player in matter.js