diff --git a/js/level.js b/js/level.js index 06c1518..8776a70 100644 --- a/js/level.js +++ b/js/level.js @@ -183,15 +183,15 @@ const level = { spawn.boost(1500, 0, 900); // spawn.bomberBoss(2900, -500) - // spawn.launcherBoss(1200, -500) - spawn.launcher(1600, -400) - // spawn.stabber(1600, -500) + spawn.launcherBoss(1200, -500) + // spawn.launcher(1600, -400) + // spawn.spawner(1600, -500) // spawn.cellBossCulture(1600, -500) // spawn.shooter(1600, -500) // spawn.striker(1600, -500) // spawn.shield(mob[mob.length - 1], 1200, -500, 1); - // spawn.nodeBoss(1200, -500, "spiker") + // spawn.nodeBoss(1200, -500, "launcher") // spawn.spiderBoss(1200, -500) // spawn.timeSkipBoss(2900, -500) // spawn.randomMob(1600, -500) diff --git a/js/mob.js b/js/mob.js index 008f6b4..f66b6b3 100644 --- a/js/mob.js +++ b/js/mob.js @@ -244,7 +244,7 @@ const mobs = { locatePlayer() { // updates mob's memory of player location this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //seconds before mob falls a sleep this.seePlayer.position.x = player.position.x; - this.seePlayer.position.y = player.position.y + this.seePlayer.position.y = player.position.y; }, // locatePlayerByDist() { // if (this.distanceToPlayer2() < this.locateRange) { @@ -886,52 +886,20 @@ const mobs = { // } } }, - launch() { - if (!mech.isBodiesAsleep) { - const setNoseShape = () => { - const mag = this.radius + this.radius * this.noseLength; - this.vertices[1].x = this.position.x + Math.cos(this.angle) * mag; - this.vertices[1].y = this.position.y + Math.sin(this.angle) * mag; - }; - //throw a mob/bullet at player - if (this.seePlayer.recall) { - //set direction to turn to fire - if (!(game.cycle % this.seePlayerFreq)) { - this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position)); - } - //rotate towards fireAngle - const angle = this.angle + Math.PI / 2; - c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y; - const threshold = 0.1; - if (c > threshold) { - this.torque += 0.0000045 * this.inertia; - } else if (c < -threshold) { - this.torque -= 0.0000045 * this.inertia; - } else if (this.noseLength > 1.5) { - //fire - spawn.seeker(this.vertices[1].x, this.vertices[1].y, 5 + Math.ceil(this.radius / 15), 5); - const v = 15; - Matter.Body.setVelocity(mob[mob.length - 1], { - x: this.velocity.x + this.fireDir.x * v + Math.random(), - y: this.velocity.y + this.fireDir.y * v + Math.random() - }); - this.noseLength = 0; - // recoil - this.force.x -= 0.005 * this.fireDir.x * this.mass; - this.force.y -= 0.005 * this.fireDir.y * this.mass; - } - if (this.noseLength < 1.5) this.noseLength += this.fireFreq; - setNoseShape(); - } else if (this.noseLength > 0.1) { - this.noseLength -= this.fireFreq / 2; - setNoseShape(); - } - // else if (this.noseLength < -0.1) { - // this.noseLength += this.fireFreq / 4; - // setNoseShape(); - // } - } - }, + // launch() { + // if (this.seePlayer.recall) { + // //fire + // spawn.seeker(this.vertices[1].x, this.vertices[1].y, 5 + Math.ceil(this.radius / 15), 5); + // const v = 15; + // Matter.Body.setVelocity(mob[mob.length - 1], { + // x: this.velocity.x + this.fireDir.x * v + Math.random(), + // y: this.velocity.y + this.fireDir.y * v + Math.random() + // }); + // // recoil + // this.force.x -= 0.005 * this.fireDir.x * this.mass; + // this.force.y -= 0.005 * this.fireDir.y * this.mass; + // } + // }, turnToFacePlayer() { //turn to face player const dx = player.position.x - this.position.x; diff --git a/js/spawn.js b/js/spawn.js index 4e06d55..f709ab9 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -81,8 +81,8 @@ 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", "spiderBoss"] // , "timeSkipBoss" + // 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"] // , "timeSkipBoss" spawn[options[Math.floor(Math.random() * options.length)]](x, y) }, //mob templates ********************************************************************************************* @@ -1437,69 +1437,97 @@ const spawn = { this.timeLimit(); }; }, - launcher(x, y, radius = 25 + Math.ceil(Math.random() * 50)) { + launcher(x, y, radius = 30 + Math.ceil(Math.random() * 40)) { mobs.spawn(x, y, 3, radius, "rgb(150,150,255)"); let me = mob[mob.length - 1]; - me.vertices = Matter.Vertices.clockwiseSort(Matter.Vertices.rotate(me.vertices, Math.PI, me.position)); //make the pointy side of triangle the front - me.isVerticesChange = true - // Matter.Body.rotate(me, Math.PI) - - me.memory = 120; - me.fireFreq = 0.0065 + Math.random() * 0.003; - me.noseLength = 0; - me.fireAngle = 0; - me.accelMag = 0.0006 * game.accelScale; - me.frictionAir = 0.04; - me.lookTorque = 0.0000028 * (Math.random() > 0.5 ? -1 : 1); - me.fireDir = { - x: 0, - y: 0 - }; - me.onDeath = function () { //helps collisions functions work better after vertex have been changed - // this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) - } - // spawn.shield(me, x, y); + me.accelMag = 0.00002 * game.accelScale; + me.frictionStatic = 0; + me.friction = 0; + // me.memory = 200; + me.delay = 770 * game.CDScale; + me.cd = Infinity; + spawn.shield(me, x, y); + me.onDamage = function () {}; me.do = function () { - this.seePlayerByLookingAt(); + if (!(game.cycle % this.seePlayerFreq)) { // this.seePlayerCheck(); from mobs + if ( + this.distanceToPlayer2() < this.seeAtDistance2 && + Matter.Query.ray(map, this.position, this.mechPosRange()).length === 0 && + Matter.Query.ray(body, this.position, this.mechPosRange()).length === 0 && + !mech.isStealth + ) { + this.foundPlayer(); + if (this.cd === Infinity) this.cd = game.cycle + this.delay * 0.3; + } else if (this.seePlayer.recall) { + this.lostPlayer(); + this.cd = Infinity + } + } this.checkStatus(); - this.launch(); + this.attraction(); + if (this.seePlayer.recall && this.cd < game.cycle) { + this.cd = game.cycle + this.delay; + // this.torque += 0.0002 * this.inertia; + Matter.Body.setAngularVelocity(this, 0.14) + //fire a bullet from each vertex + for (let i = 0, len = this.vertices.length; i < len; i++) { + spawn.seeker(this.vertices[i].x, this.vertices[i].y, 5) + //give the bullet a rotational velocity as if they were attached to a vertex + const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -8) + Matter.Body.setVelocity(mob[mob.length - 1], { + x: this.velocity.x + velocity.x, + y: this.velocity.y + velocity.y + }); + } + } }; }, - launcherBoss(x, y, radius = 100) { - mobs.spawn(x, y, 3, radius, "rgb(175,125,255)"); + launcherBoss(x, y, radius = 75 + Math.ceil(Math.random() * 20)) { + mobs.spawn(x, y, 7, radius, "rgb(150,150,255)"); 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.isVerticesChange = true - me.memory = 240; - me.homePosition = { - x: x, - y: y - }; - me.fireFreq = 0.015; - me.noseLength = 0; - me.fireAngle = 0; - me.accelMag = 0.005 * game.accelScale; - 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.0008 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger + me.accelMag = 0.000065 * game.accelScale; + me.memory = 720; + me.delay = 420 * game.CDScale; + me.cd = Infinity; + spawn.shield(me, x, y, 1); + me.onDamage = function () {}; + Matter.Body.setDensity(me, 0.002 + 0.0002 * 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) // this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed }; - me.do = function () { - this.seePlayerByLookingAt(); + if (!(game.cycle % this.seePlayerFreq)) { // this.seePlayerCheck(); from mobs + if ( + this.distanceToPlayer2() < this.seeAtDistance2 && + Matter.Query.ray(map, this.position, this.mechPosRange()).length === 0 && + Matter.Query.ray(body, this.position, this.mechPosRange()).length === 0 && + !mech.isStealth + ) { + this.foundPlayer(); + if (this.cd === Infinity) this.cd = game.cycle + this.delay * 0.2; + } else if (this.seePlayer.recall) { + this.lostPlayer(); + this.cd = Infinity + } + } this.checkStatus(); - this.launch(); - - //gently return to starting location - 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.0002) + this.attraction(); + if (this.seePlayer.recall && this.cd < game.cycle) { + this.cd = game.cycle + this.delay; + // this.torque += 0.0002 * this.inertia; + Matter.Body.setAngularVelocity(this, 0.11) + //fire a bullet from each vertex + for (let i = 0, len = this.vertices.length; i < len; i++) { + spawn.seeker(this.vertices[i].x, this.vertices[i].y, 7) + //give the bullet a rotational velocity as if they were attached to a vertex + const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -10) + Matter.Body.setVelocity(mob[mob.length - 1], { + x: this.velocity.x + velocity.x, + y: this.velocity.y + velocity.y + }); + } + } }; }, seeker(x, y, radius = 6, sides = 0) { @@ -1511,9 +1539,9 @@ const spawn = { this.explode(this.mass * 10); }; Matter.Body.setDensity(me, 0.00005); //normal is 0.001 - me.timeLeft = 420; - me.accelMag = 0.0004 * game.accelScale; - me.frictionAir = 0.033; + me.timeLeft = 380 * (0.8 + 0.4 * Math.random()); + me.accelMag = 0.00012 * (0.8 + 0.4 * Math.random()) * game.accelScale; + me.frictionAir = 0.01 * (0.8 + 0.4 * Math.random()); me.restitution = 0.5; me.leaveBody = false; me.dropPowerUp = false; @@ -1521,7 +1549,11 @@ const spawn = { me.collisionFilter.category = cat.mobBullet; me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet; me.do = function () { - this.seePlayerCheck(); + // this.seePlayer.yes = false; + this.seePlayer.recall = true; + this.seePlayer.position.x = player.position.x; + this.seePlayer.position.y = player.position.y; + this.attraction(); this.timeLimit(); }; diff --git a/todo.txt b/todo.txt index c3b5eda..ea34efc 100644 --- a/todo.txt +++ b/todo.txt @@ -1,27 +1,16 @@ +mob: launchers now have a new fire mechanic +mob: launcher boss +huge rework of code organization, this might produce some new bugs around mods ************** TODO - n-gon ************** -new bug - NaN: player position, velocity, and mouse - level 1 skyscrapers: hard - after blocking with default field, or maybe getting hit, or maybe picking up a reroll (but I have credit for all 3 from quantum immortality) - only mod was quantum immortality - only gun grenades - mob: hoppers - mob: shooters - mob: boss shooter - best guess is something to do with the renamed mods - - launchers shouldn't have to face the player fire after a spin give bullets velocity from spin mob boss - launcher -impact shear buff to 3 nails? - -make a lower tier of basic mods +lower tier of basic mods 33% chance for basic mod on each selection make an odds variable that starts at 0% and gains 33% for each normal mod, resets to 0% after get a basic mod don't track these mods for avoiding no repeats @@ -40,7 +29,7 @@ make a lower tier of basic mods spawn 2 heal spawn 2 reroll //or 1? -improve movement fluidity, through mods, or default improvements +movement fluidity let legs jump on mobs, but player will still take damage like: ori and the blind forest, celeste many of the movement abilities in these games require levels to be built around the ability @@ -57,6 +46,9 @@ rays can have width, how to use this? Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth]) wide lasers? +new type of mob vision that uses ray query with thickness + maybe use for bosses + bug - mines spawn extra mines when fired at thin map wall while jumping mod - negative mass field move faster @@ -83,7 +75,8 @@ boss levels - small levels just a boss, and maybe a few mobs boss level for timeSkipBoss because of game instability for boss on normal levels this might not fix issues -atmosphere levels: change the pace, give the user a rest between combat +atmosphere levels + change the pace, give the user a rest between combat low or no combat, but more graphics explore lore find power ups in "wrecked" mechs representing previous simulations