From 7d1b212c8a13c0ea2d7708ce89bfd1ba36428572 Mon Sep 17 00:00:00 2001 From: landgreen Date: Tue, 28 Dec 2021 21:03:06 -0800 Subject: [PATCH] vanish platform new training levels "stack", "mine", "grenades", "harpoon" new map element vanish goes away after you touch it, returns in 3 seconds bug fixes --- .DS_Store | Bin 6148 -> 6148 bytes index.html | 3 +- js/bullet.js | 2 +- js/level.js | 2676 +++++++++++++++++++++++++++------------------- js/simulation.js | 1 + js/spawn.js | 10 +- js/tech.js | 6 +- todo.txt | 53 +- 8 files changed, 1579 insertions(+), 1172 deletions(-) diff --git a/.DS_Store b/.DS_Store index 92755255b61e690e99888bab293c0c5f8b9e8d11..6fc3f54fa528bb41b41c351be983ffcc3ca4706b 100644 GIT binary patch delta 22 dcmZoMXffEJ#msbuak37xFO$N9&DG4EA^=cO2J`>` delta 22 dcmZoMXffEJ#mrQZI$4L=mr1^1b2W3P2mnrn2BQD~ diff --git a/index.html b/index.html index 7c463e8..31f687d 100644 --- a/index.html +++ b/index.html @@ -95,7 +95,8 @@ - training + + training
diff --git a/js/bullet.js b/js/bullet.js index 77cf0c5..db996d6 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -5453,7 +5453,7 @@ const b = { } else { const bodyCollisions = Matter.Query.collides(this, body) if (bodyCollisions.length) { - if (!bodyCollisions[0].bodyA.isComposite) { + if (!bodyCollisions[0].bodyA.isNonStick) { onCollide(this) this.stuckTo = bodyCollisions[0].bodyA //find the relative position for when the mob is at angle zero by undoing the mobs rotation diff --git a/js/level.js b/js/level.js index 0674ce3..010c795 100644 --- a/js/level.js +++ b/js/level.js @@ -8,8 +8,12 @@ const level = { onLevel: -1, levelsCleared: 0, playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber"], //intro, gauntlet, final are added in at the start and end of level order - trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "dhotGun", "superBall", "matterWave", "missile"], communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "n-gon", "house", "perplex", "coliseum", "tunnel"], + trainingLevels: [ + "walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", + "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", + "stack", "mine", "grenades", "harpoon" + ], levels: [], start() { if (level.levelsCleared === 0) { //this code only runs on the first level @@ -30,7 +34,7 @@ const level = { // for (let i = 0; i < 1; i++) tech.giveTech("reticulum") // for (let i = 0; i < 2; i++) tech.giveTech("laser-bot") // tech.tech[297].frequency = 100 - // level.deflect(); + // level.harpoon(); if (simulation.isTraining) { level.walk(); } else { level.intro(); } // level.testing(); //not in rotation, used for testing @@ -63,7 +67,7 @@ const level = { // for (let i = 0; i < 3; i++) tech.giveTech("undefined") // lore.techCount = 3 // simulation.isCheating = false //true; - // localSettings.loreCount = 3; //this sets what conversation is heard + // localSettings.loreCount = 1; //this sets what conversation is heard // localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation // level.null() @@ -136,1121 +140,12 @@ const level = { }, trainingText(say) { simulation.lastLogTime = 0; //clear previous messages - simulation.makeTextLog(`supervised.learning(${(Date.now()/1000).toFixed(0)} s):
${say}
`, Infinity) + simulation.isTextLogOpen = true + simulation.makeTextLog(`supervised.learning(${(Date.now()/1000).toFixed(0)} s):
${say}
`, Infinity) + simulation.isTextLogOpen = false // lore.trainer.text("Wow. Just a platform.") }, trainingBackgroundColor: "#e1e1e1", - walk() { //learn to walk - - var img = new Image(); // Create new img element - img.src = 'myImage.png'; // Set source path - - - m.addHealth(Infinity) - document.getElementById("health").style.display = "none" //hide your health bar - document.getElementById("health-bg").style.display = "none" - - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - simulation.lastLogTime = 0; //clear previous messages - let instruction = 0 - level.trainingText(`move with ${input.key.left.replace('Key', '').replace('Digit', '')} and ${input.key.right.replace('Key', '').replace('Digit', '')}`) - - level.custom = () => { - if (instruction === 0 && input.right) { - instruction++ - level.trainingText(`move with ${input.key.left.replace('Key', '').replace('Digit', '')} and ${input.key.right.replace('Key', '').replace('Digit', '')} -
exit through the blue door`) - } - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - }; - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 0, 3500, 1800); //floor - spawn.mapRect(1575, 0, 500, 100); - spawn.mapRect(-250, -2800, 3500, 2200); //roof - spawn.mapRect(700, -8, 50, 25); - spawn.mapRect(725, -16, 75, 25); - spawn.mapRect(1375, -16, 50, 50); - spawn.mapRect(1400, -8, 50, 25); - spawn.mapRect(750, -24, 650, 100); - spawn.mapRect(1600, -1200, 500, 850); //exit roof - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - }, - crouch() { //learn to crouch - m.addHealth(Infinity) - level.setPosToSpawn(75, -100); //normal spawn - spawn.mapRect(25, -60, 100, 20); //small platform for player - spawn.mapRect(0, -50, 150, 25); //stairs - spawn.mapRect(-25, -40, 200, 25); - spawn.mapRect(-50, -30, 250, 25); - spawn.mapRect(-75, -20, 300, 25); - spawn.mapRect(-100, -10, 350, 25); - spawn.mapRect(-150, -50, 175, 75); - - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - let instruction = 0 - level.trainingText(`press ${input.key.down.replace('Key', '').replace('Digit', '')} to crouch`) - level.custom = () => { - if (instruction === 0 && input.down) { - instruction++ - level.trainingText(`press ${input.key.down.replace('Key', '').replace('Digit', '')} to crouch`) - } - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1625, -350, 375, 350) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1625, -350, 375, 350) - //dark - ctx.fillStyle = "rgba(0,0,0,0.2)" - ctx.fillRect(500, -100, 1125, 175); - }; - - // spawn.mapRect(1025, -675, 300, 623); //crouch wall - // spawn.mapRect(625, -650, 1025, 550); - spawn.mapRect(500, -650, 1125, 550); - spawn.mapRect(-200, -650, 875, 300); - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(1575, 0, 500, 100); - spawn.mapRect(-250, -2800, 3500, 2200); //roof - - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - spawn.mapRect(1525, 25, 75, 50); - spawn.mapRect(1500, 38, 50, 25); - spawn.mapRect(1550, 12, 50, 25); - spawn.mapRect(1600, -1200, 500, 850); //exit roof - }, - jump() { //learn to jump - m.addHealth(Infinity) - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - let instruction = 0 - level.trainingText(`hold down ${input.key.up.replace('Key', '').replace('Digit', '')} longer to jump higher`) - - level.custom = () => { - if (instruction === 0 && m.pos.x > 300) { - instruction++ - level.trainingText(`hold down ${input.key.up.replace('Key', '').replace('Digit', '')} longer to jump higher`) - } - m.health = 1 //can't die - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - //dark - ctx.fillStyle = "rgba(0,0,0,0.2)" - ctx.fillRect(1000, 0, 450, 1800) - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - }; - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(275, -350, 200, 375); - spawn.mapRect(-250, 0, 1250, 1800); //floor - spawn.mapRect(1450, 0, 1075, 1800); //floor - spawn.mapRect(-250, -2800, 1250, 2200); //roof - spawn.mapRect(1450, -2800, 1075, 2200); //roof - spawn.mapVertex(375, 0, "150 0 -150 0 -100 -50 100 -50"); //base - - spawn.mapRect(1600, -1200, 500, 850); //exit roof - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - - //roof steps - spawn.mapRect(1000, -650, 25, 25); - spawn.mapRect(1000, -675, 50, 25); - spawn.mapRect(1000, -700, 75, 25); - spawn.mapRect(1000, -725, 100, 25); - spawn.mapRect(1425, -650, 25, 25); - spawn.mapRect(1400, -675, 50, 25); - spawn.mapRect(1375, -700, 75, 25); - spawn.mapRect(1350, -725, 100, 25); - spawn.mapRect(1325, -750, 150, 25); - spawn.mapRect(1300, -775, 150, 25); - spawn.mapRect(1000, -750, 125, 25); - spawn.mapRect(1275, -2800, 200, 2025); - spawn.mapRect(975, -2800, 200, 2025); - spawn.mapRect(1000, -775, 150, 25); - }, - hold() { //put block on button to open door - m.addHealth(Infinity) - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - spawn.bodyRect(1025, -75, 50, 50); //block to go on button - const buttonDoor = level.button(500, 0) - const door = level.door(1612.5, -175, 25, 190, 185, 3) - - let instruction = 0 - level.trainingText(`activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse`) - - level.custom = () => { - if (instruction === 0 && input.field) { - instruction++ - level.trainingText(`activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse
release your field on a block to pick it up`) - } else if (instruction === 1 && m.isHolding) { - instruction++ - level.trainingText(`activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse
release your field on a block to pick it up

drop the block on the red button to open the door`) - } else if (instruction === 2 && !buttonDoor.isUp && Vector.magnitudeSquared(Vector.sub(body[0].position, buttonDoor.min)) < 10000) { - instruction++ - level.trainingText(`activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse
release your field on a block to pick it up
drop the block on the red button to open the door
`) - } - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - buttonDoor.query(); - buttonDoor.draw(); - if (buttonDoor.isUp) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - }; - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(1575, 0, 500, 100); - spawn.mapRect(-250, -2800, 3500, 2200); //roof - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - spawn.mapRect(1525, 25, 75, 50); - spawn.mapRect(1500, 38, 50, 25); - spawn.mapRect(1550, 12, 50, 25); - spawn.mapRect(1600, -1200, 500, 850); //exit roof - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - }, - throw () { //throw a block on button to open door - m.addHealth(Infinity) - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - spawn.bodyRect(1025, -75, 50, 50); //block to go on button - const buttonDoor = level.button(1635, -400) - const door = level.door(1612.5, -175, 25, 190, 185, 3) - - // activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse - let instruction = 0 - level.trainingText(`pick up the block with your field`) - - level.custom = () => { - if (instruction === 0 && m.isHolding) { - instruction++ - level.trainingText(`pick up the block with your field -
hold your field down to charge up then release to throw a block`) - } else if (instruction === 1 && m.throwCharge > 2) { - instruction++ - level.trainingText(`pick up the block with your field -
hold your field down to charge up then release to throw a block
-
throw the block onto the button`) - // the block at the button - } else if (instruction === 2 && !buttonDoor.isUp && Vector.magnitudeSquared(Vector.sub(body[0].position, buttonDoor.min)) < 10000) { - instruction++ - level.trainingText(`pick up the block with your field -
hold your field down to charge up then release to throw a block -
throw the block onto the button
`) - } - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - buttonDoor.query(); - buttonDoor.draw(); - if (buttonDoor.isUp) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - }; - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(1575, 0, 500, 100); - spawn.mapRect(-250, -2800, 3500, 2200); //roof - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - spawn.mapRect(1525, 25, 75, 50); - spawn.mapRect(1500, 38, 50, 25); - spawn.mapRect(1550, 12, 50, 25); - // spawn.mapRect(1600, -1200, 500, 850); //exit roof - spawn.mapRect(1790, -600, 250, 225); //button left wall - spawn.mapRect(1625, -400, 400, 50); - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - }, - throwAt() { //throw a block at mob to open door - m.addHealth(Infinity) - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - const door = level.door(1612.5, -175, 25, 190, 185, 3) - - let instruction = 0 - level.trainingText(`throw the block at the mobs to open the door`) - - level.custom = () => { - if (instruction === 0 && !mob.length) { - instruction++ - level.trainingText(`throw the block at the mobs to open the door`) - } - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - if (mob.length > 0) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - }; - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(1575, 0, 500, 100); - spawn.mapRect(-250, -2800, 3500, 2200); //roof - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - spawn.mapRect(1525, 25, 75, 50); - spawn.mapRect(1500, 38, 50, 25); - spawn.mapRect(1550, 12, 50, 25); - // spawn.mapRect(1600, -1200, 500, 850); //exit roof - // spawn.mapRect(1790, -600, 250, 225); //button left wall - // spawn.mapRect(1625, -400, 400, 50); - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - spawn.mapRect(1600, -600, 425, 250); - - spawn.bodyRect(1025, -75, 50, 50); //block to go on button - spawn.starter(425, -350, 35) - spawn.starter(800, -350, 44) - }, - fire() { //throw a block at mob to open door - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = 15; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - const door = level.door(1612.5, -125, 25, 190, 185, 3) - const buttonDoor = level.button(400, 0) - - let instruction = 0 - level.trainingText(`use your field to pick up the gun power up`) - - level.custom = () => { - if (instruction === 0 && simulation.isChoosing) { - instruction++ - level.trainingText(`use your field to pick up the gun power up -
choose a gun`) - } else if (instruction === 1 && !simulation.isChoosing) { - instruction++ - level.trainingText(`use your field to pick up the gun power up -
choose a gun
-
use the left mouse button to shoot the mobs`) - } else if (instruction === 2 && mob.length === 0) { - instruction++ - level.trainingText(`use your field to pick up the gun power up -
choose a gun -
use the left mouse button to shoot the mobs
-
drop a block on the red button to open the door`) - } else if (instruction === 3 && !door.isClosing) { - instruction++ - level.trainingText(`use your field to pick up the gun power up -
choose a gun -
use the left mouse button to shoot the mobs -
put a block on the red button to open the door
`) - } - //spawn ammo if you run out - if (!powerUp.length && b.inventory.length && b.guns[b.activeGun].ammo === 0) powerUps.directSpawn(1300, -2000, "ammo", false); - - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -350, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - buttonDoor.query(); - buttonDoor.draw(); - if (buttonDoor.isUp) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -350, 400, 400) - //ammo tunnel shadow - ctx.fillStyle = "rgba(0,0,0,0.4)" - ctx.fillRect(1250, -2800, 100, 2200) - }; - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(-150, -2800, 1400, 2200); //roof with tunnel for ammo - spawn.mapRect(1350, -2800, 675, 2200); - - //ceiling steps - spawn.mapRect(725, -588, 50, 25); - spawn.mapRect(725, -600, 75, 25); - spawn.mapRect(750, -612, 75, 25); - spawn.mapRect(-275, -650, 1025, 87); - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - - spawn.mapRect(1600, -600, 425, 300); - spawn.mapRect(1600, -400, 50, 275); - - powerUps.directSpawn(1300, -1500, "gun", false); - spawn.starter(900, -300, 35) - spawn.starter(1400, -400, 44) - }, - deflect() { //learn to jump - m.addHealth(Infinity) - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - let instruction = 0 - // activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse - level.trainingText(`use your field to deflect the mobs`) - - level.custom = () => { - if (instruction === 0 && m.pos.x > 1350) { - instruction++ - level.trainingText(`use your field to deflect the mobs`) - } - //teleport to start if hit - if (m.immuneCycle > m.cycle) { - m.energy = m.maxEnergy - Matter.Body.setPosition(player, { x: 60, y: -50 }) - } - //spawn bullets - if (!(simulation.cycle % 5)) { - spawn.sniperBullet(660 + 580 * Math.random(), -2000, 10, 4); - const who = mob[mob.length - 1] - Matter.Body.setVelocity(who, { x: 0, y: 8 }); - who.timeLeft = 300 - } - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - //dark - ctx.fillStyle = "rgba(0,0,0,0.05)" - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - //center falling bullets - ctx.fillStyle = "rgba(255,0,255,0.013)" //pink? - ctx.fillRect(650, -2800, 600, 2800) - }; - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - - spawn.mapRect(-250, 0, 3000, 1800); //floor - spawn.mapRect(-250, -2800, 900, 2200); //roof - spawn.mapRect(1250, -2800, 1275, 2200); //roof - spawn.mapVertex(950, 0, "400 0 -400 0 -300 -50 300 -50"); //base - - spawn.mapRect(1600, -1200, 500, 850); //exit roof - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - - //spawn bullets on load to avoid rush - for (let i = 0; i < 32; i++) { - spawn.sniperBullet(660 + 580 * Math.random(), -2000 + 40 * i, 10, 4); - const who = mob[mob.length - 1] - Matter.Body.setVelocity(who, { x: 0, y: 8 }); - who.timeLeft = 300 - } - }, - heal() { //learn to heal - m.addHealth(Infinity) - m.health = 0; - m.addHealth(0.25) - document.getElementById("health").style.display = "inline" //show your health bar - document.getElementById("health-bg").style.display = "inline" - - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - let instruction = 0 - level.trainingText(`your health is displayed in the top left corner -
use your field to pick up
until your health is full`) - - level.custom = () => { - if (instruction === 0 && m.health === 1) { - instruction++ - level.trainingText(`use your field to pick up
until your health is full
`) - } - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - if (m.health !== 1) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - }; - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 0, 3500, 1800); //floor - - spawn.mapRect(1575, 0, 500, 100); - spawn.mapRect(-250, -2800, 3500, 2200); //roof - - spawn.mapRect(700, -8, 50, 25); - spawn.mapRect(725, -16, 75, 25); - spawn.mapRect(1375, -16, 50, 50); - spawn.mapRect(1400, -8, 50, 25); - spawn.mapRect(750, -24, 650, 100); - powerUps.directSpawn(875, -40, "heal", false, null, 15); - powerUps.directSpawn(1075, -50, "heal", false, null, 25); - powerUps.directSpawn(1275, -65, "heal", false, null, 35); - - const door = level.door(1612.5, -175, 25, 190, 185, 3) - spawn.mapRect(1600, -1200, 500, 850); //exit roof - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - }, - nailGun() { //throw a block on button to open door - level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); - b.giveGuns("nail gun") - b.guns[b.activeGun].ammo = 0 - simulation.updateGunHUD(); - - const door = level.door(1612.5, -175, 25, 190, 185, 3) - let instruction = 0 - level.trainingText(`use your field to pick up
for your nail gun`) - - level.custom = () => { - if (instruction === 0 && b.inventory.length && b.guns[b.activeGun].ammo > 0) { - instruction++ - level.trainingText(`use your field to pick up
for your nail gun
-
use the left mouse button to shoot the mobs`) - } else if (instruction === 1 && mob.length === 0) { - instruction++ - level.trainingText(`use your field to pick up
for your nail gun -
use the left mouse button to shoot the mobs
`) - } - //spawn ammo if you run out - let isAmmo = false - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === 'ammo') isAmmo = true - } - if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { - powerUps.directSpawn(1300, -2000, "ammo", false); - powerUps.directSpawn(1301, -2200, "ammo", false); - } - - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - if (mob.length > 0) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - //ammo tunnel shadow - ctx.fillStyle = "rgba(0,0,0,0.4)" - ctx.fillRect(1250, -2800, 100, 2200) - }; - - if (m.health < 1) { - powerUps.directSpawn(1298, -3500, "heal", false, 23); - powerUps.directSpawn(1305, -3000, "heal", false, 35); - } - for (let i = 0; i < 2; i++) { - spawn.spinner(1300 + i, -3000 - 200 * i, 25 + 5 * i) - Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 62 }); - } - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(1575, 0, 500, 100); - spawn.mapRect(-150, -2800, 1400, 2200); //roof with tunnel for ammo - spawn.mapRect(1350, -2800, 675, 2200); - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - spawn.mapRect(1525, 25, 75, 50); - spawn.mapRect(1500, 38, 50, 25); - spawn.mapRect(1550, 12, 50, 25); - // spawn.mapRect(1600, -1200, 500, 850); //exit roof - // spawn.mapRect(1790, -600, 250, 225); //button left wall - // spawn.mapRect(1625, -400, 400, 50); - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - spawn.mapRect(1600, -600, 425, 250); - }, - shotGun() { //throw a block on button to open door - level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); - b.giveGuns("shotgun") - // b.guns[b.activeGun].ammo = 0 - // simulation.updateGunHUD(); - const door = level.door(1612.5, -175, 25, 190, 185, 3) - let instruction = 0 - level.trainingText(`use your shotgun to clear the room of mobs`) - - level.custom = () => { - if (instruction === 0 && mob.length === 0) { - instruction++ - level.trainingText(`use your shotgun to clear the room of mobs`) - } - //spawn ammo if you run out - let isAmmo = false - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === 'ammo') isAmmo = true - } - if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { - powerUps.directSpawn(1300, -2000, "ammo", false); - powerUps.directSpawn(1301, -2200, "ammo", false); - } - - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - if (mob.length > 0) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - //ammo tunnel shadow - ctx.fillStyle = "rgba(0,0,0,0.4)" - ctx.fillRect(1250, -2800, 100, 2200) - }; - - if (m.health < 1) { - powerUps.directSpawn(1298, -3500, "heal", false, 23); - powerUps.directSpawn(1305, -3000, "heal", false, 35); - } - for (let i = 0; i < 3; i++) { - spawn.hopper(1300 + i, -3000 - 2000 * i, 25 + 5 * i) - // Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 0 }); - } - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(1575, 0, 500, 100); - spawn.mapRect(-150, -2800, 1400, 2200); //roof with tunnel for ammo - spawn.mapRect(1350, -2800, 675, 2200); - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - spawn.mapRect(1525, 25, 75, 50); - spawn.mapRect(1500, 38, 50, 25); - spawn.mapRect(1550, 12, 50, 25); - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - spawn.mapRect(1600, -600, 425, 250); - }, - superBall() { //throw a block on button to open door - level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); - b.giveGuns("super balls") - // b.guns[b.activeGun].ammo = 0 - // simulation.updateGunHUD(); - const door = level.door(1612.5, -175, 25, 190, 185, 3) - let instruction = 0 - level.trainingText(`use super balls to clear the room of mobs`) - - level.custom = () => { - if (instruction === 0 && mob.length === 0) { - instruction++ - level.trainingText(`use super balls to clear the room of mobs`) - } - //spawn ammo if you run out - let isAmmo = false - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === 'ammo') isAmmo = true - } - if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { - powerUps.directSpawn(1300, -2000, "ammo", false); - powerUps.directSpawn(1301, -2200, "ammo", false); - } - - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - if (mob.length > 0) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - //ammo tunnel shadow - ctx.fillStyle = "rgba(0,0,0,0.2)" - // ctx.fillRect(1225, -2800, 125, 2450) - ctx.fillRect(-150, -2800, 1500, 2450); - }; - - if (m.health < 1) { - powerUps.directSpawn(1298, -3500, "heal", false, 23); - powerUps.directSpawn(1305, -3000, "heal", false, 35); - } - for (let i = 0; i < 6; i++) { - spawn.spawner(i * 230, -800) - // Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 0 }); - } - spawn.mapVertex(510, -430, "725 0 725 80 -650 80 -650 -80 650 -80"); //upper room with mobs - spawn.mapRect(-225, -2800, 1450, 2000); - spawn.mapRect(1350, -2800, 675, 2450); - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(1575, 0, 500, 100); - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - spawn.mapRect(1525, 25, 75, 50); - spawn.mapRect(1500, 38, 50, 25); - spawn.mapRect(1550, 12, 50, 25); - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - }, - matterWave() { //throw a block on button to open door - level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); - b.giveGuns("matter wave") - // b.guns[b.activeGun].ammo = 0 - // simulation.updateGunHUD(); - const door = level.door(1612.5, -175, 25, 190, 185, 3) - let instruction = 0 - level.trainingText(`use matter wave to clear the room of mobs`) - - level.custom = () => { - if (instruction === 0 && mob.length === 0) { - instruction++ - level.trainingText(`use matter wave to clear the room of mobs`) - } - //spawn ammo if you run out - let isAmmo = false - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === 'ammo') isAmmo = true - } - if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { - powerUps.directSpawn(1300, -2000, "ammo", false); - powerUps.directSpawn(1301, -2200, "ammo", false); - } - - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - if (mob.length > 0) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - //ammo tunnel shadow - ctx.fillStyle = "rgba(0,0,0,0.2)" - // ctx.fillRect(1225, -2800, 125, 2450) - ctx.fillRect(-150, -2800, 1500, 2450); - }; - - if (m.health < 1) { - powerUps.directSpawn(1298, -3500, "heal", false, 23); - powerUps.directSpawn(1305, -3000, "heal", false, 35); - } - for (let i = 0; i < 6; i++) { - spawn.springer(i * 200, -800) - // Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 0 }); - } - spawn.springer(1825, -330, 20); - - spawn.mapRect(1125, -850, 100, 500); //upper room with mobs - spawn.mapRect(-225, -450, 1450, 100); - spawn.mapRect(-225, -2800, 1450, 2000); - spawn.mapRect(1350, -2800, 675, 2450); - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(1575, 0, 500, 100); - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - spawn.mapRect(1525, 25, 75, 50); - spawn.mapRect(1500, 38, 50, 25); - spawn.mapRect(1550, 12, 50, 25); - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - }, - missile() { //throw a block on button to open door - level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 30); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); - b.giveGuns("missiles") - // b.guns[b.activeGun].ammo = 0 - // simulation.updateGunHUD(); - const buttonDoor = level.button(2500, 50) - const door = level.door(1612.5, -175, 25, 190, 185, 3) - let instruction = 0 - level.trainingText(`use missiles to drop a block on the button`) - - level.custom = () => { - if (instruction === 0 && mob.length === 0) { - instruction++ - level.trainingText(`use missiles to drop a block on the button`) - } - //spawn ammo if you run out - let isAmmo = false - for (let i = 0; i < powerUp.length; i++) { - if (powerUp[i].name === 'ammo') isAmmo = true - } - if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { - powerUps.directSpawn(1300, -2000, "ammo", false); - powerUps.directSpawn(1301, -2200, "ammo", false); - } - - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - buttonDoor.query(); - buttonDoor.draw(); - if (buttonDoor.isUp) { - door.isClosing = true - } else { - door.isClosing = false - } - door.openClose(); - door.draw(); - - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - //tunnel shadow - ctx.fillStyle = "rgba(0,0,0,0.4)" - ctx.fillRect(1250, -2800, 100, 2200) - ctx.fillRect(1550, 25, 475, 25); - }; - if (m.health < 1) { - powerUps.directSpawn(1298, -3500, "heal", false, 23); - powerUps.directSpawn(1305, -3000, "heal", false, 35); - } - for (let i = 0; i < 10; i++) { - spawn.springer(2100 + i * 100, -250) - // Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 0 }); - } - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - // spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(3050, -2800, 1550, 4600); - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(-150, -2800, 1400, 2200); //roof with tunnel for ammo - spawn.mapRect(1350, -2800, 675, 2200); - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - // spawn.mapRect(1350, 0, 675, 30); - spawn.mapRect(1550, 0, 475, 35); - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - spawn.mapRect(1600, -600, 425, 250); - - spawn.mapRect(1975, -600, 50, 625); - spawn.mapRect(2025, -2800, 1075, 2450); - - - }, - trainingTemplate() { //learn to crouch - m.addHealth(Infinity) - document.getElementById("health").style.display = "none" //hide your health bar - document.getElementById("health-bg").style.display = "none" - - level.setPosToSpawn(60, -50); //normal spawn - spawn.mapRect(10, -10, 100, 20); //small platform for player - level.exit.x = 1775; - level.exit.y = -35; - spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump - simulation.zoomScale = 1400 //1400 is normal - level.defaultZoom = 1400 - simulation.zoomTransition(level.defaultZoom, 1) - document.body.style.backgroundColor = level.trainingBackgroundColor - - - let instruction = 0 - level.trainingText(`press ${input.key.down.replace('Key', '').replace('Digit', '')} to crouch`) - - level.custom = () => { - if (instruction === 0 && input.down) { - instruction++ - - level.trainingText(`press ${input.key.down.replace('Key', '').replace('Digit', '')} to crouch`) - } - //exit room - ctx.fillStyle = "#f2f2f2" - ctx.fillRect(1600, -400, 400, 400) - level.exit.draw(); - level.enter.draw(); - level.playerExitCheck(); - }; - level.customTopLayer = () => { - //exit room glow - ctx.fillStyle = "rgba(0,255,255,0.05)" - ctx.fillRect(1600, -400, 400, 400) - }; - - spawn.mapRect(-2750, -2800, 2600, 4600); //left wall - spawn.mapRect(2000, -2800, 2600, 4600); //right wall - spawn.mapRect(-250, 50, 3500, 1750); //floor - spawn.mapRect(-200, 0, 950, 100); - spawn.mapRect(1575, 0, 500, 100); - spawn.mapRect(-250, -2800, 3500, 2200); //roof - - spawn.mapRect(725, 12, 50, 25); - spawn.mapRect(725, 25, 75, 25); - spawn.mapRect(750, 38, 75, 25); - spawn.mapRect(1525, 25, 75, 50); - spawn.mapRect(1500, 38, 50, 25); - spawn.mapRect(1550, 12, 50, 25); - spawn.mapRect(1600, -1200, 500, 850); //exit roof - spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall - }, custom() {}, customTopLayer() {}, setDifficulty() { @@ -1685,13 +580,13 @@ const level = { const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, { density: density, isNotHoldable: true, - isComposite: true + isNonStick: true }); const rotor2 = Matter.Bodies.rectangle(x, y, width, radius, { angle: Math.PI / 2, density: density, isNotHoldable: true, - isComposite: true + isNonStick: true }); rotor = Body.create({ //combine rotor1 and rotor2 parts: [rotor1, rotor2], @@ -1858,6 +753,72 @@ const level = { } } }, + vanish(x, y, width, height, hide = { x: 0, y: 100 }) { + x = x + width / 2 + y = y + height / 2 + const block = body[body.length] = Bodies.rectangle(x, y, width, height, { + collisionFilter: { + category: cat.map, + mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + }, + isNoSetCollision: true, + inertia: Infinity, //prevents rotation + isNotHoldable: true, + isNonStick: true, //this keep sporangium from sticking + isTouched: false, + fadeTime: 30, + fadeCount: 30, + isThere: true, + returnTime: 180, + returnCount: 0, + query() { + if (this.isThere) { + if (this.isTouched) { + if (!m.isBodiesAsleep) this.fadeCount-- + if (this.fadeCount < 1) { + Matter.Body.setPosition(this, hide) + this.isThere = false + this.isTouched = false + this.collisionFilter.mask = 0 //cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + this.returnCount = this.returnTime + } + } else if (Matter.Query.collides(this, [player]).length) { // || (Matter.Query.collides(this, body).length)) { + this.isTouched = true + this.fadeCount = this.fadeTime; + } + } else { + if (!m.isBodiesAsleep) { + this.returnCount-- + if (this.returnCount < 1) { + Matter.Body.setPosition(this, { x: x, y: y }) + if (Matter.Query.collides(this, [player]).length) { //|| (Matter.Query.collides(this, body).length)) { + Matter.Body.setPosition(this, hide) + this.returnCount = 15 + } else { + this.isThere = true + this.collisionFilter.mask = cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + this.fadeCount = this.fadeTime + } + } + } + } + ctx.beginPath(); + const 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); + ctx.lineTo(v[0].x, v[0].y); + const color = 220 * (1 - this.fadeCount / this.fadeTime) + ctx.fillStyle = `rgb(${color},220, 200)` + // ctx.fillStyle = `rgba(0,220,200,${this.fadeCount/this.fadeTime+0.05})` + ctx.fill(); + // ctx.strokeStyle = `#bff` + // ctx.stroke(); + }, + }); + Matter.Body.setStatic(block, true); //make static + Composite.add(engine.world, block); //add to world + return block + }, door(x, y, width, height, distance, speed = 1) { x = x + width / 2 y = y + height / 2 @@ -3419,8 +2380,17 @@ const level = { level.customTopLayer = () => { button.query(); button.draw(); + vanish1.query(); + vanish2.query(); + vanish3.query(); + vanish4.query(); + vanish5.query(); }; - + const vanish1 = level.vanish(1400, -200, 200, 50) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it + const vanish2 = level.vanish(1825, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it + const vanish3 = level.vanish(1975, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it + const vanish4 = level.vanish(1825, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it + const vanish5 = level.vanish(1975, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it level.setPosToSpawn(0, -450); //normal spawn spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); level.exit.x = 6500; @@ -3473,7 +2443,7 @@ const level = { spawn.mapRect(4850, -275, 50, 175); //??? - level.difficultyIncrease(20) //30 is near max on hard //60 is near max on why + level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why m.addHealth(Infinity) // spawn.starter(1900, -500, 200) //big boy @@ -3494,7 +2464,7 @@ const level = { // spawn.launcherBoss(3200, -500) // spawn.blockBoss(1700, -500) // spawn.blinkBoss(3200, -500) - spawn.mantisBoss(1700, -500) + // spawn.mantisBoss(1700, -500) // spawn.tetherBoss(1700, -500) //go to actual level? // spawn.revolutionBoss(1900, -500) // spawn.bomberBoss(1400, -500) @@ -5135,9 +4105,9 @@ const level = { } } else if (!elevator1.isOn) { elevator1.isOn = true - elevator1.isUp = true + elevator1.isUp = false elevator1.removeConstraint(); - elevator1.frictionAir = 0.01 //elevator.isUp ? 0.01 : 0.2 + elevator1.frictionAir = 0.2 //elevator.isUp ? 0.01 : 0.2 } if (elevator1.isOn) { elevator1.move(); @@ -5158,9 +4128,9 @@ const level = { } } else if (!elevator2.isOn) { elevator2.isOn = true - elevator2.isUp = true + elevator2.isUp = false elevator2.removeConstraint(); - elevator2.frictionAir = 0.01 //elevator.isUp ? 0.01 : 0.2 + elevator2.frictionAir = 0.2 //elevator.isUp ? 0.01 : 0.2 } if (elevator2.isOn) { @@ -5337,9 +4307,9 @@ const level = { } } else if (!elevator1.isOn) { elevator1.isOn = true - elevator1.isUp = true + elevator1.isUp = false elevator1.removeConstraint(); - elevator1.frictionAir = 0.01 //elevator.isUp ? 0.01 : 0.2 + elevator1.frictionAir = 0.2 //elevator.isUp ? 0.01 : 0.2 } if (elevator1.isOn) { elevator1.move(); @@ -5359,9 +4329,9 @@ const level = { } } else if (!elevator2.isOn) { elevator2.isOn = true - elevator2.isUp = true + elevator2.isUp = false elevator2.removeConstraint(); - elevator2.frictionAir = 0.01 //elevator.isUp ? 0.01 : 0.2 + elevator2.frictionAir = 0.2 //elevator.isUp ? 0.01 : 0.2 } if (elevator2.isOn) { @@ -9309,4 +8279,1454 @@ const level = { initialSpawn == true; } }, + // ******************************************************************************************************** + // ******************************************************************************************************** + // ***************************************** training levels ********************************************** + // ******************************************************************************************************** + // ******************************************************************************************************** + walk() { //learn to walk + m.addHealth(Infinity) + document.getElementById("health").style.display = "none" //hide your health bar + document.getElementById("health-bg").style.display = "none" + + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + simulation.lastLogTime = 0; //clear previous messages + let instruction = 0 + level.trainingText(`move with ${input.key.left.replace('Key', '').replace('Digit', '')} and ${input.key.right.replace('Key', '').replace('Digit', '')}`) + + level.custom = () => { + if (instruction === 0 && input.right) { + instruction++ + level.trainingText(`move with ${input.key.left.replace('Key', '').replace('Digit', '')} and ${input.key.right.replace('Key', '').replace('Digit', '')} +
exit through the blue door`) + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + }; + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 0, 3500, 1800); //floor + spawn.mapRect(1575, 0, 500, 100); + spawn.mapRect(-250, -2800, 3500, 2200); //roof + spawn.mapRect(700, -8, 50, 25); + spawn.mapRect(725, -16, 75, 25); + spawn.mapRect(1375, -16, 50, 50); + spawn.mapRect(1400, -8, 50, 25); + spawn.mapRect(750, -24, 650, 100); + spawn.mapRect(1600, -1200, 500, 850); //exit roof + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + }, + crouch() { //learn to crouch + m.addHealth(Infinity) + level.setPosToSpawn(75, -100); //normal spawn + spawn.mapRect(25, -60, 100, 20); //small platform for player + spawn.mapRect(0, -50, 150, 25); //stairs + spawn.mapRect(-25, -40, 200, 25); + spawn.mapRect(-50, -30, 250, 25); + spawn.mapRect(-75, -20, 300, 25); + spawn.mapRect(-100, -10, 350, 25); + spawn.mapRect(-150, -50, 175, 75); + + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + let instruction = 0 + level.trainingText(`press ${input.key.down.replace('Key', '').replace('Digit', '')} to crouch`) + level.custom = () => { + if (instruction === 0 && input.down) { + instruction++ + level.trainingText(`press ${input.key.down.replace('Key', '').replace('Digit', '')} to crouch`) + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1625, -350, 375, 350) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1625, -350, 375, 350) + //dark + ctx.fillStyle = "rgba(0,0,0,0.2)" + ctx.fillRect(500, -100, 1125, 175); + }; + + // spawn.mapRect(1025, -675, 300, 623); //crouch wall + // spawn.mapRect(625, -650, 1025, 550); + spawn.mapRect(500, -650, 1125, 550); + spawn.mapRect(-200, -650, 875, 300); + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(1575, 0, 500, 100); + spawn.mapRect(-250, -2800, 3500, 2200); //roof + + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + spawn.mapRect(1525, 25, 75, 50); + spawn.mapRect(1500, 38, 50, 25); + spawn.mapRect(1550, 12, 50, 25); + spawn.mapRect(1600, -1200, 500, 850); //exit roof + }, + jump() { //learn to jump + m.addHealth(Infinity) + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + let instruction = 0 + level.trainingText(`hold down ${input.key.up.replace('Key', '').replace('Digit', '')} longer to jump higher`) + + level.custom = () => { + if (instruction === 0 && m.pos.x > 300) { + instruction++ + level.trainingText(`hold down ${input.key.up.replace('Key', '').replace('Digit', '')} longer to jump higher`) + } + m.health = 1 //can't die + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + //dark + ctx.fillStyle = "rgba(0,0,0,0.2)" + ctx.fillRect(1000, 0, 450, 1800) + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + }; + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(275, -350, 200, 375); + spawn.mapRect(-250, 0, 1250, 1800); //floor + spawn.mapRect(1450, 0, 1075, 1800); //floor + spawn.mapRect(-250, -2800, 1250, 2200); //roof + spawn.mapRect(1450, -2800, 1075, 2200); //roof + spawn.mapVertex(375, 0, "150 0 -150 0 -100 -50 100 -50"); //base + + spawn.mapRect(1600, -1200, 500, 850); //exit roof + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + + //roof steps + spawn.mapRect(1000, -650, 25, 25); + spawn.mapRect(1000, -675, 50, 25); + spawn.mapRect(1000, -700, 75, 25); + spawn.mapRect(1000, -725, 100, 25); + spawn.mapRect(1425, -650, 25, 25); + spawn.mapRect(1400, -675, 50, 25); + spawn.mapRect(1375, -700, 75, 25); + spawn.mapRect(1350, -725, 100, 25); + spawn.mapRect(1325, -750, 150, 25); + spawn.mapRect(1300, -775, 150, 25); + spawn.mapRect(1000, -750, 125, 25); + spawn.mapRect(1275, -2800, 200, 2025); + spawn.mapRect(975, -2800, 200, 2025); + spawn.mapRect(1000, -775, 150, 25); + }, + hold() { //put block on button to open door + m.addHealth(Infinity) + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + spawn.bodyRect(1025, -75, 50, 50); //block to go on button + const buttonDoor = level.button(500, 0) + const door = level.door(1612.5, -175, 25, 190, 185, 3) + + let instruction = 0 + level.trainingText(`activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse`) + + level.custom = () => { + if (instruction === 0 && input.field) { + instruction++ + level.trainingText(`activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse
release your field on a block to pick it up`) + } else if (instruction === 1 && m.isHolding) { + instruction++ + level.trainingText(`activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse
release your field on a block to pick it up

drop the block on the red button to open the door`) + } else if (instruction === 2 && !buttonDoor.isUp && Vector.magnitudeSquared(Vector.sub(body[0].position, buttonDoor.min)) < 10000) { + instruction++ + level.trainingText(`activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse
release your field on a block to pick it up
drop the block on the red button to open the door
`) + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + buttonDoor.query(); + buttonDoor.draw(); + if (buttonDoor.isUp) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + }; + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(1575, 0, 500, 100); + spawn.mapRect(-250, -2800, 3500, 2200); //roof + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + spawn.mapRect(1525, 25, 75, 50); + spawn.mapRect(1500, 38, 50, 25); + spawn.mapRect(1550, 12, 50, 25); + spawn.mapRect(1600, -1200, 500, 850); //exit roof + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + }, + throw () { //throw a block on button to open door + m.addHealth(Infinity) + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + spawn.bodyRect(1025, -75, 50, 50); //block to go on button + const buttonDoor = level.button(1635, -400) + const door = level.door(1612.5, -175, 25, 190, 185, 3) + + // activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse + let instruction = 0 + level.trainingText(`pick up the block with your field`) + + level.custom = () => { + if (instruction === 0 && m.isHolding) { + instruction++ + level.trainingText(`pick up the block with your field +
hold your field down to charge up then release to throw a block`) + } else if (instruction === 1 && m.throwCharge > 2) { + instruction++ + level.trainingText(`pick up the block with your field +
hold your field down to charge up then release to throw a block
+
throw the block onto the button`) + // the block at the button + } else if (instruction === 2 && !buttonDoor.isUp && Vector.magnitudeSquared(Vector.sub(body[0].position, buttonDoor.min)) < 10000) { + instruction++ + level.trainingText(`pick up the block with your field +
hold your field down to charge up then release to throw a block +
throw the block onto the button
`) + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + buttonDoor.query(); + buttonDoor.draw(); + if (buttonDoor.isUp) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + }; + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(1575, 0, 500, 100); + spawn.mapRect(-250, -2800, 3500, 2200); //roof + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + spawn.mapRect(1525, 25, 75, 50); + spawn.mapRect(1500, 38, 50, 25); + spawn.mapRect(1550, 12, 50, 25); + // spawn.mapRect(1600, -1200, 500, 850); //exit roof + spawn.mapRect(1790, -600, 250, 225); //button left wall + spawn.mapRect(1625, -400, 400, 50); + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + }, + throwAt() { //throw a block at mob to open door + m.addHealth(Infinity) + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + const door = level.door(1612.5, -175, 25, 190, 185, 3) + + let instruction = 0 + level.trainingText(`throw the block at the mobs to open the door`) + + level.custom = () => { + if (instruction === 0 && !mob.length) { + instruction++ + level.trainingText(`throw the block at the mobs to open the door`) + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + if (mob.length > 0) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + }; + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(1575, 0, 500, 100); + spawn.mapRect(-250, -2800, 3500, 2200); //roof + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + spawn.mapRect(1525, 25, 75, 50); + spawn.mapRect(1500, 38, 50, 25); + spawn.mapRect(1550, 12, 50, 25); + // spawn.mapRect(1600, -1200, 500, 850); //exit roof + // spawn.mapRect(1790, -600, 250, 225); //button left wall + // spawn.mapRect(1625, -400, 400, 50); + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + spawn.mapRect(1600, -600, 425, 250); + + spawn.bodyRect(1025, -75, 50, 50); //block to go on button + spawn.starter(425, -350, 35) + spawn.starter(800, -350, 44) + }, + fire() { //throw a block at mob to open door + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = 15; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + const door = level.door(1612.5, -125, 25, 190, 185, 3) + const buttonDoor = level.button(400, 0) + + let instruction = 0 + level.trainingText(`use your field to pick up the gun power up`) + + level.custom = () => { + if (instruction === 0 && simulation.isChoosing) { + instruction++ + level.trainingText(`use your field to pick up the gun power up +
choose a gun`) + } else if (instruction === 1 && !simulation.isChoosing) { + instruction++ + level.trainingText(`use your field to pick up the gun power up +
choose a gun
+
use the left mouse button to shoot the mobs`) + } else if (instruction === 2 && mob.length === 0) { + instruction++ + level.trainingText(`use your field to pick up the gun power up +
choose a gun +
use the left mouse button to shoot the mobs
+
drop a block on the red button to open the door`) + } else if (instruction === 3 && !door.isClosing) { + instruction++ + level.trainingText(`use your field to pick up the gun power up +
choose a gun +
use the left mouse button to shoot the mobs +
put a block on the red button to open the door
`) + } + //spawn ammo if you run out + if (!powerUp.length && b.inventory.length && b.guns[b.activeGun].ammo === 0) powerUps.directSpawn(1300, -2000, "ammo", false); + + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -350, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + buttonDoor.query(); + buttonDoor.draw(); + if (buttonDoor.isUp) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -350, 400, 400) + //ammo tunnel shadow + ctx.fillStyle = "rgba(0,0,0,0.4)" + ctx.fillRect(1250, -2800, 100, 2200) + }; + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(-150, -2800, 1400, 2200); //roof with tunnel for ammo + spawn.mapRect(1350, -2800, 675, 2200); + + //ceiling steps + spawn.mapRect(725, -588, 50, 25); + spawn.mapRect(725, -600, 75, 25); + spawn.mapRect(750, -612, 75, 25); + spawn.mapRect(-275, -650, 1025, 87); + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + + spawn.mapRect(1600, -600, 425, 300); + spawn.mapRect(1600, -400, 50, 275); + + powerUps.directSpawn(1300, -1500, "gun", false); + spawn.starter(900, -300, 35) + spawn.starter(1400, -400, 44) + }, + deflect() { //learn to jump + m.addHealth(Infinity) + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + let instruction = 0 + // activate your field with ${input.key.field.replace('Key', '').replace('Digit', '')} or right mouse + level.trainingText(`use your field to deflect the mobs`) + + level.custom = () => { + if (instruction === 0 && m.pos.x > 1350) { + instruction++ + level.trainingText(`use your field to deflect the mobs`) + } + //teleport to start if hit + if (m.immuneCycle > m.cycle) { + m.energy = m.maxEnergy + Matter.Body.setPosition(player, { x: 60, y: -50 }) + } + //spawn bullets + if (!(simulation.cycle % 5)) { + spawn.sniperBullet(660 + 580 * Math.random(), -2000, 10, 4); + const who = mob[mob.length - 1] + Matter.Body.setVelocity(who, { x: 0, y: 8 }); + who.timeLeft = 300 + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + //dark + ctx.fillStyle = "rgba(0,0,0,0.05)" + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + //center falling bullets + ctx.fillStyle = "rgba(255,0,255,0.013)" //pink? + ctx.fillRect(650, -2800, 600, 2800) + }; + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + + spawn.mapRect(-250, 0, 3000, 1800); //floor + spawn.mapRect(-250, -2800, 900, 2200); //roof + spawn.mapRect(1250, -2800, 1275, 2200); //roof + spawn.mapVertex(950, 0, "400 0 -400 0 -300 -50 300 -50"); //base + + spawn.mapRect(1600, -1200, 500, 850); //exit roof + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + + //spawn bullets on load to avoid rush + for (let i = 0; i < 32; i++) { + spawn.sniperBullet(660 + 580 * Math.random(), -2000 + 40 * i, 10, 4); + const who = mob[mob.length - 1] + Matter.Body.setVelocity(who, { x: 0, y: 8 }); + who.timeLeft = 300 + } + }, + heal() { //learn to heal + m.addHealth(Infinity) + m.health = 0; + m.addHealth(0.25) + document.getElementById("health").style.display = "inline" //show your health bar + document.getElementById("health-bg").style.display = "inline" + + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + let instruction = 0 + level.trainingText(`your health is displayed in the top left corner +
use your field to pick up
until your health is full`) + + level.custom = () => { + if (instruction === 0 && m.health === 1) { + instruction++ + level.trainingText(`use your field to pick up
until your health is full
`) + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + if (m.health !== 1) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + }; + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 0, 3500, 1800); //floor + + spawn.mapRect(1575, 0, 500, 100); + spawn.mapRect(-250, -2800, 3500, 2200); //roof + + spawn.mapRect(700, -8, 50, 25); + spawn.mapRect(725, -16, 75, 25); + spawn.mapRect(1375, -16, 50, 50); + spawn.mapRect(1400, -8, 50, 25); + spawn.mapRect(750, -24, 650, 100); + powerUps.directSpawn(875, -40, "heal", false, null, 15); + powerUps.directSpawn(1075, -50, "heal", false, null, 25); + powerUps.directSpawn(1275, -65, "heal", false, null, 35); + + const door = level.door(1612.5, -175, 25, 190, 185, 3) + spawn.mapRect(1600, -1200, 500, 850); //exit roof + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + }, + nailGun() { + level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + b.removeAllGuns(); + b.giveGuns("nail gun") + b.guns[b.activeGun].ammo = 0 + simulation.updateGunHUD(); + + const door = level.door(1612.5, -175, 25, 190, 185, 3) + let instruction = 0 + level.trainingText(`use your field to pick up
for your nail gun`) + + level.custom = () => { + if (instruction === 0 && b.inventory.length && b.guns[b.activeGun].ammo > 0) { + instruction++ + level.trainingText(`use your field to pick up
for your nail gun
+
use the left mouse button to shoot the mobs`) + } else if (instruction === 1 && mob.length === 0) { + instruction++ + level.trainingText(`use your field to pick up
for your nail gun +
use the left mouse button to shoot the mobs
`) + } + //spawn ammo if you run out + let isAmmo = false + for (let i = 0; i < powerUp.length; i++) { + if (powerUp[i].name === 'ammo') isAmmo = true + } + if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { + powerUps.directSpawn(1300, -2000, "ammo", false); + powerUps.directSpawn(1301, -2200, "ammo", false); + } + + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + if (mob.length > 0) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + //ammo tunnel shadow + ctx.fillStyle = "rgba(0,0,0,0.4)" + ctx.fillRect(1250, -2800, 100, 2200) + }; + + if (m.health < 1) { + powerUps.directSpawn(1298, -3500, "heal", false, 23); + powerUps.directSpawn(1305, -3000, "heal", false, 35); + } + for (let i = 0; i < 2; i++) { + spawn.spinner(1300 + i, -3000 - 200 * i, 25 + 5 * i) + Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 62 }); + } + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(1575, 0, 500, 100); + spawn.mapRect(-150, -2800, 1400, 2200); //roof with tunnel for ammo + spawn.mapRect(1350, -2800, 675, 2200); + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + spawn.mapRect(1525, 25, 75, 50); + spawn.mapRect(1500, 38, 50, 25); + spawn.mapRect(1550, 12, 50, 25); + // spawn.mapRect(1600, -1200, 500, 850); //exit roof + // spawn.mapRect(1790, -600, 250, 225); //button left wall + // spawn.mapRect(1625, -400, 400, 50); + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + spawn.mapRect(1600, -600, 425, 250); + }, + shotGun() { + level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + b.removeAllGuns(); + b.giveGuns("shotgun") + // b.guns[b.activeGun].ammo = 0 + // simulation.updateGunHUD(); + const door = level.door(1612.5, -175, 25, 190, 185, 3) + let instruction = 0 + level.trainingText(`use your shotgun to clear the room of mobs`) + + level.custom = () => { + if (instruction === 0 && mob.length === 0) { + instruction++ + level.trainingText(`use your shotgun to clear the room of mobs`) + } + //spawn ammo if you run out + let isAmmo = false + for (let i = 0; i < powerUp.length; i++) { + if (powerUp[i].name === 'ammo') isAmmo = true + } + if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { + powerUps.directSpawn(1300, -2000, "ammo", false); + powerUps.directSpawn(1301, -2200, "ammo", false); + } + + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + if (mob.length > 0) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + //ammo tunnel shadow + ctx.fillStyle = "rgba(0,0,0,0.4)" + ctx.fillRect(1250, -2800, 100, 2200) + }; + + if (m.health < 1) { + powerUps.directSpawn(1298, -3500, "heal", false, 23); + powerUps.directSpawn(1305, -3000, "heal", false, 35); + } + for (let i = 0; i < 3; i++) { + spawn.hopper(1300 + i, -3000 - 2000 * i, 25 + 5 * i) + // Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 0 }); + } + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(1575, 0, 500, 100); + spawn.mapRect(-150, -2800, 1400, 2200); //roof with tunnel for ammo + spawn.mapRect(1350, -2800, 675, 2200); + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + spawn.mapRect(1525, 25, 75, 50); + spawn.mapRect(1500, 38, 50, 25); + spawn.mapRect(1550, 12, 50, 25); + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + spawn.mapRect(1600, -600, 425, 250); + }, + superBall() { + level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + b.removeAllGuns(); + b.giveGuns("super balls") + // b.guns[b.activeGun].ammo = 0 + // simulation.updateGunHUD(); + const door = level.door(1612.5, -175, 25, 190, 185, 3) + let instruction = 0 + level.trainingText(`use super balls to clear the room of mobs`) + + level.custom = () => { + if (instruction === 0 && mob.length === 0) { + instruction++ + level.trainingText(`use super balls to clear the room of mobs`) + } + //spawn ammo if you run out + let isAmmo = false + for (let i = 0; i < powerUp.length; i++) { + if (powerUp[i].name === 'ammo') isAmmo = true + } + if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { + powerUps.directSpawn(1300, -2000, "ammo", false); + powerUps.directSpawn(1301, -2200, "ammo", false); + } + + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + if (mob.length > 0) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + //ammo tunnel shadow + ctx.fillStyle = "rgba(0,0,0,0.2)" + // ctx.fillRect(1225, -2800, 125, 2450) + ctx.fillRect(-150, -2800, 1500, 2450); + }; + + if (m.health < 1) { + powerUps.directSpawn(1298, -3500, "heal", false, 23); + powerUps.directSpawn(1305, -3000, "heal", false, 35); + } + for (let i = 0; i < 6; i++) { + spawn.spawner(i * 230, -800) + // Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 0 }); + } + spawn.mapVertex(510, -430, "725 0 725 80 -650 80 -650 -80 650 -80"); //upper room with mobs + spawn.mapRect(-225, -2800, 1450, 2000); + spawn.mapRect(1350, -2800, 675, 2450); + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(1575, 0, 500, 100); + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + spawn.mapRect(1525, 25, 75, 50); + spawn.mapRect(1500, 38, 50, 25); + spawn.mapRect(1550, 12, 50, 25); + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + }, + matterWave() { //fire matter wave through the map to kill mosb + level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + b.removeAllGuns(); + b.giveGuns("matter wave") + // b.guns[b.activeGun].ammo = 0 + // simulation.updateGunHUD(); + const door = level.door(1612.5, -175, 25, 190, 185, 3) + let instruction = 0 + level.trainingText(`use matter wave to clear the room of mobs`) + + level.custom = () => { + if (instruction === 0 && mob.length === 0) { + instruction++ + level.trainingText(`use matter wave to clear the room of mobs`) + } + //spawn ammo if you run out + let isAmmo = false + for (let i = 0; i < powerUp.length; i++) { + if (powerUp[i].name === 'ammo') isAmmo = true + } + if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { + powerUps.directSpawn(1300, -2000, "ammo", false); + powerUps.directSpawn(1301, -2200, "ammo", false); + } + + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + if (mob.length > 0) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + //ammo tunnel shadow + ctx.fillStyle = "rgba(0,0,0,0.2)" + // ctx.fillRect(1225, -2800, 125, 2450) + ctx.fillRect(-150, -2800, 1500, 2450); + }; + + if (m.health < 1) { + powerUps.directSpawn(1298, -3500, "heal", false, 23); + powerUps.directSpawn(1305, -3000, "heal", false, 35); + } + for (let i = 0; i < 6; i++) { + spawn.springer(i * 200, -800) + // Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 0 }); + } + spawn.springer(1825, -330, 20); + + spawn.mapRect(1175, -850, 50, 500); //upper room with mobs + spawn.mapRect(-225, -400, 1450, 50); + spawn.mapRect(-225, -2800, 1450, 2000); + spawn.mapRect(1350, -2800, 675, 2450); + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(1575, 0, 500, 100); + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + spawn.mapRect(1525, 25, 75, 50); + spawn.mapRect(1500, 38, 50, 25); + spawn.mapRect(1550, 12, 50, 25); + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + }, + missile() { //fire a missile to kill mobs and trigger button + level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 30); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + b.removeAllGuns(); + b.giveGuns("missiles") + // b.guns[b.activeGun].ammo = 0 + // simulation.updateGunHUD(); + const buttonDoor = level.button(2500, 50) + const door = level.door(1612.5, -175, 25, 190, 185, 3) + let instruction = 0 + level.trainingText(`use missiles to drop a block on the button`) + + level.custom = () => { + if (instruction === 0 && mob.length === 0) { + instruction++ + level.trainingText(`use missiles to drop a block on the button`) + } + //spawn ammo if you run out + let isAmmo = false + for (let i = 0; i < powerUp.length; i++) { + if (powerUp[i].name === 'ammo') isAmmo = true + } + if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { + powerUps.directSpawn(1300, -2000, "ammo", false); + powerUps.directSpawn(1301, -2200, "ammo", false); + } + + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + buttonDoor.query(); + buttonDoor.draw(); + if (buttonDoor.isUp) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + door.draw(); + + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + //tunnel shadow + ctx.fillStyle = "rgba(0,0,0,0.4)" + ctx.fillRect(1250, -2800, 100, 2200) + ctx.fillRect(1550, 25, 475, 25); + }; + if (m.health < 1) { + powerUps.directSpawn(1298, -3500, "heal", false, 23); + powerUps.directSpawn(1305, -3000, "heal", false, 35); + } + for (let i = 0; i < 10; i++) { + spawn.springer(2100 + i * 100, -250) + // Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 0 }); + } + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + // spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(3050, -2800, 1550, 4600); + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(-150, -2800, 1400, 2200); //roof with tunnel for ammo + spawn.mapRect(1350, -2800, 675, 2200); + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + // spawn.mapRect(1350, 0, 675, 30); + spawn.mapRect(1550, 0, 475, 35); + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + spawn.mapRect(1600, -600, 425, 250); + + spawn.mapRect(1975, -600, 50, 625); + spawn.mapRect(2025, -2800, 1075, 2450); + }, + stack() { //stack blocks to get to exit + level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -685; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + b.removeAllGuns(); + let instruction = 0 + level.trainingText(`use your field to stack the blocks`) + + level.custom = () => { + if (instruction === 0 && m.pos.x > 1635) { + instruction++ + level.trainingText(`use your field to stack the blocks`) + } + + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -1050, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -1050, 400, 400) + //ammo tunnel shadow + ctx.fillStyle = "rgba(0,0,0,0.4)" + ctx.fillRect(250, -2800, 200, 1800) + }; + + if (m.health < 1) { + powerUps.directSpawn(298, -3500, "heal", false, 23); + powerUps.directSpawn(305, -3000, "heal", false, 35); + } + for (let i = 0; i < 15; i++) { + spawn.bodyRect(280, -2000 - 500 * i, 30 + 80 * Math.random(), 30 + 80 * Math.random()); + } + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 0, 3500, 1800); //floor + spawn.mapRect(1600, -650, 450, 775); + spawn.mapRect(-150, -2800, 400, 1800); //roof with tunnel for ammo + spawn.mapRect(450, -2800, 1675, 1800); + spawn.mapVertex(1300, 0, "400 0 -500 0 -300 -125 400 -125"); //base + }, + mine() { //kill mobs and tack their bodies + level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level + level.setPosToSpawn(300, -50); //normal spawn + spawn.mapRect(250, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -685; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + b.removeAllGuns(); + b.giveGuns("mine") + + let instruction = 0 + level.trainingText(`press the red button to spawn a mob`) + const button = level.button(-100, -200) + button.isUp = true + spawn.mapRect(-150, -200, 240, 425); + + level.custom = () => { + if (instruction === 0 && !button.isUp) { + instruction++ + level.trainingText(`press the red button to spawn a mob
turn the mobs into blocks`) + } else if (instruction === 1 && body.length > 2) { + instruction++ + level.trainingText(`press the red button to spawn a mob
turn the mobs into blocks

use your field to stack the blocks`) + } else if (instruction === 2 && m.pos.x > 1635) { + instruction++ + level.trainingText(`press the red button to spawn a mob
turn the mobs into blocks
use your field to stack the blocks
`) + } + //spawn ammo if you run out + let isAmmo = false + for (let i = 0; i < powerUp.length; i++) { + if (powerUp[i].name === 'ammo') isAmmo = true + } + if (!isAmmo && b.inventory.length && b.guns[b.activeGun].ammo === 0) { + powerUps.directSpawn(1300, -2000, "ammo", false); + powerUps.directSpawn(1301, -2200, "ammo", false); + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -1050, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + button.query(); + button.draw(); + if (!button.isUp) { + if (button.isReady) { + button.isReady = false + spawn.exploder(335, -1700) + Matter.Body.setVelocity(mob[mob.length - 1], { x: 0, y: 20 }); + ctx.fillStyle = "rgba(255,0,0,0.9)" + ctx.fillRect(550, -2800, 200, 1800) + } + } else { + button.isReady = true + } + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -1050, 400, 400) + //ammo tunnel shadow + ctx.fillStyle = "rgba(0,0,0,0.4)" + ctx.fillRect(550, -2800, 200, 1800) + }; + + if (m.health < 1) { + powerUps.directSpawn(298, -3500, "heal", false, 23); + powerUps.directSpawn(305, -3000, "heal", false, 35); + } + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 0, 3500, 1800); //floor + spawn.mapRect(1600, -650, 450, 775); + spawn.mapRect(-150, -2800, 700, 1800); //roof with tunnel for ammo + spawn.mapRect(750, -2800, 1675, 1800); + spawn.mapVertex(1300, 0, "400 0 -600 0 -300 -125 400 -125"); //base + }, + grenades() { //jump at the top of the elevator's path to go extra high + level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level + level.setPosToSpawn(0, -50); //normal spawn + spawn.mapRect(-50, -10, 100, 20); //small platform for player + level.exit.x = 1900; + level.exit.y = -2835; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + b.removeAllGuns(); + b.giveGuns("grenades") + + const elevator1 = level.elevator(550, -100, 180, 25, -840, 0.003, { up: 0.05, down: 0.2 }) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { + elevator1.addConstraint(); + const toggle1 = level.toggle(275, 0) //(x,y,isOn,isLockOn = true/false) + + const elevator2 = level.elevator(1400, -950, 180, 25, -2400, 0.0025) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { + elevator2.addConstraint(); + const button2 = level.button(1000, -850) + + let instruction = 0 + level.trainingText(`flip the switch to turn on the elevator`) + level.custom = () => { + if (instruction === 0 && elevator1.isOn) { + instruction++ + level.trainingText(`flip the switch to turn on the elevator +
put a block on the button to active the elevator`) + } else if (instruction === 1 && elevator2.isOn) { + instruction++ + level.trainingText(`flip the switch to turn on the elevator
put a block on the button to active the elevator
+
hold jump before the elevator's apex to reach the exit`) + } else if (instruction === 2 && m.pos.x > 1635) { + instruction++ + level.trainingText(`flip the switch to turn on the elevator
put a block on the button to active the elevator
hold jump before the elevator's apex to reach the exit
`) + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1725, -3100, 375, 300); + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + toggle1.query(); + if (!toggle1.isOn) { + if (elevator1.isOn) { + elevator1.isOn = false + elevator1.frictionAir = 0.2 + elevator1.addConstraint(); + } + } else if (!elevator1.isOn) { + elevator1.isOn = true + elevator1.isUp = false + elevator1.removeConstraint(); + elevator1.frictionAir = 0.2 //elevator.isUp ? 0.01 : 0.2 + } + if (elevator1.isOn) { + elevator1.move(); + ctx.fillStyle = "#444" + } else { + ctx.fillStyle = "#aaa" + } + ctx.fillRect(640, -825, 1, 745) + + button2.query(); + button2.draw(); + if (button2.isUp) { + if (elevator2.isOn) { + elevator2.isOn = false + elevator2.frictionAir = 0.2 + elevator2.addConstraint(); + } + } else if (!elevator2.isOn) { + elevator2.isOn = true + elevator2.isUp = false + elevator2.removeConstraint(); + elevator2.frictionAir = 0.2 //elevator.isUp ? 0.01 : 0.2 + } + if (elevator2.isOn) { + elevator2.move(); + ctx.fillStyle = "#444" + } else { + ctx.fillStyle = "#aaa" + } + ctx.fillRect(1490, -2300, 1, 1375) + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1725, -3100, 375, 300); + //shadows + ctx.fillStyle = "rgba(0,0,0,0.05)" + ctx.fillRect(-150, -250, 300, 250); + let grd = ctx.createLinearGradient(0, -150, 0, -2300); + grd.addColorStop(0, "rgba(0,0,0,0.35)"); + grd.addColorStop(1, "rgba(0,0,0,0)"); + ctx.fillStyle = grd //"rgba(0,0,100,0.01)" + ctx.fillRect(-200, -2300, 1825, 2300); + }; + + if (m.health < 1) { + powerUps.directSpawn(298, -3500, "heal", false, 23); + powerUps.directSpawn(305, -3000, "heal", false, 35); + } + spawn.mapRect(-2750, -4800, 2600, 6600); //left wall + spawn.mapRect(1600, -2800, 3000, 4600); //right wall + spawn.mapRect(-150, -4800, 300, 4550); + spawn.mapRect(2125, -4775, 2475, 2050); + spawn.mapRect(-250, 0, 3500, 1800); //floor + spawn.mapRect(750, -850, 950, 950); + spawn.mapRect(125, -275, 25, 100); + spawn.mapRect(2100, -3150, 50, 350); + spawn.mapRect(1725, -3150, 50, 175); + spawn.mapRect(1725, -3150, 425, 50); + + spawn.nodeGroup(1200, -1500, "grenadier", 7); + }, + harpoon() { //jump at the top of the elevator's path to go extra high + level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level + level.setPosToSpawn(0, -50); //normal spawn + spawn.mapRect(-50, -10, 100, 20); //small platform for player + level.exit.x = 1900; + level.exit.y = -2835; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + b.removeAllGuns(); + b.giveGuns("harpoon") + + + let instruction = 0 + level.trainingText(`climb up to the exit`) + level.custom = () => { + if (instruction === 0 && m.pos.x > 1635) { + instruction++ + level.trainingText(`climb up to the exit`) + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1725, -3100, 375, 300); + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1725, -3100, 375, 300); + //shadows + ctx.fillStyle = "rgba(0,90,100,0.05)" + ctx.fillRect(-150, -250, 300, 250); + let grd = ctx.createLinearGradient(0, -150, 0, -2300); + grd.addColorStop(0, "rgba(0,90,100,0.35)"); + grd.addColorStop(1, "rgba(0,90,100,0)"); + ctx.fillStyle = grd //"rgba(0,0,100,0.01)" + ctx.fillRect(-200, -2300, 1825, 2300); + vanish1.query(); + vanish2.query(); + vanish3.query(); + vanish4.query(); + vanish5.query(); + vanish6.query(); + vanish7.query(); + vanish8.query(); + vanish9.query(); + vanish10.query(); + vanish11.query(); + vanish12.query(); + }; + const vanish1 = level.vanish(175, -325, 175, 25); //x, y, width, height, hide = { x: 0, y: 100 } //hide should just be somewhere behind the map so the player can't see it + const vanish2 = level.vanish(525, -625, 175, 25); + const vanish3 = level.vanish(1125, -1125, 175, 25); + const vanish4 = level.vanish(1500, -1450, 100, 25); + const vanish5 = level.vanish(1125, -1675, 175, 25); + const vanish6 = level.vanish(750, -1950, 175, 25); + const vanish7 = level.vanish(550, -1950, 175, 25); + const vanish8 = level.vanish(350, -1950, 175, 25); + const vanish9 = level.vanish(150, -1950, 175, 25); + const vanish10 = level.vanish(325, -2300, 200, 25); + const vanish11 = level.vanish(725, -2550, 100, 25); + const vanish12 = level.vanish(1125, -2700, 150, 25); + + if (m.health < 1) { + powerUps.directSpawn(298, -3500, "heal", false, 23); + powerUps.directSpawn(305, -3000, "heal", false, 35); + } + spawn.mapRect(-2750, -4800, 2600, 6600); //left wall + spawn.mapRect(1600, -2800, 3000, 4600); //right wall + spawn.mapRect(-150, -4800, 300, 4550); + spawn.mapRect(2125, -4775, 2475, 2050); + spawn.mapRect(-250, 0, 3500, 1800); //floor + spawn.mapRect(750, -850, 950, 950); + spawn.mapRect(125, -275, 25, 100); + spawn.mapRect(2100, -3150, 50, 350); + spawn.mapRect(1725, -3150, 50, 175); + spawn.mapRect(1725, -3150, 425, 50); + + spawn.grower(250, -375); + spawn.grower(1000, -900) + spawn.grower(1475, -925); + spawn.grower(275, -2000); + spawn.grower(650, -2000); + spawn.grower(1475, -975); + spawn.grower(1575, -1525); + spawn.grower(1700, -2850); + }, + trainingTemplate() { //learn to crouch + m.addHealth(Infinity) + document.getElementById("health").style.display = "none" //hide your health bar + document.getElementById("health-bg").style.display = "none" + + level.setPosToSpawn(60, -50); //normal spawn + spawn.mapRect(10, -10, 100, 20); //small platform for player + level.exit.x = 1775; + level.exit.y = -35; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump + simulation.zoomScale = 1400 //1400 is normal + level.defaultZoom = 1400 + simulation.zoomTransition(level.defaultZoom, 1) + document.body.style.backgroundColor = level.trainingBackgroundColor + + + let instruction = 0 + level.trainingText(`press ${input.key.down.replace('Key', '').replace('Digit', '')} to crouch`) + + level.custom = () => { + if (instruction === 0 && input.down) { + instruction++ + + level.trainingText(`press ${input.key.down.replace('Key', '').replace('Digit', '')} to crouch`) + } + //exit room + ctx.fillStyle = "#f2f2f2" + ctx.fillRect(1600, -400, 400, 400) + level.exit.draw(); + level.enter.draw(); + level.playerExitCheck(); + }; + level.customTopLayer = () => { + //exit room glow + ctx.fillStyle = "rgba(0,255,255,0.05)" + ctx.fillRect(1600, -400, 400, 400) + }; + + spawn.mapRect(-2750, -2800, 2600, 4600); //left wall + spawn.mapRect(2000, -2800, 2600, 4600); //right wall + spawn.mapRect(-250, 50, 3500, 1750); //floor + spawn.mapRect(-200, 0, 950, 100); + spawn.mapRect(1575, 0, 500, 100); + spawn.mapRect(-250, -2800, 3500, 2200); //roof + + spawn.mapRect(725, 12, 50, 25); + spawn.mapRect(725, 25, 75, 25); + spawn.mapRect(750, 38, 75, 25); + spawn.mapRect(1525, 25, 75, 50); + spawn.mapRect(1500, 38, 50, 25); + spawn.mapRect(1550, 12, 50, 25); + spawn.mapRect(1600, -1200, 500, 850); //exit roof + spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall + }, }; \ No newline at end of file diff --git a/js/simulation.js b/js/simulation.js index 8799432..d2b8bb0 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -593,6 +593,7 @@ const simulation = { }, 1000); }, startGame(isBuildRun = false, isTrainingRun = false) { + simulation.isTextLogOpen = true simulation.clearMap() if (!isBuildRun) { //if a build run logic flow returns to "experiment-button").addEventListener document.body.style.cursor = "none"; diff --git a/js/spawn.js b/js/spawn.js index 35ce949..2cd38f9 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -1146,14 +1146,14 @@ const spawn = { powerUps.spawnRandomPowerUp(this.position.x, this.position.y) // manual power up spawn to avoid spawning too many tech with "symbiosis" } } - me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + me.damageReduction = 0.23 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //required setup for invulnerable me.isInvulnerable = false me.invulnerabilityCountDown = 0 me.do = function() { if (this.isInvulnerable) { if (this.invulnerabilityCountDown > 0) { - this.invulnerabilityCountDown-- + if (!m.isBodiesAsleep) this.invulnerabilityCountDown-- ctx.beginPath(); let vertices = this.vertices; ctx.moveTo(vertices[0].x, vertices[0].y); @@ -1234,7 +1234,7 @@ const spawn = { me.do = function() { if (this.isInvulnerable) { if (this.invulnerabilityCountDown > 0) { - this.invulnerabilityCountDown-- + if (!m.isBodiesAsleep) this.invulnerabilityCountDown-- ctx.beginPath(); let vertices = this.vertices; ctx.moveTo(vertices[0].x, vertices[0].y); @@ -1982,7 +1982,7 @@ const spawn = { ctx.strokeStyle = "rgba(255,255,255,0.7)"; ctx.stroke(); } else if (this.invulnerabilityCountDown > 0) { - this.invulnerabilityCountDown-- + if (!m.isBodiesAsleep) this.invulnerabilityCountDown-- } else { this.isInvulnerable = true if (this.damageReduction) this.startingDamageReduction = this.damageReduction @@ -3401,7 +3401,7 @@ const spawn = { } if (this.isInvulnerable) { if (this.invulnerabilityCountDown > 0) { - this.invulnerabilityCountDown-- + if (!m.isBodiesAsleep) this.invulnerabilityCountDown-- //graphics //draw a super shield? ctx.beginPath(); let vertices = this.vertices; diff --git a/js/tech.js b/js/tech.js index a7e9b67..3f2fc7b 100644 --- a/js/tech.js +++ b/js/tech.js @@ -4498,7 +4498,7 @@ const tech = { }, { name: "MIRV", - description: "fire +1 missile, grenade, and super ball
decrease explosion radius up to 10%", + description: "fire +1 missile and grenade
decrease explosion radius up to 10%", isGunTech: true, maxCount: 9, count: 0, @@ -8834,7 +8834,7 @@ const tech = { }, { name: "black hole cluster", - description: `spawn nearby black holes`, + description: `spawn 30 nearby black holes`, maxCount: 1, count: 0, frequency: 0, @@ -8847,7 +8847,7 @@ const tech = { const unit = { x: 1, y: 0 } for (let i = 0; i < 30; i++) { const where = Vector.add(m.pos, Vector.mult(Vector.rotate(unit, Math.random() * 2 * Math.PI), 2000 + 1200 * Math.random())) - spawn.sucker(where.x, where.y, 200) + spawn.sucker(where.x, where.y, 140) const who = mob[mob.length - 1] who.locatePlayer() // who.damageReduction = 0.2 diff --git a/todo.txt b/todo.txt index 2a9338e..8d8cb68 100644 --- a/todo.txt +++ b/todo.txt @@ -1,14 +1,19 @@ ******************************************************** NEXT PATCH ************************************************** -tech: super duper - fire +0-2 extra super balls - super balls no longer part of MIRV +new training levels "stack", "mine", "grenades", "harpoon" -bug fix for plasma extruder interaction with doors that collide with power ups -mantisBoss moves slower, can be damaged for longer time, has less total life, has a smaller punch range +new map element vanish goes away after you touch it, returns in 3 seconds +bug fixes ******************************************************** TODO ******************************************************** -merge various multi bullet tech under one name +shrink crumble width as it fades out + player moves through a grid of stacked crumble blocks + +boss that gives nearby mobs invulnerability + boss is only mildly aggressive + repulsed by player upto a point + attracted to mobs training save training level progress as local variable @@ -18,34 +23,17 @@ training uses the lore voice/text code? replace all mob clear triggers with button triggers? tutorial rooms: - done walk forwards and backwards - done crouch through tunnel - done jump over wall and gap - look around with your mouse - done pick up a block an drop onto a button to open door - done fire block at button to open door - done fire block at mob to open door + look around with your mouse? easier deflecting level, with 1-2 attacking mobs - done use field to deflect bullets - done pick up heal power ups with field to open door - done use a gun to kill a mob and use it's block body to activate a button to open a door gun rooms: (different mobs type in each room) different mobs in each room - how to introduce shields? + how to introduce mob shields? "hopper" "slasher" "shooter "grenadier" "striker" "laser" "stabber" "springer" "pulsar" "launcher" "launcherOne" "exploder" "sneaker" "sucker" "sniper" "spinner" "grower" "beamer" "focuser" "spawner" "ghoster" - done nailgun - start with no ammo collect ammo and shoot at mobs - done shotgun - some simple close range combat - done superball - use 1 ammo to take out several mobs - done matter wave - kill a mob inside a map element - done missiles - take out mobs that are around corner and have them drop on a button - grenades - use 1 ammo to take out a ring of mob`s spores - use 1 ammo to take out several mobs at once, you have to block with your shield until the mobs die drones - use mouse to bring drones around a couple corners foam - slow boss mob, and run away harpoon - kill one close mob, pick up ammo that is out of reach, first at several far away mobs with crouch or just some hard melee combat - mine - built kill zone, get mobs to follow into mine kill zone - maybe a boss mob? laser - reflect off walls to hit mobs field rooms: standing wave - bullets come from every direction @@ -58,24 +46,21 @@ training pilot wave - toss blocks at mobs worm hole - teleport past lasers puzzle/platforming rooms: - stack blocks to get to high ground - also make a harder version of stacking blocks - portal rooms - jump at the top of a elevator to jump high - use the double constrained platforms + use the double constrained platforms combat rooms: - kill so many mobs that the mob bodies pile up and you can get over a wall by jumping on them boss gauntlet, spawn with nothing but a few power ups and fight 10 bosses use no gun, just bots to kil stuff -JUNK tech disable level exit for 5 minutes - level.disableExit = true - setTimeout( () => {level.disableExit = false;}, 5*60000); - balance time dilation with bose einstein (you can freeze everything and take no damage) code is still there, need to balance balance with energy drain? +overflowing energy does harm? + or just reduces harm reduction? + +make a line of constained mobs move like a snake + apply forces with directions determined by time and position on the snake + tech: basic research - heal power ups spawn as research power ups instead, and using research heals you (needs to be pretty low, like 3% health) tech: maintenance - heals no longer spawn, but using research heals you 100%