diff --git a/js/bullet.js b/js/bullet.js index 8f062a9..df5f824 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1965,8 +1965,8 @@ const b = { name: "flak", description: "fire a cluster of short range projectiles
explodes on contact or after half a second", ammo: 0, - ammoPack: 6, - defaultAmmoPack: 6, //use to revert ammoPack after mod changes drop rate + ammoPack: 8, + defaultAmmoPack: 8, //use to revert ammoPack after mod changes drop rate have: false, isEasyToAim: false, fire() { @@ -2264,10 +2264,16 @@ const b = { } else { const bodyCollisions = Matter.Query.collides(this, body) if (bodyCollisions.length) { - onCollide(this) - this.stuckTo = bodyCollisions[0].bodyA - //find the relative position for when the mob is at angle zero by undoing the mobs rotation - this.stuckToRelativePosition = Vector.rotate(Vector.sub(this.position, this.stuckTo.position), -this.stuckTo.angle) + + + if (!bodyCollisions[0].bodyA.isNotSticky) { + onCollide(this) + this.stuckTo = bodyCollisions[0].bodyA + //find the relative position for when the mob is at angle zero by undoing the mobs rotation + this.stuckToRelativePosition = Vector.rotate(Vector.sub(this.position, this.stuckTo.position), -this.stuckTo.angle) + } else { + this.do = this.radiationMode; + } this.stuck = function () { if (this.stuckTo) { const rotate = Vector.rotate(this.stuckToRelativePosition, this.stuckTo.angle) //add in the mob's new angle to the relative position vector @@ -2419,10 +2425,14 @@ const b = { } else { const bodyCollisions = Matter.Query.collides(this, body) if (bodyCollisions.length) { - onCollide(this) - this.stuckTo = bodyCollisions[0].bodyA - //find the relative position for when the mob is at angle zero by undoing the mobs rotation - this.stuckToRelativePosition = Vector.rotate(Vector.sub(this.position, this.stuckTo.position), -this.stuckTo.angle) + if (!bodyCollisions[0].bodyA.isNotSticky) { + onCollide(this) + this.stuckTo = bodyCollisions[0].bodyA + //find the relative position for when the mob is at angle zero by undoing the mobs rotation + this.stuckToRelativePosition = Vector.rotate(Vector.sub(this.position, this.stuckTo.position), -this.stuckTo.angle) + } else { + this.do = this.grow; + } this.stuck = function () { if (this.stuckTo) { const rotate = Vector.rotate(this.stuckToRelativePosition, this.stuckTo.angle) //add in the mob's new angle to the relative position vector diff --git a/js/game.js b/js/game.js index 6f3c86a..606c389 100644 --- a/js/game.js +++ b/js/game.js @@ -606,23 +606,6 @@ const game = { if (game.firstRun) { mech.spawn(); //spawns the player mod.setupAllMods(); //doesn't run on reset so that gun mods carry over to new runs - - function shuffle(array) { - var currentIndex = array.length, - temporaryValue, - randomIndex; - // While there remain elements to shuffle... - while (0 !== currentIndex) { - // Pick a remaining element... - randomIndex = Math.floor(Math.random() * currentIndex); - currentIndex -= 1; - // And swap it with the current element. - temporaryValue = array[currentIndex]; - array[currentIndex] = array[randomIndex]; - array[randomIndex] = temporaryValue; - } - return array; - } if (game.isCommunityMaps) level.levels.push("stronghold"); level.levels = shuffle(level.levels); //shuffles order of maps level.levels.unshift("bosses"); //add bosses level to the end of the randomized levels list @@ -806,9 +789,9 @@ const game = { } }, testingOutput() { + ctx.fillStyle = "#000"; if (!game.isConstructionMode) { ctx.textAlign = "right"; - ctx.fillStyle = "#000"; let line = 500; const x = canvas.width - 5; ctx.fillText("T: exit testing mode", x, line); @@ -1083,7 +1066,7 @@ const game = { enableConstructMode() { game.isConstructionMode = true; game.isAutoZoom = false; - game.zoomScale = 2200; + game.zoomScale = 2600; game.setZoom(); document.body.addEventListener("mouseup", (e) => { diff --git a/js/index.js b/js/index.js index fa3b919..48c4a5d 100644 --- a/js/index.js +++ b/js/index.js @@ -13,6 +13,23 @@ const cat = { phased: 0x100000000, } +function shuffle(array) { + var currentIndex = array.length, + temporaryValue, + randomIndex; + // While there remain elements to shuffle... + while (0 !== currentIndex) { + // Pick a remaining element... + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex -= 1; + // And swap it with the current element. + temporaryValue = array[currentIndex]; + array[currentIndex] = array[randomIndex]; + array[randomIndex] = temporaryValue; + } + return array; +} + //example https://landgreen.github.io/sidescroller/index.html? // &gun1=minigun&gun2=laser // &mod1=laser-bot&mod2=mass%20driver&mod3=overcharge&mod4=laser-bot&mod5=laser-bot&field=phase%20decoherence%20field&difficulty=2 diff --git a/js/level.js b/js/level.js index d094191..ed3744f 100644 --- a/js/level.js +++ b/js/level.js @@ -6,12 +6,12 @@ const level = { defaultZoom: 1400, onLevel: 0, levelsCleared: 0, - levels: ["skyscrapers", "rooftops", "warehouse", "highrise", "office", "aerie", "satellite"], + levels: ["skyscrapers", "rooftops", "warehouse", "highrise", "office", "aerie", "satellite", "sewers"], start() { if (build.isURLBuild && level.levelsCleared === 0) build.onLoadPowerUps(); if (level.levelsCleared === 0) { //this code only runs on the first level // game.enableConstructMode() //used to build maps in testing mode - // level.difficultyIncrease(9) + // level.difficultyIncrease(4) // mech.isStealth = true; // mod.giveMod("superfluidity"); // b.giveGuns("ice IX") @@ -68,20 +68,19 @@ const level = { //****************************************************************************************************************** //****************************************************************************************************************** //****************************************************************************************************************** - rotor(x, y, radius = 900, width = 50, density = 0.0002) { + rotor(x, y, rotate = 0, radius = 900, width = 50, density = 0.001) { const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, { density: density, + isNotSticky: true }); const rotor2 = Matter.Bodies.rectangle(x, y, width, radius, { angle: Math.PI / 2, density: density, + isNotSticky: true }); const rotor = Body.create({ //combine rotor1 and rotor2 parts: [rotor1, rotor2], - // friction: 0, - // frictionAir: 0, - // frictionStatic: 0, - // restitution: 0, + restitution: 0, collisionFilter: { category: cat.body, mask: cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.powerUp | cat.player | cat.bullet @@ -108,83 +107,215 @@ const level = { bodyB: rotor }); World.add(engine.world, constraint); + + if (rotate) { + rotor.rotate = function () { + if (!mech.isBodiesAsleep) { + Matter.Body.applyForce(rotor, { + x: rotor.position.x + 100, + y: rotor.position.y + 100 + }, { + x: rotate * rotor.mass, + y: 0 + }) + } else { + Matter.Body.setAngularVelocity(rotor, 0); + } + } + } + return rotor }, - sewer() { - const rotor = level.rotor(3050, 1850) - // const rotor2 = level.rotor(3050, 1200) + button(x, y, width = 70, height = 20) { + spawn.mapVertex(x + 35, y + 27, "70 10 -70 10 -40 -10 40 -10"); + // map[map.length - 1].friction = 1; + return { + isUp: false, + min: { + x: x, + y: y + }, + max: { + x: x + width, + y: y + height + }, + width: width, + height: height, + query() { + if (Matter.Query.region(body, this).length === 0 && Matter.Query.region([player], this).length === 0) { + this.isUp = true; + } else { + this.isUp = false; + } + }, + draw() { + ctx.fillStyle = "hsl(0, 100%, 70%)" + // ctx.fillStyle = "hsl(287, 30%, 65%)" + if (this.isUp) { + ctx.fillRect(this.min.x, this.min.y, this.width, 20) + } else { + ctx.fillRect(this.min.x, this.min.y + 10, this.width, 25) + } + } + } + }, + hazard(x, y, width, height, damage = 0.0005, color = "hsl(160, 100%, 35%)") { + return { + min: { + x: x, + y: y + }, + max: { + x: x + width, + y: y + height + }, + width: width, + height: height, + maxHeight: height, + query() { + if (this.height > 0 && Matter.Query.region([player], this).length) { + mech.damage(damage) + const drain = 0.005 + if (mech.energy > drain) mech.energy -= drain + } + }, + draw() { + ctx.fillStyle = color + ctx.fillRect(this.min.x, this.min.y, this.width, this.height) + }, + level(isFill) { + const growSpeed = 1 + if (isFill) { + if (this.height < this.maxHeight) { + this.height += growSpeed + this.min.y -= growSpeed + this.max.y = this.min.y + this.height + } + } else if (this.height > 0) { + this.height -= growSpeed + this.min.y += growSpeed + this.max.y = this.min.y + this.height + } + } + } + }, + sewers() { + const rotor = level.rotor(5100, 2425, -0.001) + const button = level.button(6600, 2650) + const hazard = level.hazard(4550, 2750, 4550, 150) level.custom = () => { - Matter.Body.applyForce(rotor, { - x: rotor.position.x + 100, - y: rotor.position.y + 100 - }, { - x: 0.001 * rotor.mass, - y: 0 - }) - // Matter.Body.applyForce(rotor2, { - // x: rotor2.position.x + 100, - // y: rotor2.position.y + 100 - // }, { - // x: -0.001 * rotor2.mass, - // y: 0 - // }) - + button.query(); + button.draw(); + hazard.draw(); + hazard.query(); + hazard.level(button.isUp) + rotor.rotate(); level.playerExitCheck(); }; - level.setPosToSpawn(3775, 425); //normal spawn - // level.setPosToSpawn(0, -50); //normal spawn + + level.setPosToSpawn(0, -50); //normal spawn spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); - level.exit.x = 1500; - level.exit.y = -1875; + level.exit.x = 9700; + level.exit.y = 2560; level.defaultZoom = 1800 game.zoomTransition(level.defaultZoom) document.body.style.backgroundColor = "hsl(138, 3%, 74%)"; - // powerUps.spawnStartingPowerUps(1475, -1175); - // spawn.debris(750, -2200, 3700, 16); //16 debris per level - // level.fill.push({ //foreground - // x: 2500, - // y: -1100, - // width: 450, - // height: 250, - // color: "rgba(0,0,0,0.1)" - // }); - // level.fillBG.push({ //background - // x: 1300, - // y: -1800, - // width: 750, - // height: 1800, - // color: "#d4d4d7" - // }); + powerUps.spawnStartingPowerUps(3475, 1775); + spawn.debris(4575, 2550, 1600, 9); //16 debris per level + spawn.debris(7000, 2550, 2000, 7); //16 debris per level + + level.fill.push({ + x: 9300, + y: 2200, + width: 600, + height: 400, + color: "rgba(0,255,255,0.1)" + }); + level.fillBG.push({ + x: 9300, + y: 2200, + width: 600, + height: 400, + color: "hsl(138, 10%, 80%)" //c4f4f4 + }); spawn.mapRect(-400, -500, 100, 600); //left entrance wall - spawn.mapRect(-400, -500, 3800, 100); //ceiling + spawn.mapRect(-400, -500, 3550, 100); //ceiling spawn.mapRect(-400, 0, 3000, 100); //floor spawn.mapRect(300, -500, 100, 400); //right entrance wall + spawn.bodyRect(340, -100, 25, 100); + spawn.bodyRect(1450, -300, 150, 50); + const xPos = shuffle([600, 1250, 2000]); + spawn.mapRect(xPos[0], -200, 400, 100); + spawn.mapRect(xPos[1], -250, 300, 300); + spawn.mapRect(xPos[2], -150, 300, 200); - spawn.mapRect(600, -200, 400, 100); - spawn.mapRect(1250, -250, 300, 300); - spawn.mapRect(2000, -150, 300, 200); + spawn.bodyRect(3100, 410, 75, 100); + spawn.bodyRect(2450, -25, 250, 25); - spawn.mapRect(3300, -500, 100, 700); //right down tube wall - spawn.mapRect(3000, 500, 100, 1400); //right down tube wall - spawn.mapRect(3000, 500, 1000, 100); //tube right exit floor - spawn.mapRect(3300, 100, 1000, 100); //tube right exit ceiling + spawn.mapRect(3050, -500, 100, 700); //right down tube wall + spawn.mapRect(3050, 100, 1250, 100); //tube right exit ceiling + spawn.mapRect(4200, 100, 100, 1800); + spawn.mapRect(3000, 400, 1000, 1250); + spawn.mapRect(3000, 1925, 1000, 150); - spawn.mapRect(2500, 0, 100, 1900); //left down tube wall - spawn.mapRect(850, 2300, 2800, 100); - spawn.mapRect(3000, 1800, 600, 100); + spawn.mapRect(3100, 1875, 800, 100); + spawn.mapRect(3100, 1600, 800, 100); + spawn.mapRect(3100, 350, 800, 100); + spawn.mapRect(3100, 2025, 800, 100); + spawn.mapRect(2500, 0, 100, 1950); //left down tube wall + spawn.mapRect(600, 2300, 3750, 100); + spawn.bodyRect(3800, 275, 125, 125); + spawn.mapRect(4200, 1800, 5000, 100); + spawn.mapRect(4250, 2300, 100, 400); + spawn.mapRect(4250, 2300, 100, 400); - // spawn.bodyRect(1540, -1110, 300, 25, 0.9); - // spawn.boost(4150, 0, 1300); - // spawn.randomSmallMob(1300, -70); - // spawn.randomMob(2650, -975, 0.8); - // spawn.randomBoss(1700, -900, 0.4); - // if (game.difficulty > 3) spawn.randomLevelBoss(2200, -1300); + spawn.mapRect(600, 1800, 2000, 100); //bottom left room ceiling + spawn.mapRect(600, 1800, 100, 600); //left wall + spawn.mapRect(1775, 2225, 550, 125); + spawn.mapRect(675, 1875, 325, 150); + + spawn.mapRect(4450, 2900, 4900, 100); //boss room floor + spawn.mapRect(4250, 2600, 300, 400); + spawn.mapRect(6250, 2675, 700, 325); + spawn.mapRect(8000, 2600, 600, 400); + spawn.bodyRect(5875, 2725, 200, 200); + spawn.bodyRect(6800, 2490, 50, 50); + spawn.bodyRect(6800, 2540, 50, 50); + spawn.bodyRect(6800, 2590, 50, 50); + spawn.bodyRect(8225, 2200, 100, 400); + spawn.mapRect(6250, 1875, 700, 150); + spawn.mapRect(8000, 1875, 600, 150); + + spawn.mapRect(9100, 1800, 900, 400); //exit + spawn.mapRect(9100, 2600, 900, 400); + spawn.mapRect(9900, 2125, 100, 575); //back wall + spawn.mapRect(9300, 2150, 50, 250); + spawn.mapRect(9300, 2590, 650, 25); + spawn.mapRect(9700, 2580, 100, 50); + + spawn.randomBoss(1300, 2100, 0.7); + spawn.randomMob(8300, 2225, 0.5); + spawn.randomSmallMob(2575, -75, 0.5); //entrance + spawn.randomMob(8125, 2450, 0.5); + spawn.randomSmallMob(3200, 250, 0.5); + spawn.randomMob(2425, 2150, 0.5); + spawn.randomSmallMob(3825, 300, 0.5); + spawn.randomMob(3800, 2175, 0.5); + spawn.randomSmallMob(1100, -300, 0.5); //entrance + spawn.randomMob(4450, 2500, 0.5); + spawn.randomMob(6350, 2525, 0.5); + spawn.randomSmallMob(1900, -250, 0.5); //entrance + spawn.randomMob(1500, 2100, 0.8); + spawn.randomSmallMob(1700, -150, 0.5); //entrance + spawn.randomMob(8800, 2725, 0.5); + spawn.randomBoss(8650, 2275, 0.5); + if (game.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss"]); }, template() { level.custom = () => { @@ -611,8 +742,8 @@ const level = { height: 1500, color: "rgba(0,20,40,0.13)" }); - spawn.mapRect(3950, -350, 375, 50); - spawn.mapRect(4725, -350, 375, 50); + spawn.mapRect(3925, -300, 425, 50); + spawn.mapRect(4700, -375, 425, 50); spawn.mapRect(4000, -1300, 1050, 100); //steep stairs diff --git a/js/mods.js b/js/mods.js index 39e1240..42785e2 100644 --- a/js/mods.js +++ b/js/mods.js @@ -1482,7 +1482,7 @@ const mod = { requires: "flak", effect() { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "flak") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * (3 + this.count); + if (b.guns[i].name === "flak") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * (3 * this.count); } }, remove() { diff --git a/js/player.js b/js/player.js index 6f6295f..fa9e20f 100644 --- a/js/player.js +++ b/js/player.js @@ -451,6 +451,7 @@ const mech = { return dmg }, damage(dmg) { + // , noTransition = false mech.lastHarmCycle = mech.cycle if (mod.isDroneOnDamage) { //chance to build a drone on damage from mod @@ -549,6 +550,11 @@ const mech = { } mech.defaultFPSCycle = mech.cycle } + // if (!noTransition) { + // document.getElementById("health").style.transition = "width 0s ease-out" + // } else { + // document.getElementById("health").style.transition = "width 1s ease-out" + // } }, hitMob(i, dmg) { //prevents damage happening too quick diff --git a/js/spawn.js b/js/spawn.js index 10aee9d..ff8eb26 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -81,9 +81,8 @@ const spawn = { } } }, - randomLevelBoss(x, y) { + randomLevelBoss(x, y, options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss"]) { // other bosses: suckerBoss, laserBoss, tetherBoss, snakeBoss //all need a particular level to work so they are not included - const options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss"] // , "timeSkipBoss" spawn[options[Math.floor(Math.random() * options.length)]](x, y) }, //mob templates ********************************************************************************************* @@ -897,18 +896,18 @@ const spawn = { }; } }, - laserTargetingBoss(x, y, radius = 65) { + laserTargetingBoss(x, y, radius = 80) { const color = "#05f" mobs.spawn(x, y, 3, radius, color); let me = mob[mob.length - 1]; me.isBoss = true; me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front Matter.Body.rotate(me, Math.random() * Math.PI * 2); - me.accelMag = 0.0005 * game.accelScale; + me.accelMag = 0.00065 * game.accelScale; me.seePlayerFreq = Math.floor(25 * game.lookFreqScale); me.memory = 420; me.restitution = 1; - me.frictionAir = 0.05; + me.frictionAir = 0.035; me.frictionStatic = 0; me.friction = 0; @@ -1015,7 +1014,7 @@ const spawn = { // hitting player if (best.who === player) { if (mech.immuneCycle < mech.cycle) { - const dmg = 0.002 * game.dmgScale; + const dmg = 0.001 * game.dmgScale; mech.damage(dmg); //draw damage ctx.fillStyle = color; diff --git a/todo.txt b/todo.txt index 7970aa3..b768760 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,35 @@ +new level, sewers +flak ammo buff ************** TODO - n-gon ************** +mod: do more damage for each reroll you are holding + do more damage for the ammo/ammoPack ratio? + +mod: taking damage slows (or stuns) all mobs on the map + requires the mod that slows time, overclock + +button: blocks that are on the button at an angle will slowly slide off the button + maybe just avoid long blocks near the button? + maybe actively hold the button in place? + +slime should affect blocks, bullets, mobs + and do mob damage? + +rotor doesn't work with + plasma torch + seems to have no effect + pilot wave + maybe rewrite pilot wave to apply a force from an angle, like plasma torch + this would be probably too much work, but worth a try + time dilation field (mostly fixed, but it would be nice if it started up faster after a pause) + sporangium and neutron bomb (mostly fixed, but it would be nice if it sticked instead of bounced) + +new gun - deploy a turret that last for 20 seconds + fire nails at nearby targets once a second. + use mine code and bot code + field that pushes blocks and mobs away charges up on mouse down and triggers on mouse up drain mana while charging up