diff --git a/js/level.js b/js/level.js index b58a2d6..555d2ed 100644 --- a/js/level.js +++ b/js/level.js @@ -13,20 +13,20 @@ const level = { levelsCleared: 0, start() { if (level.levelsCleared === 0) { - level.difficultyIncrease(5) - b.giveGuns("minigun") + // level.difficultyIncrease(5) + // b.giveGuns("minigun") // mech.setField("phase decoherence field") // b.giveMod("ground stomp"); // level.intro(); //starting level - // level.testingMap(); + level.testingMap(); // level.bosses(); // level.satellite(); // level.skyscrapers(); // level.aerie(); // level.rooftops(); // level.warehouse(); - level.highrise(); + // level.highrise(); // level.office(); } else { spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns @@ -126,10 +126,10 @@ const level = { // powerUps.spawn(450, -400, "mod", false, 6); // powerUps.spawn(450, -400, "mod", false); // spawn.bodyRect(-45, -100, 40, 50); - // spawn.bomber(800, -450); - spawn.cellBoss(400, -750); - spawn.cellBoss(400, -750); - spawn.cellBoss(400, -750); + // spawn.bomberBoss(800, -450); + // spawn.cellBoss(400, -750); + + spawn.randomLevelBoss(400, -750) // spawn.laser(400, -550); // spawn.starter(1200, -1050); @@ -728,7 +728,7 @@ const level = { spawn.randomBoss(2225, -1325, 0.4); spawn.randomBoss(4900, -1200, 0); //spawn.randomBoss(4850, -1250,0.7); - if (game.difficulty > 4) spawn.bomber(2500, -2400, 100); + if (game.difficulty > 4) spawn.randomLevelBoss(3000, -2400); }, aerie() { // game.setZoom(3000); @@ -1058,7 +1058,7 @@ const level = { spawn.randomMob(-100, -900, -0.2); spawn.randomBoss(3700, -1500, 0.4); spawn.randomBoss(1700, -900, 0.4); - if (game.difficulty > 3) spawn.shooterBoss(2200, -1300); + if (game.difficulty > 3) spawn.randomLevelBoss(2200, -1300); }, highrise() { level.defaultZoom = 1500 @@ -1237,14 +1237,8 @@ const level = { spawn.randomMob(-550, -100, -0.1); spawn.randomBoss(-3250, -2700, 0.2); spawn.randomBoss(-2450, -1100, 0); - if (game.difficulty > 4) { - const x = -2000 - Math.floor(1600 * Math.random()); - const y = -2700 - Math.floor(600 * Math.random()); - const d = 800; - for (let i = 0; i < 6; i++) { - spawn.cellBoss(x + Math.floor(d * (Math.random() - 0.5)), y + Math.floor(d * (Math.random() - 0.5))); - } - } + if (game.difficulty > 4) spawn.randomLevelBoss(-2400, -3100); + }, warehouse() { level.defaultZoom = 1300 @@ -1420,7 +1414,7 @@ const level = { //spawn.randomMob(1120, -1200, 0.3); //spawn.randomSmallMob(2200, -1775); - if (game.difficulty > 2) spawn.snaker(-1300 + Math.random() * 2000, -2200); //boss snake with head + if (game.difficulty > 2) spawn.snakeBoss(-1300 + Math.random() * 2000, -2200); //boss snake with head }, office() { level.defaultZoom = 1400 @@ -1569,7 +1563,7 @@ const level = { height: 525, color: "#ccc" }); - spawn.tether(2850, -80) + spawn.tetherBoss(2850, -80) cons[cons.length] = Constraint.create({ pointA: { x: 2500, diff --git a/js/mobs.js b/js/mobs.js index c1bef91..ad42cf9 100644 --- a/js/mobs.js +++ b/js/mobs.js @@ -962,7 +962,7 @@ const mobs = { death() { this.onDeath(this); //custom death effects this.removeConsBB(); - this.alive = false; + this.alive = false; //triggers mob removal in mob[i].replace(i) if (this.dropPowerUp) { powerUps.spawnRandomPowerUp(this.position.x, this.position.y, this.mass, radius); if (Math.random() < b.modSpores) { diff --git a/js/spawn.js b/js/spawn.js index 1fbda6c..1048bec 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -78,7 +78,11 @@ const spawn = { } } }, - + randomLevelBoss(x, y) { + // suckerBoss, laserBoss, tetherBoss, snakeBoss all need a particular level to work so they are not included + const options = ["shooterBoss", "cellBossCulture", "bomberBoss"] + spawn[options[Math.floor(Math.random() * options.length)]](x, y) + }, //mob templates ********************************************************************************************* //*********************************************************************************************************** groupBoss(x, y, num = 3 + Math.random() * 8) { @@ -142,8 +146,13 @@ const spawn = { this.attraction(); }; }, - cellBoss(x, y, radius = 20 + 40 * Math.random()) { - mobs.spawn(x, y, 0, radius, "rgba(0,150,155,0.7)"); + cellBossCulture(x, y, radius = 20, num = 5) { + for (let i = 0; i < num; i++) { + spawn.cellBoss(x, y, radius) + } + }, + cellBoss(x, y, radius = 20) { + mobs.spawn(x + Math.random(), y + Math.random(), 20, radius * (1 + 1.2 * Math.random()), "rgba(0,150,155,0.7)"); let me = mob[mob.length - 1]; me.isCell = true; me.accelMag = 0.00018 * game.accelScale; @@ -193,15 +202,6 @@ const spawn = { } } } - // if (!(game.cycle % this.seePlayerFreq)) { //move away from other mobs - // let q = Matter.Query.point(mob, this.position) - // for (let i = 0; i < q.length; i++) { - // if (q[i].id !== this.id) { - // THRUST = 0.005 - // this.force = Vector.mult(Vector.normalise(Vector.sub(this.position, q[i].position)), this.mass * THRUST) - // } - // } - // } } }; me.onDeath = function () { @@ -212,79 +212,11 @@ const spawn = { if (count === 1) { //only drop a power up if this is the last cell powerUps.spawnBossPowerUp(this.position.x, this.position.y) } else { + this.leaveBody = false; this.dropPowerUp = false; } } }, - // cellBoss(x, y, radius = 30) { - // mobs.spawn(x, y, 8, radius, "rgb(70,170,140)"); - // let me = mob[mob.length - 1]; - // me.isCell = true; - // me.accelMag = 0.0003 * game.accelScale; - // me.memory = 60; - // me.spawnFrequency = Math.floor(15 + Math.random() * 8) - // me.cellRadiusMax = 600 - // me.cellRadius = 100 - // me.seeAtDistance2 = me.cellRadius * me.cellRadius // vision range - // // Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback - - // //count other cells - // let count = 0 - // for (let i = 0, len = mob.length; i < len; i++) { - // if (mob[i].isCell) count++ - // } - // me.growRate = 4 / count //grow proportional to the number of cells alive when born - - // me.do = function () { - // //grow cell radius - // if (this.cellRadius < this.cellRadiusMax) { - // this.cellRadius += this.growRate - // this.seeAtDistance2 = this.cellRadius * this.cellRadius - // } - // if (this.cellRadius > this.cellRadiusMax / 2) { - // this.seePlayerByDistOrLOS(); - // this.attraction(); - // //when near player split and hurt player - // if (!(game.cycle % this.spawnFrequency) && this.distanceToPlayer() < this.cellRadius) { - // spawn.cellBoss(this.position.x, this.position.y, 30); - // this.cellRadius = 100 - // // let dmg = 0.1 * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 - // // mech.damage(dmg); - // } - - // //eat blocks and power ups, gain an increases in radius, and split - // //remember what was eaten and release it out on death - // } - - // ctx.beginPath(); //draw range - // ctx.arc(this.position.x, this.position.y, this.cellRadius, 0, 2 * Math.PI); - // ctx.fillStyle = `rgba(70,170,140,${0.7*this.cellRadius/this.cellRadiusMax})` - // ctx.fill(); - - // //flocking behavior? - // // for (let i = 0, len = mob.length; i < len; i++) { - - // // } - // }; - // me.onDeath = function () { - // //find other cells and have them reset their growth rate - // let count = 0 - // for (let i = 0, len = mob.length; i < len; i++) { - // if (mob[i].isCell) count++ - // } - // const growRate = 4 / count //grow proportional to the number of cells alive when born - // for (let i = 0, len = mob.length; i < len; i++) { - // if (mob[i].isCell) mob[i].growRate = growRate - // } - // //only drop a power up if this is the last cell - // if (count === 1) { - // powerUps.spawnBossPowerUp(this.position.x, this.position.y) - // } else { - // this.dropPowerUp = false; - // } - // } - // }, - // healer(x, y, radius = 20) { // mobs.spawn(x, y, 3, radius, "rgba(50,255,200,0.4)"); // let me = mob[mob.length - 1]; @@ -1081,7 +1013,7 @@ const spawn = { // } // }; // }, - bomber(x, y, radius = 120 + Math.ceil(Math.random() * 70)) { + bomberBoss(x, y, radius = 90 + Math.ceil(Math.random() * 20)) { //boss that drops bombs from above and holds a set distance from player mobs.spawn(x, y, 3, radius, "transparent"); let me = mob[mob.length - 1]; @@ -1139,24 +1071,33 @@ const spawn = { let me = mob[mob.length - 1]; me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front me.memory = 240; + me.homePosition = { + x: x, + y: y + }; me.fireFreq = 0.025; me.noseLength = 0; me.fireAngle = 0; me.accelMag = 0.005 * game.accelScale; - me.frictionAir = 0.1; + me.frictionAir = 0.05; me.lookTorque = 0.000007 * (Math.random() > 0.5 ? -1 : 1); me.fireDir = { x: 0, y: 0 }; - Matter.Body.setDensity(me, 0.02 + 0.001 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger - // spawn.shield(me, x, y, 1); + Matter.Body.setDensity(me, 0.023 + 0.001 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger me.onDeath = function () { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; me.do = function () { this.seePlayerByLookingAt(); this.fire(); + //gently return to starting location + if (!(game.cycle % this.seePlayerFreq)) { + const sub = Vector.sub(this.homePosition, this.position) + const dist = Vector.magnitude(sub) + if (dist > 50) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.001) + } }; }, bullet(x, y, radius = 6, sides = 0) { @@ -1237,7 +1178,7 @@ const spawn = { this.attraction(); }; }, - snaker(x, y, radius = 80) { + snakeBoss(x, y, radius = 80) { //snake boss with a laser head mobs.spawn(x, y, 8, radius, "rgb(255,50,130)"); let me = mob[mob.length - 1]; @@ -1276,7 +1217,7 @@ const spawn = { }); }, - tether(x, y, radius = 90) { + tetherBoss(x, y, radius = 90) { // constrained mob boss for the towers level // often has a ring of mobs around it mobs.spawn(x, y, 8, radius, "rgb(0,60,80)");