diff --git a/js/bullet.js b/js/bullet.js
index 94143ba..d1544a2 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -156,7 +156,7 @@ const b = {
}
}
},
- explosion(where, radius, isBurn = false) {
+ explosion(where, radius) {
radius *= mod.explosionRadius
// typically explode is used for some bullets with .onEnd
//add dmg to draw queue
@@ -969,7 +969,7 @@ const b = {
nailBot(position = mech.pos) {
const me = bullet.length;
const dir = mech.angle;
- const RADIUS = (10 + 5 * Math.random())
+ const RADIUS = (12 + 4 * Math.random())
bullet[me] = Bodies.polygon(position.x, position.y, 4, RADIUS, {
angle: dir,
friction: 0,
@@ -1076,6 +1076,273 @@ const b = {
})
World.add(engine.world, bullet[me]); //add bullet to world
},
+ plasmaBot(position = mech.pos) {
+ const me = bullet.length;
+ const dir = mech.angle;
+ const RADIUS = 18
+ bullet[me] = Bodies.polygon(position.x, position.y, 5, RADIUS, {
+ angle: dir,
+ friction: 0,
+ frictionStatic: 0,
+ frictionAir: 0.05,
+ restitution: 1,
+ dmg: 0, // 0.14 //damage done in addition to the damage from momentum
+ minDmgSpeed: 2,
+ lookFrequency: 15,
+ cd: 0,
+ acceleration: 0.0085,
+ endCycle: Infinity,
+ classType: "bullet",
+ collisionFilter: {
+ category: cat.bullet,
+ mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
+ },
+ lockedOn: null,
+ onDmg() {
+ this.lockedOn = null
+ },
+ onEnd() {},
+ do() {
+ const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos))
+ if (distanceToPlayer > 100) { //if far away move towards player
+ this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration)
+ }
+ Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); //add player's velocity
+
+ //find closest
+ if (!(game.cycle % this.lookFrequency)) {
+ this.lockedOn = null;
+ let closeDist = mod.isPlasmaRange * 1000;
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius;
+ if (DIST < closeDist && mob[i].dropPowerUp &&
+ Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
+ closeDist = DIST;
+ this.lockedOn = mob[i]
+ }
+ }
+ }
+
+ //fire plasma at target
+
+ const DRAIN = 0.0014
+ if (this.lockedOn && this.lockedOn.alive && mech.energy > DRAIN && mech.fieldCDcycle < mech.cycle) {
+ mech.energy -= DRAIN;
+ if (mech.energy < 0) {
+ mech.fieldCDcycle = mech.cycle + 120;
+ mech.energy = 0;
+ }
+
+ const sub = Vector.sub(this.lockedOn.position, this.position)
+ const DIST = Vector.magnitude(sub);
+ const unit = Vector.normalise(sub)
+ if (DIST < mod.isPlasmaRange * 600) {
+ //calculate laser collision
+ let best;
+ let range = mod.isPlasmaRange * (140 + 300 * Math.sqrt(Math.random()))
+ const path = [{
+ x: this.position.x,
+ y: this.position.y
+ },
+ {
+ x: this.position.x + range * unit.x,
+ y: this.position.y + range * unit.y
+ }
+ ];
+ const vertexCollision = function (v1, v1End, domain) {
+ for (let i = 0; i < domain.length; ++i) {
+ let vertices = domain[i].vertices;
+ const len = vertices.length - 1;
+ for (let j = 0; j < len; j++) {
+ results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
+ if (results.onLine1 && results.onLine2) {
+ const dx = v1.x - results.x;
+ const dy = v1.y - results.y;
+ const dist2 = dx * dx + dy * dy;
+ if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
+ best = {
+ x: results.x,
+ y: results.y,
+ dist2: dist2,
+ who: domain[i],
+ v1: vertices[j],
+ v2: vertices[j + 1]
+ };
+ }
+ }
+ }
+ results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
+ if (results.onLine1 && results.onLine2) {
+ const dx = v1.x - results.x;
+ const dy = v1.y - results.y;
+ const dist2 = dx * dx + dy * dy;
+ if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
+ best = {
+ x: results.x,
+ y: results.y,
+ dist2: dist2,
+ who: domain[i],
+ v1: vertices[0],
+ v2: vertices[len]
+ };
+ }
+ }
+ }
+ };
+
+ //check for collisions
+ best = {
+ x: null,
+ y: null,
+ dist2: Infinity,
+ who: null,
+ v1: null,
+ v2: null
+ };
+ vertexCollision(path[0], path[1], mob);
+ vertexCollision(path[0], path[1], map);
+ vertexCollision(path[0], path[1], body);
+ if (best.dist2 != Infinity) { //if hitting something
+ path[path.length - 1] = {
+ x: best.x,
+ y: best.y
+ };
+ if (best.who.alive) {
+ const dmg = 0.8 * b.dmgScale; //********** SCALE DAMAGE HERE *********************
+ best.who.damage(dmg);
+ best.who.locatePlayer();
+
+ //push mobs away
+ const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.01 * Math.min(5, best.who.mass))
+ Matter.Body.applyForce(best.who, path[1], force)
+ Matter.Body.setVelocity(best.who, { //friction
+ x: best.who.velocity.x * 0.7,
+ y: best.who.velocity.y * 0.7
+ });
+ //draw mob damage circle
+ game.drawList.push({
+ x: path[1].x,
+ y: path[1].y,
+ radius: Math.sqrt(dmg) * 50,
+ color: "rgba(255,0,255,0.2)",
+ time: game.drawTime * 4
+ });
+ } else if (!best.who.isStatic) {
+ //push blocks away
+ const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.007 * Math.sqrt(Math.sqrt(best.who.mass)))
+ Matter.Body.applyForce(best.who, path[1], force)
+ }
+ }
+
+ //draw blowtorch laser beam
+ ctx.strokeStyle = "rgba(255,0,255,0.1)"
+ ctx.lineWidth = 14
+ ctx.beginPath();
+ ctx.moveTo(path[0].x, path[0].y);
+ ctx.lineTo(path[1].x, path[1].y);
+ ctx.stroke();
+ ctx.strokeStyle = "#f0f";
+ ctx.lineWidth = 2
+ ctx.stroke();
+
+ //draw electricity
+ const Dx = Math.cos(mech.angle);
+ const Dy = Math.sin(mech.angle);
+ let x = this.position.x + 20 * Dx;
+ let y = this.position.y + 20 * Dy;
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ const step = Vector.magnitude(Vector.sub(path[0], path[1])) / 5
+ for (let i = 0; i < 4; i++) {
+ x += step * (Dx + 1.5 * (Math.random() - 0.5))
+ y += step * (Dy + 1.5 * (Math.random() - 0.5))
+ ctx.lineTo(x, y);
+ }
+ ctx.lineWidth = 2 * Math.random();
+ ctx.stroke();
+ }
+ }
+ }
+ })
+ World.add(engine.world, bullet[me]); //add bullet to world
+ },
+ boomBot(position = mech.pos) {
+ const me = bullet.length;
+ const dir = mech.angle;
+ const RADIUS = (7 + 2 * Math.random())
+ bullet[me] = Bodies.polygon(position.x, position.y, 4, RADIUS, {
+ angle: dir,
+ friction: 0,
+ frictionStatic: 0,
+ frictionAir: 0.05,
+ restitution: 1,
+ dmg: 0,
+ minDmgSpeed: 0,
+ lookFrequency: 35 + Math.floor(7 * Math.random()),
+ acceleration: 0.005 * (1 + 0.5 * Math.random()),
+ range: 500 * (1 + 0.1 * Math.random()),
+ endCycle: Infinity,
+ classType: "bullet",
+ collisionFilter: {
+ category: cat.bullet,
+ mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield
+ },
+ lockedOn: null,
+ explode: 0,
+ onDmg() {
+ if (this.lockedOn) {
+ const explosionRadius = Math.min(170, Vector.magnitude(Vector.sub(this.position, mech.pos)) - 30)
+ if (explosionRadius > 60) {
+ this.explode = explosionRadius
+ //
+ //push away from player, because normal explosion knock doesn't do much
+ // const sub = Vector.sub(this.lockedOn.position, mech.pos)
+ // mag = Math.min(35, 20 / Math.sqrt(this.lockedOn.mass))
+ // Matter.Body.setVelocity(this.lockedOn, Vector.mult(Vector.normalise(sub), mag))
+ }
+ this.lockedOn = null //lose target so bot returns to player
+ }
+ },
+ onEnd() {},
+ do() {
+ if (this.explode) {
+ b.explosion(this.position, this.explode); //makes bullet do explosive damage at end
+ this.explode = 0;
+ }
+ const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos))
+ if (distanceToPlayer > 100) { //if far away move towards player
+ this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration)
+ } else if (distanceToPlayer < 250) { //close to player
+ Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); //add player's velocity
+ //find targets
+ if (!(game.cycle % this.lookFrequency) && !mech.isStealth) {
+ this.lockedOn = null;
+ let closeDist = this.range;
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius;
+ if (DIST < closeDist && mob[i].dropPowerUp &&
+ Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
+ closeDist = DIST;
+ this.lockedOn = mob[i]
+ }
+ }
+ }
+ }
+ //punch target
+ if (this.lockedOn && this.lockedOn.alive) {
+ const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position));
+ if (DIST - this.lockedOn.radius < this.range &&
+ Matter.Query.ray(map, this.position, this.lockedOn.position).length === 0) {
+ //move towards the target
+ this.force = Vector.add(this.force, Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), 0.012 * this.mass))
+ }
+ }
+ }
+ })
+ World.add(engine.world, bullet[me]); //add bullet to world
+ },
laserBot(position = mech.pos) {
const me = bullet.length;
const dir = mech.angle;
@@ -2212,7 +2479,7 @@ const b = {
},
{
name: "drones",
- description: "deploy drones that crash into mobs
collisions reduce their lifespan by 1 second",
+ description: "deploy drones that crash into mobs
crashes reduce their lifespan by 1 second",
ammo: 0,
ammoPack: 14,
have: false,
@@ -2660,7 +2927,7 @@ const b = {
isEasyToAim: false,
fire() {
//calculate laser collision
- let best;
+ let best, energy, explosionRange;
let range = 3000
const path = [{
x: mech.pos.x + 20 * Math.cos(mech.angle),
@@ -2722,15 +2989,22 @@ const b = {
v2: null
};
if (mod.isPulseAim) { //find mobs in line of sight
+ let dist = 2200
+ energy = 0.25 * Math.min(mech.energy, 1.75)
+ explosionRange = 1000 * energy
for (let i = 0, len = mob.length; i < len; i++) {
- if (Vector.magnitude(Vector.sub(path[0], mob[i].position)) < 2200 &&
+ const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
+ if (explosionRange < newDist &&
+ newDist < dist &&
Matter.Query.ray(map, path[0], mob[i].position).length === 0 &&
Matter.Query.ray(body, path[0], mob[i].position).length === 0) {
+ dist = newDist
best.who = mob[i]
path[path.length - 1] = mob[i].position
- break
}
}
+
+
}
if (!best.who) {
vertexCollision(path[0], path[1], mob);
@@ -2743,16 +3017,16 @@ const b = {
};
}
}
- let energy
+
if (mod.isPulseAim) {
- energy = 0.25 * Math.min(mech.energy, 1.75)
mech.energy -= energy * mod.isLaserDiode
- if (best.who) b.explosion(path[1], 1000 * energy, true)
+ if (best.who) b.explosion(path[1], explosionRange, true)
mech.fireCDcycle = mech.cycle + Math.floor(25 * b.fireCD); // cool down
} else {
energy = 0.3 * Math.min(mech.energy, 1.75)
mech.energy -= energy * mod.isLaserDiode
- if (best.who) b.explosion(path[1], 1000 * energy, true)
+ explosionRange = 1000 * energy
+ if (best.who) b.explosion(path[1], explosionRange, true)
mech.fireCDcycle = mech.cycle + Math.floor(50 * b.fireCD); // cool down
}
if (mod.isPulseStun) {
diff --git a/js/engine.js b/js/engine.js
index 9eab081..599e6aa 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -208,7 +208,7 @@ function collisionChecks(event) {
if (mod.isCrit && !mob[k].seePlayer.recall && !mob[k].shield) dmg *= 5
mob[k].foundPlayer();
mob[k].damage(dmg);
- obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn
+ obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here
game.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
diff --git a/js/game.js b/js/game.js
index 1725a51..61ff2f8 100644
--- a/js/game.js
+++ b/js/game.js
@@ -2,33 +2,6 @@
//*********************************************************************
const game = {
loop() {}, //main game loop, gets se tto normal or testing loop
- testingLoop() {
- game.gravity();
- Engine.update(engine, game.delta);
- game.wipe();
- game.textLog();
- if (mech.onGround) {
- mech.groundControl()
- } else {
- mech.airControl()
- }
- level.checkZones();
- level.checkQuery();
- mech.move();
- mech.look();
- game.checks();
- ctx.save();
- game.camera();
- mech.draw();
- game.draw.wireFrame();
- game.draw.cons();
- game.draw.testing();
- game.drawCircle();
- game.constructCycle()
- ctx.restore();
- game.testingOutput();
- game.drawCursor();
- },
normalLoop() {
game.gravity();
Engine.update(engine, game.delta);
@@ -39,7 +12,8 @@ const game = {
} else {
mech.airControl()
}
- level.checkZones();
+ // level.checkZones();
+ level.custom();
level.checkQuery();
mech.move();
mech.look();
@@ -65,10 +39,38 @@ const game = {
b.bulletDraw();
b.bulletDo();
game.drawCircle();
- game.clip();
+ // game.clip();
ctx.restore();
game.drawCursor();
},
+ testingLoop() {
+ game.gravity();
+ Engine.update(engine, game.delta);
+ game.wipe();
+ game.textLog();
+ if (mech.onGround) {
+ mech.groundControl()
+ } else {
+ mech.airControl()
+ }
+ // level.checkZones();
+ level.custom();
+ level.checkQuery();
+ mech.move();
+ mech.look();
+ game.checks();
+ ctx.save();
+ game.camera();
+ mech.draw();
+ game.draw.wireFrame();
+ game.draw.cons();
+ game.draw.testing();
+ game.drawCircle();
+ game.constructCycle()
+ ctx.restore();
+ game.testingOutput();
+ game.drawCursor();
+ },
isTimeSkipping: false,
timeSkip(cycles = 60) {
game.isTimeSkipping = true;
@@ -146,9 +148,9 @@ const game = {
// };
// requestAnimationFrame(normalFPS);
// },
- clip() {
+ // clip() {
- },
+ // },
drawCursor() {
const size = 10;
ctx.beginPath();
@@ -397,7 +399,7 @@ const game = {
});
// game.noCameraScroll()
} else if (keys[85]) { // next level with U
- level.zoneActions.nextLevel();
+ level.nextLevel();
}
}
},
@@ -659,11 +661,9 @@ const game = {
powerUps.totalPowerUps = powerUp.length
- //if player is holding something this remembers it before it gets deleted
- let holdTarget;
- if (mech.holdingTarget) {
- holdTarget = mech.holdingTarget;
- }
+ let holdTarget; //if player is holding something this remembers it before it gets deleted
+ if (mech.holdingTarget) holdTarget = mech.holdingTarget;
+
mech.fireCDcycle = 0
mech.drop();
level.fill = [];
@@ -697,7 +697,11 @@ const game = {
frictionAir: holdTarget.frictionAir,
frictionStatic: holdTarget.frictionStatic
});
+ Matter.Body.setPosition(body[len], mech.pos);
+ mech.isHolding = true
mech.holdingTarget = body[len];
+ mech.holdingTarget.collisionFilter.category = 0;
+ mech.holdingTarget.collisionFilter.mask = 0;
}
},
getCoords: {
@@ -811,20 +815,20 @@ const game = {
let line = 500;
const x = canvas.width - 5;
ctx.fillText("T: exit testing mode", x, line);
- line += 20;
- ctx.fillText("Y: give all mods", x, line);
- line += 20;
- ctx.fillText("R: teleport to mouse", x, line);
- line += 20;
- ctx.fillText("F: cycle field", x, line);
- line += 20;
- ctx.fillText("G: give all guns", x, line);
- line += 20;
- ctx.fillText("H: heal", x, line);
- line += 20;
- ctx.fillText("U: next level", x, line);
- line += 20;
- ctx.fillText("1-7: spawn things", x, line);
+ // line += 20;
+ // ctx.fillText("Y: give all mods", x, line);
+ // line += 20;
+ // ctx.fillText("R: teleport to mouse", x, line);
+ // line += 20;
+ // ctx.fillText("F: cycle field", x, line);
+ // line += 20;
+ // ctx.fillText("G: give all guns", x, line);
+ // line += 20;
+ // ctx.fillText("H: heal", x, line);
+ // line += 20;
+ // ctx.fillText("U: next level", x, line);
+ // line += 20;
+ // ctx.fillText("1-7: spawn things", x, line);
}
ctx.textAlign = "center";
ctx.fillText(`(${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)})`, game.mouse.x, game.mouse.y - 20);
@@ -924,13 +928,6 @@ const game = {
ctx.stroke();
},
testing() {
- //zones
- ctx.beginPath();
- for (let i = 0, len = level.zones.length; i < len; ++i) {
- ctx.rect(level.zones[i].x1, level.zones[i].y1 + 70, level.zones[i].x2 - level.zones[i].x1, level.zones[i].y2 - level.zones[i].y1);
- }
- ctx.fillStyle = "rgba(0, 255, 0, 0.3)";
- ctx.fill();
//query zones
ctx.beginPath();
for (let i = 0, len = level.queryList.length; i < len; ++i) {
diff --git a/js/level.js b/js/level.js
index 8c2b641..031c00a 100644
--- a/js/level.js
+++ b/js/level.js
@@ -1,29 +1,28 @@
-//global game variables
let body = []; //non static bodies
let map = []; //all static bodies
let cons = []; //all constraints between a point and a body
let consBB = []; //all constraints between two bodies
-//main object for spawning levels
const level = {
- maxJump: 390,
defaultZoom: 1400,
- boostScale: 0.000023,
- levels: ["skyscrapers", "rooftops", "warehouse", "highrise", "office", "aerie", "satellite"],
onLevel: 0,
levelsCleared: 0,
+ levels: ["skyscrapers", "rooftops", "warehouse", "highrise", "office", "aerie", "satellite"],
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)
// mech.isStealth = true;
- // mod.giveMod("logistics");
+ // mod.giveMod("plasma-bot");
+ // mod.giveMod("nail-bot");
+ // mod.giveMod("laser-bot");
+ // mod.giveMod("boom-bot");
// mod.giveMod("supply chain");
// b.giveGuns("pulse")
- // mech.setField("phase decoherence field")
+ // mech.setField("plasma torch")
level.intro(); //starting level
- // level.testing();
+ // level.testing();
// level.stronghold()
// level.bosses();
// level.satellite();
@@ -53,6 +52,13 @@ const level = {
for (let i = 0; i < mod.foamBotCount; i++) {
b.foamBot()
}
+ for (let i = 0; i < mod.boomBotCount; i++) {
+ b.boomBot()
+ }
+ for (let i = 0; i < mod.plasmaBotCount; i++) {
+ b.plasmaBot()
+ }
+
if (mod.isArmorFromPowerUps) {
// for (let i = 0; i < powerUps.totalPowerUps; i++) {}
mech.maxHealth += 0.04 * powerUps.totalPowerUps
@@ -85,31 +91,6 @@ const level = {
if (game.difficulty < 1) game.difficulty = 0;
game.healScale = 1 / (1 + game.difficulty * 0.09)
},
- // difficultyIncrease(num = 1) {
- // // if (level.isBuildRun) num++
- // for (let i = 0; i < num; i++) {
- // game.difficulty++
- // game.dmgScale += 0.17; //damage done by mobs increases each level
- // b.dmgScale *= 0.91; //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
- // game.CDScale *= 0.97 //mob CD time decreases each level
- // }
- // game.healScale = 1 / (1 + game.difficulty * 0.09) //a higher denominator makes for lower heals // mech.health += heal * game.healScale;
- // },
- // difficultyDecrease(num = 1) { //used in easy mode for game.reset()
- // for (let i = 0; i < num; i++) {
- // game.difficulty--
- // game.dmgScale -= 0.17; //damage done by mobs increases each level
- // if (game.dmgScale < 0.1) game.dmgScale = 0.1;
- // b.dmgScale /= 0.91; //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
- // game.CDScale /= 0.97 //mob CD time decreases each level
- // }
- // if (game.difficulty < 1) game.difficulty = 0;
- // game.healScale = 1 / (1 + game.difficulty * 0.09)
- // },
difficultyText(mode = document.getElementById("difficulty-select").value) {
if (mode === "0") {
return "easy"
@@ -128,10 +109,207 @@ const level = {
document.title = "n-gon: L" + (level.levelsCleared) + " " + level.levels[level.onLevel] + " (" + level.difficultyText() + ")";
}
},
- //******************************************************************************************************************
- //******************************************************************************************************************
+ custom() {}, //each level runs it's own custom code (level exits, ...)
+ nextLevel() {
+ level.levelsCleared++;
+ level.onLevel++; //cycles map to next level
+ if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
+ level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes
+ if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1);
+ game.clearNow = true; //triggers in game.clearMap to remove all physics bodies and setup for new map
+ },
+ playerExitCheck() {
+ if (
+ player.position.x > level.exit.x &&
+ player.position.x < level.exit.x + 100 &&
+ player.position.y > level.exit.y - 150 &&
+ player.position.y < level.exit.y - 40 &&
+ player.velocity.y < 0.1
+ ) {
+ level.nextLevel()
+ }
+ },
+ setPosToSpawn(xPos, yPos) {
+ mech.spawnPos.x = mech.pos.x = xPos;
+ mech.spawnPos.y = mech.pos.y = yPos;
+ level.enter.x = mech.spawnPos.x - 50;
+ level.enter.y = mech.spawnPos.y + 20;
+ mech.transX = mech.transSmoothX = canvas.width2 - mech.pos.x;
+ mech.transY = mech.transSmoothY = canvas.height2 - mech.pos.y;
+ mech.Vx = mech.spawnVel.x;
+ mech.Vy = mech.spawnVel.y;
+ player.force.x = 0;
+ player.force.y = 0;
+ Matter.Body.setPosition(player, mech.spawnPos);
+ Matter.Body.setVelocity(player, mech.spawnVel);
+ },
+ enter: {
+ x: 0,
+ y: 0,
+ draw() {
+ ctx.beginPath();
+ ctx.moveTo(level.enter.x, level.enter.y + 30);
+ ctx.lineTo(level.enter.x, level.enter.y - 80);
+ ctx.bezierCurveTo(level.enter.x, level.enter.y - 170, level.enter.x + 100, level.enter.y - 170, level.enter.x + 100, level.enter.y - 80);
+ ctx.lineTo(level.enter.x + 100, level.enter.y + 30);
+ ctx.lineTo(level.enter.x, level.enter.y + 30);
+ ctx.fillStyle = "#ccc";
+ ctx.fill();
+ }
+ },
+ exit: {
+ x: 0,
+ y: 0,
+ draw() {
+ ctx.beginPath();
+ ctx.moveTo(level.exit.x, level.exit.y + 30);
+ ctx.lineTo(level.exit.x, level.exit.y - 80);
+ ctx.bezierCurveTo(level.exit.x, level.exit.y - 170, level.exit.x + 100, level.exit.y - 170, level.exit.x + 100, level.exit.y - 80);
+ ctx.lineTo(level.exit.x + 100, level.exit.y + 30);
+ ctx.lineTo(level.exit.x, level.exit.y + 30);
+ ctx.fillStyle = "#0ff";
+ ctx.fill();
+ }
+ },
+ fillBG: [],
+ drawFillBGs() {
+ for (let i = 0, len = level.fillBG.length; i < len; ++i) {
+ const f = level.fillBG[i];
+ ctx.fillStyle = f.color;
+ ctx.fillRect(f.x, f.y, f.width, f.height);
+ }
+ },
+ fill: [],
+ drawFills() {
+ for (let i = 0, len = level.fill.length; i < len; ++i) {
+ const f = level.fill[i];
+ ctx.fillStyle = f.color;
+ ctx.fillRect(f.x, f.y, f.width, f.height);
+ }
+ },
+ queryList: [], //queries do actions on many objects in regions
+ checkQuery() {
+ let bounds, action, info;
+
+ function isInZone(targetArray) {
+ let results = Matter.Query.region(targetArray, bounds);
+ for (let i = 0, len = results.length; i < len; ++i) {
+ level.queryActions[action](results[i], info);
+ }
+ }
+ for (let i = 0, len = level.queryList.length; i < len; ++i) {
+ bounds = level.queryList[i].bounds;
+ action = level.queryList[i].action;
+ info = level.queryList[i].info;
+ for (let j = 0, l = level.queryList[i].groups.length; j < l; ++j) {
+ isInZone(level.queryList[i].groups[j]);
+ }
+ }
+ },
+ //oddly query regions can't get smaller than 50 width?
+ addQueryRegion(x, y, width, height, action, groups = [
+ [player], body, mob, powerUp, bullet
+ ], info) {
+ level.queryList[level.queryList.length] = {
+ bounds: {
+ min: {
+ x: x,
+ y: y
+ },
+ max: {
+ x: x + width,
+ y: y + height
+ }
+ },
+ action: action,
+ groups: groups,
+ info: info
+ };
+ },
+ queryActions: {
+ bounce(target, info) {
+ //jerky fling upwards
+ Matter.Body.setVelocity(target, {
+ x: info.Vx + (Math.random() - 0.5) * 6,
+ y: info.Vy
+ });
+ target.torque = (Math.random() - 0.5) * 2 * target.mass;
+ },
+ boost(target, yVelocity) {
+ // if (target.velocity.y < 0) {
+ // mech.undoCrouch();
+ // mech.enterAir();
+ mech.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
+ mech.hardLandCD = 0 // disable hard landing
+ if (target.velocity.y > 30) {
+ Matter.Body.setVelocity(target, {
+ x: target.velocity.x + (Math.random() - 0.5) * 2,
+ y: -23 //gentle bounce if coming down super fast
+ });
+ } else {
+ Matter.Body.setVelocity(target, {
+ x: target.velocity.x + (Math.random() - 0.5) * 2,
+ y: yVelocity
+ });
+ }
+
+ },
+ force(target, info) {
+ if (target.velocity.y < 0) {
+ //gently force up if already on the way up
+ target.force.x += info.Vx * target.mass;
+ target.force.y += info.Vy * target.mass;
+ } else {
+ target.force.y -= 0.0007 * target.mass; //gently fall in on the way down
+ }
+ },
+ antiGrav(target) {
+ target.force.y -= 0.0011 * target.mass;
+ },
+ death(target) {
+ target.death();
+ }
+ },
+ addToWorld() {
+ //needs to be run to put bodies into the world
+ for (let i = 0; i < body.length; i++) {
+ //body[i].collisionFilter.group = 0;
+ if (body[i] !== mech.holdingTarget) {
+ body[i].collisionFilter.category = cat.body;
+ body[i].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet
+ }
+ body[i].classType = "body";
+ World.add(engine.world, body[i]); //add to world
+ }
+ for (let i = 0; i < map.length; i++) {
+ //map[i].collisionFilter.group = 0;
+ map[i].collisionFilter.category = cat.map;
+ map[i].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet;
+ Matter.Body.setStatic(map[i], true); //make static
+ World.add(engine.world, map[i]); //add to world
+ }
+ for (let i = 0; i < cons.length; i++) {
+ World.add(engine.world, cons[i]);
+ }
+ for (let i = 0; i < consBB.length; i++) {
+ World.add(engine.world, consBB[i]);
+ }
+ },
+ //******************************************************************************************************************
+ //******************************************************************************************************************
+ //******************************************************************************************************************
+ //******************************************************************************************************************
testing() {
+ level.custom = () => {
+ level.playerExitCheck();
+ };
+
+ level.setPosToSpawn(0, -750); //normal spawn
+ spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
+ level.exit.x = 6500;
+ level.exit.y = -230;
+
// level.difficultyIncrease(14); //hard mode level 7
spawn.setSpawnList();
spawn.setSpawnList();
@@ -150,13 +328,7 @@ const level = {
color: "rgba(0,255,255,0.1)"
});
- mech.setPosToSpawn(0, -750); //normal spawn
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
- spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
- level.exit.x = 6500;
- level.exit.y = -230;
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
+ // level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
spawn.mapRect(-950, 0, 8200, 800); //ground
spawn.mapRect(-950, -1200, 800, 1400); //left wall
@@ -205,29 +377,18 @@ const level = {
// spawn.randomMob(1600, -500)
},
bosses() {
+ level.custom = () => {
+ level.playerExitCheck();
+ };
+
+ level.setPosToSpawn(0, -750); //normal spawn
+ spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
+ level.exit.x = 6500;
+ level.exit.y = -230;
+
level.defaultZoom = 1500
game.zoomTransition(level.defaultZoom)
-
- // spawn.setSpawnList();
- // spawn.setSpawnList();
- // game.difficulty = 7; //for testing to simulate all possible mobs spawns
- // for (let i = 0; i < game.difficulty; i++) {
- // game.dmgScale += 0.4; //damage done by mobs increases each level
- // b.dmgScale *= 0.9; //damage done by player decreases each level
- // }
-
document.body.style.backgroundColor = "#ddd";
- // game.draw.mapFill = "#444"
- // game.draw.bodyFill = "rgba(140,140,140,0.85)"
- // game.draw.bodyStroke = "#222"
-
- // level.fillBG.push({
- // x: -150,
- // y: -1150,
- // width: 7000,
- // height: 1200,
- // color: "#eee"
- // });
level.fill.push({
x: 6400,
@@ -237,15 +398,6 @@ const level = {
color: "rgba(0,255,255,0.1)"
});
- mech.setPosToSpawn(0, -750); //normal spawn
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
- spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
-
- level.exit.x = 6500;
- level.exit.y = -230;
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
-
spawn.mapRect(-950, 0, 8200, 800); //ground
spawn.mapRect(-950, -1200, 800, 1400); //left wall
spawn.mapRect(-950, -1800, 8200, 800); //roof
@@ -284,23 +436,22 @@ const level = {
}
},
intro() {
- // b.giveGuns(0, 1000)
+ level.custom = () => {
+ level.playerExitCheck();
+ };
+
+ level.setPosToSpawn(460, -100); //normal spawn
+ level.enter.x = -1000000; //hide enter graphic for first level by moving to the far left
+ level.exit.x = 2800;
+ level.exit.y = -335;
+ spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
+
game.zoomScale = 1000 //1400 is normal
level.defaultZoom = 1600
game.zoomTransition(level.defaultZoom, 1)
- mech.setPosToSpawn(460, -100); //normal spawn
- level.enter.x = -1000000; //offscreen
- level.enter.y = -400;
- level.exit.x = 2800;
- level.exit.y = -335;
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
- spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
document.body.style.backgroundColor = "#ddd";
- // game.draw.mapFill = "#444"
- // game.draw.bodyFill = "rgba(140,140,140,0.85)"
- // game.draw.bodyStroke = "#222"
level.fill.push({
x: 2600,
@@ -317,14 +468,6 @@ const level = {
color: "#fff"
});
- // level.fill.push({
- // x: -150,
- // y: -1000,
- // width: 2750,
- // height: 1000,
- // color: "rgba(0,10,30,0.04)"
- // });
-
const lineColor = "#ccc"
level.fillBG.push({
x: 1600,
@@ -397,20 +540,6 @@ const level = {
spawn.mapRect(-95, -1100, 80, 110); //wire source
spawn.mapRect(410, -10, 90, 20); //small platform for player
- // spawn.bodyRect(-35, -50, 50, 50);
- // spawn.bodyRect(-40, -100, 50, 50);
- // spawn.bodyRect(-45, -150, 60, 50);
- // spawn.bodyRect(-40, -200, 50, 50);
- // spawn.bodyRect(5, -50, 40, 50);
- // spawn.bodyRect(10, -100, 60, 50);
- // spawn.bodyRect(-10, -150, 40, 50);
- // spawn.bodyRect(55, -100, 40, 50);
- // spawn.bodyRect(-150, -300, 100, 100);
- // spawn.bodyRect(-150, -200, 100, 100);
- // spawn.bodyRect(-150, -100, 100, 100);
-
- // spawn.bodyRect(1790, -50, 40, 50);
- // spawn.bodyRect(1875, -100, 200, 90);
spawn.bodyRect(2425, -120, 70, 50);
spawn.bodyRect(2400, -100, 100, 60);
spawn.bodyRect(2500, -150, 100, 150); //exit step
@@ -423,38 +552,24 @@ const level = {
// powerUps.spawn(2050, -150, "field", false); //starting gun
powerUps.spawnStartingPowerUps(2300, -150);
- // powerUps.spawn(2300, -150, "gun", false); //starting gun
- // if (game.isEasyMode) {
- // // powerUps.spawn(2050, -150, "mod", false); //starting gun
- // // powerUps.spawn(2050, -150, "mod", false); //starting gun
- // // powerUps.spawn(-100, -150, "ammo", false); //starting gun
- // powerUps.spawn(-100, 0, "heal", false); //starting gun
- // }
-
spawn.wireFoot();
spawn.wireFootLeft();
spawn.wireKnee();
spawn.wireKneeLeft();
spawn.wireHead();
- // spawn.mapRect(1400, -700, 50, 300); //ground
- // spawn.healer(1600, -500)
- // spawn.healer(1600, -500)
- // spawn.healer(1900, -500)
- // spawn.healer(1000, -500)
- // spawn.healer(1000, -400)
},
satellite() {
- // game.zoomScale = 4500 // remove
- level.defaultZoom = 1700 // 4500 // 1400
- game.zoomTransition(level.defaultZoom)
- mech.setPosToSpawn(-50, -50); //normal spawn
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
+ level.custom = () => {
+ level.playerExitCheck();
+ };
+
+ level.setPosToSpawn(-50, -50); //normal spawn
level.exit.x = -100;
level.exit.y = -425;
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
spawn.mapRect(level.exit.x, level.exit.y + 15, 100, 50); //exit bump
+ level.defaultZoom = 1700 // 4500 // 1400
+ game.zoomTransition(level.defaultZoom)
powerUps.spawnStartingPowerUps(4450, -1400);
spawn.debris(1000, 20, 1800, 3); //16 debris per level //but less here because a few mobs die from laser
@@ -462,9 +577,6 @@ const level = {
spawn.debris(3035, -3900, 1500, 3); //16 debris per level
document.body.style.backgroundColor = "#dbdcde";
- // game.draw.mapFill = "#444"
- // game.draw.bodyFill = "rgba(140,140,140,0.85)"
- // game.draw.bodyStroke = "#222"
//spawn start building
spawn.mapRect(-300, -800, 50, 800);
@@ -643,16 +755,18 @@ const level = {
}
},
rooftops() {
+ level.custom = () => {
+ level.playerExitCheck();
+ };
+
level.defaultZoom = 1700
game.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#dcdcde";
- // game.draw.mapFill = "#444"
- // game.draw.bodyFill = "rgba(140,140,140,0.85)"
- // game.draw.bodyStroke = "#222"
+
if (Math.random() < 0.75) {
//normal direction start in top left
- mech.setPosToSpawn(-450, -2060);
+ level.setPosToSpawn(-450, -2060);
level.exit.x = 3600;
level.exit.y = -300;
spawn.mapRect(3600, -285, 100, 50); //ground bump wall
@@ -677,7 +791,7 @@ const level = {
});
} else {
//reverse direction, start in bottom right
- mech.setPosToSpawn(3650, -325);
+ level.setPosToSpawn(3650, -325);
level.exit.x = -550;
level.exit.y = -2030;
spawn.mapRect(-550, -2015, 100, 50); //ground bump wall
@@ -697,10 +811,7 @@ const level = {
color: "rgba(0,0,0,0.1)"
});
}
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
spawn.debris(1650, -1800, 3800, 16); //16 debris per level
powerUps.spawnStartingPowerUps(2450, -1675);
@@ -843,10 +954,12 @@ const level = {
spawn.randomBoss(600, -1575, 0);
spawn.randomBoss(2225, -1325, 0.4);
spawn.randomBoss(4900, -1200, 0);
- //spawn.randomBoss(4850, -1250,0.7);
if (game.difficulty > 3) spawn.randomLevelBoss(3200, -2050);
},
aerie() {
+ level.custom = () => {
+ level.playerExitCheck();
+ };
// game.setZoom(3000);
// game.difficulty = 4; //for testing to simulate possible mobs spawns
level.defaultZoom = 2100
@@ -854,33 +967,24 @@ const level = {
const backwards = (Math.random() < 0.25 && game.difficulty > 8) ? true : false;
if (backwards) {
- mech.setPosToSpawn(4000, -3300); //normal spawn
+ level.setPosToSpawn(4000, -3300); //normal spawn
level.exit.x = -100;
level.exit.y = -1025;
} else {
- mech.setPosToSpawn(-50, -1050); //normal spawn
+ level.setPosToSpawn(-50, -1050); //normal spawn
level.exit.x = 3950;
level.exit.y = -3275;
}
- // mech.setPosToSpawn(2250, -900);
- // game.zoomTransition(1500) //1400 is normal
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
spawn.mapRect(level.exit.x, level.exit.y + 15, 100, 20);
- // spawn.mapRect(3950, -3260, 100, 30);
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
powerUps.spawnStartingPowerUps(1075, -550);
spawn.debris(-250, 50, 1650, 2); //16 debris per level
spawn.debris(2475, 0, 750, 2); //16 debris per level
spawn.debris(3450, 0, 2000, 16); //16 debris per level
spawn.debris(3500, -2350, 1500, 2); //16 debris per level
document.body.style.backgroundColor = "#dcdcde";
- // game.draw.mapFill = "#444"
- // game.draw.bodyFill = "rgba(140,140,140,0.85)"
- // game.draw.bodyStroke = "#222"
//foreground
level.fill.push({
@@ -1046,19 +1150,20 @@ const level = {
//add mini boss, giant hopper? or a black hole that spawns hoppers?
},
skyscrapers() {
+ level.custom = () => {
+ level.playerExitCheck();
+ };
+
+ level.setPosToSpawn(-50, -60); //normal spawn
+ spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
+ level.exit.x = 1500;
+ level.exit.y = -1875;
+
level.defaultZoom = 2000
game.zoomTransition(level.defaultZoom)
- mech.setPosToSpawn(-50, -60); //normal spawn
- //mech.setPosToSpawn(1550, -1200); //spawn left high
- //mech.setPosToSpawn(1800, -2000); //spawn near exit
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
- spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
-
- level.exit.x = 1500;
- level.exit.y = -1875;
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
+ //level.setPosToSpawn(1550, -1200); //spawn left high
+ //level.setPosToSpawn(1800, -2000); //spawn near exit
powerUps.spawnStartingPowerUps(1475, -1175);
spawn.debris(750, -2200, 3700, 16); //16 debris per level
@@ -1203,32 +1308,25 @@ const level = {
if (game.difficulty > 3) spawn.randomLevelBoss(2200, -1300);
},
highrise() {
+ level.custom = () => {
+ level.playerExitCheck();
+ };
+
+ level.setPosToSpawn(0, -700); //normal spawn
+ spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
+ level.exit.x = -4275;
+ level.exit.y = -2805;
+
level.defaultZoom = 1500
game.zoomTransition(level.defaultZoom)
- mech.setPosToSpawn(0, -700); //normal spawn
- //mech.setPosToSpawn(-2000, -1700); // left ledge spawn
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
- spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
-
- level.exit.x = -4275;
- level.exit.y = -2805;
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
powerUps.spawnStartingPowerUps(-2550, -700);
document.body.style.backgroundColor = "#dcdcde" //"#fafcff";
- // game.draw.mapFill = "#444"
- // game.draw.bodyFill = "rgba(140,140,140,0.85)"
- // game.draw.bodyStroke = "#222"
- // spawn.laserZone(-550, -350, 10, 400, 0.3)
- // spawn.deathQuery(-550, -350, 50, 400)
-
- // spawn.debris(-3950, -2575, 1050, 4); //16 debris per level
spawn.debris(-2325, -1825, 2400); //16 debris per level
spawn.debris(-2625, -600, 600, 5); //16 debris per level
spawn.debris(-2000, -60, 1200, 5); //16 debris per level
- // if (!game.difficulty) powerUps.spawn(2450, -1675, "gun", false);
+
//background
level.fillBG.push({
x: -4425,
@@ -1275,20 +1373,13 @@ const level = {
height: 360,
color: "rgba(64,64,64,0.97)"
});
- // level.fill.push({
- // x: -4050,
- // y: -955,
- // width: 625,
- // height: 360,
- // color: "#444"
- // });
+
powerUps.spawn(-4300, -700, "heal");
powerUps.spawn(-4200, -700, "ammo");
powerUps.spawn(-4000, -700, "ammo");
spawn.mapRect(-4450, -1000, 100, 500);
spawn.bodyRect(-3576, -750, 150, 150);
-
//building 1
spawn.bodyRect(-1000, -675, 25, 25);
spawn.mapRect(-2225, 0, 2475, 150);
@@ -1307,10 +1398,8 @@ const level = {
spawn.mapRect(-1125, -1575, 50, 475);
spawn.bodyRect(-1475, -1275, 250, 125);
spawn.bodyRect(-825, -1160, 250, 10);
-
spawn.mapRect(-1650, -1575, 400, 50);
spawn.mapRect(-600, -1150, 850, 175);
-
spawn.mapRect(-1850, -1150, 1050, 175);
spawn.bodyRect(-1907, -1600, 550, 25);
if (game.difficulty < 4) {
@@ -1320,10 +1409,6 @@ const level = {
spawn.bodyRect(-1200, -125, 125, 125);
spawn.bodyRect(-1160, -200, 75, 75);
}
- // spawn.bodyRect(-1100, -125, 150, 125);
-
- // spawn.bodyRect(-1200, -75, 75, 75);
-
//building 2
spawn.mapRect(-4450, -600, 2300, 750);
spawn.mapRect(-2225, -500, 175, 550);
@@ -1338,7 +1423,6 @@ const level = {
spawn.bodyRect(-3415, -1425, 100, 100);
spawn.bodyRect(-3400, -1525, 100, 100);
spawn.bodyRect(-3305, -1425, 100, 100);
-
//building 3
spawn.mapRect(-4450, -1750, 1025, 1000);
spawn.mapRect(-3750, -2000, 175, 275);
@@ -1348,7 +1432,6 @@ const level = {
spawn.bodyRect(-3715, -2050, 50, 50);
spawn.bodyRect(-3570, -1800, 50, 50);
spawn.bodyRect(-2970, -2250, 50, 50);
-
spawn.bodyRect(-3080, -2250, 40, 40);
spawn.bodyRect(-3420, -650, 50, 50);
@@ -1387,31 +1470,23 @@ const level = {
if (game.difficulty > 4) spawn.randomLevelBoss(-3400, -2800);
},
warehouse() {
- level.defaultZoom = 1300
- game.zoomTransition(level.defaultZoom)
+ level.custom = () => {
+ level.playerExitCheck();
+ };
- mech.setPosToSpawn(25, -55); //normal spawn
- //mech.setPosToSpawn(-2000, -1700); // left ledge spawn
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
+ level.setPosToSpawn(25, -55); //normal spawn
level.exit.x = 425;
level.exit.y = -30;
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
- //level.addQueryRegion(-600, -250, 180, 420, "death", [[player]],{});
+
+ level.defaultZoom = 1300
+ game.zoomTransition(level.defaultZoom)
spawn.debris(-2250, 1330, 3000, 6); //16 debris per level
spawn.debris(-3000, -800, 3280, 6); //16 debris per level
spawn.debris(-1400, 410, 2300, 5); //16 debris per level
powerUps.spawnStartingPowerUps(25, 500);
document.body.style.backgroundColor = "#dcdcde" //"#f2f5f3";
- // game.draw.mapFill = "#444"
- // game.draw.bodyFill = "rgba(140,140,140,0.85)"
- // game.draw.bodyStroke = "#222"
- //foreground
- // level.fill.push({ x: -3025, y: 50, width: 4125, height: 1350, color: "rgba(0,0,0,0.05)"});
- // level.fill.push({ x: -1800, y: -500, width: 1975, height: 550, color: "rgba(0,0,0,0.05)"});
- // level.fill.push({ x: -2600, y: -150, width: 700, height: 200, color: "rgba(0,0,0,0.05)"});
//background
const BGColor = "rgba(0,0,0,0.1)";
level.fill.push({
@@ -1457,9 +1532,7 @@ const level = {
spawn.mapRect(-175, -550, 50, 400);
spawn.mapRect(-175, -10, 350, 50);
spawn.mapRect(-25, -20, 100, 50);
- // spawn.mapRect(-175, -275, 350, 25);
- // spawn.mapRect(-175, -250, 25, 75);
- // spawn.bodyRect(-170, -175, 14, 160, 1, spawn.propsFriction); //door to starting room
+
//exit house
spawn.mapRect(300, -10, 350, 50);
spawn.mapRect(-150, -300, 800, 50);
@@ -1506,7 +1579,6 @@ const level = {
spawn.bodyRect(-2700, 1150, 100, 160, 1, spawn.propsSlide); //weight
spawn.bodyRect(-2550, 1150, 200, 100, 1, spawn.propsSlide); //weight
-
spawn.bodyRect(-2775, 1300, 400, 100, 1, spawn.propsHoist); //hoist
cons[cons.length] = Constraint.create({
pointA: {
@@ -1519,7 +1591,6 @@ const level = {
});
//blocks
- //spawn.bodyRect(-155, -150, 10, 140, 1, spawn.propsFriction);
spawn.bodyRect(-165, -150, 30, 35, 1);
spawn.bodyRect(-165, -115, 30, 35, 1);
spawn.bodyRect(-165, -80, 30, 35, 1);
@@ -1527,7 +1598,6 @@ const level = {
spawn.bodyRect(-750, 400, 150, 150, 0.5);
spawn.bodyRect(-400, 1175, 100, 250, 1); //block to get to top path on bottom level
- // spawn.bodyRect(-1450, 737, 75, 103, 0.5); //blocking path
spawn.bodyRect(-2525, -50, 145, 100, 0.5);
spawn.bodyRect(-2325, -300, 150, 100, 0.5);
@@ -1559,9 +1629,6 @@ const level = {
spawn.randomBoss(-125, 275, -0.2);
spawn.randomBoss(-825, 1000, 0.2);
spawn.randomBoss(-1300, -1100, -0.3);
- //spawn.randomBoss(600, -1575, 0);
- //spawn.randomMob(1120, -1200, 0.3);
- //spawn.randomSmallMob(2200, -1775);
if (game.difficulty > 3) {
if (Math.random() < 0.1) {
@@ -1572,12 +1639,16 @@ const level = {
}
},
office() {
+ level.custom = () => {
+ level.playerExitCheck();
+ };
+
level.defaultZoom = 1400
game.zoomTransition(level.defaultZoom)
if (Math.random() < 0.75) {
//normal direction start in top left
- mech.setPosToSpawn(1375, -1550); //normal spawn
+ level.setPosToSpawn(1375, -1550); //normal spawn
level.exit.x = 3250;
level.exit.y = -530;
// spawn.randomSmallMob(3550, -550);
@@ -1590,7 +1661,7 @@ const level = {
});
} else {
//reverse direction, start in bottom right
- mech.setPosToSpawn(3250, -550); //normal spawn
+ level.setPosToSpawn(3250, -550); //normal spawn
level.exit.x = 1375;
level.exit.y = -1530;
// spawn.bodyRect(3655, -650, 40, 150); //door
@@ -1603,16 +1674,10 @@ const level = {
});
}
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 50); //ground bump wall
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
+
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
-
document.body.style.backgroundColor = "#e0e5e0";
- // game.draw.mapFill = "#444"
- // game.draw.bodyFill = "rgba(140,140,140,0.85)"
- // game.draw.bodyStroke = "#222"
// foreground
level.fill.push({
@@ -1651,9 +1716,6 @@ const level = {
color: "rgba(0,0,0,0.1)"
});
- //mech.setPosToSpawn(600, -1200); //normal spawn
- //mech.setPosToSpawn(525, -150); //ground first building
- //mech.setPosToSpawn(3150, -700); //near exit spawn
spawn.debris(-300, -200, 1000, 4); //ground debris //16 debris per level
spawn.debris(3500, -200, 800, 4); //ground debris //16 debris per level
spawn.debris(-300, -650, 1200, 4); //1st floor debris //16 debris per level
@@ -1760,15 +1822,17 @@ const level = {
}
},
stronghold() { // player made level by Francois 👑 from discord
- level.defaultZoom = 1400
+ level.custom = () => {
+ level.playerExitCheck();
+ };
- game.zoomTransition(level.defaultZoom)
- mech.setPosToSpawn(1900, -10); //normal spawn
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y - 10;
+ level.setPosToSpawn(1900, -40); //normal spawn
level.exit.x = -350;
level.exit.y = -1250;
- level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
+
+ level.defaultZoom = 1400
+ game.zoomTransition(level.defaultZoom)
+
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 20); //exit bump
spawn.debris(3800, -1480, 300, 12);
spawn.debris(3600, -1130, 200, 2);
@@ -1992,218 +2056,4 @@ const level = {
if (game.difficulty > 3) spawn.randomLevelBoss(1850, -1400, 1);
},
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- enter: {
- x: 0,
- y: 0,
- draw() {
- ctx.beginPath();
- ctx.moveTo(level.enter.x, level.enter.y + 30);
- ctx.lineTo(level.enter.x, level.enter.y - 80);
- ctx.bezierCurveTo(level.enter.x, level.enter.y - 170, level.enter.x + 100, level.enter.y - 170, level.enter.x + 100, level.enter.y - 80);
- ctx.lineTo(level.enter.x + 100, level.enter.y + 30);
- ctx.lineTo(level.enter.x, level.enter.y + 30);
- ctx.fillStyle = "#ccc";
- ctx.fill();
- }
- },
- exit: {
- x: 0,
- y: 0,
- draw() {
- ctx.beginPath();
- ctx.moveTo(level.exit.x, level.exit.y + 30);
- ctx.lineTo(level.exit.x, level.exit.y - 80);
- ctx.bezierCurveTo(level.exit.x, level.exit.y - 170, level.exit.x + 100, level.exit.y - 170, level.exit.x + 100, level.exit.y - 80);
- ctx.lineTo(level.exit.x + 100, level.exit.y + 30);
- ctx.lineTo(level.exit.x, level.exit.y + 30);
- ctx.fillStyle = "#0ff";
- ctx.fill();
- }
- },
- fillBG: [],
- drawFillBGs() {
- for (let i = 0, len = level.fillBG.length; i < len; ++i) {
- const f = level.fillBG[i];
- ctx.fillStyle = f.color;
- ctx.fillRect(f.x, f.y, f.width, f.height);
- }
- },
- fill: [],
- drawFills() {
- for (let i = 0, len = level.fill.length; i < len; ++i) {
- const f = level.fill[i];
- ctx.fillStyle = f.color;
- ctx.fillRect(f.x, f.y, f.width, f.height);
- }
- },
- zones: [], //zone do actions when player is in a region // to effect everything use a query
- checkZones() {
- for (let i = 0, len = level.zones.length; i < len; ++i) {
- if (
- player.position.x > level.zones[i].x1 &&
- player.position.x < level.zones[i].x2 &&
- player.position.y > level.zones[i].y1 &&
- player.position.y < level.zones[i].y2
- ) {
- level.zoneActions[level.zones[i].action](i);
- break;
- }
- }
- },
- addZone(x, y, width, height, action, info) {
- level.zones[level.zones.length] = {
- x1: x,
- y1: y - 150,
- x2: x + width,
- y2: y + height - 70, //-70 to adjust for player height
- action: action,
- info: info
- };
- },
- zoneActions: {
- fling(i) {
- Matter.Body.setVelocity(player, {
- x: level.zones[i].info.Vx,
- y: level.zones[i].info.Vy
- });
- },
- nextLevel() {
- //enter when player isn't falling
- if (player.velocity.y < 0.1) {
- level.levelsCleared++;
- level.onLevel++; //cycles map to next level
- if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
-
- level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes
- if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1);
- game.clearNow = true; //triggers in game.clearMap to remove all physics bodies and setup for new map
- }
- },
- death() {
- mech.death();
- },
- laser(i) {
- //draw these in game with spawn.background
- mech.damage(level.zones[i].info.dmg);
- },
- slow() {
- Matter.Body.setVelocity(player, {
- x: player.velocity.x * 0.5,
- y: player.velocity.y * 0.5
- });
- }
- },
- queryList: [], //queries do actions on many objects in regions (for only player use a zone)
- checkQuery() {
- let bounds, action, info;
-
- function isInZone(targetArray) {
- let results = Matter.Query.region(targetArray, bounds);
- for (let i = 0, len = results.length; i < len; ++i) {
- level.queryActions[action](results[i], info);
- }
- }
- for (let i = 0, len = level.queryList.length; i < len; ++i) {
- bounds = level.queryList[i].bounds;
- action = level.queryList[i].action;
- info = level.queryList[i].info;
- for (let j = 0, l = level.queryList[i].groups.length; j < l; ++j) {
- isInZone(level.queryList[i].groups[j]);
- }
- }
- },
- //oddly query regions can't get smaller than 50 width?
- addQueryRegion(x, y, width, height, action, groups = [
- [player], body, mob, powerUp, bullet
- ], info) {
- level.queryList[level.queryList.length] = {
- bounds: {
- min: {
- x: x,
- y: y
- },
- max: {
- x: x + width,
- y: y + height
- }
- },
- action: action,
- groups: groups,
- info: info
- };
- },
- queryActions: {
- bounce(target, info) {
- //jerky fling upwards
- Matter.Body.setVelocity(target, {
- x: info.Vx + (Math.random() - 0.5) * 6,
- y: info.Vy
- });
- target.torque = (Math.random() - 0.5) * 2 * target.mass;
- },
- boost(target, yVelocity) {
- // if (target.velocity.y < 0) {
- // mech.undoCrouch();
- // mech.enterAir();
- mech.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
- mech.hardLandCD = 0 // disable hard landing
- if (target.velocity.y > 30) {
- Matter.Body.setVelocity(target, {
- x: target.velocity.x + (Math.random() - 0.5) * 2,
- y: -23 //gentle bounce if coming down super fast
- });
- } else {
- Matter.Body.setVelocity(target, {
- x: target.velocity.x + (Math.random() - 0.5) * 2,
- y: yVelocity
- });
- }
-
- },
- force(target, info) {
- if (target.velocity.y < 0) {
- //gently force up if already on the way up
- target.force.x += info.Vx * target.mass;
- target.force.y += info.Vy * target.mass;
- } else {
- target.force.y -= 0.0007 * target.mass; //gently fall in on the way down
- }
- },
- antiGrav(target) {
- target.force.y -= 0.0011 * target.mass;
- },
- death(target) {
- target.death();
- }
- },
- addToWorld() {
- //needs to be run to put bodies into the world
- for (let i = 0; i < body.length; i++) {
- //body[i].collisionFilter.group = 0;
- body[i].collisionFilter.category = cat.body;
- body[i].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet
- body[i].classType = "body";
- World.add(engine.world, body[i]); //add to world
- }
- for (let i = 0; i < map.length; i++) {
- //map[i].collisionFilter.group = 0;
- map[i].collisionFilter.category = cat.map;
- map[i].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet;
- Matter.Body.setStatic(map[i], true); //make static
- World.add(engine.world, map[i]); //add to world
- }
- for (let i = 0; i < cons.length; i++) {
- World.add(engine.world, cons[i]);
- }
- for (let i = 0; i < consBB.length; i++) {
- World.add(engine.world, consBB[i]);
- }
- }
};
\ No newline at end of file
diff --git a/js/mob.js b/js/mob.js
index 3e07b52..26e0d09 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -1000,12 +1000,14 @@ const mobs = {
}
}
if (Math.random() < mod.isBotSpawner) {
- if (Math.random() < 0.33) {
+ if (Math.random() < 0.25) {
b.nailBot(this.position)
- } else if (Math.random() < 0.5) {
+ } else if (Math.random() < 0.33) {
b.laserBot(this.position)
- } else {
+ } else if (Math.random() < 0.5) {
b.foamBot(this.position)
+ } else {
+ b.boomBot(this.position)
}
// if (mech.energy > 0.33) mech.energy -= 0.33
}
diff --git a/js/mods.js b/js/mods.js
index 5f597a4..215f20a 100644
--- a/js/mods.js
+++ b/js/mods.js
@@ -276,23 +276,6 @@ const mod = {
mod.throwChargeRate = 1
}
},
- {
- name: "laser-bot",
- description: "a bot defends the space around you
uses a short range laser that drains energy",
- maxCount: 9,
- count: 0,
- allowed() {
- return true
- },
- requires: "",
- effect() {
- mod.laserBotCount++;
- b.laserBot();
- },
- remove() {
- mod.laserBotCount = 0;
- }
- },
{
name: "nail-bot",
description: "a bot fires nails at targets in line of sight",
@@ -327,13 +310,64 @@ const mod = {
mod.foamBotCount = 0;
}
},
+ {
+ name: "boom-bot",
+ description: "a bot defends the space around you
ignites an explosion after hitting a mob",
+ maxCount: 9,
+ count: 0,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ mod.boomBotCount++;
+ b.boomBot();
+ },
+ remove() {
+ mod.boomBotCount = 0;
+ }
+ },
+ {
+ name: "laser-bot",
+ description: "a bot defends the space around you
uses a short range laser that drains energy",
+ maxCount: 9,
+ count: 0,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ mod.laserBotCount++;
+ b.laserBot();
+ },
+ remove() {
+ mod.laserBotCount = 0;
+ }
+ },
+ {
+ name: "plasma-bot",
+ description: "a bot uses energy to emit short range plasma
plasma damages and pushes mobs",
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return mech.fieldUpgrades[mech.fieldMode].name === "plasma torch"
+ },
+ requires: "plasma torch",
+ effect() {
+ mod.plasmaBotCount++;
+ b.plasmaBot();
+ },
+ remove() {
+ mod.plasmaBotCount = 0;
+ }
+ },
{
name: "scrap bots",
description: "12% chance to build a bot after killing a mob
the bot only functions until the end of the level",
maxCount: 6,
count: 0,
allowed() {
- return mod.foamBotCount + mod.nailBotCount + mod.laserBotCount > 0
+ return mod.foamBotCount + mod.nailBotCount + mod.laserBotCount + mod.boomBotCount + mod.plasmaBotCount > 0
},
requires: "a bot",
effect() {
@@ -345,19 +379,19 @@ const mod = {
},
{
name: "bot replication",
- description: "duplicate your permanent bots
remove 80% of your ammo",
+ description: "duplicate your permanent bots
remove 90% of your ammo",
maxCount: 1,
count: 0,
// isNonRefundable: true,
allowed() {
- return mod.foamBotCount + mod.nailBotCount + mod.laserBotCount > 2
+ return mod.foamBotCount + mod.nailBotCount + mod.laserBotCount + mod.boomBotCount + mod.plasmaBotCount > 1
},
- requires: "3 or more bots",
+ requires: "2 or more bots",
effect() {
//remove ammo
for (let i = 0, len = b.guns.length; i < len; ++i) {
if (b.guns[i].ammo != Infinity) {
- b.guns[i].ammo = Math.floor(b.guns[i].ammo * 0.2);
+ b.guns[i].ammo = Math.floor(b.guns[i].ammo * 0.1);
}
}
@@ -374,6 +408,14 @@ const mod = {
b.foamBot();
}
mod.foamBotCount *= 2
+ for (let i = 0; i < mod.boomBotCount; i++) {
+ b.boomBot();
+ }
+ mod.boomBotCount *= 2
+ for (let i = 0; i < mod.plasmaBotCount; i++) {
+ b.plasmaBot();
+ }
+ mod.plasmaBotCount *= 2
},
remove() {}
},
@@ -545,7 +587,7 @@ const mod = {
},
{
name: "Pauli exclusion",
- description: `immune to harm for 1 seconds
activates after being harmed from a collision`,
+ description: `immune to harm for 1 second
activates after being harmed from a collision`,
maxCount: 9,
count: 0,
allowed() {
@@ -1400,7 +1442,7 @@ const mod = {
maxCount: 1,
count: 0,
allowed() {
- return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField;
+ return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.isExplodeMob
},
requires: "an explosive gun",
effect: () => {
@@ -2163,6 +2205,8 @@ const mod = {
laserBotCount: null,
nailBotCount: null,
foamBotCount: null,
+ boomBotCount: null,
+ plasmaBotCount: null,
collisionImmuneCycles: null,
blockDmg: null,
isPiezo: null,
diff --git a/js/player.js b/js/player.js
index 67ce6b3..41e2da2 100644
--- a/js/player.js
+++ b/js/player.js
@@ -94,20 +94,6 @@ const mech = {
x: 0,
y: 0
},
- setPosToSpawn(xPos, yPos) {
- this.spawnPos.x = this.pos.x = xPos;
- this.spawnPos.y = this.pos.y = yPos;
- this.transX = this.transSmoothX = canvas.width2 - this.pos.x;
- this.transY = this.transSmoothY = canvas.height2 - this.pos.y;
- this.Vx = this.spawnVel.x;
- this.Vy = this.spawnVel.y;
- player.force.x = 0;
- player.force.y = 0;
- Matter.Body.setPosition(player, this.spawnPos);
- Matter.Body.setVelocity(player, this.spawnVel);
- // mech.transX = -player.position.x
- // mech.transY = player.position.y
- },
Sy: 0, //adds a smoothing effect to vertical only
Vx: 0,
Vy: 0,
@@ -1507,7 +1493,7 @@ const mech = {
} else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed
mech.grabPowerUp();
mech.lookForPickUp();
- const DRAIN = 0.0013
+ const DRAIN = 0.0014
if (mech.energy > DRAIN) {
mech.energy -= DRAIN;
if (mech.energy < 0) {
diff --git a/todo.txt b/todo.txt
index e09fbb8..3491c58 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,10 +1,21 @@
-rerolls drop 60% more often
-mines delay a 1/2 second longer before they arm
-mod: supply chain - doubles your current ammo, requires mod:logistics
-mod: neocognitron - pulse auto aiming
+mod - boomBot: explodes on mobs in close range
+mod - plasma-bot: bot that fires your plasma torch
+(limit 1 bot) (requires plasma torch)
+(you can get 2 plasma-bots with bot replication)
+(you can switch to a new field after getting plasma-bot)
+
************** TODO - n-gon **************
+mob that flashes the player (makes the graphics not update for a couple seconds)
+
+held blocks aren't moving to the next level
+ only issue is setting held block to not collide
+
+mod do 50% more damage in close, but 50% less at a distance
+ code it like mod.isFarAwayDmg
+ have these mods disable each other
+
phase field still isn't fun
rework renormalization mod as well
does phase field need the stealth flag?
@@ -12,9 +23,6 @@ phase field still isn't fun
mod: use the stealth flag from the phase decoherence field
maybe trigger it along with the damage immunity CD
-levels: make a function in the main game loop that runs level specific code
- reset the level function as each new level loads
-
mod: efficient shielding (requires standing wave harmonics field)
lowers force applied when blocking mobs (instead of flinging them away, you push them like with plasma torch), but uses less energy to block mobs
and making it so liquid nitrogen and uranium reactor core have that effect in a radius around the player instead of on contact
@@ -23,9 +31,6 @@ mod: efficient shielding (requires standing wave harmonics field)
mod harmonic shield: slow everything in range around shield (temporal shield)
set max speed?
-need a mod that effects ice status
- mod: ice status effect lasts twice as long
-
mod: bot very slowly follows you and gives you a bonus when it's in range
it moves through walls
effect: damage bonus?, damage reduction?, push away mobs, limit top speed of mobs/blocks/player?