From f89b2282267a4c32afeb2835583c3f296e14c84e Mon Sep 17 00:00:00 2001 From: landgreen Date: Thu, 17 Jun 2021 13:03:03 -0700 Subject: [PATCH] labs 2/6 done tech: chain reaction - blocks caught in explosions, explode tech: shock wave reduces explosion damage by 30% (was 40%) slime hazards now draw themselves in hazard.query() I updated all the maps to remove hazard.draw() but maybe I missed one let me know if you find a buggy slime laser hazards also draw themselves in hazard.opticalQuery() 2/6 rooms for new level.labs() are completed --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 38 ++-- js/engine.js | 4 +- js/level.js | 494 ++++++++++++++++++++++++++++++++++++++++----------- js/spawn.js | 2 +- js/tech.js | 29 ++- todo.txt | 37 ++-- 7 files changed, 456 insertions(+), 148 deletions(-) diff --git a/.DS_Store b/.DS_Store index 2c19a3b443cf101dd6295747f8bb35f6b6a59f7a..3edfce39e78e41dc9f9b947c48a4209d21dcb8cd 100644 GIT binary patch delta 15 WcmZoMXffEJ#muyL>1G|~8zKNJ4Fz5R delta 15 WcmZoMXffEJ#mp4XzFCL)h6n&9eFS^} diff --git a/js/bullet.js b/js/bullet.js index 3658bdf..6296e76 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -302,7 +302,7 @@ const b = { explosion(where, radius, color = "rgba(255,25,0,0.6)") { // typically explode is used for some bullets with .onEnd radius *= tech.explosiveRadius let dist, sub, knock; - let dmg = radius * 0.013 * (tech.isExplosionStun ? 0.6 : 1); + let dmg = radius * 0.013 * (tech.isExplosionStun ? 0.7 : 1); if (tech.isExplosionHarm) radius *= 1.8 // 1/sqrt(2) radius -> area if (tech.isSmallExplosion) { color = "rgba(255,0,30,0.7)" @@ -387,18 +387,30 @@ const b = { } //body knock backs - for (let i = 0, len = body.length; i < len; ++i) { - if (body[i].isNotHoldable) continue - sub = Vector.sub(where, body[i].position); - dist = Vector.magnitude(sub); - if (dist < radius) { - knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.022); - body[i].force.x += knock.x; - body[i].force.y += knock.y; - } else if (dist < alertRange) { - knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.011); - body[i].force.x += knock.x; - body[i].force.y += knock.y; + for (let i = body.length - 1; i > -1; i--) { + if (!body[i].isNotHoldable) { + sub = Vector.sub(where, body[i].position); + dist = Vector.magnitude(sub); + if (dist < radius) { + knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.022); + body[i].force.x += knock.x; + body[i].force.y += knock.y; + if (tech.isBlockExplode) { + if (body[i] === m.holdingTarget) m.drop() + const size = 20 + 350 * Math.pow(body[i].mass, 0.25) + const where = body[i].position + const onLevel = level.onLevel //prevent explosions in the next level + Matter.World.remove(engine.world, body[i]); + body.splice(i, 1); + setTimeout(() => { + if (onLevel === level.onLevel) b.explosion(where, size); //makes bullet do explosive damage at end + }, 150 + 300 * Math.random()); + } + } else if (dist < alertRange) { + knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.011); + body[i].force.x += knock.x; + body[i].force.y += knock.y; + } } } diff --git a/js/engine.js b/js/engine.js index 9d0cd5c..03c816d 100644 --- a/js/engine.js +++ b/js/engine.js @@ -41,8 +41,8 @@ function playerOnGroundCheck(event) { m.yOff = m.yOffWhen.jump; m.hardLandCD = m.cycle + Math.min(momentum / 6.5 - 6, 40) //falling damage - if (tech.isFallingDamage && m.immuneCycle < m.cycle) { - m.damage(Math.min(Math.sqrt(momentum - 123) * 0.01, 0.25)); + if (tech.isFallingDamage && m.immuneCycle < m.cycle && momentum > 150) { + m.damage(Math.min(Math.sqrt(momentum - 133) * 0.01, 0.25)); m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles } } else { diff --git a/js/level.js b/js/level.js index d493762..f0df606 100644 --- a/js/level.js +++ b/js/level.js @@ -12,17 +12,15 @@ const level = { start() { if (level.levelsCleared === 0) { //this code only runs on the first level - // simulation.zoomScale = 1000; - // simulation.setZoom(); // simulation.enableConstructMode() //used to build maps in testing mode // simulation.isHorizontalFlipped = true // level.difficultyIncrease(30) // m.setField("standing wave harmonics") // tech.giveTech("spherical harmonics") // for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics") - // b.giveGuns("super balls") + // b.giveGuns("grenades") // tech.isExplodeRadio = true - // tech.giveTech("Z-pinch") + // tech.giveTech("chain reaction") // tech.giveTech("MACHO") // tech.giveTech("supertemporal") // for (let i = 0; i < 3; i++) tech.giveTech("packet length") @@ -31,6 +29,7 @@ const level = { // for (let i = 0; i < 9; i++) tech.giveTech("WIMPs") level.intro(); //starting level + // level.labs(); // level.testing(); //not in rotation, used for testing // level.template(); //not in rotation, blank start new map development // level.final() //final boss level @@ -273,7 +272,7 @@ const level = { World.add(engine.world, map[i]); //add to world } }, - spinner(x, y, width, height, density = 0.001) { + spinner(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0) { x = x + width / 2 y = y + height / 2 const who = body[body.length] = Bodies.rectangle(x, y, width, height, { @@ -282,11 +281,14 @@ const level = { 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 }, isNotHoldable: true, - frictionAir: 0.001, + frictionAir: frictionAir, friction: 1, frictionStatic: 1, restitution: 0, }); + Matter.Body.setAngle(who, angle) + Matter.Body.setAngularVelocity(who, angularVelocity); + Matter.Body.setDensity(who, density) const constraint = Constraint.create({ //fix rotor in place, but allow rotation @@ -547,13 +549,13 @@ const level = { composite[composite.length] = rotor return rotor }, - toggle(x, y, isLockOn = false) { + toggle(x, y, isOn = false, isLockOn = false) { spawn.mapVertex(x + 65, y + 2, "70 10 -70 10 -40 -10 40 -10"); map[map.length - 1].restitution = 0; map[map.length - 1].friction = 1; map[map.length - 1].frictionStatic = 1; - spawn.bodyRect(x, y, 125, 15) //Portal platform + spawn.bodyRect(x, y - 5, 120, 15) //Portal platform let flip = body[body.length - 1]; flip.isNoSetCollision = true //prevents collision form being rewritten in level.addToWorld flip.collisionFilter.category = cat.body @@ -563,13 +565,20 @@ const level = { flip.frictionAir = 0.01 flip.restitution = 0 Matter.Body.setDensity(flip, 0.003) - Matter.Body.setAngle(flip, (-0.25 - 0.5) * Math.PI) - setTimeout(function() {}, 100); + if (isOn) { + Matter.Body.setAngle(flip, (0.25 - 0.5) * Math.PI) + } else { + Matter.Body.setAngle(flip, (-0.25 - 0.5) * Math.PI) + } + + // setTimeout(function() { + + // }, 100); cons[cons.length] = Constraint.create({ pointA: { x: x + 65, - y: y + y: y - 5 }, bodyB: flip, stiffness: 1, @@ -580,7 +589,7 @@ const level = { return { flip: flip, - isOn: false, + isOn: isOn, query() { const limit = { right: (-0.25 - 0.5) * Math.PI, @@ -923,7 +932,7 @@ const level = { } } }, - hazard(x, y, width, height, damage = 0.003, color = "hsla(160, 100%, 35%,0.75)") { + hazard(x, y, width, height, damage = 0.003) { return { min: { x: x, @@ -938,29 +947,13 @@ const level = { maxHeight: height, isOn: true, opticalQuery() { - if (this.isOn && this.height > 0 && Matter.Query.region([player], this).length && !(m.isCloak)) { - if (m.immuneCycle < m.cycle) { - m.immuneCycle = m.cycle + tech.collisionImmuneCycles; - m.damage(damage) - simulation.drawList.push({ //add dmg to draw queue - x: player.position.x, - y: player.position.y, - radius: damage * 1500, - color: simulation.mobDmgColor, - time: 20 - }); - } - } - }, - query() { - if (this.isOn && this.height > 0 && Matter.Query.region([player], this).length) { - const drain = 0.003 + m.fieldRegen - if (m.energy > drain) { - m.energy -= drain - } else { - if (damage < 0.02) { - m.damage(damage) - } else if (m.immuneCycle < m.cycle) { + if (this.isOn) { + //draw + ctx.fillStyle = `hsla(0, 100%, 50%,${0.6+0.4*Math.random()})` + ctx.fillRect(this.min.x, this.min.y, this.width, this.height) + //collision with player + if (this.height > 0 && Matter.Query.region([player], this).length && !(m.isCloak)) { + if (m.immuneCycle < m.cycle) { m.immuneCycle = m.cycle + tech.collisionImmuneCycles; m.damage(damage) simulation.drawList.push({ //add dmg to draw queue @@ -972,39 +965,60 @@ const level = { }); } } - //float - if (player.velocity.y > 5) player.force.y -= 0.95 * player.mass * simulation.g - const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - 0.002 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up - Matter.Body.setVelocity(player, { - x: Math.max(0.95, 1 - 0.036 * Math.abs(player.velocity.x)) * player.velocity.x, - y: slowY * player.velocity.y - }); - } - //float power ups - powerUpCollide = Matter.Query.region(powerUp, this) - for (let i = 0, len = powerUpCollide.length; i < len; i++) { - const diameter = 2 * powerUpCollide[i].size - const buoyancy = 1 - 0.2 * Math.max(0, Math.min(diameter, this.min.y - powerUpCollide[i].position.y + powerUpCollide[i].size)) / diameter - powerUpCollide[i].force.y -= buoyancy * 1.1 * powerUpCollide[i].mass * simulation.g; - Matter.Body.setVelocity(powerUpCollide[i], { - x: powerUpCollide[i].velocity.x, - y: 0.95 * powerUpCollide[i].velocity.y - }); } }, - draw() { + query() { if (this.isOn) { - ctx.fillStyle = color - ctx.fillRect(this.min.x, this.min.y, this.width, this.height) - } - }, - drawTides() { - if (this.isOn) { - ctx.fillStyle = color - const offset = 10 * Math.sin(simulation.cycle * 0.015) + ctx.fillStyle = "hsla(160, 100%, 35%,0.75)" + const offset = 5 * Math.sin(simulation.cycle * 0.015) ctx.fillRect(this.min.x, this.min.y + offset, this.width, this.height - offset) + + if (this.height > 0 && Matter.Query.region([player], this).length) { + const drain = 0.003 + m.fieldRegen + if (m.energy > drain) { + m.energy -= drain + } else { + if (damage < 0.02) { + m.damage(damage) + } else if (m.immuneCycle < m.cycle) { + m.immuneCycle = m.cycle + tech.collisionImmuneCycles; + m.damage(damage) + simulation.drawList.push({ //add dmg to draw queue + x: player.position.x, + y: player.position.y, + radius: damage * 1500, + color: simulation.mobDmgColor, + time: 20 + }); + } + } + //float + if (player.velocity.y > 5) player.force.y -= 0.95 * player.mass * simulation.g + const slowY = (player.velocity.y > 0) ? Math.max(0.8, 1 - 0.002 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up + Matter.Body.setVelocity(player, { + x: Math.max(0.95, 1 - 0.036 * Math.abs(player.velocity.x)) * player.velocity.x, + y: slowY * player.velocity.y + }); + } + //float power ups + powerUpCollide = Matter.Query.region(powerUp, this) + for (let i = 0, len = powerUpCollide.length; i < len; i++) { + const diameter = 2 * powerUpCollide[i].size + const buoyancy = 1 - 0.2 * Math.max(0, Math.min(diameter, this.min.y - powerUpCollide[i].position.y + powerUpCollide[i].size)) / diameter + powerUpCollide[i].force.y -= buoyancy * 1.1 * powerUpCollide[i].mass * simulation.g; + Matter.Body.setVelocity(powerUpCollide[i], { + x: powerUpCollide[i].velocity.x, + y: 0.95 * powerUpCollide[i].velocity.y + }); + } } }, + // draw() { + // if (this.isOn) { + // ctx.fillStyle = color + // ctx.fillRect(this.min.x, this.min.y, this.width, this.height) + // } + // }, level(isFill) { if (!m.isBodiesAsleep) { const growSpeed = 1 @@ -1071,6 +1085,282 @@ const level = { //****************************************************************************************************************** //****************************************************************************************************************** //****************************************************************************************************************** + labs() { + // level.difficultyIncrease(30) + level.defaultZoom = 1800 + simulation.zoomTransition(level.defaultZoom) + document.body.style.backgroundColor = "#dcdcdf"; + // document.body.style.backgroundColor = "#d5d5d5"; + let isDoorLeft, isDoorRight, x, y + doCustom = [] + doCustomTopLayer = [] + offset = { x: 0, y: 0 } + enterOptions = [ + () => { //lasers + const x = offset.x + const y = offset.y + level.setPosToSpawn(x + 2300, y - 800); + spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); + spawn.mapRect(x + 1450, y - 750, 1300, 50); //entrance shelf + spawn.mapRect(x + 1850, y - 1350, 50, 450); //entrance left wall + spawn.bodyRect(x + 1860, y - 900, 30, 150); //entrance door + + spawn.mapRect(x + 2000, y - 350, 750, 150); //toggle shelf + const toggle = level.toggle(x + 2050, y - 350, true) //(x,y,isOn,isLockOn = true/false) + + const hazard = level.hazard(x + 1040, y - 660, 1700, 10, 0.4) //laser + spawn.mapRect(x + 1050, y - 665, 10, 20); //laser nose + spawn.mapRect(x + 650, y - 705, 400, 100); //laser body + const hazard2 = level.hazard(x - 150, y - 330, 600, 10, 0.4) //laser + spawn.mapRect(x + 440, y - 335, 10, 20); //laser nose + spawn.mapRect(x + 450, y - 375, 400, 100); //laser body + //exit hazards + const Xoffset = Math.floor(400 * Math.random()) + const hazard3 = level.hazard(x + Xoffset, y - 1300, 10, 1300, 0.4) //laser + spawn.mapRect(x + Xoffset - 5, y - 1310, 20, 20); //laser nose + const hazard4 = level.hazard(x + 2100, y - 200, 10, 200, 0.4) //laser + spawn.mapRect(x + 2100 - 5, y - 210, 20, 20); //laser nose + + spawn.randomSmallMob(x + 2225, y - 100); + spawn.randomMob(x + 0, y - 125, 0); + spawn.randomMob(x + 650, y - 100, 0.5); + spawn.randomGroup(x + 1300, y - 250, 0.1); + // spawn.randomSmallMob(1300, -70); + // spawn.randomMob(2650, -975, 0.8); + // spawn.randomGroup(1700, -900, 0.4); + doCustomTopLayer.push( + () => { + toggle.query(); + hazard.isOn = toggle.isOn + hazard2.isOn = toggle.isOn + hazard3.isOn = toggle.isOn + hazard4.isOn = toggle.isOn + hazard.opticalQuery(); + hazard2.opticalQuery(); + hazard3.opticalQuery(); + hazard4.opticalQuery(); + } + ) + + }, + // () => { + // level.setPosToSpawn(x + 1250, y - 50); + // spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); + // } + ] + exitOptions = [ + () => { //9 spinners + const x = offset.x + const y = offset.y + level.exit.x = x + 1250; + level.exit.y = y - 980; + spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); + spawn.mapRect(x + 1050, y - 950, 500, 25); //exit platform + spawn.mapRect(x + 1100, y - 1300, 25, 175); //exit side wall + spawn.mapRect(x + 1475, y - 1300, 25, 175); //exit side wall + if (0.33 < Math.random()) { //center large stage + spawn.mapRect(x + 1050, y - 350, 500, 400); + } else if (0.5 < Math.random()) { + spawn.mapVertex(x + 1300, y - 310, "-300 0 -250 -425 250 -425 300 0"); + } else { + spawn.mapVertex(x + 1300, y - 125, "-400 0 -250 -400 250 -400 400 0"); + } + + spawn.bodyRect(x + 1275, y - 475, 125, 125, 0.25); + spawn.bodyRect(x + 1825, y - 125, 125, 125, 0.25); + spawn.bodyRect(x + 500, y - 100, 125, 100, 0.25); + spawn.bodyRect(x + 0, y - 150, 100, 150, 0.25); + spawn.bodyRect(x + 2375, y - 150, 125, 150, 0.25); + spawn.bodyRect(x + 1075, y - 1075, 100, 125, 0.25); + spawn.bodyRect(x + 1450, y - 1050, 100, 100, 0.25); + + const density = 0.001 + const angle = 0 + const variance = Math.PI + const frictionAir = 0 + const angularVelocity = 0.01 + const spinVariance = 0.02 + + balance1 = level.spinner(x + 150, y - 600, 25, 410, 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 + 300, y - 1000, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) + balance3 = level.spinner(x + 650, y - 750, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) + balance4 = level.spinner(x + 800, y - 1150, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) + + balance5 = level.spinner(x + 1770, y - 1150, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) + balance6 = level.spinner(x + 1930, y - 750, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) + balance7 = level.spinner(x + 2270, y - 1000, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) + balance8 = level.spinner(x + 2410, y - 600, 25, 410, density, angle + variance * (Math.random() - 0.5), frictionAir, angularVelocity + spinVariance * (Math.random() - 0.5)) + + spawn.randomMob(x + 1175, y - 725, 0.1); + spawn.randomMob(x + 1450, y - 725, 0.2); + spawn.randomMob(x + 425, y - 100, 0.3); + spawn.randomMob(x + 2300, y - 125, 0.4); + spawn.randomMob(x + 1300, y - 375, 0.5); + + doCustom.push( + () => { + ctx.fillStyle = "#d4f4f4" + ctx.fillRect(x + 1100, y - 1300, 400, 350) + } + ) + doCustomTopLayer.push( + () => { + ctx.fillStyle = "#233" + ctx.beginPath(); + ctx.arc(balance1.pointA.x, balance1.pointA.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance2.pointA.x, balance2.pointA.y) + ctx.arc(balance2.pointA.x, balance2.pointA.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance3.pointA.x, balance3.pointA.y) + ctx.arc(balance3.pointA.x, balance3.pointA.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance4.pointA.x, balance4.pointA.y) + ctx.arc(balance4.pointA.x, balance4.pointA.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance5.pointA.x, balance5.pointA.y) + ctx.arc(balance5.pointA.x, balance5.pointA.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance6.pointA.x, balance6.pointA.y) + ctx.arc(balance6.pointA.x, balance6.pointA.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance7.pointA.x, balance7.pointA.y) + ctx.arc(balance7.pointA.x, balance7.pointA.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance8.pointA.x, balance8.pointA.y) + ctx.arc(balance8.pointA.x, balance8.pointA.y, 9, 0, 2 * Math.PI); + ctx.fill(); + } + ) + } + ] + emptyOptions = [ //nothing good here + () => { + const x = offset.x + const y = offset.y + if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 1250, y - 600); + } + ] + lootOptions = [ //has some power up reward //field, ammo, research, gun + () => { + const x = offset.x + const y = offset.y + powerUps.spawnStartingPowerUps(x + 1250, y - 100); + } + ] + upDownOptions = [ //extra tall vertical section 3000x3000 //this is where the level boss is + () => { + const x = offset.x + const y = offset.y + if (simulation.difficulty > 3) spawn.randomLevelBoss(x + 1250, y - 600); + + } + ] + //pick which type of room spawns + enter = enterOptions[Math.floor(Math.random() * enterOptions.length)]; + exit = exitOptions[Math.floor(Math.random() * exitOptions.length)]; + empty = emptyOptions[Math.floor(Math.random() * emptyOptions.length)]; + loot = lootOptions[Math.floor(Math.random() * lootOptions.length)]; + upDown = upDownOptions[Math.floor(Math.random() * upDownOptions.length)]; + + //3x2: 4 short rooms (3000x1500), 1 double tall room (3000x3000) + //rooms + let rooms = ["enter", "empty", "loot", "exit"] + rooms = shuffle(rooms); //shuffles array order + //look... you and I both know there is a better way to do this, but it works so I'm gonna focus on other things + while ( //makes sure that the exit and entrance aren't both on the same floor + (rooms[0] === "enter" && rooms[2] === "exit") || + (rooms[2] === "enter" && rooms[0] === "exit") || + (rooms[1] === "enter" && rooms[3] === "exit") || + (rooms[3] === "enter" && rooms[1] === "exit") + ) rooms = shuffle(rooms); //shuffles array order + for (let i = 0; i < rooms.length; i++) { + if (rooms[i] === "enter") rooms[i] = enter + if (rooms[i] === "exit") rooms[i] = exit + if (rooms[i] === "empty") rooms[i] = empty + if (rooms[i] === "loot") rooms[i] = loot + } + //*********************************DON"T RUN THIS LINE IN THE FINAL VERSION *************************************** + rooms = [exit, enter, empty, loot] //this is used to control what level spawns while building + + outlineDoors = () => { + spawn.mapRect(offset.x - 200, offset.y, 3000, 100); //floor + spawn.mapRect(offset.x - 200, offset.y - 1400, 3000, 100); //ceiling + if (!isDoorLeft) spawn.mapRect(offset.x - 200, offset.y - 1400, 100, 1500); //left wall + if (isDoorRight) { //if door only add wall on right side + spawn.mapRect(offset.x + 2700, offset.y - 1400, 100, 1225); //right wall + spawn.mapRect(offset.x + 2700, offset.y - 10, 100, 20); //right doorstep + const doorWidth = 15 + Math.floor(100 * Math.random() * Math.random()) + spawn.bodyRect(offset.x + 2750 - doorWidth / 2, offset.y - 175, doorWidth, 165); //block door + } else { + spawn.mapRect(offset.x + 2700, offset.y - 1400, 100, 1500); //right wall + } + } + outlineUpDown = () => { + spawn.mapRect(offset.x - 200, offset.y + 1400, 3000, 100); //floor + spawn.mapRect(offset.x - 200, offset.y - 1400, 3000, 100); //ceiling + if (!isDoorLeft) spawn.mapRect(offset.x - 200, offset.y - 1400, 100, 2800); //left wall + if (isDoorRight) { //if door only add wall on right side + //upper door + spawn.mapRect(offset.x + 2700, offset.y - 1400, 100, 1225); //right wall + spawn.mapRect(offset.x + 2700, offset.y - 10, 100, 20); //right doorstep + const doorWidth = 15 + Math.floor(100 * Math.random() * Math.random()) + spawn.bodyRect(offset.x + 2750 - doorWidth / 2, offset.y - 175, doorWidth, 165); //block door + //lower door + spawn.mapRect(offset.x + 2700, offset.y - 1400 + 1400, 100, 1225); //right wall + spawn.mapRect(offset.x + 2700, offset.y - 10 + 1400, 100, 20); //right doorstep + const doorWidth2 = 15 + Math.floor(100 * Math.random() * Math.random()) + spawn.bodyRect(offset.x + 2750 - doorWidth2 / 2, offset.y - 175 + 1400, doorWidth2, 165); //block door + } else { + spawn.mapRect(offset.x + 2700, offset.y - 1400, 100, 2800); //right wall + } + } + + let rows = [ + () => { + offset.y = 0 + rooms[0]() + outlineDoors() + + offset.y = -1400 + rooms[1]() + outlineDoors() + }, + () => { + offset.y = -1400 + upDown() + outlineUpDown() + }, + () => { + offset.y = 0 + rooms[2]() + outlineDoors() + + offset.y = -1400 + rooms[3]() + outlineDoors() + } + ] + //*********************************RUN THIS LINE IN THE FINAL VERSION *************************************** + // rows = shuffle(rows) + for (let i = 0; i < 3; i++) { + if (i === 0) { + isDoorLeft = false + isDoorRight = true + } else if (i === 1) { + isDoorLeft = true + isDoorRight = true + } else { + isDoorLeft = true + isDoorRight = false + } + offset.x = i * 2900 + rows[i]() + } + level.custom = () => { + for (let i = 0, len = doCustom.length; i < len; i++) doCustom[i]() //runs all the active code from each room + level.playerExitCheck(); + level.exit.draw(); + level.enter.draw(); + }; + level.customTopLayer = () => { + for (let i = 0, len = doCustomTopLayer.length; i < len; i++) doCustomTopLayer[i]() //runs all the active code from each room + }; + powerUps.addResearchToLevel() //needs to run after mobs are spawned + }, null() { level.levels.pop(); //remove lore level from rotation //start a conversation based on the number of conversations seen @@ -1121,7 +1411,7 @@ const level = { level.customTopLayer = () => { ctx.fillStyle = "rgba(0,0,0,0.1)"; ctx.fillRect(-1950, -950, 3900, 1900); - hazardSlime.drawTides(); + // hazardSlime.drawTides(); //draw center circle lines ctx.beginPath(); @@ -1635,8 +1925,10 @@ const level = { spawn.mapRect(1225, -1955, 175, 30); const removeIndex2 = map.length - 1 //so much work to catch blocks caught at the bottom of the vertical portals let portal, portal2, portal3 - const hazard = level.hazard((simulation.isHorizontalFlipped ? -350 - 700 : 350), -2025, 700, 10, 0.4, "hsl(0, 100%, 50%)") //laser - const hazard2 = level.hazard((simulation.isHorizontalFlipped ? -1775 - 150 : 1775), -2550, 150, 10, 0.4, "hsl(0, 100%, 50%)") //laser + const hazard = level.hazard((simulation.isHorizontalFlipped ? -350 - 700 : 350), -2025, 700, 10, 0.4) //laser + spawn.mapRect(340, -2032.5, 20, 25); //laser nose + const hazard2 = level.hazard((simulation.isHorizontalFlipped ? -1775 - 150 : 1775), -2550, 150, 10, 0.4) //laser + spawn.mapRect(1920, -2557.5, 20, 25); //laser nose const button = level.button(2100, -2600) const buttonDoor = level.button(600, -550) const door = level.door(312, -750, 25, 190, 185) @@ -1680,8 +1972,7 @@ const level = { portal2[3].query() portal3[2].query() portal3[3].query() - hazard.opticalQuery(); - hazard2.opticalQuery(); + if (button.isUp) { hazard.isOn = false; hazard2.isOn = false; @@ -1700,8 +1991,8 @@ const level = { }; level.customTopLayer = () => { door.draw(); - hazard.draw(); - hazard2.draw(); + hazard.opticalQuery(); + hazard2.opticalQuery(); portal[0].draw(); portal[1].draw(); portal[2].draw(); @@ -1899,8 +2190,7 @@ const level = { button1.query(); button1.draw(); - hazard.query(); - hazard.level(button1.isUp) + rotor.rotate(); ctx.fillStyle = "hsl(175, 15%, 76%)" @@ -1919,9 +2209,11 @@ const level = { ctx.arc(balance3.pointA.x, balance3.pointA.y, 9, 0, 2 * Math.PI); ctx.moveTo(balance4.pointA.x, balance4.pointA.y) ctx.arc(balance4.pointA.x, balance4.pointA.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance5.pointA.x, balance5.pointA.y) + ctx.arc(balance5.pointA.x, balance5.pointA.y, 9, 0, 2 * Math.PI); ctx.fill(); - - hazard.draw(); + hazard.query(); + hazard.level(button1.isUp) }; level.setPosToSpawn(0, -50); //normal spawn @@ -2031,6 +2323,8 @@ const level = { balance2 = level.spinner(-2605 - 390, 500, 390, 25, 0.001) //falling balance3 = level.spinner(-2608 - 584, 1900, 584, 25, 0.001) //falling balance4 = level.spinner(-9300 - 25, 2205, 25, 380, 0.001) //exit + balance5 = level.spinner(-2605 - 390, 1100, 390, 25, 0.001) //falling + // boost1.boostBounds.min.x = -boost1.boostBounds.min.x - 100 // boost1.boostBounds.max.x = -boost1.boostBounds.max.x + 100 // level.setPosToSpawn(300, -700); //-x // no need since 0 @@ -2063,6 +2357,7 @@ const level = { balance2 = level.spinner(2605, 500, 390, 25, 0.001) //falling balance3 = level.spinner(2608, 1900, 584, 25, 0.001) //falling balance4 = level.spinner(9300, 2205, 25, 380, 0.001) //exit + balance5 = level.spinner(2605, 1100, 390, 25, 0.001) //falling } }, @@ -2805,12 +3100,12 @@ const level = { const elevator1 = level.elevator(-790, -190, 180, 25, -1150) //, 0.007 elevator1.addConstraint(); // const button1 = level.button(-500, -200) - const toggle1 = level.toggle(-500, -200) //(x,y,isLockOn = true/false) + const toggle1 = level.toggle(-500, -200) //(x,y,isOn,isLockOn = true/false) const elevator2 = level.elevator(-3630, -1000, 180, 25, -1740) //, 0.007 elevator2.addConstraint(); // const button2 = level.button(-3100, -1330) - const toggle2 = level.toggle(-3100, -1330) //(x,y,isLockOn = true/false) + const toggle2 = level.toggle(-3100, -1330) //(x,y,isOn, isLockOn = true/false) level.custom = () => { @@ -2958,7 +3253,7 @@ const level = { spawn.bodyRect(-3410, -1425, 100, 100); spawn.bodyRect(-3390, -1525, 100, 100); - spawn.bodyRect(-3245, -1425, 100, 100); + // spawn.bodyRect(-3245, -1425, 100, 100); //building 3 spawn.mapRect(-4450, -1750, 800, 1050); // spawn.mapRect(-3850, -2000, 125, 400); @@ -3819,7 +4114,7 @@ const level = { doorPlateform.openClose(); } hazard.level(button.isUp) - hazard.query(); + level.exit.draw(); level.enter.draw(); }; @@ -3836,7 +4131,7 @@ const level = { portal[1].draw(); portal[2].draw(); portal[3].draw(); - hazard.draw(); + hazard.query(); //elevator if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { if (elevator.plat.position.y > -200) { //bottom @@ -4461,7 +4756,6 @@ const level = { ctx.fillRect(4050, -905, 1125, 2); ctx.fillRect(4050, -865, 1125, 2); - hazard.query(); buttonBedroom.query(); buttonBedroom.draw(); if (buttonBedroom.isUp) { @@ -4525,7 +4819,7 @@ const level = { ctx.fillStyle = "rgba(64,64,64,0.97)"; ctx.fillRect(2800, -400, 275, 175); - hazard.draw(); + hazard.query(); doorBedroom.draw(); doorGrenier.draw(); voletLucarne1.draw(); @@ -5178,17 +5472,15 @@ const level = { const slimePitThree = level.hazard(6500, 200, 1000, 170); level.custom = () => { - slimePitOne.query(); - slimePitTwo.query(); - slimePitThree.query(); - slimePitOne.draw(); - slimePitTwo.draw(); - slimePitThree.draw(); level.playerExitCheck(); level.exit.draw(); level.enter.draw(); }; - level.customTopLayer = () => {}; + level.customTopLayer = () => { + slimePitOne.query(); + slimePitTwo.query(); + slimePitThree.query(); + }; level.setPosToSpawn(-500, 550); //normal spawn spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); @@ -5696,13 +5988,11 @@ const level = { slimePit.query(); ctx.shadowColor = 'hsla(160, 100%, 50%, 1)' ctx.shadowBlur = 100; - slimePit.draw() + // slimePit.draw() ctx.shadowBlur = 0; ctx.shadowColor = 'rgba(0, 0, 0, 0)' - topSlime.query(); + deliveryButton.query() - deliverySlime.query() - deliverySlime2.query() portal[2].query() //portal[3].query() portal2[2].query() @@ -5719,6 +6009,9 @@ const level = { } level.customTopLayer = () => { + topSlime.query(); + deliverySlime.query() + deliverySlime2.query() drip1.draw() drip2.draw() drip3.draw() @@ -5763,9 +6056,9 @@ const level = { ctx.fill() deliveryButton.draw() - deliverySlime.draw() - deliverySlime2.draw() - topSlime.draw() + // deliverySlime.draw() + // deliverySlime2.draw() + // topSlime.draw() buttonGreen.draw() buttonYellow.draw() buttonRed.draw() @@ -6224,7 +6517,6 @@ const level = { } button.query(); - hazard.query(); isButtonTapped = isButtonTapped || !button.isUp; hazard.level(!isButtonTapped); if (Matter.Query.region([player], hazard).length) m.energy -= 0.001; @@ -6271,8 +6563,7 @@ const level = { if (secretAnimTime2 > 150) secretAnimTime2 = 0; } - secretHazard.level(emergencyActivated); - secretHazard.query(); + ctx.beginPath(); ctx.arc(m.pos.x, m.pos.y, 200, 0, 2 * Math.PI); @@ -6290,12 +6581,11 @@ const level = { elevator.drawTrack(); }; level.customTopLayer = () => { - hazard.draw(); - secretHazard.draw(); + hazard.query(); + secretHazard.level(emergencyActivated); + secretHazard.query(); button.draw(); - - // Fire damage let isInRange = flames.reduce((a, i) => a || Math.sqrt((m.pos.x - i[0]) * (m.pos.x - i[0]) + (m.pos.y + 90 - i[1]) * (m.pos.y + 90 - i[1])) < 50, false); diff --git a/js/spawn.js b/js/spawn.js index 5580198..b606b2c 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -1526,7 +1526,7 @@ const spawn = { ctx.stroke(); ctx.beginPath(); ctx.arc(m.pos.x, m.pos.y, 40, 0, 2 * Math.PI); - ctx.fillStyle = "rgba(150,0,255,0.15)"; + ctx.fillStyle = "rgba(150,0,255,0.1)"; ctx.fill(); } diff --git a/js/tech.js b/js/tech.js index 8d6773c..b425f73 100644 --- a/js/tech.js +++ b/js/tech.js @@ -754,12 +754,30 @@ } }, { - name: "shock wave", - description: "explosions stun mobs for 1-2 seconds
decrease explosive damage by 40%", + name: "chain reaction", + description: "blocks caught in explosions also explode", isGunTech: true, maxCount: 1, count: 0, - frequency: 2, + frequency: 1, + allowed() { + return !tech.isExplodeRadio && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isBlockExplosion) + }, + requires: "an explosive damage source, not iridium-192", + effect() { + tech.isBlockExplode = true; + }, + remove() { + tech.isBlockExplode = false; + } + }, + { + name: "shock wave", + description: "explosions stun mobs for 1-2 seconds
decrease explosive damage by 30%", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 1, allowed() { return !tech.isExplodeRadio && (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isBlockExplosion) }, @@ -3794,7 +3812,7 @@ }, remove() { tech.waveBeamSpeed = 10; - tech.waveBeamDamage = 1.3 //this sets base wave beam damage + tech.waveBeamDamage = 1.5 //this sets base wave beam damage } }, { @@ -6928,5 +6946,6 @@ harmonics: null, isStandingWaveExpand: null, isBlockExplosion: null, - superBallDelay: null + superBallDelay: null, + isBlockExplode: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index fd05420..da7ecc6 100644 --- a/todo.txt +++ b/todo.txt @@ -1,23 +1,14 @@ ******************************************************** NEXT PATCH ******************************************************** -tech supertemporal - fire your super balls at the same place in space, but delayed in time +tech: chain reaction - blocks caught in explosions, explode +tech: shock wave reduces explosion damage by 30% (was 40%) -super ball starts with 3 not 4 balls, but they are is 25% larger, 10% faster, and 25% lower divergence - (this makes adding more balls much stronger) -gun - super balls has 15% less ammo - -standing wave harmonics - still has no block cooldown, but now it has a cooldown for how often it can drain energy - this should make rapidly blocking drain upto 10x less energy - base blocking cost have increased by 25% - -wormhole gets 10% duplication (was 7%) -ice-IX does 15% more damage - -new level element - toggle(x, y, isLockOn = false) - similar to a button but doesn't require a block - used on the level highrise - can toggle "off and on" or "lock on" +slime hazards now draw themselves in hazard.query() +I updated all the maps to remove hazard.draw() + but maybe I missed one let me know if you find a buggy slime +laser hazards also draw themselves in hazard.opticalQuery() +2/6 rooms for new level.labs() are completed ******************************************************** BUGS ******************************************************** @@ -76,10 +67,12 @@ make a switch level element angle of stick "light-switch" with colors? +level element: carousel + use rotor code + add blocks at the 4 ends of the rotor that maintain horizontal angle + ******************************************************** TODO ******************************************************** -standing wave harmonics - can block too often on the same mob if you push it into a corner - add a cool down that only stops energy drain and iceIX, but still lets you block let standing wave harmonics get tech decorrelation tech: cloaking field - decrease/increase cooldown on sneak attack? @@ -90,13 +83,6 @@ have throw charge scale with fire delay in testing mode console log the body you click on -default negative mass field- move block horizontally? - should this be a tech? - -negative mass field tech - increase flight speed - use the sphere ellipse graphic? - move block horizontally and vertically with player - throwing a block removes the block and rewinds time 10 seconds (including health and energy) requires CPT, CPT gun, time dilation field? @@ -386,6 +372,7 @@ possible names for tech axion - maybe a 3rd dark matter type tech Pigeonhole principle - if there are several things that are matched up regression to the mean + tessellation = tiling of a flat surface is the covering of a plane using one or more geometric shapes, called tiles, with no overlaps and no gaps.