diff --git a/img/ammonium nitrate.webp b/img/ammonium nitrate.webp index e2fe4e0..7b430f4 100644 Binary files a/img/ammonium nitrate.webp and b/img/ammonium nitrate.webp differ diff --git a/img/boson composite.webp b/img/boson composite.webp index 3f0daa9..18fb1ec 100644 Binary files a/img/boson composite.webp and b/img/boson composite.webp differ diff --git a/img/chain reaction.webp b/img/chain reaction.webp index 3ab476f..cea1259 100644 Binary files a/img/chain reaction.webp and b/img/chain reaction.webp differ diff --git a/img/dazzler.webp b/img/dazzler.webp index 7ae326c..2cdb34f 100644 Binary files a/img/dazzler.webp and b/img/dazzler.webp differ diff --git a/img/dynamical systems.webp b/img/dynamical systems.webp index 825d7fd..141e818 100644 Binary files a/img/dynamical systems.webp and b/img/dynamical systems.webp differ diff --git a/img/field/metamaterial cloaking.webp b/img/field/metamaterial cloaking.webp index 2273eab..08d39e0 100644 Binary files a/img/field/metamaterial cloaking.webp and b/img/field/metamaterial cloaking.webp differ diff --git a/img/fireworks.webp b/img/fireworks.webp index b73b126..27fad96 100644 Binary files a/img/fireworks.webp and b/img/fireworks.webp differ diff --git a/img/flame test.webp b/img/flame test.webp index c9f5013..d4fe1d8 100644 Binary files a/img/flame test.webp and b/img/flame test.webp differ diff --git a/img/futures exchange.webp b/img/futures exchange.webp index 8d492ac..561c99f 100644 Binary files a/img/futures exchange.webp and b/img/futures exchange.webp differ diff --git a/img/negative feedback.webp b/img/negative feedback.webp index e48783b..68611ba 100644 Binary files a/img/negative feedback.webp and b/img/negative feedback.webp differ diff --git a/img/no-cloning theorem.webp b/img/no-cloning theorem.webp index 25a5c43..cd6cdee 100644 Binary files a/img/no-cloning theorem.webp and b/img/no-cloning theorem.webp differ diff --git a/img/options exchange.webp b/img/options exchange.webp index 6ff2c4f..a805ffc 100644 Binary files a/img/options exchange.webp and b/img/options exchange.webp differ diff --git a/img/patch.webp b/img/patch.webp index dd94f4d..2e65da5 100644 Binary files a/img/patch.webp and b/img/patch.webp differ diff --git a/img/perturbation theory.webp b/img/perturbation theory.webp index 6e68752..ffff9b8 100644 Binary files a/img/perturbation theory.webp and b/img/perturbation theory.webp differ diff --git a/img/pyrotechnics.webp b/img/pyrotechnics.webp index 7d6457d..8ab0921 100644 Binary files a/img/pyrotechnics.webp and b/img/pyrotechnics.webp differ diff --git a/img/quantum eraser.webp b/img/quantum eraser.webp index fc86480..42bb32b 100644 Binary files a/img/quantum eraser.webp and b/img/quantum eraser.webp differ diff --git a/img/replication.webp b/img/replication.webp index e15df43..8dfb21c 100644 Binary files a/img/replication.webp and b/img/replication.webp differ diff --git a/img/rocket-propelled grenade.webp b/img/rocket-propelled grenade.webp index 1ef1b92..efe978b 100644 Binary files a/img/rocket-propelled grenade.webp and b/img/rocket-propelled grenade.webp differ diff --git a/img/sentry gun.webp b/img/sentry.webp similarity index 100% rename from img/sentry gun.webp rename to img/sentry.webp diff --git a/img/stimulated emission.webp b/img/stimulated emission.webp index 1fa9f74..ce9a1cc 100644 Binary files a/img/stimulated emission.webp and b/img/stimulated emission.webp differ diff --git a/img/symbiosis.webp b/img/symbiosis.webp index 32b35db..61c253e 100644 Binary files a/img/symbiosis.webp and b/img/symbiosis.webp differ diff --git a/js/bullet.js b/js/bullet.js index 4b9ff7e..aef31f6 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -114,7 +114,7 @@ const b = { } }, refundAmmo() { //triggers after firing when you removed ammo for a gun, but didn't need to - if (tech.crouchAmmoCount && input.down) { + if (tech.crouchAmmoCount && input.down && b.activeGun !== null) { tech.crouchAmmoCount-- if ((tech.crouchAmmoCount) % 2) { b.guns[b.activeGun].ammo++; @@ -144,13 +144,13 @@ const b = { gun = options[Math.floor(Math.random() * options.length)] } if (gun === "all") { - b.inventoryGun = 0; for (let i = 0; i < b.guns.length; i++) { b.inventory[i] = i; b.guns[i].have = true; if (b.guns[i].ammo !== Infinity) b.guns[i].ammo = Math.ceil(b.guns[i].ammoPack * ammoPacks); } - b.activeGun = 0; + b.inventoryGun = 0; + b.activeGun = b.inventory[0]; } else { if (isNaN(gun)) { //find gun by name let found = false; @@ -167,7 +167,8 @@ const b = { b.guns[gun].have = true; if (b.guns[gun].ammo !== Infinity) b.guns[gun].ammo = Math.ceil(b.guns[gun].ammoPack * ammoPacks); if (b.activeGun === null) { - b.activeGun = gun //if no active gun switch to new gun + b.inventoryGun = 0; + b.activeGun = b.inventory[0] //if no active gun switch to new gun if (b.guns[b.activeGun].charge) b.guns[b.activeGun].charge = 0; //set foam charge to zero if foam is a new gun } // if (tech.infiniteWaveAmmo === 2) b.guns[3].ammo = Infinity @@ -219,11 +220,10 @@ const b = { } if (b.inventory.length > 0) { b.activeGun = b.inventory[0]; - b.inventoryGun = 0; } else { b.activeGun = null; - b.inventoryGun = 0; } + b.inventoryGun = 0; simulation.makeGunHUD(); break } @@ -237,7 +237,10 @@ const b = { b.guns[i].have = false; if (b.guns[i].ammo != Infinity) b.guns[i].ammo = 0; } + tech.buffedGun = 0 b.activeGun = null; + b.inventoryGun = 0; + simulation.drawCursor = simulation.drawCursorBasic //set cross hairs }, bulletRemove() { //run in main loop //remove bullet if at end cycle for that bullet @@ -445,9 +448,9 @@ const b = { if (dist < radius) { if (simulation.dmgScale) { const harm = tech.isExplosionHarm ? 0.07 : 0.05 - if (tech.isImmuneExplosion && m.energy > 0.12) { + if (tech.isImmuneExplosion && m.energy > 0.25) { // const mitigate = Math.min(1, Math.max(1 - m.energy * 0.5, 0)) - m.energy -= 0.12 + m.energy -= 0.25 // m.damage(0.01 * harm); //remove 99% of the damage 1-0.99 knock = Vector.mult(Vector.normalise(sub), -0.6 * player.mass * Math.max(0, Math.min(0.15 - 0.002 * player.speed, 0.15))); player.force.x = knock.x; // not += so crazy forces can't build up with MIRV @@ -2759,26 +2762,17 @@ const b = { if (collide.length > 0) { for (let i = 0; i < collide.length; i++) { if (collide[i].bodyA.collisionFilter.category === cat.map) { // || collide[i].bodyB.collisionFilter.category === cat.map) { - const angle = Vector.angle(collide[i].normal, { - x: 1, - y: 0 - }) + const angle = Vector.angle(collide[i].normal, { x: 1, y: 0 }) Matter.Body.setAngle(this, Math.atan2(collide[i].tangent.y, collide[i].tangent.x)) for (let j = 0; j < 10; j++) { //move until touching map again after rotation if (Matter.Query.collides(this, map).length > 0) { //touching map if (angle > -0.2 || angle < -1.5) { //don't stick to level ground - Matter.Body.setVelocity(this, { - x: 0, - y: 0 - }); + Matter.Body.setVelocity(this, { x: 0, y: 0 }); Matter.Body.setStatic(this, true) //don't set to static if not touching map this.collisionFilter.category = 0 this.collisionFilter.mask = 0 //cat.map | cat.bullet } else { - Matter.Body.setVelocity(this, { - x: 0, - y: 0 - }); + Matter.Body.setVelocity(this, { x: 0, y: 0 }); Matter.Body.setAngularVelocity(this, 0) } this.arm(); @@ -3764,6 +3758,7 @@ const b = { bullet[me].friction = 0; if (tech.superHarm) { bullet[me].collidePlayerDo = function() { + this.force.y += this.mass * 0.0012; if (Matter.Query.collides(this, [player]).length) { this.endCycle = 0 let dmg = 0.02 * this.mass * tech.superHarm @@ -3779,7 +3774,8 @@ const b = { } bullet[me].cycle = 0 bullet[me].do = function() { - if (this.cycle > 6) this.do = this.collidePlayerDo + this.cycle++ + if (this.cycle > 2) this.do = this.collidePlayerDo this.force.y += this.mass * 0.0012; }; } else { diff --git a/js/index.js b/js/index.js index dd5fd46..6ca12d6 100644 --- a/js/index.js +++ b/js/index.js @@ -382,7 +382,7 @@ ${simulation.isCheating ? "

lore disabled": ""} } let el = document.getElementById("pause-grid-left") - el.style.display = tech.isNoDraftPause ? "none" : "grid" //disabled for eternalism because eternalism lets the player play while this menu is up but the menu doesn't update + el.style.display = "grid" el.innerHTML = text //right side text = ""; @@ -433,7 +433,7 @@ ${simulation.isCheating ? "

lore disabled": ""} } } el = document.getElementById("pause-grid-right") - el.style.display = tech.isNoDraftPause ? "none" : "grid" //disabled for eternalism because eternalism lets the player play while this menu is up but the menu doesn't update + el.style.display = "grid" el.innerHTML = text document.getElementById("tech").style.display = "none" @@ -500,7 +500,10 @@ ${simulation.isCheating ? "

lore disabled": ""} b.guns[index].count = 0; b.guns[index].have = false; if (b.guns[index].ammo != Infinity) b.guns[index].ammo = 0; - if (b.inventory.length === 0) b.activeGun = null; + if (b.inventory.length === 0) { + b.activeGun = null; + b.inventoryGun = 0; + } simulation.makeGunHUD(); break } @@ -698,6 +701,7 @@ ${simulation.isCheating ? "

lore disabled": ""} if (b.guns[i].ammo != Infinity) b.guns[i].ammo = 0; } b.activeGun = null; + b.inventoryGun = 0; simulation.makeGunHUD(); tech.setupAllTech(); build.populateGrid(); @@ -765,6 +769,7 @@ ${simulation.isCheating ? "

lore disabled": ""} spawn.setSpawnList(); if (b.inventory.length > 0) { b.activeGun = b.inventory[0] //set first gun to active gun + b.inventoryGun = 0; simulation.makeGunHUD(); } for (let i = 0; i < bullet.length; ++i) Matter.Composite.remove(engine.world, bullet[i]); diff --git a/js/level.js b/js/level.js index 1420c5e..9250a59 100644 --- a/js/level.js +++ b/js/level.js @@ -25,14 +25,14 @@ const level = { // m.immuneCycle = Infinity //you can't take damage // tech.tech[297].frequency = 100 // m.couplingChange(5) - // m.setField("perfect diamagnetism") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave plasma torch + // m.setField("metamaterial cloaking") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave plasma torch // simulation.molecularMode = 2 // m.damage(0.1); // b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.guns[0].ammo = 10000 // tech.giveTech("needle gun") - // tech.giveTech("repeater") + // tech.giveTech("eternalism") // tech.giveTech("ice-shot") // for (let i = 0; i < 1; ++i) tech.giveTech("super ball") // tech.isFoamBall = true @@ -42,7 +42,8 @@ const level = { // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); - // level.testing(); + // level.testChamber2(); + // spawn.nodeGroup(1200, 0, "slasher") // spawn.blinkBoss(1900, -500) // spawn.sneakBoss(1900, -500) // spawn.starter(1900, -500, 200) @@ -56,12 +57,7 @@ const level = { // for (let i = 0; i < 40; ++i) tech.giveTech() // for (let i = 0; i < 13; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research"); - //normal starting level ************************************************ - if (simulation.isTraining) { - level.walk() - } else { - level.intro() - } + level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************ // for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech"); // for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "gun"); @@ -156,7 +152,7 @@ const level = { //used for generalist and pigeonhole principle tech.buffedGun++ if (tech.buffedGun > b.inventory.length - 1) tech.buffedGun = 0; - if (tech.isGunCycle) { + if (tech.isGunCycle && b.activeGun !== null && b.inventory.length) { b.inventoryGun = tech.buffedGun; simulation.switchGun(); } @@ -1264,22 +1260,13 @@ const level = { const width = 50 const height = 150 const mapWidth = 200 - const unitA = Matter.Vector.rotate({ - x: 1, - y: 0 - }, angleA) - const unitB = Matter.Vector.rotate({ - x: 1, - y: 0 - }, angleB) - + const unitA = Matter.Vector.rotate({ x: 1, y: 0 }, angleA) + const unitB = Matter.Vector.rotate({ x: 1, y: 0 }, angleB) draw = function() { ctx.beginPath(); //portal let v = this.vertices; ctx.moveTo(v[0].x, v[0].y); - for (let i = 1; i < v.length; ++i) { - ctx.lineTo(v[i].x, v[i].y); - } + for (let i = 1; i < v.length; ++i) ctx.lineTo(v[i].x, v[i].y); ctx.fillStyle = this.color ctx.fill(); } @@ -1315,10 +1302,7 @@ const level = { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) })); - Matter.Body.setVelocity(bullet[i], { - x: 0, - y: 0 - }); + Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 }); } } } @@ -2827,7 +2811,7 @@ const level = { } // const hazardSlime = level.hazard(-1800, 150, 3600, 650, 0.004, "hsla(160, 100%, 35%,0.75)") level.isHazardRise = false //this is set to true to make the slime rise up - const hazardSlime = level.hazard(-1800, -800, 3600, 1600, 0.004, "hsla(160, 100%, 35%,0.75)") + const hazardSlime = level.hazard(-1800, -800, 3600, 1600, 0.004) hazardSlime.height -= 950 hazardSlime.min.y += 950 hazardSlime.max.y = hazardSlime.min.y + hazardSlime.height @@ -4464,261 +4448,70 @@ const level = { }, testChamber2() { - level.setPosToSpawn(0, -50); //lower start - level.exit.y = level.enter.y - 550; + level.setPosToSpawn(0, -65); //lower start + level.exit.y = -1550; spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); - level.exit.x = level.enter.x; + level.exit.x = -1000; spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); level.defaultZoom = 2200 simulation.zoomTransition(level.defaultZoom) document.body.style.backgroundColor = "#d0d5d5"; color.map = "#444" - spawn.mapRect(0, -1955, 175, 30); - const removeIndex1 = map.length - 1 //so much work to catch blocks caught at the bottom of the vertical portals - 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) //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) + const portal = level.portal({ x: 1070, y: -1485 }, -0.9, { x: 475, y: 50 }, -Math.PI / 2) + const hazardSlime = level.hazard(900, -300, 3625, 2550) //hazard(x, y, width, height, damage = 0.002) { + const button = level.button(3975, -1425) level.custom = () => { - if (!(m.cycle % 60)) { //so much work to catch blocks caught at the bottom of the vertical portals - let touching = Matter.Query.collides(map[removeIndex1], body) - if (touching.length) { - Matter.Composite.remove(engine.world, touching[0].bodyB); - for (let i = 0, len = body.length; i < len; i++) { - if (body[i].id === touching[0].bodyB.id) { - body.splice(i, 1); - break - } - } - } - touching = Matter.Query.collides(map[removeIndex2], body) - if (touching.length) { - Matter.Composite.remove(engine.world, touching[0].bodyB); - for (let i = 0, len = body.length; i < len; i++) { - if (body[i].id === touching[0].bodyB.id) { - body.splice(i, 1); - break - } - } - } - } - - buttonDoor.query(); - buttonDoor.draw(); - if (buttonDoor.isUp) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - portal[2].query() portal[3].query() - portal2[2].query() - portal2[3].query() - portal3[2].query() - portal3[3].query() - - if (button.isUp) { - hazard.isOn = false; - hazard2.isOn = false; - } else { - hazard.isOn = true; - hazard2.isOn = true; - } + level.exit.drawAndCheck(); + level.enter.draw(); button.query(); button.draw(); - - ctx.fillStyle = "#d4f4f4" - ctx.fillRect(-300, -1000, 650, 500) - level.exit.drawAndCheck(); - - level.enter.draw(); }; level.customTopLayer = () => { - door.draw(); - hazard.opticalQuery(); - hazard2.opticalQuery(); + hazardSlime.query(); portal[0].draw(); portal[1].draw(); portal[2].draw(); portal[3].draw(); - portal2[0].draw(); - portal2[1].draw(); - portal2[2].draw(); - portal2[3].draw(); - portal3[0].draw(); - portal3[1].draw(); - portal3[2].draw(); - portal3[3].draw(); + ctx.fillStyle = "#444" //below portal + ctx.fillRect(375, 150, 200, 2525); + ctx.fillStyle = "rgba(0,0,0,0.1)" //shadows + ctx.fillRect(-250, -1550, 1250, 1575); + for (let i = 0, len = vanish.length; i < len; i++) vanish[i].query() }; - powerUps.spawnStartingPowerUps(1875, -3075); - - const powerUpPos = shuffle([{ //no debris on this level but 2 random spawn instead - x: -150, - y: -1775 - }, { - x: 2400, - y: -2650 - }, { - x: -175, - y: -1375 - }, { - x: 1325, - y: -150 - }]); - powerUps.chooseRandomPowerUp(powerUpPos[0].x, powerUpPos[0].y); - powerUps.chooseRandomPowerUp(powerUpPos[1].x, powerUpPos[1].y); //outer wall - spawn.mapRect(2500, -3700, 1200, 3800); //right map wall - spawn.mapRect(-1400, -3800, 1100, 3900); //left map wall - spawn.mapRect(-1400, -4800, 5100, 1200); //map ceiling - spawn.mapRect(-1400, 0, 5100, 1200); //floor - //lower entrance /exit - spawn.mapRect(300, -375, 50, 225); - spawn.bodyRect(312, -150, 25, 140); - spawn.mapRect(300, -10, 50, 50); - spawn.mapVertex(1555, 0, "625 0 75 0 200 -100 500 -100"); //entrance ramp - //upper entrance / exit - spawn.mapRect(-400, -1050, 750, 50); - spawn.mapRect(300, -1050, 50, 300); - // spawn.bodyRect(312, -750, 25, 190); - spawn.mapRect(300, -560, 50, 50); - spawn.bodyRect(750, -725, 125, 125); - spawn.mapRect(1150, -1050, 250, 575); - spawn.mapRect(1725, -550, 50, 200); //walls around portal 3 - spawn.mapRect(1925, -550, 500, 200); - spawn.mapRect(1750, -390, 200, 40); - spawn.mapRect(-400, -550, 1800, 200); - spawn.mapRect(-200, -1700, 150, 25); //platform above exit room - spawn.mapRect(-200, -1325, 350, 25); - //portal 3 angled - spawn.mapRect(2425, -450, 100, 100); - //portal 1 bottom - spawn.mapRect(2290, -12, 375, 100); - spawn.mapRect(2350, -24, 375, 100); - spawn.mapRect(2410, -36, 375, 100); - //portal 1 top - spawn.mapRect(2290, -3012, 375, 50); - spawn.mapRect(2350, -3024, 375, 50); - spawn.mapRect(2410, -3036, 375, 50); - spawn.mapRect(1400, -3000, 1300, 50); //floor - spawn.mapRect(1750, -3050, 250, 75); - spawn.mapRect(1400, -3625, 50, 200); - spawn.mapRect(350, -3625, 50, 225); - spawn.mapRect(350, -3260, 50, 60); - spawn.mapRect(200, -3250, 1240, 50); - spawn.mapRect(1400, -3260, 50, 310); - spawn.bodyRect(1412, -3425, 25, 165); - spawn.mapRect(-150, -2925, 150, 25); - //portal 2 - spawn.mapRect(-300, -2600, 300, 675); //left platform - spawn.mapRect(1400, -2600, 375, 675); //right platform - spawn.mapRect(1925, -2600, 775, 675); //far right platform - spawn.bodyRect(2130, -2660, 50, 50); //button's block - spawn.mapRect(150, -2100, 200, 175); - spawn.mapRect(1050, -2100, 200, 175); - //mobs - spawn.randomMob(1075, -3500, -0.3); - spawn.randomMob(2175, -700, -0.2); - spawn.randomMob(-75, -850, -0.1); - spawn.randomMob(550, -3400, 0); - spawn.randomMob(0, -1175, 0.5); - spawn.randomMob(-75, -1150, 0.5); - spawn.randomMob(1075, -625, 0.5); - spawn.randomMob(800, -3400, -0.3); - spawn.randomMob(1225, -3375, -0.2); - spawn.randomMob(1200, -1125, -0.1); - spawn.randomMob(2050, -950, 0.5); - if (simulation.difficulty > 40) { - spawn.randomMob(2300, -2775, -0.5); - spawn.randomMob(600, -925, -0.5); - spawn.randomMob(1550, -2750, -0.5); - spawn.randomMob(1350, -1150, -0.5); - spawn.randomMob(-75, -1475, 0); - spawn.randomGroup(600, -2600, 0); - } - if (simulation.difficulty > 1) { - if (Math.random() < 0.5) { - spawn.randomLevelBoss(700, -1550); - } else { - spawn.randomLevelBoss(675, -2775); //["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "shieldingBoss", "pulsarBoss", "grenadierBoss"] - } - } - powerUps.addResearchToLevel() //needs to run after mobs are spawned - spawn.secondaryBossChance(1925, -1250) + // spawn.mapRect(-1400, 0, 1800, 1200); //floor + spawn.mapRect(-1400, 0, 1800, 2675); + spawn.mapRect(-1400, -1025, 1225, 1500); + spawn.mapRect(-325, -15, 525, 225); + spawn.mapRect(150, -350, 50, 175); - if (simulation.isHorizontalFlipped) { //flip the map horizontally - level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit - // level.setPosToSpawn(0, -50); //-x // no need since 0 - button.min.x = -button.min.x - 126 // flip the button horizontally - button.max.x = -button.max.x + 126 // flip the button horizontally - buttonDoor.min.x = -buttonDoor.min.x - 126 // flip the button horizontally - buttonDoor.max.x = -buttonDoor.max.x + 126 // flip the button horizontally + spawn.mapRect(-1400, -3525, 1600, 3225); + spawn.mapRect(550, 0, 450, 2675); - //this makes the hazard draw, but not collide for reasons I don't understand - //so don't use it, instead just call the hazard differently based on this flip flag - // hazard.min.x = -hazard.min.x - hazard.width //-x-width - // hazard.max.x = -hazard.max.x - hazard.width //-x-width - // hazard2.min.x = -hazard2.min.x - hazard2.width //-x-width - // hazard2.max.x = -hazard2.max.x - hazard2.width //-x-width - portal = level.portal({ - x: -2475, - y: -140 - }, 2 * Math.PI, { //right - x: -2475, - y: -3140 - }, 2 * Math.PI) //right + spawn.mapRect(550, -1550, 450, 125); + spawn.mapRect(150, -1550, 250, 125); + spawn.mapRect(750, -1425, 1100, 175); + spawn.mapRect(750, -1400, 250, 825); + spawn.mapRect(750, -350, 250, 575); + // spawn.mapRect(750, -1275, 250, 600); + // spawn.mapRect(3550, -1850, 1200, 600); - portal2 = level.portal({ - x: -75, - y: -2150 - }, -Math.PI / 2, { //up - x: -1325, - y: -2150 - }, -Math.PI / 2) //up + spawn.mapRect(3825, -1425, 975, 175); + spawn.mapRect(625, 2050, 4300, 625); + spawn.mapRect(4450, -3525, 1400, 6200); + //the pit + const vanish = [] + vanish.push(level.vanish(400, -1512, 150, 50)) + vanish.push(level.vanish(2625, -675, 300, 175)) + vanish.push(level.vanish(1775, -675, 325, 150)) + //blocks at entrance + spawn.bodyRect(150, -175, 50, 165); + spawn.bodyRect(825, -425, 155, 75, 0.5); - portal3 = level.portal({ - x: -1850, - y: -585 - }, -Math.PI / 2, { //up - x: -2425, - y: -600 - }, -1 * Math.PI / 3) //up left - // level.custom = () => { }; - // level.customTopLayer = () => {}; - - } else { - portal = level.portal({ - x: 2475, - y: -140 - }, Math.PI, { //left - x: 2475, - y: -3140 - }, Math.PI) //left - portal2 = level.portal({ - x: 75, - y: -2150 - }, -Math.PI / 2, { //up - x: 1325, - y: -2150 - }, -Math.PI / 2) //up - portal3 = level.portal({ - x: 1850, - y: -585 - }, -Math.PI / 2, { //up - x: 2425, - y: -600 - }, -2 * Math.PI / 3) //up left - } }, sewers() { @@ -8219,8 +8012,8 @@ const level = { let r = false; const deliverySlime = level.hazard(3700, -940, 100, 480) const deliverySlime2 = level.hazard(3700, -461, 100, 1141) - const slimePit = level.hazard(700, 1200, 2500, 1300, 0.004, "hsla(160, 100%, 35%,0.75)") - const topSlime = level.hazard(800, -460, 2900, 90, 0.004, "hsla(160, 100%, 35%,0.75)") + const slimePit = level.hazard(700, 1200, 2500, 1300, 0.004) + const topSlime = level.hazard(800, -460, 2900, 90, 0.004) // const rotor = level.rotor(0, -725, 0.001) const rotor = level.rotor(-400, -725, 800, 50, 0.001, 0, 0.01, 0, 0.001) @@ -11869,7 +11662,7 @@ const level = { const hazard3 = level.hazard(740, -1050, 10, 700, 0.4) const hazard4 = level.hazard(3400, -380, 350, 6, 0.2) const hazard5 = level.hazard(3425, -1420, 400, 8, 0.2) - const slimePit = level.hazard(2250, -100, 2700, 200, 0.004, "hsla(160, 100%, 35%,0.75)") + const slimePit = level.hazard(2250, -100, 2700, 200, 0.004) const door2 = level.door(3131, -898, 40, 520, 522) const buttonDoor2 = level.button(2495, -270) const toggle = level.toggle(1463, -708, true) diff --git a/js/player.js b/js/player.js index ca04f10..87e64f1 100644 --- a/js/player.js +++ b/js/player.js @@ -3016,20 +3016,10 @@ const m = { //not shooting (or using field) enable cloak if (m.energy < 0.05 && m.fireCDcycle < m.cycle && !input.fire) m.fireCDcycle = m.cycle if (m.fireCDcycle + 30 < m.cycle && !input.fire) { //automatically cloak if not firing - const drain = 0.05 - if (!m.isCloak && m.energy > drain + 0.05) { + const drain = 0.03 + if (!m.isCloak && m.energy > drain + 0.03) { m.energy -= drain m.isCloak = true //enter cloak - - - // m.color = { - // hue: 0, - // sat: 0, - // light: 100 - // } - // m.setFillColorsAlpha(0) - - m.enterCloakCycle = m.cycle if (tech.isCloakHealLastHit && m.lastHit > 0) { const heal = Math.min(0.75 * m.lastHit, m.energy) @@ -3063,7 +3053,7 @@ const m = { if (tech.isCloakStun) { //stun nearby mobs after exiting cloak let isMobsAround = false const stunRange = m.fieldDrawRadius * 1.5 - const drain = 0.2 + const drain = 0.15 if (m.energy > drain) { for (let i = 0, len = mob.length; i < len; ++i) { if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) < stunRange && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 && !mob[i].isBadTarget) { @@ -3085,11 +3075,11 @@ const m = { } } if (m.isCloak) { - m.fieldRange = m.fieldRange * 0.9 + 80 - m.fieldDrawRadius = m.fieldRange * 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy)); + m.fieldRange = m.fieldRange * 0.85 + 115 + m.fieldDrawRadius = m.fieldRange * 1.1 //* 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy)); m.drawCloak() } else if (m.fieldRange < 4000) { - m.fieldRange += 50 + m.fieldRange += 90 m.fieldDrawRadius = m.fieldRange //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy)); m.drawCloak() } diff --git a/js/powerup.js b/js/powerup.js index 88ba7f9..e4e0a6f 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -305,7 +305,8 @@ const powerUps = { document.getElementById("choose-grid").style.pointerEvents = "none"; document.body.style.cursor = "none"; setTimeout(() => { - if (!tech.isNoDraftPause) document.body.style.cursor = "auto"; + // if (!tech.isNoDraftPause) + document.body.style.cursor = "auto"; document.getElementById("choose-grid").style.pointerEvents = "auto"; document.getElementById("choose-grid").style.transitionDuration = "0s"; }, 400); @@ -313,7 +314,7 @@ const powerUps = { if (!simulation.paused) { if (tech.isNoDraftPause) { - document.getElementById("choose-grid").style.opacity = "0.92" + document.getElementById("choose-grid").style.opacity = "1" } else { simulation.paused = true; document.getElementById("choose-grid").style.opacity = "1" @@ -565,7 +566,7 @@ const powerUps = { }, effect() { if (b.inventory.length > 0) { - if (tech.isAmmoForGun && b.activeGun) { //give extra ammo to one gun only with tech logistics + if (tech.isAmmoForGun && b.activeGun !== null) { //give extra ammo to one gun only with tech logistics const target = b.guns[b.activeGun] if (target.ammo !== Infinity) { if (tech.ammoCap) { @@ -1164,10 +1165,7 @@ const powerUps = { if (tech.isLaserMine && input.down) { b.laserMine(who.position) } else { - b.mine(who.position, { - x: 0, - y: 0 - }, 0) + b.mine(who.position, { x: 0, y: 0 }, 0) } } if (tech.isRelay) { diff --git a/js/simulation.js b/js/simulation.js index 0a41b58..ed842a7 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -314,7 +314,7 @@ const simulation = { ctx.strokeStyle = "#000"; //'rgba(0,0,0,0.4)' ctx.beginPath(); if (m.fireCDcycle > m.cycle) { - ctx.strokeStyle = "#777"; //'rgba(0,0,0,0.4)' + ctx.strokeStyle = "#000"; //'rgba(0,0,0,0.4)' ctx.arc(simulation.mouse.x, simulation.mouse.y, size + 1, 0, 2 * Math.PI); } else { ctx.strokeStyle = "#000"; //'rgba(0,0,0,0.4)' @@ -474,10 +474,8 @@ const simulation = { switchGun() { if (tech.isLongitudinal && b.activeGun === 3) b.guns[3].waves = []; //empty array of wave bullets if (tech.crouchAmmoCount) tech.crouchAmmoCount = 1 //this prevents hacking the tech by switching guns - if (b.inventory.length > 0) { - b.activeGun = b.inventory[b.inventoryGun]; - if (b.guns[b.activeGun].charge) b.guns[b.activeGun].charge = 0; //if switching into foam set charge to 0 - } + if (b.inventory.length > 0) b.activeGun = b.inventory[b.inventoryGun]; + b.guns[8].charge = 0; // foam charge to 0 simulation.updateGunHUD(); simulation.boldActiveGunHUD(); //set crosshairs @@ -774,8 +772,6 @@ const simulation = { input.endKeySensing(); b.removeAllGuns(); - simulation.switchGun(); - tech.setupAllTech(); //sets tech to default values tech.cancelCount = 0; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun @@ -904,28 +900,30 @@ const simulation = { clearMap() { ctx.setTransform(1, 0, 0, 1, 0, 0); if (m.alive) { - if (tech.isLongitudinal) { - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "wave") { - b.guns[i].waves = []; //empty array of wave bullets - break; + if (tech.isLongitudinal) b.guns[3].waves = []; //empty array of wave bullets + if (b.guns[10].have) { //do you have mines as a gun + let count = 0; + for (i = 0, len = bullet.length; i < len; i++) { //count mines left on map + if ( + (bullet[i].bulletType === "mine" && (!tech.isMineSentry || bullet[i].shots === undefined)) || + bullet[i].bulletType === "laser mine") { + count++ } } + if (tech.crouchAmmoCount) count = Math.ceil(count / 2) + b.guns[10].ammo += count + if (tech.ammoCap) b.guns[10].ammo = Math.min(tech.ammoCap, b.guns[10].ammo) + simulation.updateGunHUD(); } - let count = 0; - for (i = 0, len = bullet.length; i < len; i++) { //count mines left on map - if ((bullet[i].bulletType === "mine" || bullet[i].bulletType === "laser mine") && !bullet[i].isArmed) count++ - } - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is mine - if (b.guns[i].name === "mine") { - if (tech.crouchAmmoCount) count = Math.ceil(count / 2) - b.guns[i].ammo += count - if (tech.ammoCap) b.guns[i].ammo = Math.min(tech.ammoCap, b.guns[i].ammo) - simulation.updateGunHUD(); - break; - } - } + // for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is mine + // if (b.guns[i].name === "mine") { + // b.guns[i].ammo += count + // if (tech.ammoCap) b.guns[i].ammo = Math.min(tech.ammoCap, b.guns[i].ammo) + // simulation.updateGunHUD(); + // break; + // } + // } if (tech.isMutualism && !tech.isEnergyHealth) { for (let i = 0; i < bullet.length; i++) { diff --git a/js/spawn.js b/js/spawn.js index a4b97a5..be31bf8 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -578,7 +578,7 @@ const spawn = { }, { name: "laser", - spinForce: 0.00000012, // * (Math.random() < 0.5 ? -1 : 1), + spinForce: 0.00000008, // * (Math.random() < 0.5 ? -1 : 1), fadeCycle: 0, //fades in over 4 seconds do() { this.fadeCycle++ diff --git a/js/tech.js b/js/tech.js index b943323..3a6b261 100644 --- a/js/tech.js +++ b/js/tech.js @@ -381,6 +381,14 @@ const tech = { if (regex !== -1 && (not === -1 || not > regex)) gunTechPool.push(j) //look for the gun name in the requirements, but the gun name needs to show up before the word ' not ' } b.activeGun = originalActiveGunIndex + if (!b.guns[b.activeGun].have) { + if (b.inventory.length === 0) { + b.activeGun = null + } else { + b.activeGun = b.inventory[0] + } + b.inventoryGun = 0; + } } if (gunTechPool.length) { const index = Math.floor(Math.random() * gunTechPool.length) @@ -4356,7 +4364,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !(tech.isFoamMine || tech.isSuperMine)) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1 + return tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isFoamMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1 }, requires: "nails, nail gun, rivets, shotgun, super balls, mine", effect() { @@ -5280,26 +5288,26 @@ const tech = { if (this.count > 0) powerUps.research.changeRerolls(3) } }, - { - name: "electric armor", - // description: "explosions do no defense
while your energy is above 98%", - description: "instead of causing health loss, explosions
drain 12 energy and have more knockback", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return !tech.isSmartRadius && !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() - }, - requires: "an explosive damage source, not iridium-192", - effect() { - tech.isImmuneExplosion = true; - }, - remove() { - tech.isImmuneExplosion = false; - } - }, + // { + // name: "electric armor", + // // description: "explosions do no defense
while your energy is above 98%", + // description: "instead of causing health loss, explosions
drain 12 energy and have more knockback", + // isGunTech: true, + // maxCount: 1, + // count: 0, + // frequency: 2, + // frequencyDefault: 2, + // allowed() { + // return !tech.isSmartRadius && !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() + // }, + // requires: "an explosive damage source, not iridium-192", + // effect() { + // tech.isImmuneExplosion = true; + // }, + // remove() { + // tech.isImmuneExplosion = false; + // } + // }, { name: "MIRV", description: "fire +1 missile or grenade per shot
–12% explosion damage and radius", @@ -5321,21 +5329,23 @@ const tech = { }, { name: "rocket-propelled grenade", - description: "grenades rapidly accelerate forward
map collisions trigger an explosion", + description: "grenades explode on map collisions
explosions drain energy, not health", isGunTech: true, maxCount: 1, count: 0, frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("grenades") + return tech.haveGunCheck("grenades") && !tech.isVacuumBomb }, - requires: "grenades", + requires: "grenades, not vacuum bomb", effect() { + tech.isImmuneExplosion = true; tech.isRPG = true; b.setGrenadeMode() }, remove() { + tech.isImmuneExplosion = true; tech.isRPG = false; b.setGrenadeMode() } @@ -5349,9 +5359,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("grenades") && !tech.isNeutronBomb && !tech.isBlockExplode + return tech.haveGunCheck("grenades") && !tech.isNeutronBomb && !tech.isBlockExplode && !tech.isRPG }, - requires: "grenades, not neutron bomb, chain reaction", + requires: "grenades, not neutron bomb, chain reaction, RPG", effect() { tech.isVacuumBomb = true; b.setGrenadeMode() @@ -5646,7 +5656,7 @@ const tech = { } }, { - name: "sentry gun", + name: "sentry", descriptionFunction() { return `mines fire one ${b.guns[10].nameString()} at a time
mines fire 50% more ${b.guns[10].nameString('s')}` }, diff --git a/style.css b/style.css index 6f56a5f..7a6e97b 100644 --- a/style.css +++ b/style.css @@ -1,5 +1,7 @@ :root { --build-bg-color: #aeb6c2; + --card-color: #fafcfd; + --hover-card-color: #e5e5ed; } body { @@ -185,15 +187,15 @@ summary { .choose-grid-module { line-height: 160%; - background-color: #fafcfd; + background-color: var(--card-color); font-size: 0.75em; } .choose-grid-module:hover { - background-color: #efeff5; + background-color: var(--hover-card-color); } .choose-grid-module:hover .card-text { - background-color: #efeff5; + background-color: var(--hover-card-color); } .research-select { @@ -244,7 +246,7 @@ summary { .pause-grid-module { line-height: 160%; - background-color: #fafcfd; + background-color: var(--card-color); font-size: 0.75em; } @@ -276,7 +278,7 @@ summary { .experiment-grid-module { line-height: 160%; - background-color: #fafcfd; + background-color: var(--card-color); font-size: 0.75em; } @@ -292,11 +294,11 @@ summary { } .experiment-grid-module:hover:not(.build-tech-selected, .build-field-selected, .build-gun-selected) { - background-color: #efeff5; + background-color: var(--card-color); } .experiment-start-box{ - background-color: #fafcfd; + background-color: var(--card-color); /* font-size: 1em; */ position: sticky; top:0; @@ -347,10 +349,10 @@ summary { margin-right: -1px; padding: 1px; line-height: 160%; - background-color: #fafcfd; + background-color: var(--card-color); } .cancel-card:hover { - background-color: #efeff5; + background-color: var(--hover-card-color); } .research-card { font-size: 1.1em; @@ -360,15 +362,15 @@ summary { margin-right: -1px; padding: 1px 0px 1px 10px; line-height: 160%; - background-color: #fafcfd; + background-color: var(--card-color); } .research-card:hover { - background-color: #efeff5; + background-color: var(--hover-card-color); } /* keeps 5 columns at 1440px */ -@media (1710px <= width < 1950px) { +@media (min-width: 1710px) and (max-width: 1950px) { .experiment-grid-module, .choose-grid-module, .pause-grid-module { line-height: 143%; font-size: 0.68em; @@ -383,7 +385,8 @@ summary { min-height: 75px; } } -@media (width < 1710px) { +/* (min-width: 30em) and (max-width: 80em) */ +@media (max-width: 1709px) { .experiment-grid-module, .choose-grid-module, .pause-grid-module { line-height: 139%; font-size: 0.58em; @@ -431,7 +434,7 @@ summary { } */ .experiment-grid-module:hover .card-text { - background-color: #efeff5; + background-color: var(--hover-card-color); } .build-tech-selected .card-text{ background-color: hsl(253, 100%, 84%); @@ -453,9 +456,9 @@ summary { } .experiment-grid-disabled { - background-color: var(--build-bg-color); - color: #000; - opacity: 0.25; + /* background-color: var(--build-bg-color); */ + /* color: #000; */ + opacity: 0.35; } .experiment-grid-disabled[data-descr] { @@ -756,7 +759,7 @@ summary { font-weight: 100; } .color-cancel { - background-color: #fafcfd; + background-color: var(--card-color); border: 0.15em #444 solid; padding: 0.2em; border-radius: 0.2em; @@ -980,7 +983,7 @@ summary { text-align: center; letter-spacing: 10px; border: none; - background-color: #efeff5; + background-color: var(--card-color); } .flipX { animation: 14s anim-flipX linear infinite; diff --git a/todo.txt b/todo.txt index d27446f..8dbde54 100644 --- a/todo.txt +++ b/todo.txt @@ -1,25 +1,64 @@ ******************************************************** NEXT PATCH ************************************************** +tech: RPG - gains the rocket jumping effects from electric armor -tech: repeater - shotgun gets another shot, and a longer fire delay - shotgun cross hairs show when fire is on cooldown +eternalism no longer makes tech options have 50% opacity when choosing -keys 1,2,3,4,5,6,7,8,9,0,-,= switch to a gun in your inventory -Nerfed blinkBoss health and speed -sneaker mobs are immune to harm for one cycles after vanishing -experiment button new style -new images for energy, bots +some new images for cloaking tech +and some images were made brighter bug fixes + safari media rules css fixed *********************************************************** TODO ***************************************************** + + tech: maybe missiles explode when they hit walls, but explosions only drain energy + +tech: sticky grenades + needs another effect to be good enough + stick to mobs? + +testChamber2 + mechanics + cover exit with slime, press button to lower slime and exit + companion cube + bring cube to the end and use it to unlock research + level draws on the block to show it's different + only this block can trigger a button? + if cube no longer exists or is off the map spawn a new one + or maybe add a button for the player to destroy current cube and spawn new cube + double portal fling chain + for player? + for cube + button that activates a laser beam that hits a target and opens a door + in order to enter the door you need to place the cube on the button to activate the laser + cube has to fly through a portal in order to get to the button + you can't use your body + story: + you pick up the cube early on and have to get it to a button + you run through the level to get the cube, clearing the level of mobs + picking up the cube spawns the boss + maybe an extra hard boss that is designed for that level + blockBoss? + you must get the cube to a button near the start of the level + the button opens a door + normal blocks don't work + normal blocks spawn into mobs like blockBoss + or mobs don't spawn blocks + or just the code looks for the cube + or the cube is resting on a button, and when you take the cube off the button the laser fires + + +make a mob similar to slasher + because it's just a very well made mob. + + tech - only allow 1,2 turrets at time? - turrets drain energy? turrets never run out of ammo - turrets automatically use one of your mine ammos when they run out? + or turrets automatically use one of your mine ammos when they run out? good with multi gun builds - conflict with booby trap + conflict with booby trap? tech: Bose Einstein condensate - freezes enemies in pilot wave, and drains some energy? @@ -62,14 +101,6 @@ tech: sporangium that grow little trees the trees have an area of effect damage for about 6-10 seconds maybe something similar to radioactive drones, but maybe a few smaller shapes -spores, worms, fleas - can target player - when to target player - probably have to not go after player for at least a few seconds - only go after player if there are no mobs - go after what ever is closest target - go after a random target - if distance to player < 60 damage player - new bot type that makes phonon waves name: phono-bot? each bot has to generate it themselves, can't run code in gun.do @@ -337,34 +368,6 @@ make plasma ball power up and block pick up still work when you have no no energ tech: entropic gravity - gain defense for each research requires wormhole or pilot wave or negative mass field? -testChamber2 - mechanics - companion cube - bring cube to the end and use it to unlock research - level draws on the block to show it's different - only this block can trigger a button - if cube no longer exists or is off the map spawn a new one - double portal fling chain - for player? - for cube - button that activates a laser beam that hits a target and opens a door - in order to enter the door you need to place the cube on the button to activate the laser - cube has to fly through a portal in order to get to the button - you can't use your body - story: - you pick up the cube early on and have to get it to a button - you run through the level to get the cube, clearing the level of mobs - picking up the cube spawns the boss - maybe an extra hard boss that is designed for that level - blockBoss? - you must get the cube to a button near the start of the level - the button opens a door - normal blocks don't work - normal blocks spawn into mobs like blockBoss - or mobs don't spawn blocks - or just the code looks for the cube - or the cube is resting on a button, and when you take the cube off the button the laser fires - mitosis: after needle,bullets or rivets hit a surface split off into two smaller less damaging versions that have their velocity reset -firerate after killing a mob go invulnerable for 1 second @@ -1164,9 +1167,9 @@ if pause is pressed while selecting power ups, display pause menu on top of sele quantum stuff -- Hypertorus, Glowing Opal Pearlescent, Physics, Hydro-Dipping Hydrodipped, Vija Celmins, Matt Molloy (photo of golden waves in the sky) ***major themes missing*** ***maybe redo*** - dynamical systems heuristics negative feedback - too dark + supercritical fission ***past style themes*** field emitter - isometric, clean white robot spherical gun turret on bird legs, blender 3d, style of artstation and behance, Disney Pixar, cute standing wave - concentric transparent blue geometric circles science @@ -1174,7 +1177,7 @@ if pause is pressed while selecting power ups, display pause menu on top of sele time dilation - graphic of a hyperbolic equation Luminogram negative mass - Blacklight painting by Moebius plasma torch - by Dan Mumford - metamaterial cloaking - Scientific photography by Miki Asai + metamaterial cloaking - Scientific photography by Miki Asai, by Bruce Munro molecular assembler - by Laurie Greasley 16-bit Isometric wormhole - by Tim White