diff --git a/js/bullets.js b/js/bullets.js
index 1fa9dac..c7f605e 100644
--- a/js/bullets.js
+++ b/js/bullets.js
@@ -148,19 +148,19 @@ const b = {
},
{
name: "high explosives",
- description: "the radius of explosions are +25% larger",
+ description: "explosions do +20% more damage
explosive area is +44% larger",
maxCount: 3,
count: 0,
allowed() {
return true
},
effect: () => {
- b.modExplosionRadius += 0.25;
+ b.modExplosionRadius += 0.2;
}
},
{
name: "electric reactive armour",
- description: "explosions drain energy instead of doing harm",
+ description: "explosions do no harm, but drain energy",
maxCount: 1,
count: 0,
allowed() {
@@ -276,7 +276,7 @@ const b = {
},
{
name: "entanglement",
- description: "using your first gun reduces harm
scales by 10% for each gun in your inventory",
+ description: "when your first gun is equipped
reduce harm by 10% for each gun you have",
maxCount: 1,
count: 0,
allowed() {
@@ -377,28 +377,28 @@ const b = {
},
{
name: "overcharge",
- description: "charge energy +33% beyond your maximum",
+ description: "charge energy +50% beyond your maximum",
maxCount: 9,
count: 0,
allowed() {
return true
},
effect() {
- mech.fieldEnergyMax += 0.33
- mech.fieldMeter += 0.33
+ mech.fieldEnergyMax += 0.5
+ mech.fieldMeter += 0.5
}
},
{
name: "supersaturation",
- description: "heal +33% beyond your max health",
+ description: "heal +50% beyond your max health",
maxCount: 9,
count: 0,
allowed() {
return true
},
effect() {
- mech.maxHealth += 0.33
- mech.addHealth(0.33)
+ mech.maxHealth += 0.50
+ mech.addHealth(0.50)
}
},
{
diff --git a/js/level.js b/js/level.js
index adf25e4..b4fe94e 100644
--- a/js/level.js
+++ b/js/level.js
@@ -19,14 +19,14 @@ const level = {
// 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
@@ -50,7 +50,7 @@ const level = {
// if (level.isBuildRun) num++
for (let i = 0; i < num; i++) {
game.difficulty++
- game.dmgScale += 0.13; //damage done by mobs increases each level
+ game.dmgScale += 0.135; //damage done by mobs increases each level
b.dmgScale *= 0.93; //damage done by player decreases each level
game.accelScale *= 1.02 //mob acceleration increases each level
game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level
@@ -61,7 +61,7 @@ const level = {
difficultyDecrease(num = 1) { //used in easy mode for game.reset()
for (let i = 0; i < num; i++) {
game.difficulty--
- game.dmgScale -= 0.13; //damage done by mobs increases each level
+ game.dmgScale -= 0.135; //damage done by mobs increases each level
if (game.dmgScale < 0.1) game.dmgScale = 0.1;
b.dmgScale /= 0.93; //damage done by player decreases each level
game.accelScale /= 1.02 //mob acceleration increases each level
@@ -128,6 +128,8 @@ const level = {
// spawn.bodyRect(-45, -100, 40, 50);
// spawn.bomber(800, -450);
spawn.cellBoss(400, -750);
+ spawn.cellBoss(400, -750);
+ spawn.cellBoss(400, -750);
// spawn.laser(400, -550);
// spawn.starter(1200, -1050);
@@ -1207,6 +1209,7 @@ const level = {
spawn.mapRect(-4450, -3075, 450, 25);
spawn.mapRect(-4025, -3075, 25, 100);
spawn.mapRect(-4275, -2785, 100, 25);
+ if (game.difficulty < 4) spawn.bodyRect(-3760, -2400, 50, 50);
//mobs
spawn.randomMob(-2500, -2700, 1);
@@ -1233,7 +1236,14 @@ const level = {
spawn.randomMob(-550, -100, -0.1);
spawn.randomBoss(-3250, -2700, 0.2);
spawn.randomBoss(-2450, -1100, 0);
- if (game.difficulty < 4) spawn.bodyRect(-3760, -2400, 50, 50);
+ if (game.difficulty > 3) {
+ const x = -2000 - Math.floor(1600 * Math.random());
+ const y = -2700 - Math.floor(600 * Math.random());
+ const d = 800;
+ for (let i = 0; i < 5; i++) {
+ spawn.cellBoss(x + Math.floor(d * (Math.random() - 0.5)), y + Math.floor(d * (Math.random() - 0.5)));
+ }
+ }
},
warehouse() {
level.defaultZoom = 1300
diff --git a/js/mobs.js b/js/mobs.js
index 0fa6a0c..c1bef91 100644
--- a/js/mobs.js
+++ b/js/mobs.js
@@ -727,7 +727,7 @@ const mobs = {
//accelerate towards the searchTarget
if (!this.seePlayer.recall) {
const newTarget = function (that) {
- if (Math.random() < 0.025) {
+ if (Math.random() < 0.0005) {
that.searchTarget = player.position; //chance to target player
} else {
//target random body
@@ -945,7 +945,7 @@ const mobs = {
if (b.modHealthDrain && dmg !== Infinity) mech.addHealth(Math.min(this.health, dmg) * b.modHealthDrain)
this.health -= dmg
//this.fill = this.color + this.health + ')';
- this.onDamage(this); //custom damage effects
+ this.onDamage(dmg); //custom damage effects
if (this.health < 0.05) this.death();
}
},
@@ -966,7 +966,8 @@ const mobs = {
if (this.dropPowerUp) {
powerUps.spawnRandomPowerUp(this.position.x, this.position.y, this.mass, radius);
if (Math.random() < b.modSpores) {
- for (let i = 0, len = Math.floor(4 + this.mass * Math.random()); i < len; i++) {
+ const len = Math.min(30, Math.floor(4 + this.mass * Math.random()))
+ for (let i = 0; i < len; i++) {
b.spore(this) //spawn drone
}
}
diff --git a/js/powerups.js b/js/powerups.js
index c6614a0..d6e1fd8 100644
--- a/js/powerups.js
+++ b/js/powerups.js
@@ -232,7 +232,7 @@ const powerUps = {
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "gun");
return;
}
- if (Math.random() < 0.003 * (11 - b.modCount)) { //a new mod has a low chance for each not acquired mod up to 7
+ if (Math.random() < 0.003 * (12 - b.modCount)) { //a new mod has a low chance for each not acquired mod up to 7
powerUps.spawn(x, y, "mod");
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "mod");
return;
@@ -247,25 +247,34 @@ const powerUps = {
if (mech.fieldMode === 0) {
powerUps.spawn(x, y, "field")
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "field")
- } else if (Math.random() < 0.65) {
+ } else if (Math.random() < 0.75) {
powerUps.spawn(x, y, "mod")
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "mod")
- } else if (Math.random() < 0.06) {
+ } else if (Math.random() < 0.2) {
powerUps.spawn(x, y, "gun")
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "gun")
- } else if (Math.random() < 0.15) {
+ } else if (Math.random() < 0.6) {
powerUps.spawn(x, y, "field");
if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "field");
- } else if (mech.health < 0.65) {
+ } else if (mech.health < 0.7) {
powerUps.spawn(x, y, "heal");
powerUps.spawn(x, y, "heal");
powerUps.spawn(x, y, "heal");
- if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "heal");
+ powerUps.spawn(x, y, "heal");
+ if (Math.random() < b.isModBayesian) {
+ powerUps.spawn(x, y, "heal");
+ powerUps.spawn(x, y, "heal");
+ }
} else {
powerUps.spawn(x, y, "ammo");
powerUps.spawn(x, y, "ammo");
powerUps.spawn(x, y, "ammo");
- if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "ammo");
+ powerUps.spawn(x, y, "ammo");
+ if (Math.random() < b.isModBayesian) {
+ powerUps.spawn(x, y, "ammo");
+ powerUps.spawn(x, y, "ammo");
+ }
+
}
},
chooseRandomPowerUp(x, y) { //100% chance to drop a random power up //used in spawn.debris
diff --git a/js/spawn.js b/js/spawn.js
index 5a28a2f..059af3e 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -127,10 +127,11 @@ const spawn = {
}
}
},
- starter(x, y, radius = 30) {
+ starter(x, y, radius = Math.floor(20 + 20 * Math.random())) {
//easy mob for on level 1
mobs.spawn(x, y, 8, radius, "#9ccdc6");
let me = mob[mob.length - 1];
+ // console.log(`mass=${me.mass}, radius = ${radius}`)
me.accelMag = 0.0005 * game.accelScale;
me.memory = 60;
me.seeAtDistance2 = 1400000 //1200 vision range
@@ -141,70 +142,146 @@ const spawn = {
this.attraction();
};
},
- cellBoss(x, y, radius = 30, dropPowerUp = true) {
- //easy mob for on level 1
-
- mobs.spawn(x, y, 8, radius, "rgb(70,170,140)");
+ cellBoss(x, y, radius = 20 + 60 * Math.random()) {
+ mobs.spawn(x, y, 0, radius, "rgba(0,150,155,0.7)");
let me = mob[mob.length - 1];
me.isCell = true;
- me.accelMag = 0.0005 * game.accelScale;
+ me.accelMag = 0.00025 * game.accelScale;
me.memory = 60;
- me.spawnFrequency = Math.floor(15 + Math.random() * 8)
- me.cellRadiusMax = 1000
- me.cellRadius = 100
- me.seeAtDistance2 = me.cellRadius * me.cellRadius // vision range
+ me.frictionAir = 0.012
+ me.seePlayerFreq = Math.floor(5 + 5 * Math.random())
+ me.seeAtDistance2 = 9000000;
+ me.cellMassMax = 100
+
+ me.collisionFilter.mask = cat.player | cat.bullet
// 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.split = function () {
+ Matter.Body.scale(this, 0.5, 0.5);
+ this.radius = Math.sqrt(this.mass * 1100 / Math.PI)
+ spawn.cellBoss(this.position.x, this.position.y, this.radius);
+ }
+ me.onHit = function () { //run this function on hitting player
+ this.split();
+ };
+ me.onDamage = function (dmg) {
+ if (Math.random() * 1.8 < dmg && this.health > dmg) this.split();
}
- me.growRate = 4 / count //grow proportional to the number of cells alive when born
-
me.do = function () {
- //grow cell radius
- if (this.cellRadius < 700) {
- this.cellRadius += this.growRate
- this.seeAtDistance2 = this.cellRadius * this.cellRadius
- } else {
- this.seePlayerByDistOrLOS();
+ if (!mech.isBodiesAsleep) {
+ this.seePlayerByDistAndLOS();
this.attraction();
- if (!(game.cycle % this.spawnFrequency) && this.distanceToPlayer() < this.cellRadius) {
- spawn.cellBoss(this.position.x, this.position.y, 30, false);
- this.cellRadius = 100
+
+ if (this.mass < this.cellMassMax) { //grow cell radius
+ const scale = 1 + 0.00015 * this.cellMassMax / this.mass;
+ Matter.Body.scale(this, scale, scale);
+ this.radius = Math.sqrt(this.mass * 1100 / Math.PI)
}
+ if (!(game.cycle % this.seePlayerFreq)) { //move away from other mobs
+ const repelRange = 70
+ const attractRange = 600
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].isCell && mob[i].id !== this.id) {
+ const sub = Vector.sub(this.position, mob[i].position)
+ const dist = Vector.magnitude(sub)
+ if (dist < repelRange) {
+ this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.002)
+ } else if (dist > attractRange) {
+ this.force = Vector.mult(Vector.normalise(sub), -this.mass * 0.0015)
+ }
+ }
+ }
+ }
+ // 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)
+ // }
+ // }
+ // }
}
-
-
- //draw range
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, this.cellRadius, 0, 2 * Math.PI);
- ctx.fillStyle = "rgba(70,170,140,0.3)";
- ctx.fill();
-
- //spread out away from other cells
- // for (let i = 0, len = mob.length; i < len; i++) {
-
- // }
};
me.onDeath = function () {
- if (dropPowerUp) {
+ let count = 0 //count other cells
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].isCell) count++
+ }
+ if (count === 1) { //only drop a power up if this is the last cell
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
} else {
this.dropPowerUp = false;
}
- //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
- }
}
},
+ // 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)");
@@ -541,31 +618,6 @@ const spawn = {
toMe(body, this.position, this.eventHorizon)
toMe(mob, this.position, this.eventHorizon)
toMe(bullet, this.position, this.eventHorizon)
-
- //push everything away
- // function push(who, pos, range) {
- // for (let i = 0, len = who.length; i < len; ++i) {
- // const SUB = Vector.sub(who[i].position, pos)
- // const DISTANCE = Vector.magnitude(SUB)
- // if (DISTANCE < range) {
- // const depth = range - DISTANCE
- // const force = Vector.mult(Vector.normalise(SUB), 30 * who[i].mass / depth)
- // who[i].force.x += force.x;
- // who[i].force.y += force.y;
- // }
- // }
- // }
- // push(body, this.position, this.eventHorizon)
- // push(mob, this.position, this.eventHorizon)
- // push(bullet, this.position, this.eventHorizon)
- // push([player], this.position, this.eventHorizon)
- // for (let i = 0; i < (game.difficulty - 3); ++i) {
- // spawn.sucker(this.position.x + (Math.random() - 0.5) * radius * 2, this.position.y + (Math.random() - 0.5) * radius * 2, 70 * Math.random());
- // Matter.Body.setVelocity(mob[mob.length - 1], {
- // x: (Math.random() - 0.5) * 70,
- // y: (Math.random() - 0.5) * 70
- // });
- // }
}
};
me.do = function () {
@@ -613,8 +665,11 @@ const spawn = {
ctx.fill();
//when player is inside event horizon
if (Vector.magnitude(Vector.sub(this.position, player.position)) < eventHorizon && !mech.isStealth) {
- mech.damage(0.00015 * game.dmgScale);
- if (mech.fieldMeter > 0.1) mech.fieldMeter -= 0.0045
+ if (mech.fieldMeter > 0.1) {
+ mech.fieldMeter -= 0.0055
+ } else {
+ mech.damage(0.0003 * game.dmgScale);
+ }
const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x);
player.force.x -= 1.3 * Math.cos(angle) * player.mass * game.g * (mech.onGround ? 1.7 : 1);
player.force.y -= 1.2 * Math.sin(angle) * player.mass * game.g;