"
- // game.makeTextLog(text, 1);
- }
- }
-
- //toggle testing mode
- if (keys[84]) {
- // 84 = t
- if (this.testing) {
- this.testing = false;
- } else {
- this.testing = true;
- }
- } else if (this.testing) {
- //only in testing mode
-
- if (keys[70]) { //cycle fields with F
- if (mech.fieldMode === mech.fieldUpgrades.length - 1) {
- mech.fieldUpgrades[0].effect()
- } else {
- mech.fieldUpgrades[mech.fieldMode + 1].effect()
- }
- }
- if (keys[71]) { // give all guns with G
- b.giveGuns("all", 1000)
- }
- if (keys[72]) { // power ups with H
- powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "gun");
- powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "gun");
- powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "gun");
- powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "field");
- powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "mod");
- powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "heal");
- powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "heal");
- }
- if (keys[89]) { //cycle fields with F
- if (b.mod === b.mods.length - 1) {
- b.mods[0].effect()
- } else {
- b.mods[b.mod + 1].effect()
- }
- }
- if (keys[82]) { // teleport to mouse with R
- Matter.Body.setPosition(player, this.mouseInGame);
- Matter.Body.setVelocity(player, {
- x: 0,
- y: 0
- });
- }
- }
- },
- zoom: null,
- zoomScale: 1000,
- setZoom(zoomScale = game.zoomScale) { //use in window resize in index.js
- game.zoomScale = zoomScale
- game.zoom = canvas.height / zoomScale; //sets starting zoom scale
- },
- zoomTransition(newZoomScale, step = 2) {
- const isBigger = (newZoomScale - game.zoomScale > 0) ? true : false;
- requestAnimationFrame(zLoop);
- const currentLevel = level.onLevel
-
- function zLoop() {
- if (currentLevel != level.onLevel) return //stop the zoom if player goes to a new level
-
- if (isBigger) {
- game.zoomScale += step
- if (game.zoomScale >= newZoomScale) {
- game.setZoom(newZoomScale);
- return
- }
- } else {
- game.zoomScale -= step
- if (game.zoomScale <= newZoomScale) {
- game.setZoom(newZoomScale);
- return
- }
- }
-
- game.setZoom();
- requestAnimationFrame(zLoop);
- }
- },
- camera() {
- ctx.translate(canvas.width2, canvas.height2); //center
- ctx.scale(game.zoom, game.zoom); //zoom in once centered
- ctx.translate(-canvas.width2 + mech.transX, -canvas.height2 + mech.transY); //translate
- //calculate in game mouse position by undoing the zoom and translations
- game.mouseInGame.x = (game.mouse.x - canvas.width2) / game.zoom + canvas.width2 - mech.transX;
- game.mouseInGame.y = (game.mouse.y - canvas.height2) / game.zoom + canvas.height2 - mech.transY;
- },
- zoomInFactor: 0,
- startZoomIn(time = 180) {
- game.zoom = 0;
- let count = 0;
- requestAnimationFrame(zLoop);
-
- function zLoop() {
- game.zoom += canvas.height / game.zoomScale / time;
- count++;
- if (count < time) {
- requestAnimationFrame(zLoop);
- } else {
- game.setZoom();
- }
- }
- },
- wipe() {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
-
- // ctx.fillStyle = "rgba(255,255,255,1)";
- // ctx.globalCompositeOperation = "difference";
- // ctx.fillRect(0, 0, canvas.width, canvas.height);
- // ctx.globalCompositeOperation = "source-over";
-
- // ctx.globalAlpha = (mech.health < 0.7) ? (mech.health+0.3)*(mech.health+0.3) : 1
- // if (mech.health < 0.7) {
- // ctx.globalAlpha= 0.3 + mech.health
- // ctx.fillStyle = document.body.style.backgroundColor
- // ctx.fillRect(0, 0, canvas.width, canvas.height);
- // ctx.globalAlpha=1;
- // } else {
- // ctx.clearRect(0, 0, canvas.width, canvas.height);
- // }
- //ctx.fillStyle = "rgba(255,255,255," + (1 - Math.sqrt(player.speed)*0.1) + ")";
- //ctx.fillStyle = "rgba(255,255,255,0.4)";
- //ctx.fillRect(0, 0, canvas.width, canvas.height);
- },
- gravity() {
- function addGravity(bodies, magnitude) {
- for (var i = 0; i < bodies.length; i++) {
- bodies[i].force.y += bodies[i].mass * magnitude;
- }
- }
- addGravity(powerUp, game.g);
- addGravity(body, game.g);
- player.force.y += player.mass * mech.gravity;
- },
- reset() {
- b.inventory = []; //removes guns and ammo
- for (let i = 0, len = b.guns.length; i < len; ++i) {
- b.guns[i].have = false;
- if (b.guns[i].ammo != Infinity) b.guns[i].ammo = 0;
- }
- b.activeGun = null;
- game.paused = false;
- engine.timing.timeScale = 1;
- game.dmgScale = 1;
- b.dmgScale = 0.7;
- game.makeGunHUD();
- mech.drop();
- mech.addHealth(1);
- mech.alive = true;
- level.onLevel = 0;
- game.levelsCleared = 0;
- game.clearNow = true;
- document.getElementById("text-log").style.opacity = 0;
- document.getElementById("fade-out").style.opacity = 0;
- document.title = "n-gon";
- if (!mech.fieldMode) mech.fieldUpgrades[0].effect(); //reset to starting field? or let them keep the field
- },
- firstRun: true,
- splashReturn() {
- game.onTitlePage = true;
- // document.getElementById('splash').onclick = 'run(this)';
- document.getElementById("splash").onclick = function () {
- game.startGame();
- };
- document.getElementById("controls").style.display = "inline";
- document.getElementById("splash").style.display = "inline";
- document.getElementById("dmg").style.display = "none";
- document.getElementById("health-bg").style.display = "none";
- document.body.style.cursor = "auto";
- },
- fpsInterval: 0, //set in startGame
- then: null,
- startGame() {
- game.onTitlePage = false;
- document.getElementById("controls").style.display = "none";
- document.getElementById("splash").onclick = null; //removes the onclick effect so the function only runs once
- document.getElementById("splash").style.display = "none"; //hides the element that spawned the function
- document.getElementById("dmg").style.display = "inline";
- document.getElementById("health-bg").style.display = "inline";
-
- // window.onmousedown = function (e) {
- // //mouse up event in set in index.js
-
- // // game.mouseDown = true;
- // if (e.which === 3) {
- // game.mouseDownRight = true;
- // } else {
- // game.mouseDown = true;
- // }
- // // keep this disabled unless building maps
- // // if (!game.mouseDown){
- // // game.getCoords.pos1.x = Math.round(game.mouseInGame.x / 25) * 25;
- // // game.getCoords.pos1.y = Math.round(game.mouseInGame.y / 25) * 25;
- // // }
-
- // // mech.throw();
- // };
-
- document.body.style.cursor = "none";
- if (this.firstRun) {
- mech.spawn(); //spawns the player
- b.setModDefaults(); //doesn't run on reset so that gun mods carry over to new runs
- level.levels = shuffle(level.levels); //shuffles order of maps
- level.levels.unshift("bosses"); //add bosses level to the end of the randomized levels list
- }
- game.reset();
- game.firstRun = false;
-
-
- //setup FPS cap
- game.fpsInterval = 1000 / game.fpsCap;
- game.then = Date.now();
- requestAnimationFrame(cycle); //starts game loop
- },
- clearNow: false,
- clearMap() {
- //if player is holding something this remembers it before it gets deleted
- let holdTarget;
- if (mech.holdingTarget) {
- holdTarget = mech.holdingTarget;
- }
- mech.drop();
- level.fill = [];
- level.fillBG = [];
- level.zones = [];
- level.queryList = [];
- this.drawList = [];
-
- function removeAll(array) {
- for (let i = 0; i < array.length; ++i) Matter.World.remove(engine.world, array[i]);
- }
- removeAll(map);
- map = [];
- removeAll(body);
- body = [];
- removeAll(mob);
- mob = [];
- removeAll(powerUp);
- powerUp = [];
- removeAll(cons);
- cons = [];
- removeAll(consBB);
- consBB = [];
- removeAll(bullet);
- bullet = [];
- // if player was holding something this makes a new copy to hold
- if (holdTarget) {
- len = body.length;
- body[len] = Matter.Bodies.fromVertices(0, 0, holdTarget.vertices, {
- friction: holdTarget.friction,
- frictionAir: holdTarget.frictionAir,
- frictionStatic: holdTarget.frictionStatic
- });
- mech.holdingTarget = body[len];
- }
- },
- getCoords: {
- //used when building maps, outputs a draw rect command to console, only works in testing mode
- pos1: {
- x: 0,
- y: 0
- },
- pos2: {
- x: 0,
- y: 0
- },
- out() {
- if (keys[49]) {
- this.pos1.x = Math.round(game.mouseInGame.x / 25) * 25;
- this.pos1.y = Math.round(game.mouseInGame.y / 25) * 25;
- }
- if (keys[50]) {
- //press 1 in the top left; press 2 in the bottom right;copy command from console
- this.pos2.x = Math.round(game.mouseInGame.x / 25) * 25;
- this.pos2.y = Math.round(game.mouseInGame.y / 25) * 25;
- window.getSelection().removeAllRanges();
- var range = document.createRange();
- range.selectNode(document.getElementById("test"));
- window.getSelection().addRange(range);
- document.execCommand("copy");
- window.getSelection().removeAllRanges();
- console.log(`spawn.mapRect(${this.pos1.x}, ${this.pos1.y}, ${this.pos2.x - this.pos1.x}, ${this.pos2.y - this.pos1.y}); //`);
- }
- }
- },
- fallChecks() {
- // if 4000px deep
- if (mech.pos.y > game.fallHeight) {
- mech.death();
- // if (b.modNonEuclidean) {
- // Matter.Body.setPosition(player, {
- // x: player.position.x,
- // y: player.position.y - 12000
- // });
- // Matter.Body.setVelocity(player, {
- // x: player.velocity.x,
- // y: player.velocity.y * 0
- // });
-
- // mech.pos.x = player.position.x;
- // mech.pos.y = playerBody.position.y - mech.yOff;
-
- // //smoothed mouse look translations
- // const scale = 10;
- // mech.transSmoothX = canvas.width2 - mech.pos.x - (game.mouse.x - canvas.width2) * scale;
- // mech.transSmoothY = canvas.height2 - mech.pos.y - (game.mouse.y - canvas.height2) * scale;
-
- // mech.transX = mech.transSmoothX
- // mech.transY = mech.transSmoothY
-
- // } else {
- // mech.death();
- // }
- }
-
- if (!(mech.cycle % 420)) {
- remove = function (who) {
- let i = who.length;
- while (i--) {
- if (who[i].position.y > game.fallHeight) {
- Matter.World.remove(engine.world, who[i]);
- who.splice(i, 1);
- }
- }
- };
- remove(mob);
- remove(body);
- remove(powerUp);
- }
- },
- testingOutput() {
- ctx.textAlign = "right";
- ctx.fillStyle = "#000";
- let line = 100;
- const x = canvas.width - 5;
- ctx.fillText("T: exit testing mode", 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: spawn power ups", x, line);
- line += 30;
-
- ctx.fillText("cycle: " + game.cycle, x, line);
- line += 20;
- ctx.fillText("player cycle: " + mech.cycle, x, line);
- line += 20;
- ctx.fillText("x: " + player.position.x.toFixed(0), x, line);
- line += 20;
- ctx.fillText("y: " + player.position.y.toFixed(0), x, line);
- line += 20;
- ctx.fillText("Vx: " + mech.Vx.toFixed(2), x, line);
- line += 20;
- ctx.fillText("Vy: " + mech.Vy.toFixed(2), x, line);
- line += 20;
- ctx.fillText("Fx: " + player.force.x.toFixed(3), x, line);
- line += 20;
- ctx.fillText("Fy: " + player.force.y.toFixed(3), x, line);
- line += 20;
- ctx.fillText("yOff: " + mech.yOff.toFixed(1), x, line);
- line += 20;
- ctx.fillText("mass: " + player.mass.toFixed(1), x, line);
- line += 20;
- ctx.fillText("onGround: " + mech.onGround, x, line);
- line += 20;
- ctx.fillText("crouch: " + mech.crouch, x, line);
- line += 20;
- ctx.fillText("isHeadClear: " + mech.isHeadClear, x, line);
- line += 20;
- ctx.fillText("HeadIsSensor: " + headSensor.isSensor, x, line);
- line += 20;
- ctx.fillText("frictionAir: " + player.frictionAir.toFixed(3), x, line);
- line += 20;
- ctx.fillText("stepSize: " + mech.stepSize.toFixed(2), x, line);
- line += 20;
- ctx.fillText("zoom: " + this.zoom.toFixed(4), x, line);
- line += 20;
- ctx.textAlign = "center";
- ctx.fillText(`(${this.mouseInGame.x.toFixed(1)}, ${this.mouseInGame.y.toFixed(1)})`, this.mouse.x, this.mouse.y - 20);
- },
- draw: {
- powerUp() {
- // draw power up
- // ctx.globalAlpha = 0.4 * Math.sin(mech.cycle * 0.15) + 0.6;
- // for (let i = 0, len = powerUp.length; i < len; ++i) {
- // let vertices = powerUp[i].vertices;
- // ctx.beginPath();
- // ctx.moveTo(vertices[0].x, vertices[0].y);
- // for (let j = 1; j < vertices.length; j += 1) {
- // ctx.lineTo(vertices[j].x, vertices[j].y);
- // }
- // ctx.lineTo(vertices[0].x, vertices[0].y);
- // ctx.fillStyle = powerUp[i].color;
- // ctx.fill();
- // }
- // ctx.globalAlpha = 1;
- ctx.globalAlpha = 0.4 * Math.sin(mech.cycle * 0.15) + 0.6;
- for (let i = 0, len = powerUp.length; i < len; ++i) {
- ctx.beginPath();
- ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI);
- ctx.fillStyle = powerUp[i].color;
- ctx.fill();
- }
- ctx.globalAlpha = 1;
- },
- // map: function() {
- // ctx.beginPath();
- // for (let i = 0, len = map.length; i < len; ++i) {
- // let vertices = map[i].vertices;
- // ctx.moveTo(vertices[0].x, vertices[0].y);
- // for (let j = 1; j < vertices.length; j += 1) {
- // ctx.lineTo(vertices[j].x, vertices[j].y);
- // }
- // ctx.lineTo(vertices[0].x, vertices[0].y);
- // }
- // ctx.fillStyle = "#444";
- // ctx.fill();
- // },
- mapPath: null, //holds the path for the map to speed up drawing
- setPaths() {
- //runs at each new level to store the path for the map since the map doesn't change
- this.mapPath = new Path2D();
- for (let i = 0, len = map.length; i < len; ++i) {
- let vertices = map[i].vertices;
- this.mapPath.moveTo(vertices[0].x, vertices[0].y);
- for (let j = 1; j < vertices.length; j += 1) {
- this.mapPath.lineTo(vertices[j].x, vertices[j].y);
- }
- this.mapPath.lineTo(vertices[0].x, vertices[0].y);
- }
- },
- mapFill: "#444",
- bodyFill: "#999",
- bodyStroke: "#222",
- drawMapPath() {
- ctx.fillStyle = this.mapFill;
- ctx.fill(this.mapPath);
- },
-
- seeEdges() {
- const eye = {
- x: mech.pos.x + 20 * Math.cos(mech.angle),
- y: mech.pos.y + 20 * Math.sin(mech.angle)
- };
- //find all vertex nodes in range and in LOS
- findNodes = function (domain, center) {
- let nodes = [];
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
-
- for (let j = 0, len = vertices.length; j < len; j++) {
- //calculate distance to player
- const dx = vertices[j].x - center.x;
- const dy = vertices[j].y - center.y;
- if (dx * dx + dy * dy < 800 * 800 && Matter.Query.ray(domain, center, vertices[j]).length === 0) {
- nodes.push(vertices[j]);
- }
- }
- }
- return nodes;
- };
- let nodes = findNodes(map, eye);
- //sort node list by angle to player
- nodes.sort(function (a, b) {
- //sub artan2 from player loc
- const dx = a.x - eye.x;
- const dy = a.y - eye.y;
- return Math.atan2(dy, dx) - Math.atan2(dy, dx);
- });
- //draw nodes
- ctx.lineWidth = 2;
- ctx.strokeStyle = "#000";
- ctx.beginPath();
- for (let i = 0; i < nodes.length; ++i) {
- ctx.lineTo(nodes[i].x, nodes[i].y);
- }
- ctx.stroke();
- },
- see() {
- const vertexCollision = function (
- v1,
- v1End,
- domain,
- best = {
- x: null,
- y: null,
- dist2: Infinity,
- who: null,
- v1: null,
- v2: null
- }
- ) {
- 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]
- };
- }
- }
- }
- return best;
- };
- const range = 3000;
- ctx.beginPath();
- for (let i = 0; i < Math.PI * 2; i += Math.PI / 2 / 100) {
- const cosAngle = Math.cos(mech.angle + i);
- const sinAngle = Math.sin(mech.angle + i);
-
- const start = {
- x: mech.pos.x + 20 * cosAngle,
- y: mech.pos.y + 20 * sinAngle
- };
- const end = {
- x: mech.pos.x + range * cosAngle,
- y: mech.pos.y + range * sinAngle
- };
- let result = vertexCollision(start, end, map);
- result = vertexCollision(start, end, body, result);
- result = vertexCollision(start, end, mob, result);
-
- if (result.dist2 < range * range) {
- // ctx.arc(result.x, result.y, 2, 0, 2 * Math.PI);
- ctx.lineTo(result.x, result.y);
- } else {
- // ctx.arc(end.x, end.y, 2, 0, 2 * Math.PI);
- ctx.lineTo(end.x, end.y);
- }
- }
- // ctx.lineWidth = 1;
- // ctx.strokeStyle = "#000";
- // ctx.stroke();
- ctx.fillStyle = "rgba(0,0,0,0.3)";
- ctx.fillStyle = "#fff";
- ctx.fill();
- ctx.clip();
- },
- body() {
- ctx.beginPath();
- for (let i = 0, len = body.length; i < len; ++i) {
- let vertices = body[i].vertices;
- ctx.moveTo(vertices[0].x, vertices[0].y);
- for (let j = 1; j < vertices.length; j += 1) {
- ctx.lineTo(vertices[j].x, vertices[j].y);
- }
- ctx.lineTo(vertices[0].x, vertices[0].y);
- }
- ctx.lineWidth = 2;
- ctx.fillStyle = this.bodyFill;
- ctx.fill();
- ctx.strokeStyle = this.bodyStroke;
- ctx.stroke();
- },
- cons() {
- ctx.beginPath();
- for (let i = 0, len = cons.length; i < len; ++i) {
- ctx.moveTo(cons[i].pointA.x, cons[i].pointA.y);
- ctx.lineTo(cons[i].bodyB.position.x, cons[i].bodyB.position.y);
- }
- for (let i = 0, len = consBB.length; i < len; ++i) {
- ctx.moveTo(consBB[i].bodyA.position.x, consBB[i].bodyA.position.y);
- ctx.lineTo(consBB[i].bodyB.position.x, consBB[i].bodyB.position.y);
- }
- ctx.lineWidth = 2;
- // ctx.strokeStyle = "#999";
- ctx.strokeStyle = "rgba(0,0,0,0.15)";
- ctx.stroke();
- },
- wireFrame() {
- ctx.textAlign = "center";
- ctx.textBaseline = "middle";
- ctx.fillStyle = "#999";
- const bodies = Composite.allBodies(engine.world);
- ctx.beginPath();
- for (let i = 0; i < bodies.length; ++i) {
- //ctx.fillText(bodies[i].id,bodies[i].position.x,bodies[i].position.y); //shows the id of every body
- let vertices = bodies[i].vertices;
- ctx.moveTo(vertices[0].x, vertices[0].y);
- for (let j = 1; j < vertices.length; j += 1) {
- ctx.lineTo(vertices[j].x, vertices[j].y);
- }
- ctx.lineTo(vertices[0].x, vertices[0].y);
- }
- ctx.lineWidth = 1;
- ctx.strokeStyle = "#000";
- 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) {
- ctx.rect(
- level.queryList[i].bounds.max.x,
- level.queryList[i].bounds.max.y,
- level.queryList[i].bounds.min.x - level.queryList[i].bounds.max.x,
- level.queryList[i].bounds.min.y - level.queryList[i].bounds.max.y
- );
- }
- ctx.fillStyle = "rgba(0, 0, 255, 0.2)";
- ctx.fill();
- //jump
- ctx.beginPath();
- let bodyDraw = jumpSensor.vertices;
- ctx.moveTo(bodyDraw[0].x, bodyDraw[0].y);
- for (let j = 1; j < bodyDraw.length; ++j) {
- ctx.lineTo(bodyDraw[j].x, bodyDraw[j].y);
- }
- ctx.lineTo(bodyDraw[0].x, bodyDraw[0].y);
- ctx.fillStyle = "rgba(255, 0, 0, 0.3)";
- ctx.fill();
- ctx.strokeStyle = "#000";
- ctx.stroke();
- //main body
- ctx.beginPath();
- bodyDraw = playerBody.vertices;
- ctx.moveTo(bodyDraw[0].x, bodyDraw[0].y);
- for (let j = 1; j < bodyDraw.length; ++j) {
- ctx.lineTo(bodyDraw[j].x, bodyDraw[j].y);
- }
- ctx.lineTo(bodyDraw[0].x, bodyDraw[0].y);
- ctx.fillStyle = "rgba(0, 255, 255, 0.3)";
- ctx.fill();
- ctx.stroke();
- //head
- ctx.beginPath();
- bodyDraw = playerHead.vertices;
- ctx.moveTo(bodyDraw[0].x, bodyDraw[0].y);
- for (let j = 1; j < bodyDraw.length; ++j) {
- ctx.lineTo(bodyDraw[j].x, bodyDraw[j].y);
- }
- ctx.lineTo(bodyDraw[0].x, bodyDraw[0].y);
- ctx.fillStyle = "rgba(255, 255, 0, 0.3)";
- ctx.fill();
- ctx.stroke();
- //head sensor
- ctx.beginPath();
- bodyDraw = headSensor.vertices;
- ctx.moveTo(bodyDraw[0].x, bodyDraw[0].y);
- for (let j = 1; j < bodyDraw.length; ++j) {
- ctx.lineTo(bodyDraw[j].x, bodyDraw[j].y);
- }
- ctx.lineTo(bodyDraw[0].x, bodyDraw[0].y);
- ctx.fillStyle = "rgba(0, 0, 255, 0.3)";
- ctx.fill();
- ctx.stroke();
- }
- },
- checkLineIntersection(v1, v1End, v2, v2End) {
- // if the lines intersect, the result contains the x and y of the intersection (treating the lines as infinite) and booleans for whether line segment 1 or line segment 2 contain the point
- let denominator, a, b, numerator1, numerator2;
- let result = {
- x: null,
- y: null,
- onLine1: false,
- onLine2: false
- };
- denominator = (v2End.y - v2.y) * (v1End.x - v1.x) - (v2End.x - v2.x) * (v1End.y - v1.y);
- if (denominator == 0) {
- return result;
- }
- a = v1.y - v2.y;
- b = v1.x - v2.x;
- numerator1 = (v2End.x - v2.x) * a - (v2End.y - v2.y) * b;
- numerator2 = (v1End.x - v1.x) * a - (v1End.y - v1.y) * b;
- a = numerator1 / denominator;
- b = numerator2 / denominator;
-
- // if we cast these lines infinitely in both directions, they intersect here:
- result.x = v1.x + a * (v1End.x - v1.x);
- result.y = v1.y + a * (v1End.y - v1.y);
- // if line1 is a segment and line2 is infinite, they intersect if:
- if (a > 0 && a < 1) result.onLine1 = true;
- // if line2 is a segment and line1 is infinite, they intersect if:
- if (b > 0 && b < 1) result.onLine2 = true;
- // if line1 and line2 are segments, they intersect if both of the above are true
- return result;
- },
- //was used in level design
- buildingUp(e) {
- if (game.mouseDown) {
- game.getCoords.pos2.x = Math.round(game.mouseInGame.x / 25) * 25;
- game.getCoords.pos2.y = Math.round(game.mouseInGame.y / 25) * 25;
- let out;
-
- //body rect mode
- out = `spawn.mapRect(${game.getCoords.pos1.x}, ${game.getCoords.pos1.y}, ${game.getCoords.pos2.x - game.getCoords.pos1.x}, ${game.getCoords.pos2.y -
- game.getCoords.pos1.y});`;
-
- //mob spawn
- //out = `spawn.randomMob(${game.getCoords.pos1.x}, ${game.getCoords.pos1.y}, 0.3);`
-
- //draw foreground
- //out = `level.fill.push({ x: ${game.getCoords.pos1.x}, y: ${game.getCoords.pos1.y}, width: ${game.getCoords.pos2.x-game.getCoords.pos1.x}, height: ${game.getCoords.pos2.y-game.getCoords.pos1.y}, color: "rgba(0,0,0,0.1)"});`;
-
- //draw background fill
- //out = `level.fillBG.push({ x: ${game.getCoords.pos1.x}, y: ${game.getCoords.pos1.y}, width: ${game.getCoords.pos2.x-game.getCoords.pos1.x}, height: ${game.getCoords.pos2.y-game.getCoords.pos1.y}, color: "#ccc"});`;
-
- //svg mode
- //out = 'rect x="'+game.getCoords.pos1.x+'" y="'+ game.getCoords.pos1.y+'" width="'+(game.getCoords.pos2.x-game.getCoords.pos1.x)+'" height="'+(game.getCoords.pos2.y-game.getCoords.pos1.y)+'"';
-
- console.log(out);
- // document.getElementById("copy-this").innerHTML = out
- //
- // window.getSelection().removeAllRanges();
- // var range = document.createRange();
- // range.selectNode(document.getElementById('copy-this'));
- // window.getSelection().addRange(range);
- // document.execCommand('copy')
- // window.getSelection().removeAllRanges();
- }
- }
-};
\ No newline at end of file
diff --git a/js/index.js b/js/index.js
deleted file mode 100644
index 53b2065..0000000
--- a/js/index.js
+++ /dev/null
@@ -1,233 +0,0 @@
-"use strict";
-/* TODO: *******************************************
-*****************************************************
-
-make power ups keep moving to player if the field is turned off
-
-levels spawn by having the map aspects randomly fly into place
-
-new map with repeating endlessness
- get ideas from Manifold Garden game
- if falling, get teleported above the map
- I tried it, but had trouble getting the camera to adjust
- this can apply to blocks mobs, and power ups as well
-
-Find a diegetic way to see player damage (and or field meter too)
- a health meter, like the field meter above player? (doesn't work with the field meter)
-
-Add field upgrade, and mod to a permanent display
- left side
- separate box below guns
-
-
-cap guns to 3
- can up the drop rate on guns, and lower ammo amount or drop rate
-cap mods to 2
- can up the drop rate a bit
- check if there are any double mod compatibility issues
-cap field to 1
-
-what about no cap to mods?
- mods without caps can't have major negatives
- do I want to support a power ramping game play?
- more upgrades are OK as long as they change game play
- no flat damage, or flat defense buffs
- This makes skipping content a bad idea for the player
- Is that maybe good? No need to nerf content skipping buffs
- content skipping is a cool play style, but not core game play
-
-
-field power up effects
- field produces a whirlpool effect of force around player
- field allows player to hold and throw living mobs
-
-Move mods, to power up object
- mods can be about more than the gun, defensive, traversal mods
-gun mod power ups
- bullet on mob damage effects
- add to the array mob.do new mob behaviors
- add a damage over time
- add a freeze
- fire a few smaller bullets
- killing a mob triggers: a spore bullet
- maybe you could replace the power method with a new one to get this to work
-negative mods for balancing
- self damage on fire
- knock back
- lower fire rate
- smaller bullets
- smaller explosions
- shorter lasting bullets
-
-give mobs more animal-like behaviors
- like rainworld
- give mobs something to do when they don't see player
- explore map
- eat power ups
- drop power up (if killed after eating one)
- mobs some times aren't aggressive
- when low on life or after taking a large hit
- mobs can fight each other
- this might be hard to code
- isolated mobs try to group up.
-
-game mechanics
- mechanics that support the physics engine
- add rope/constraint
- get ideas from game: limbo / inside
- environmental hazards
- laser
- lava
- button / switch
- door
- fizzler
- moving platform
- map zones
- water
- low friction ground
- bouncy ground
-
-track foot positions with velocity better as the player walks/crouch/runs
-
-Boss ideas
- boss grows and spilt, if you don't kill it fast
- sensor that locks you in after you enter the boss room
- boss that eats other mobs and gains stats from them
- chance to spawn on any level (past level 5)
- boss that knows how to shoot (player) bullets that collide with player
- overwrite custom engine collision bullet mob function.
-
-
-
-// collision info:
- category mask
-powerUp: 0x100000 0x100001
-body: 0x010000 0x011111
-player: 0x001000 0x010011
-bullet: 0x000100 0x010011
-mob: 0x000010 0x011111
-mobBullet: 0x000010 0x011101
-mobShield: 0x000010 0x001100
-map: 0x000001 0x111111
-
-
-
-
-*/
-
-//set up canvas
-var canvas = document.getElementById("canvas");
-//using "const" causes problems in safari when an ID shares the same name.
-const ctx = canvas.getContext("2d");
-document.body.style.backgroundColor = "#fff";
-
-//disable pop up menu on right click
-document.oncontextmenu = function () {
- return false;
-}
-
-function setupCanvas() {
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- canvas.width2 = canvas.width / 2; //precalculated because I use this often (in mouse look)
- canvas.height2 = canvas.height / 2;
- canvas.diagonal = Math.sqrt(canvas.width2 * canvas.width2 + canvas.height2 * canvas.height2);
- ctx.font = "15px Arial";
- ctx.lineJoin = "round";
- ctx.lineCap = "round";
- // ctx.lineCap='square';
- game.setZoom();
-}
-setupCanvas();
-window.onresize = () => {
- setupCanvas();
-};
-
-//mouse move input
-document.body.addEventListener("mousemove", (e) => {
- game.mouse.x = e.clientX;
- game.mouse.y = e.clientY;
-});
-
-document.body.addEventListener("mouseup", (e) => {
- // game.buildingUp(e); //uncomment when building levels
- game.mouseDown = false;
- // console.log(e)
- if (e.which === 3) {
- game.mouseDownRight = false;
- } else {
- game.mouseDown = false;
- }
-});
-
-document.body.addEventListener("mousedown", (e) => {
- if (e.which === 3) {
- game.mouseDownRight = true;
- } else {
- game.mouseDown = true;
- }
-});
-
-//keyboard input
-const keys = [];
-document.body.addEventListener("keydown", (e) => {
- keys[e.keyCode] = true;
- game.keyPress();
-});
-
-document.body.addEventListener("keyup", (e) => {
- keys[e.keyCode] = false;
-});
-
-document.body.addEventListener("wheel", (e) => {
- if (e.deltaY > 0) {
- game.nextGun();
- } else {
- game.previousGun();
- }
-}, {
- passive: true
-});
-
-
-// function playSound(id) {
-// //play sound
-// if (false) {
-// //sounds are turned off for now
-// // if (document.getElementById(id)) {
-// var sound = document.getElementById(id); //setup audio
-// sound.currentTime = 0; //reset position of playback to zero //sound.load();
-// sound.play();
-// }
-// }
-
-function shuffle(array) {
- var currentIndex = array.length,
- temporaryValue,
- randomIndex;
- // While there remain elements to shuffle...
- while (0 !== currentIndex) {
- // Pick a remaining element...
- randomIndex = Math.floor(Math.random() * currentIndex);
- currentIndex -= 1;
- // And swap it with the current element.
- temporaryValue = array[currentIndex];
- array[currentIndex] = array[randomIndex];
- array[randomIndex] = temporaryValue;
- }
- return array;
-}
-
-
-
-//main loop ************************************************************
-//**********************************************************************
-function cycle() {
- if (!game.paused) requestAnimationFrame(cycle);
- const now = Date.now();
- const elapsed = now - game.then; // calc elapsed time since last loop
- if (elapsed > game.fpsInterval) { // if enough time has elapsed, draw the next frame
- game.then = now - (elapsed % game.fpsInterval); // Get ready for next frame by setting then=now. Also, adjust for fpsInterval not being multiple of 16.67
- game.loop();
- }
-}
\ No newline at end of file
diff --git a/js/level.js b/js/level.js
deleted file mode 100644
index 1a62c4b..0000000
--- a/js/level.js
+++ /dev/null
@@ -1,1593 +0,0 @@
-//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"],
- onLevel: 0,
- start() {
- if (game.levelsCleared === 0) {
- // game.levelsCleared = 16; //for testing to simulate possible mobs spawns
- // b.giveGuns("all", 1000)
- // b.giveGuns(3) // set a starting gun for testing
- // mech.fieldUpgrades[2].effect(); //give a field power up for testing
- // b.mods[7].effect(); //give specific mod
-
- this.intro(); //starting level
- // this.testingMap();
- // this.bosses();
- // this.aerie();
- // this.rooftops();
- // this.warehouse();
- // this.highrise();
- // this.office();
- } else {
- spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
- level[level.levels[level.onLevel]](); //picks the current map from the the levels array
- level.levelAnnounce();
- }
- game.setZoom();
- level.addToWorld(); //add bodies to game engine
- game.draw.setPaths();
- },
- difficultyIncrease() {
- game.dmgScale += 0.35; //damage done by mobs increases each level
- b.dmgScale *= 0.92; //damage done by player decreases each level
- game.accelScale *= 1.05 //mob acceleration increases each level
- game.lookFreqScale *= 0.95 //mob cycles between looks decreases each level
- game.CDScale *= 0.95 //mob CD time decreases each level
- },
- //******************************************************************************************************************
- //******************************************************************************************************************
- testingMap() {
- //start with all guns
- b.giveGuns("all", 1000)
- game.zoomScale = 1400 //1400 is normal
- spawn.setSpawnList();
- game.levelsCleared = 3; //for testing to simulate all possible mobs spawns
- for (let i = 0; i < game.levelsCleared; i++) {
- level.difficultyIncrease()
- }
- mech.setPosToSpawn(-75, -60); //normal spawn
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
-
- level.exit.x = 3500;
- level.exit.y = -870;
- this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
- document.body.style.backgroundColor = "#dcdcde";
-
-
-
-
- // this.addZone(250, -1000, 500, 1500, "laser");
- //spawn.debris(0, -900, 4500, 10); //15 debris per level
- // setTimeout(function() {
- // document.body.style.backgroundColor = "#eee";
- // }, 1);
- // this.addQueryRegion(550, -25, 100, 50, "bounce", { Vx: 0, Vy: -25 });
- // level.fillBG.push({ x: 550, y: -25, width: 100, height: 50, color: "#ff0" });
-
- spawn.mapRect(-1200, 0, 2200, 300); //left ground
- spawn.mapRect(3500, -860, 100, 50); //ground bump wall
- spawn.mapVertex(1250, 0, "0 0 0 300 -500 600 -500 300");
- spawn.mapRect(1500, -300, 2000, 300); //upper ground
- spawn.mapVertex(3750, 0, "0 600 0 300 -500 0 -500 300");
- spawn.mapRect(4000, 0, 1000, 300); //right lower ground
- spawn.mapRect(2200, -600, 600, 50); //center platform
- spawn.mapRect(1300, -850, 700, 50); //center platform
- spawn.mapRect(3000, -850, 700, 50); //center platform
- // spawn.mapRect(0, -2000, 3000, 50); //center platform
- spawn.spawnBuilding(-200, -250, 275, 240, false, true, "left"); //far left; player spawns in side
- // spawn.boost(350, 0, -1000);
- // for (let i = 0; i < 10; i++) {
- // powerUps.spawn(950, -425, "gun", false);
- // }
- // for (let i = 0; i < 5; i++) {
- // powerUps.spawn(2500 + i * 20, -1300, "gun", false);
- // powerUps.spawn(2500 + i * 20, -1100, "ammo", false);
- // }
- // spawn.nodeBoss(-500, -600, spawn.allowedBossList[Math.floor(Math.random() * spawn.allowedBossList.length)]);
- // spawn.lineBoss(-500, -600, spawn.allowedBossList[Math.floor(Math.random() * spawn.allowedBossList.length)]);
- // spawn.bodyRect(-135, -50, 50, 50);
- // spawn.bodyRect(-140, -100, 50, 50);
- // spawn.bodyRect(-145, -150, 60, 50);
- // spawn.bodyRect(-140, -200, 50, 50);
- // spawn.bodyRect(-95, -50, 40, 50);
- // spawn.bodyRect(-90, -100, 60, 50);
- // spawn.bodyRect(300, -150, 140, 50);
- // spawn.bodyRect(300, -150, 30, 30);
- // spawn.bodyRect(300, -150, 20, 20);
- // spawn.bodyRect(300, -150, 40, 100);
- // spawn.bodyRect(300, -150, 40, 90);
- // spawn.bodyRect(300, -150, 30, 60);
- // spawn.bodyRect(300, -150, 40, 70);
- // spawn.bodyRect(300, -150, 40, 60);
- // spawn.bodyRect(300, -150, 20, 20);
- // spawn.bodyRect(500, -150, 140, 110);
- // spawn.bodyRect(600, -150, 140, 100);
- // spawn.bodyRect(400, -150, 140, 160);
- // spawn.bodyRect(500, -150, 110, 110);
- // powerUps.spawn(340, -400, "heal", false);
- // powerUps.spawn(370, -400, "gun", false);
- // powerUps.spawn(400, -400, "field", false, 2);
- // powerUps.spawn(420, -400, "ammo", false);
- powerUps.spawn(450, -400, "mod", false, 6);
- // powerUps.spawn(450, -400, "mod", false);
- // spawn.bodyRect(-45, -100, 40, 50);
- // spawn.focuser(800, -1150);
- // spawn.groupBoss(-600, -550);
- spawn.starter(800, -150, 100);
- // spawn.grower(800, -250);
- // spawn.blinker(800, -250, 40);
- // spawn.groupBoss(900, -1070);
- // for (let i = 0; i < 20; i++) {
- // spawn.randomBoss(-100, -1470);
- // }
- },
- bosses() {
- level.defaultZoom = 1500
- game.zoomTransition(level.defaultZoom)
-
- // spawn.setSpawnList();
- // spawn.setSpawnList();
- // game.levelsCleared = 7; //for testing to simulate all possible mobs spawns
- // for (let i = 0; i < game.levelsCleared; 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";
-
- // level.fillBG.push({
- // x: -150,
- // y: -1150,
- // width: 7000,
- // height: 1200,
- // color: "#eee"
- // });
-
- level.fill.push({
- x: 6400,
- y: -550,
- width: 300,
- height: 350,
- 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;
- level.exit.x = 6500;
- level.exit.y = -230;
- this.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
- spawn.mapRect(-250, -700, 1000, 900); // shelf
- spawn.mapRect(-250, -1200, 1000, 250); // shelf roof
- powerUps.spawnStartingPowerUps(600, -800);
-
- function blockDoor(x, y, blockSize = 58) {
- spawn.mapRect(x, y - 290, 40, 60); // door lip
- spawn.mapRect(x, y, 40, 50); // door lip
- for (let i = 0; i < 4; ++i) {
- spawn.bodyRect(x + 5, y - 260 + i * blockSize, 30, blockSize);
- }
- }
- blockDoor(710, -710);
-
- spawn[spawn.pickList[0]](1500, -200, 100 + game.levelsCleared * 8);
- spawn.mapRect(2500, -1200, 200, 750); //right wall
- blockDoor(2585, -210)
- spawn.mapRect(2500, -200, 200, 300); //right wall
-
- spawn.nodeBoss(3500, -200, spawn.allowedBossList[Math.floor(Math.random() * spawn.allowedBossList.length)]);
- spawn.mapRect(4500, -1200, 200, 750); //right wall
- blockDoor(4585, -210)
- spawn.mapRect(4500, -200, 200, 300); //right wall
-
- spawn.lineBoss(5000, -200, spawn.allowedBossList[Math.floor(Math.random() * spawn.allowedBossList.length)]);
- spawn.mapRect(6400, -1200, 400, 750); //right wall
- spawn.mapRect(6400, -200, 400, 300); //right wall
- spawn.mapRect(6700, -1800, 800, 2600); //right wall
- spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
-
- for (let i = 0; i < 5; ++i) {
- if (game.levelsCleared * Math.random() > 3 * i) {
- spawn.randomBoss(2000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
- }
- if (game.levelsCleared * Math.random() > 2.6 * i) {
- spawn.randomBoss(3500 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
- }
- if (game.levelsCleared * Math.random() > 2.4 * i) {
- spawn.randomBoss(5000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
- }
- }
- },
- //empty map for testing mobs
- intro() {
- // b.giveGuns(0, 1000)
- 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;
- this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
- document.body.style.backgroundColor = "#fff";
- level.fillBG.push({
- x: 2600,
- y: -600,
- width: 400,
- height: 500,
- color: "#edf9f9"
- });
-
- level.fillBG.push({
- x: 1600,
- y: -500,
- width: 100,
- height: 100,
- color: "#eee"
- });
-
- level.fillBG.push({
- x: -55,
- y: -283,
- width: 12,
- height: 100,
- color: "#eee"
- });
-
- //faster way to draw a wire
- function wallWire(x, y, width, height, front = false) {
- if (front) {
- level.fill.push({
- x: x,
- y: y,
- width: width,
- height: height,
- color: "#aaa"
- });
- } else {
- level.fillBG.push({
- x: x,
- y: y,
- width: width,
- height: height,
- color: "#eee"
- });
- }
- }
-
- for (let i = 0; i < 3; i++) {
- wallWire(100 - 10 * i, -1050 - 10 * i, 5, 800);
- wallWire(100 - 10 * i, -255 - 10 * i, -300, 5);
- }
- for (let i = 0; i < 5; i++) {
- wallWire(1000 + 10 * i, -1050 - 10 * i, 5, 600);
- wallWire(1000 + 10 * i, -450 - 10 * i, 150, 5);
- wallWire(1150 + 10 * i, -450 - 10 * i, 5, 500);
- }
- for (let i = 0; i < 3; i++) {
- wallWire(2650 - 10 * i, -700 - 10 * i, -300, 5);
- wallWire(2350 - 10 * i, -700 - 10 * i, 5, 800);
- }
- for (let i = 0; i < 5; i++) {
- wallWire(1625 + 10 * i, -1050, 5, 1200);
- }
- for (let i = 0; i < 4; i++) {
- wallWire(1650, -470 + i * 10, 670 - i * 10, 5);
- wallWire(1650 + 670 - i * 10, -470 + i * 10, 5, 600);
- }
- for (let i = 0; i < 3; i++) {
- wallWire(-200 - i * 10, -245 + i * 10, 1340, 5);
- wallWire(1140 - i * 10, -245 + i * 10, 5, 300);
- wallWire(-200 - i * 10, -215 + i * 10, 660, 5);
- wallWire(460 - i * 10, -215 + i * 10, 5, 300);
- }
- spawn.mapRect(-250, 0, 3600, 1800); //ground
- spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
- spawn.mapRect(3000, -2800, 2600, 4600); //right wall
- spawn.mapRect(-250, -2800, 3600, 1800); //roof
- spawn.mapRect(2600, -300, 500, 500); //exit shelf
- spawn.mapRect(2600, -1200, 500, 600); //exit roof
- spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
- 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
-
- mech.health = 0.25;
- mech.displayHealth();
- powerUps.spawn(-100, 0, "heal", false); //starting gun
- powerUps.spawn(1900, -150, "heal", false); //starting gun
- powerUps.spawn(2050, -150, "heal", false); //starting gun
- // powerUps.spawn(2050, -150, "field", false); //starting gun
- powerUps.spawn(2300, -150, "gun", 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)
- },
- rooftops() {
- level.defaultZoom = 1700
- game.zoomTransition(level.defaultZoom)
- document.body.style.backgroundColor = "#dcdcde";
-
- if (Math.random() < 0.75) {
- //normal direction start in top left
- mech.setPosToSpawn(-450, -2050);
- level.exit.x = 3600;
- level.exit.y = -300;
- spawn.mapRect(3600, -285, 100, 50); //ground bump wall
- //mobs that spawn in exit room
- spawn.randomSmallMob(4100, -100);
- spawn.randomSmallMob(4600, -100);
- spawn.randomMob(3765, -450, 0.3);
- level.fill.push({
- x: -650,
- y: -2300,
- width: 450,
- height: 300,
- color: "rgba(0,0,0,0.15)"
- });
- } else {
- //reverse direction, start in bottom right
- mech.setPosToSpawn(3650, -310);
- level.exit.x = -550;
- level.exit.y = -2030;
- spawn.mapRect(-550, -2015, 100, 50); //ground bump wall
- spawn.boost(4950, 0, 1600);
- level.fillBG.push({
- x: -650,
- y: -2300,
- width: 450,
- height: 300,
- color: "#d4f4f4"
- });
- }
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
- this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
-
- spawn.debris(1650, -1800, 3800, 20); //20 debris per level
- powerUps.spawnStartingPowerUps(2450, -1675);
-
- //foreground
-
- level.fill.push({
- x: 3450,
- y: -1250,
- width: 1100,
- height: 1250,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 4550,
- y: -725,
- width: 900,
- height: 725,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 3400,
- y: 100,
- width: 2150,
- height: 900,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: -700,
- y: -1950,
- width: 2100,
- height: 2950,
- color: "rgba(0,0,0,0.1)"
- });
-
- level.fill.push({
- x: 1950,
- y: -1950,
- width: 600,
- height: 350,
- color: "rgba(0,0,0,0.1)"
- });
-
- level.fill.push({
- x: 1950,
- y: -1550,
- width: 1025,
- height: 550,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 1600,
- y: -900,
- width: 1650,
- height: 1900,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 3450,
- y: -1550,
- width: 350,
- height: 300,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 700,
- y: -2225,
- width: 700,
- height: 225,
- color: "rgba(0,0,0,0.1)"
- });
-
- //spawn.mapRect(-700, 0, 6250, 100); //ground
- spawn.mapRect(3400, 0, 2150, 100); //ground
- spawn.mapRect(-700, -2000, 2100, 50); //Top left ledge
- spawn.bodyRect(1300, -2125, 50, 125, 0.8);
- spawn.bodyRect(1307, -2225, 50, 100, 0.8);
- spawn.mapRect(-700, -2350, 50, 400); //far left starting left wall
- spawn.mapRect(-700, -2010, 500, 50); //far left starting ground
- spawn.mapRect(-700, -2350, 500, 50); //far left starting ceiling
- spawn.mapRect(-250, -2350, 50, 200); //far left starting right part of wall
- spawn.bodyRect(-240, -2150, 30, 36); //door to starting room
- spawn.bodyRect(-240, -2115, 30, 36); //door to starting room
- spawn.bodyRect(-240, -2080, 30, 35); //door to starting room
- spawn.bodyRect(-240, -2045, 30, 35); //door to starting room
- spawn.mapRect(1950, -2000, 600, 50);
- spawn.bodyRect(200, -2150, 200, 220, 0.8);
- spawn.mapRect(700, -2275, 700, 50);
- spawn.bodyRect(1050, -2350, 30, 30, 0.8);
- spawn.boost(1800, -1000, 1200);
- spawn.bodyRect(1625, -1100, 100, 75);
- spawn.bodyRect(1350, -1025, 400, 25); // ground plank
- spawn.mapRect(-725, -1000, 2150, 100); //lower left ledge
- spawn.bodyRect(350, -1100, 200, 100, 0.8);
- spawn.bodyRect(370, -1200, 100, 100, 0.8);
- spawn.bodyRect(360, -1300, 100, 100, 0.8);
- spawn.bodyRect(950, -1050, 300, 50, 0.8);
- spawn.bodyRect(-600, -1250, 400, 250, 0.8);
- spawn.mapRect(1575, -1000, 1700, 100); //middle ledge
- spawn.mapRect(3400, -1000, 75, 25);
- spawn.bodyRect(2600, -1950, 100, 250, 0.8);
- spawn.bodyRect(2700, -1125, 125, 125, 0.8);
- spawn.bodyRect(2710, -1250, 125, 125, 0.8);
- spawn.bodyRect(2705, -1350, 75, 100, 0.8);
- spawn.mapRect(3450, -1600, 350, 50);
- spawn.mapRect(1950, -1600, 1025, 50);
- spawn.bodyRect(3100, -1015, 375, 15);
- spawn.bodyRect(3500, -850, 75, 125, 0.8);
- spawn.mapRect(3450, -1000, 50, 580); //left building wall
- spawn.bodyRect(3460, -420, 30, 144);
- spawn.mapRect(5450, -775, 100, 875); //right building wall
- spawn.bodyRect(4850, -750, 300, 25, 0.8);
- spawn.bodyRect(3925, -1400, 100, 150, 0.8);
- spawn.mapRect(3450, -1250, 1100, 50);
- spawn.mapRect(3450, -1225, 50, 75);
- spawn.mapRect(4500, -1225, 50, 390);
- spawn.mapRect(3450, -725, 1500, 50);
- spawn.mapRect(5100, -725, 400, 50);
- spawn.mapRect(4500, -735, 50, 635);
- spawn.bodyRect(4510, -100, 30, 100, 0.8);
- spawn.mapRect(4500, -885, 100, 50);
- spawn.spawnStairs(3800, 0, 3, 150, 206); //stairs top exit
- spawn.mapRect(3400, -275, 450, 275); //exit platform
-
- spawn.randomSmallMob(2200, -1775);
- spawn.randomSmallMob(4000, -825);
- spawn.randomSmallMob(-350, -2400);
- spawn.randomMob(4250, -1350, 0.8);
- spawn.randomMob(2550, -1350, 0.8);
- spawn.randomMob(1225, -2400, 0.3);
- spawn.randomMob(1120, -1200, 0.3);
- spawn.randomMob(3000, -1150, 0.2);
- spawn.randomMob(3200, -1150, 0.3);
- spawn.randomMob(3300, -1750, 0.3);
- spawn.randomMob(3650, -1350, 0.3);
- spawn.randomMob(3600, -1800, 0.1);
- spawn.randomMob(5200, -100, 0.3);
- spawn.randomMob(5275, -900, 0.2);
- spawn.randomMob(900, -2125, 0.3);
- spawn.randomBoss(600, -1575, 0);
- spawn.randomBoss(2225, -1325, 0.4);
- spawn.randomBoss(4900, -1200, 0);
- //spawn.randomBoss(4850, -1250,0.7);
- if (game.levelsCleared > 4) spawn.bomber(2500, -2400, 100);
- },
- aerie() {
- // game.setZoom(3000);
- // game.levelsCleared = 4; //for testing to simulate possible mobs spawns
- level.defaultZoom = 2100
- game.zoomTransition(level.defaultZoom)
-
- const backwards = (Math.random() < 0.75) ? false : true;
- if (backwards) {
- mech.setPosToSpawn(4000, -3300); //normal spawn
- level.exit.x = -100;
- level.exit.y = -1025;
- } else {
- mech.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;
- this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
- powerUps.spawnStartingPowerUps(1075, -550);
- spawn.debris(-250, 50, 1650, 2); //20 debris per level
- spawn.debris(2475, 0, 750, 2); //20 debris per level
- spawn.debris(3450, 0, 2000, 20); //20 debris per level
- spawn.debris(3500, -2350, 1500, 2); //20 debris per level
- document.body.style.backgroundColor = "#dcdcde";
-
- //foreground
- level.fill.push({
- x: -100,
- y: -1000,
- width: 1450,
- height: 1400,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 2000,
- y: -1110,
- width: 450,
- height: 1550,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 3700,
- y: -3150,
- width: 1100,
- height: 900,
- color: "rgba(0,0,0,0.1)"
- });
-
- //background
- level.fillBG.push({
- x: 4200,
- y: -2250,
- width: 100,
- height: 2600,
- color: "#c7c7ca"
- });
- if (!backwards) {
- level.fillBG.push({
- x: 3750,
- y: -3650,
- width: 550,
- height: 400,
- color: "#d4f4f4"
- });
- level.fill.push({
- x: -275,
- y: -1275,
- width: 425,
- height: 300,
- color: "rgba(0,0,0,0.1)"
- });
- } else {
- level.fill.push({
- x: 3750,
- y: -3650,
- width: 550,
- height: 400,
- color: "rgba(0,0,0,0.1)"
- });
- level.fillBG.push({
- x: -275,
- y: -1275,
- width: 425,
- height: 300,
- color: "#d4f4f4"
- });
- }
-
- // starting room
- spawn.mapRect(-100, -1010, 100, 30);
- spawn.mapRect(-300, -1000, 600, 50);
- spawn.mapRect(-300, -1300, 450, 50);
- spawn.mapRect(-300, -1300, 50, 350);
- if (!backwards) spawn.bodyRect(100, -1250, 200, 240); //remove on backwards
- //left building
- spawn.mapRect(-100, -975, 100, 975);
- spawn.mapRect(-500, 100, 1950, 400);
- spawn.boost(-425, 100, 1400);
- spawn.mapRect(600, -1000, 750, 50);
- spawn.mapRect(900, -500, 550, 50);
- spawn.mapRect(1250, -975, 100, 375);
- spawn.bodyRect(1250, -600, 100, 100, 0.7);
- spawn.mapRect(1250, -450, 100, 450);
- if (!backwards) spawn.bodyRect(1250, -1225, 100, 200); //remove on backwards
- if (!backwards) spawn.bodyRect(1200, -1025, 350, 25); //remove on backwards
- //middle super tower
- if (backwards) {
- spawn.bodyRect(2000, -800, 700, 35);
- } else {
- spawn.bodyRect(1750, -800, 700, 35);
- }
- spawn.mapVertex(2225, -2100, "0 0 450 0 300 -2500 150 -2500")
- spawn.mapRect(2000, -700, 450, 300);
- spawn.bodyRect(2360, -450, 100, 300, 0.6);
- spawn.mapRect(2000, -75, 450, 275);
- spawn.bodyRect(2450, 150, 150, 150, 0.4);
- spawn.mapRect(1550, 300, 4600, 200); //ground
- //floor below right tall tower
- spawn.bodyRect(3000, 50, 150, 250, 0.9);
- spawn.bodyRect(4500, -500, 300, 250, 0.7);
- spawn.bodyRect(3500, -100, 100, 150, 0.7);
- spawn.bodyRect(4200, -500, 110, 30, 0.7);
- spawn.bodyRect(3800, -500, 150, 130, 0.7);
- spawn.bodyRect(4000, 50, 200, 150, 0.9);
- spawn.bodyRect(4500, 50, 300, 200, 0.9);
- spawn.bodyRect(4200, -350, 200, 50, 0.9);
- spawn.bodyRect(4700, -350, 50, 200, 0.9);
- spawn.bodyRect(4900, -100, 300, 300, 0.7);
- spawn.boost(5350, 275, 2850);
- spawn.mapRect(6050, -700, 600, 1200);
- //right tall tower
- spawn.mapRect(3700, -3200, 100, 800);
- spawn.mapRect(4700, -2910, 100, 510);
- spawn.mapRect(3700, -2600, 300, 50);
- spawn.mapRect(4100, -2900, 900, 50);
- spawn.mapRect(3450, -2300, 1650, 100);
- //exit room on top of tower
- spawn.mapRect(3700, -3700, 600, 50);
- spawn.mapRect(3700, -3700, 50, 500);
- spawn.mapRect(4250, -3700, 50, 300);
- spawn.mapRect(3700, -3250, 1100, 100);
- spawn.mapRect(3950, -3260, 100, 30);
-
- spawn.randomSmallMob(-225, 25);
- spawn.randomSmallMob(1000, -1100);
- spawn.randomSmallMob(4000, -250);
- spawn.randomSmallMob(4450, -3000);
- spawn.randomSmallMob(5600, 100);
- spawn.randomMob(4275, -2600, 0.8);
- spawn.randomMob(1050, -700, 0.8)
- spawn.randomMob(6050, -850, 0.7);
- spawn.randomMob(2150, -300, 0.6)
- spawn.randomMob(3900, -2700, 0.8);
- spawn.randomMob(3600, -500, 0.8);
- spawn.randomMob(3400, -200, 0.8);
- spawn.randomMob(1650, -1300, 0.7)
- spawn.randomMob(-4100, -50, 0.7);
- spawn.randomMob(4100, -50, 0.5);
- spawn.randomMob(1700, -50, 0.3)
- spawn.randomMob(2350, -900, 0.3)
- spawn.randomMob(4700, -150, 0.2);
- spawn.randomBoss(350, -500, 1)
- spawn.randomBoss(4000, -350, 0.6);
- spawn.randomBoss(2750, -550, 0.1);
- if (game.levelsCleared > 2) spawn.suckerBoss(4500, -400);
-
- //add mini boss, giant hopper? or a black hole that spawns hoppers?
- },
- skyscrapers() {
- level.defaultZoom = 2000
- game.zoomTransition(level.defaultZoom)
-
- mech.setPosToSpawn(-50, -50); //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;
- level.exit.x = 1500;
- level.exit.y = -1875;
- this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
-
- powerUps.spawnStartingPowerUps(1475, -1175);
- spawn.debris(0, -2200, 4500, 20); //20 debris per level
- document.body.style.backgroundColor = "#dcdcde";
-
- //foreground
- level.fill.push({
- x: 2500,
- y: -1100,
- width: 450,
- height: 250,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 2400,
- y: -550,
- width: 600,
- height: 150,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 2550,
- y: -1650,
- width: 250,
- height: 200,
- color: "rgba(0,0,0,0.1)"
- });
- //level.fill.push({ x: 1350, y: -2100, width: 400, height: 250, color: "rgba(0,255,255,0.1)" });
- level.fill.push({
- x: 700,
- y: -110,
- width: 400,
- height: 110,
- color: "rgba(0,0,0,0.2)"
- });
- level.fill.push({
- x: 3600,
- y: -110,
- width: 400,
- height: 110,
- color: "rgba(0,0,0,0.2)"
- });
- level.fill.push({
- x: -250,
- y: -300,
- width: 450,
- height: 300,
- color: "rgba(0,0,0,0.15)"
- });
-
- //background
- level.fillBG.push({
- x: 1300,
- y: -1800,
- width: 750,
- height: 1800,
- color: "#d4d4d7"
- });
- level.fillBG.push({
- x: 3350,
- y: -1325,
- width: 50,
- height: 1325,
- color: "#d4d4d7"
- });
- level.fillBG.push({
- x: 1350,
- y: -2100,
- width: 400,
- height: 250,
- color: "#d4f4f4"
- });
-
- spawn.mapRect(-300, 0, 5000, 300); //***********ground
- spawn.mapRect(-300, -350, 50, 400); //far left starting left wall
- spawn.mapRect(-300, -10, 500, 50); //far left starting ground
- spawn.mapRect(-300, -350, 500, 50); //far left starting ceiling
- spawn.mapRect(150, -350, 50, 200); //far left starting right part of wall
- spawn.bodyRect(170, -130, 14, 140, 1, spawn.propsFriction); //door to starting room
- spawn.boost(475, 0, 1300);
- spawn.mapRect(700, -1100, 400, 990); //far left building
- spawn.mapRect(1600, -400, 1500, 500); //long center building
- spawn.mapRect(1345, -1100, 250, 25); //left platform
- spawn.mapRect(1755, -1100, 250, 25); //right platform
- spawn.mapRect(1300, -1850, 750, 50); //left higher platform
- spawn.mapRect(1300, -2150, 50, 350); //left higher platform left edge wall
- spawn.mapRect(1300, -2150, 450, 50); //left higher platform roof
- spawn.mapRect(1500, -1860, 100, 50); //ground bump wall
- spawn.mapRect(2400, -850, 600, 300); //center floating large square
- //spawn.bodyRect(2500, -1100, 25, 250); //wall before chasers
- spawn.mapRect(2500, -1450, 450, 350); //higher center floating large square
- spawn.mapRect(2500, -1675, 50, 300); //left wall on higher center floating large square
- spawn.mapRect(2500, -1700, 300, 50); //roof on higher center floating large square
- spawn.mapRect(3300, -850, 150, 25); //ledge by far right building
- spawn.mapRect(3300, -1350, 150, 25); //higher ledge by far right building
- spawn.mapRect(3600, -1100, 400, 990); //far right building
- spawn.boost(4150, 0, 1300);
-
- spawn.bodyRect(3200, -1375, 300, 25, 0.9);
- spawn.bodyRect(1825, -1875, 400, 25, 0.9);
- // spawn.bodyRect(1800, -575, 250, 150, 0.8);
- spawn.bodyRect(1800, -600, 250, 200, 0.8);
- spawn.bodyRect(2557, -450, 35, 55, 0.7);
- spawn.bodyRect(2957, -450, 30, 15, 0.7);
- spawn.bodyRect(2900, -450, 60, 45, 0.7);
- spawn.bodyRect(915, -1200, 60, 100, 0.95);
- spawn.bodyRect(925, -1300, 50, 100, 0.95);
- if (Math.random() < 0.9) {
- spawn.bodyRect(2300, -1720, 400, 20);
- spawn.bodyRect(2590, -1780, 80, 80);
- }
- spawn.bodyRect(2925, -1100, 25, 250, 0.8);
- spawn.bodyRect(3325, -1550, 50, 200, 0.3);
- if (Math.random() < 0.8) {
- spawn.bodyRect(1400, -75, 200, 75); //block to get up ledge from ground
- spawn.bodyRect(1525, -125, 50, 50); //block to get up ledge from ground
- }
- spawn.bodyRect(1025, -1110, 400, 25, 0.9); //block on far left building
- spawn.bodyRect(1425, -1110, 115, 25, 0.9); //block on far left building
- spawn.bodyRect(1540, -1110, 300, 25, 0.9); //block on far left building
-
- if (game.levelsCleared > 2) spawn.shooterBoss(2200, -1300);
- spawn.randomSmallMob(1300, -70);
- spawn.randomSmallMob(3200, -100);
- spawn.randomSmallMob(4450, -100);
- spawn.randomSmallMob(2700, -475);
- spawn.randomMob(2650, -975, 0.8);
- spawn.randomMob(2650, -1550, 0.8);
- spawn.randomMob(4150, -200, 0.15);
- spawn.randomMob(1700, -1300, 0.2);
- spawn.randomMob(1850, -1950, 0.25);
- spawn.randomMob(2610, -1880, 0.25);
- spawn.randomMob(3350, -950, 0.25);
- spawn.randomMob(1690, -2250, 0.25);
- spawn.randomMob(2200, -600, 0.2);
- spawn.randomMob(850, -1300, 0.25);
- spawn.randomMob(-100, -900, -0.2);
- spawn.randomBoss(3700, -1500, 0.4);
- spawn.randomBoss(1700, -900, 0.4);
- },
- highrise() {
- level.defaultZoom = 1500
- game.zoomTransition(level.defaultZoom)
-
- document.body.style.backgroundColor = "#dcdcde" //"#fafcff";
- 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;
- level.exit.x = -4275;
- level.exit.y = -2805;
- this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
- powerUps.spawnStartingPowerUps(-2550, -700);
-
- // spawn.laserZone(-550, -350, 10, 400, 0.3)
- // spawn.deathQuery(-550, -350, 50, 400)
-
- // spawn.debris(-3950, -2575, 1050, 4); //20 debris per level
- spawn.debris(-2325, -1825, 2400); //20 debris per level
- spawn.debris(-2625, -600, 600, 6); //20 debris per level
- spawn.debris(-2000, -60, 1200, 6); //20 debris per level
- // if (!game.levelsCleared) powerUps.spawn(2450, -1675, "gun", false);
- //background
- level.fillBG.push({
- x: -4425,
- y: -3050,
- width: 425,
- height: 275,
- color: "#cff"
- });
- //foreground
- level.fill.push({
- x: -1650,
- y: -1575,
- width: 550,
- height: 425,
- color: "rgba(0,0,0,0.12)"
- });
- level.fill.push({
- x: -2600,
- y: -2400,
- width: 450,
- height: 1800,
- color: "rgba(0,0,0,0.12)"
- });
- level.fill.push({
- x: -3425,
- y: -2150,
- width: 525,
- height: 1550,
- color: "rgba(0,0,0,0.12)"
- });
- level.fill.push({
- x: -1850,
- y: -1150,
- width: 2025,
- height: 1150,
- color: "rgba(0,0,0,0.12)"
- });
-
- //hidden zone
- level.fill.push({
- x: -4450,
- y: -955,
- width: 1025,
- 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(-4100, -700, "gun");
- 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);
- spawn.mapRect(175, -1000, 75, 1100);
-
- spawn.mapRect(-175, -985, 25, 175);
- spawn.bodyRect(-170, -810, 14, 160, 1, spawn.propsFriction); //door to starting room
- spawn.mapRect(-600, -650, 825, 50);
- spawn.mapRect(-1300, -650, 500, 50);
- spawn.mapRect(-175, -250, 425, 300);
- spawn.bodyRect(-75, -300, 50, 50);
-
- // spawn.boost(-750, 0, 0, -0.01);
- spawn.boost(-750, 0, 1700);
- spawn.bodyRect(-425, -1375, 400, 225);
- 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.levelsCleared < 4) {
- spawn.bodyRect(-1600, -125, 125, 125);
- spawn.bodyRect(-1560, -200, 75, 75);
- } else {
- 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);
- spawn.boost(-2800, -600, 1150);
- spawn.mapRect(-3450, -1325, 550, 50);
- spawn.mapRect(-3425, -2200, 525, 50);
- spawn.mapRect(-2600, -1750, 450, 50);
- spawn.mapRect(-2600, -2450, 450, 50);
- spawn.bodyRect(-2275, -2700, 50, 60);
- spawn.bodyRect(-2600, -1975, 250, 225);
- 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);
- spawn.mapRect(-4000, -2350, 275, 675);
- // spawn.mapRect(-4450, -2650, 475, 1000);
- spawn.mapRect(-4450, -2775, 475, 1125);
- spawn.bodyRect(-3715, -2050, 50, 50);
- spawn.bodyRect(-3570, -1800, 50, 50);
- spawn.bodyRect(-2970, -2250, 50, 50);
-
- if (game.levelsCleared < 4) spawn.bodyRect(-3760, -2400, 50, 50);
-
- spawn.bodyRect(-3080, -2250, 40, 40);
- spawn.bodyRect(-3420, -650, 50, 50);
-
- //exit
- spawn.mapRect(-4450, -3075, 25, 300);
- spawn.mapRect(-4450, -3075, 450, 25);
- spawn.mapRect(-4025, -3075, 25, 100);
- spawn.mapRect(-4275, -2785, 100, 25);
-
- //mobs
- spawn.randomMob(-2500, -2700, 1);
- spawn.randomMob(-3200, -750, 1);
- spawn.randomMob(-1875, -775, 0.2);
- spawn.randomMob(-950, -1675, 0.2);
- spawn.randomMob(-1525, -1750, 0.2);
- spawn.randomMob(-1375, -1400, 0.2);
- spawn.randomMob(-1625, -1275, 0.2);
- spawn.randomMob(-1900, -1250, 0.2);
- spawn.randomMob(-2250, -1850, 0.2);
- spawn.randomMob(-2475, -2200, 0.2);
- spawn.randomMob(-3000, -1475, 0.2);
- spawn.randomMob(-3850, -2500, 0.2);
- spawn.randomMob(-3650, -2125, 0.2);
- spawn.randomMob(-4010, -3200, 0.2);
- spawn.randomMob(-3500, -1825, 0.2);
- spawn.randomMob(-975, -100, 0);
- spawn.randomMob(-1050, -725, 0.2);
- spawn.randomMob(-1525, -100, 0);
- spawn.randomMob(-525, -1700, -0.1);
- spawn.randomMob(-125, -1500, -0.1);
- spawn.randomMob(-325, -1900, -0.1);
- spawn.randomMob(-550, -100, -0.1);
- spawn.randomBoss(-3250, -2700, 0.2);
- spawn.randomBoss(-2450, -1100, 0);
- },
- warehouse() {
- level.defaultZoom = 1300
- game.zoomTransition(level.defaultZoom)
-
- document.body.style.backgroundColor = "#f2f5f3";
- mech.setPosToSpawn(25, -60); //normal spawn
- //mech.setPosToSpawn(-2000, -1700); // left ledge spawn
- level.enter.x = mech.spawnPos.x - 50;
- level.enter.y = mech.spawnPos.y + 20;
- level.exit.x = 425;
- level.exit.y = -35;
- this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
- //level.addQueryRegion(-600, -250, 180, 420, "death", [[player]],{});
-
- spawn.debris(-2250, 1330, 3000, 7); //20 debris per level
- spawn.debris(-3000, -800, 3280, 7); //20 debris per level
- spawn.debris(-1400, 410, 2300, 6); //20 debris per level
- powerUps.spawnStartingPowerUps(25, 500);
-
- //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({
- x: -3025,
- y: 50,
- width: 4125,
- height: 1350,
- color: BGColor
- });
- level.fill.push({
- x: -1800,
- y: -500,
- width: 1625,
- height: 550,
- color: BGColor
- });
- level.fill.push({
- x: -175,
- y: -250,
- width: 350,
- height: 300,
- color: BGColor
- });
- level.fill.push({
- x: -2600,
- y: -150,
- width: 700,
- height: 200,
- color: BGColor
- });
- level.fillBG.push({
- x: 300,
- y: -250,
- width: 350,
- height: 250,
- color: "#cff"
- });
- spawn.mapRect(-1500, 0, 2750, 100);
- spawn.mapRect(175, -270, 125, 300);
- spawn.mapRect(-1900, -600, 1775, 100);
- spawn.mapRect(-1900, -600, 100, 1300);
- //house
- spawn.mapRect(-175, -550, 50, 400);
- spawn.mapRect(-175, -15, 350, 50);
- spawn.mapRect(-25, -25, 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, -15, 350, 50);
- spawn.mapRect(-150, -300, 800, 50);
- spawn.mapRect(600, -275, 50, 75);
- spawn.mapRect(425, -25, 100, 25);
- // spawn.mapRect(-1900, 600, 2700, 100);
- spawn.mapRect(1100, 0, 150, 1500);
- spawn.mapRect(-2850, 1400, 4100, 100);
- spawn.mapRect(-2375, 875, 1775, 75);
- spawn.mapRect(-1450, 865, 75, 435);
- spawn.mapRect(-1450, 662, 75, 100);
- spawn.bodyRect(-1418, 773, 11, 102, 1, spawn.propsFriction); //blocking path
- spawn.mapRect(-2950, 1250, 175, 250);
- spawn.mapRect(-3050, 1100, 150, 400);
- spawn.mapRect(-3150, 50, 125, 1450);
- spawn.mapRect(-2375, 600, 3175, 100);
- spawn.mapRect(-2125, 400, 250, 275);
- // spawn.mapRect(-1950, -400, 100, 25);
- spawn.mapRect(-3150, 50, 775, 100);
- spawn.mapRect(-2600, -250, 775, 100);
- spawn.bodyRect(-1350, -200, 200, 200, 1, spawn.propsSlide); //weight
- spawn.bodyRect(-1800, 0, 300, 100, 1, spawn.propsHoist); //hoist
- cons[cons.length] = Constraint.create({
- pointA: {
- x: -1650,
- y: -500
- },
- bodyB: body[body.length - 1],
- stiffness: 0.000076,
- length: 1
- });
-
- spawn.bodyRect(400, 400, 200, 200, 1, spawn.propsSlide); //weight
- spawn.bodyRect(800, 600, 300, 100, 1, spawn.propsHoist); //hoist
- cons[cons.length] = Constraint.create({
- pointA: {
- x: 950,
- y: 100
- },
- bodyB: body[body.length - 1],
- stiffness: 0.000076,
- length: 1
- });
-
- 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: {
- x: -2575,
- y: 150
- },
- bodyB: body[body.length - 1],
- stiffness: 0.0002,
- length: 566
- });
-
- //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);
- spawn.bodyRect(-165, -45, 30, 35, 1);
-
- 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);
- spawn.bodyRect(-1275, -750, 200, 150, 0.5); //roof block
- spawn.bodyRect(-525, -700, 125, 100, 0.5); //roof block
-
- //mobs
- spawn.randomSmallMob(-1125, 550);
- spawn.randomSmallMob(-2325, 800);
- spawn.randomSmallMob(-2950, -50);
- spawn.randomSmallMob(825, 300);
- spawn.randomSmallMob(-900, 825);
- spawn.randomMob(-2025, 175, 0.6);
- spawn.randomMob(-2325, 450, 0.6);
- spawn.randomMob(-2925, 675, 0.5);
- spawn.randomMob(-2700, 300, 0.2);
- spawn.randomMob(-2500, 300, 0.2);
- spawn.randomMob(-2075, -425, 0.2);
- spawn.randomMob(-1550, -725, 0.2);
- spawn.randomMob(375, 1100, 0.1);
- spawn.randomMob(-1425, -100, 0.1);
- spawn.randomMob(-800, -750, 0);
- spawn.randomMob(400, -350, 0);
- spawn.randomMob(650, 1300, 0);
- spawn.randomMob(-750, -150, 0);
- spawn.randomMob(475, 300, 0);
- spawn.randomMob(-75, -700, 0);
- spawn.randomMob(900, -200, -0.1);
- 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.levelsCleared > 2) spawn.snaker(-1300 + Math.random() * 2000, -2200); //boss snake with head
- },
- office() {
- 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.exit.x = 3250;
- level.exit.y = -530;
- // spawn.randomSmallMob(3550, -550);
- } else {
- //reverse direction, start in bottom right
- mech.setPosToSpawn(3250, -530); //normal spawn
- level.exit.x = 1375;
- level.exit.y = -1530;
- spawn.bodyRect(3655, -650, 40, 150); //door
- }
- 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;
- this.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel");
-
- document.body.style.backgroundColor = "#e0e5e0";
- //foreground
- level.fill.push({
- x: -550,
- y: -1700,
- width: 1300,
- height: 1700,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 750,
- y: -1450,
- width: 650,
- height: 1450,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 750,
- y: -1950,
- width: 800,
- height: 450,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 3000,
- y: -1000,
- width: 650,
- height: 1000,
- color: "rgba(0,0,0,0.1)"
- });
- level.fill.push({
- x: 3650,
- y: -1300,
- width: 1300,
- height: 1300,
- 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, 5); //ground debris //20 debris per level
- spawn.debris(3500, -200, 800, 5); //ground debris //20 debris per level
- spawn.debris(-300, -650, 1200, 5); //1st floor debris //20 debris per level
- spawn.debris(3500, -650, 800, 5); //1st floor debris //20 debris per level
- powerUps.spawnStartingPowerUps(-525, -700);
-
- spawn.mapRect(-600, 25, 5600, 300); //ground
- spawn.mapRect(-600, 0, 2000, 50); //ground
- spawn.mapRect(-600, -1700, 50, 2000 - 100); //left wall
- spawn.bodyRect(-295, -1540, 40, 40); //center block under wall
- spawn.bodyRect(-298, -1580, 40, 40); //center block under wall
- spawn.bodyRect(1500, -1540, 30, 30); //left of entrance
-
- spawn.mapRect(1550, -2000, 50, 550); //right wall
- spawn.mapRect(1350, -2000 + 505, 50, 1295); //right wall
- spawn.mapRect(-600, -2000 + 250, 2000 - 700, 50); //roof left
- spawn.mapRect(-600 + 1300, -2000, 50, 300); //right roof wall
- spawn.mapRect(-600 + 1300, -2000, 900, 50); //center wall
- map[map.length] = Bodies.polygon(425, -1700, 0, 15); //circle above door
- spawn.bodyRect(420, -1675, 15, 170, 1, spawn.propsDoor); // door
- body[body.length - 1].isNotHoldable = true;
- //makes door swing
- consBB[consBB.length] = Constraint.create({
- bodyA: body[body.length - 1],
- pointA: {
- x: 0,
- y: -90
- },
- bodyB: map[map.length - 1],
- stiffness: 1
- });
- spawn.mapRect(-600 + 300, -2000 * 0.75, 1900, 50); //3rd floor
- spawn.mapRect(-600 + 2000 * 0.7, -2000 * 0.74, 50, 375); //center wall
- spawn.bodyRect(-600 + 2000 * 0.7, -2000 * 0.5 - 106, 50, 106); //center block under wall
- spawn.mapRect(-600, -1000, 1100, 50); //2nd floor
- spawn.mapRect(600, -1000, 500, 50); //2nd floor
- spawn.spawnStairs(-600, -1000, 4, 250, 350); //stairs 2nd
- spawn.mapRect(350, -600, 350, 150); //center table
- spawn.mapRect(-600 + 300, -2000 * 0.25, 2000 - 300, 50); //1st floor
- spawn.spawnStairs(-600 + 2000 - 50, -500, 4, 250, 350, true); //stairs 1st
- spawn.spawnStairs(-600, 0, 4, 250, 350); //stairs ground
- spawn.bodyRect(700, -200, 100, 100); //center block under wall
- spawn.bodyRect(700, -300, 100, 100); //center block under wall
- spawn.bodyRect(700, -400, 100, 100); //center block under wall
- spawn.mapRect(1390, 13, 30, 20); //step left
- spawn.mapRect(2980, 13, 30, 20); //step right
- spawn.mapRect(3000, 0, 2000, 50); //ground
- spawn.bodyRect(4250, -700, 50, 100);
- spawn.bodyRect(3000, -200, 50, 200); //door
- spawn.mapRect(3000, -1000, 50, 800); //left wall
- spawn.mapRect(3000 + 2000 - 50, -1300, 50, 1100); //right wall
- spawn.mapRect(4150, -600, 350, 150); //table
- spawn.mapRect(3650, -1300, 50, 650); //exit wall
- spawn.mapRect(3650, -1300, 1350, 50); //exit wall
-
- spawn.mapRect(3000, -2000 * 0.5, 700, 50); //exit roof
- spawn.mapRect(3000, -2000 * 0.25, 2000 - 300, 50); //1st floor
- spawn.spawnStairs(3000 + 2000 - 50, 0, 4, 250, 350, true); //stairs ground
-
- // tether ball
- if (game.levelsCleared > 2) {
- level.fillBG.push({
- x: 2495,
- y: -500,
- width: 10,
- height: 525,
- color: "#ccc"
- });
- spawn.tether(2850, -80)
- cons[cons.length] = Constraint.create({
- pointA: {
- x: 2500,
- y: -500
- },
- bodyB: mob[mob.length - 1],
- stiffness: 0.00012
- });
- //chance to spawn a ring of exploding mobs around this boss
- if (game.levelsCleared > 4) spawn.nodeBoss(2850, -80, "spawns", 8, 20, 105);
- }
-
- spawn.randomSmallMob(4575, -560, 1);
- spawn.randomSmallMob(1315, -880, 1);
- spawn.randomSmallMob(800, -600);
- spawn.randomSmallMob(-100, -1600);
- spawn.randomMob(4100, -225, 0.8);
- spawn.randomMob(-250, -700, 0.8);
- spawn.randomMob(4500, -225, 0.15);
- spawn.randomMob(3250, -225, 0.15);
- spawn.randomMob(-100, -225, 0.1);
- spawn.randomMob(1150, -225, 0.15);
- spawn.randomMob(2000, -225, 0.15);
- spawn.randomMob(450, -225, 0.15);
- spawn.randomMob(100, -1200, 1);
- spawn.randomMob(950, -1150, -0.1);
- spawn.randomBoss(1800, -800, -0.2);
- spawn.randomBoss(4150, -1000, 0.6);
- },
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- //*****************************************************************************************************************
- enter: {
- x: 0,
- y: 0,
- draw() {
- ctx.beginPath();
- ctx.moveTo(this.x, this.y + 30);
- ctx.lineTo(this.x, this.y - 80);
- ctx.bezierCurveTo(this.x, this.y - 170, this.x + 100, this.y - 170, this.x + 100, this.y - 80);
- ctx.lineTo(this.x + 100, this.y + 30);
- ctx.lineTo(this.x, this.y + 30);
- ctx.fillStyle = "#ccc";
- ctx.fill();
- }
- },
- exit: {
- x: 0,
- y: 0,
- draw() {
- ctx.beginPath();
- ctx.moveTo(this.x, this.y + 30);
- ctx.lineTo(this.x, this.y - 80);
- ctx.bezierCurveTo(this.x, this.y - 170, this.x + 100, this.y - 170, this.x + 100, this.y - 80);
- ctx.lineTo(this.x + 100, this.y + 30);
- ctx.lineTo(this.x, this.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 = this.zones.length; i < len; ++i) {
- if (
- player.position.x > this.zones[i].x1 &&
- player.position.x < this.zones[i].x2 &&
- player.position.y > this.zones[i].y1 &&
- player.position.y < this.zones[i].y2
- ) {
- this.zoneActions[this.zones[i].action](i);
- break;
- }
- }
- },
- addZone(x, y, width, height, action, info) {
- this.zones[this.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) {
- game.levelsCleared++;
- if (game.levelsCleared > 1) level.difficultyIncrease()
- //cycles map to next level
- level.onLevel++;
- if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
-
- game.clearNow = true; //triggers in the physics engine to remove all physics bodies
- }
- },
- 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) {
- this.queryList[this.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, info) {
- // 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
- Matter.Body.setVelocity(target, {
- x: target.velocity.x + (Math.random() - 0.5) * 2,
- y: info
- });
- },
- 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();
- }
- },
- levelAnnounce() {
- document.title = "n-gon: L" + (game.levelsCleared) + " " + level.levels[level.onLevel];
- game.makeTextLog(`
level ${game.levelsCleared}
${level.levels[level.onLevel]}
`, 300);
- // if (game.levelsCleared === 0) text = "";
- // text = "Level " + (game.levelsCleared + 1) + ": " + spawn.pickList[0] + "s + " + spawn.pickList[1] + "s";
-
- // text = text + " with population: ";
- // for (let i = 0, len = spawn.pickList.length; i < len; ++i) {
- // if (spawn.pickList[i] != spawn.pickList[i - 1]) {
- // text += spawn.pickList[i] + ", ";
- // }
- // }
- // this.speech(text);
- // game.makeTextLog(text, 360);
- },
- addToWorld(mapName) {
- //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 = 0x010000;
- body[i].collisionFilter.mask = 0x011111;
- 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 = 0x000001;
- map[i].collisionFilter.mask = 0x111111;
- 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/mobs.js b/js/mobs.js
deleted file mode 100644
index db66bf3..0000000
--- a/js/mobs.js
+++ /dev/null
@@ -1,986 +0,0 @@
-//create array of mobs
-let mob = [];
-//method to populate the array above
-const mobs = {
- loop() {
- let i = mob.length;
- while (i--) {
- if (mob[i].alive) {
- mob[i].do();
- } else {
- mob[i].replace(i); //removing mob and replace with body, this is done here to avoid an array index bug with drawing I think
- }
- }
- },
- draw() {
- ctx.lineWidth = 2;
- let i = mob.length;
- while (i--) {
- ctx.beginPath();
- const vertices = mob[i].vertices;
- ctx.moveTo(vertices[0].x, vertices[0].y);
- for (let j = 1, len = vertices.length; j < len; ++j) {
- ctx.lineTo(vertices[j].x, vertices[j].y);
- }
- ctx.lineTo(vertices[0].x, vertices[0].y);
- ctx.fillStyle = mob[i].fill;
- ctx.strokeStyle = mob[i].stroke;
- ctx.fill();
- ctx.stroke();
- }
- },
- alert(range) {
- range = range * range;
- for (let i = 0; i < mob.length; i++) {
- if (mob[i].distanceToPlayer2() < range) mob[i].locatePlayer();
- }
- },
- startle(amount) {
- for (let i = 0; i < mob.length; i++) {
- if (!mob[i].seePlayer.yes) {
- mob[i].force.x += amount * mob[i].mass * (Math.random() - 0.5);
- mob[i].force.y += amount * mob[i].mass * (Math.random() - 0.5);
- }
- }
- },
- //**********************************************************************************************
- //**********************************************************************************************
- spawn(xPos, yPos, sides, radius, color) {
- let i = mob.length;
- mob[i] = Matter.Bodies.polygon(xPos, yPos, sides, radius, {
- //inertia: Infinity, //prevents rotation
- mob: true,
- density: 0.001,
- //friction: 0,
- frictionAir: 0.005,
- //frictionStatic: 0,
- restitution: 0.5,
- collisionFilter: {
- group: 0,
- category: 0x000010,
- mask: 0x011111
- },
- onHit: undefined,
- alive: true,
- index: i,
- health: 1,
- accelMag: 0.001,
- cd: 0, //game cycle when cooldown will be over
- delay: 60, //static: time between cooldowns
- fill: color,
- stroke: "#000",
- seePlayer: {
- yes: false,
- recall: 0,
- position: {
- x: xPos,
- y: yPos
- }
- },
- radius: radius,
- spawnPos: {
- x: xPos,
- y: yPos
- },
- seeAtDistance2: 4000000, //sqrt(4000000) = 2000 = max seeing range
- distanceToPlayer() {
- const dx = this.position.x - player.position.x;
- const dy = this.position.y - player.position.y;
- return Math.sqrt(dx * dx + dy * dy);
- },
- distanceToPlayer2() {
- const dx = this.position.x - player.position.x;
- const dy = this.position.y - player.position.y;
- return dx * dx + dy * dy;
- },
- gravity() {
- this.force.y += this.mass * this.g;
- },
- seePlayerFreq: Math.round((30 + 30 * Math.random()) * game.lookFreqScale), //how often NPC checks to see where player is, lower numbers have better vision
- foundPlayer() {
- this.locatePlayer();
- if (!this.seePlayer.yes) {
- this.alertNearByMobs();
- this.seePlayer.yes = true;
- }
- },
- lostPlayer() {
- this.seePlayer.yes = false;
- this.seePlayer.recall -= this.seePlayerFreq;
- if (this.seePlayer.recall < 0) this.seePlayer.recall = 0;
- },
- memory: 120, //default time to remember player's location
- locatePlayer() {
- if (!mech.isStealth) {
- // 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;
- }
- },
- // locatePlayerByDist() {
- // if (this.distanceToPlayer2() < this.locateRange) {
- // this.locatePlayer();
- // }
- // },
- seePlayerCheck() {
- if (!(game.cycle % this.seePlayerFreq)) {
- 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
- ) {
- this.foundPlayer();
- } else if (this.seePlayer.recall) {
- this.lostPlayer();
- }
- }
- },
- seePlayerCheckByDistance() {
- if (!(game.cycle % this.seePlayerFreq)) {
- if (this.distanceToPlayer2() < this.seeAtDistance2) {
- this.foundPlayer();
- } else if (this.seePlayer.recall) {
- this.lostPlayer();
- }
- }
- },
- seePlayerByDistOrLOS() {
- if (!(game.cycle % this.seePlayerFreq)) {
- 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)
- ) {
- this.foundPlayer();
- } else if (this.seePlayer.recall) {
- this.lostPlayer();
- }
- }
- },
- seePlayerByDistAndLOS() {
- if (!(game.cycle % this.seePlayerFreq)) {
- 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)
- ) {
- this.foundPlayer();
- } else if (this.seePlayer.recall) {
- this.lostPlayer();
- }
- }
- },
- isLookingAtPlayer(threshold) {
- const diff = Matter.Vector.normalise(Matter.Vector.sub(player.position, this.position));
- //make a vector for the mob's direction of length 1
- const dir = {
- x: Math.cos(this.angle),
- y: Math.sin(this.angle)
- };
- //the dot product of diff and dir will return how much over lap between the vectors
- const dot = Matter.Vector.dot(dir, diff);
- // console.log(Math.cos(dot)*180/Math.PI)
- if (dot > threshold) {
- return true;
- } else {
- return false;
- }
- },
- lookRange: 0.2 + Math.random() * 0.2,
- lookTorque: 0.0000004 * (Math.random() > 0.5 ? -1 : 1),
- seePlayerByLookingAt() {
- if (!(game.cycle % this.seePlayerFreq) && (this.seePlayer.recall || this.isLookingAtPlayer(this.lookRange))) {
- 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
- ) {
- this.foundPlayer();
- } else if (this.seePlayer.recall) {
- this.lostPlayer();
- }
- }
- //if you don't recall player location rotate and draw to show where you are looking
- if (!this.seePlayer.recall) {
- this.torque = this.lookTorque * this.inertia;
- //draw
- const range = Math.PI * this.lookRange;
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, this.radius * 2.5, this.angle - range, this.angle + range);
- ctx.arc(this.position.x, this.position.y, this.radius * 1.4, this.angle + range, this.angle - range, true);
- ctx.fillStyle = "rgba(0,0,0,0.07)";
- ctx.fill();
- }
- },
- mechPosRange() {
- return {
- x: player.position.x, // + (Math.random() - 0.5) * 50,
- y: player.position.y + (Math.random() - 0.5) * 110
- };
- //mob vision for testing
- // ctx.beginPath();
- // ctx.lineWidth = "5";
- // ctx.strokeStyle = "#ff0";
- // ctx.moveTo(this.position.x, this.position.y);
- // ctx.lineTo(targetPos.x, targetPos.y);
- // ctx.stroke();
- // return targetPos;
- },
- laserBeam() {
- if (game.cycle % 7 && this.seePlayer.yes) {
- ctx.setLineDash([125 * Math.random(), 125 * Math.random()]);
- // ctx.lineDashOffset = 6*(game.cycle % 215);
- if (this.distanceToPlayer() < this.laserRange) {
- //if (Math.random()>0.2 && this.seePlayer.yes && this.distanceToPlayer2()<800000) {
- mech.damage(0.0003 * game.dmgScale);
- if (mech.fieldMeter > 0.1) mech.fieldMeter -= 0.005
- ctx.beginPath();
- ctx.moveTo(this.position.x, this.position.y);
- ctx.lineTo(mech.pos.x, mech.pos.y);
- ctx.lineTo(mech.pos.x + (Math.random() - 0.5) * 3000, mech.pos.y + (Math.random() - 0.5) * 3000);
- ctx.lineWidth = 2;
- ctx.strokeStyle = "rgb(255,0,170)";
- ctx.stroke();
-
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, 40, 0, 2 * Math.PI);
- ctx.fillStyle = "rgba(255,0,170,0.15)";
- ctx.fill();
- }
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, this.laserRange * 0.9, 0, 2 * Math.PI);
- ctx.strokeStyle = "rgba(255,0,170,0.5)";
- ctx.lineWidth = 1;
- ctx.stroke();
- ctx.setLineDash([]);
- }
- },
- laser() {
- 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) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
- if (this.seePlayer.recall) {
- this.torque = this.lookTorque * this.inertia * 2;
-
- const seeRange = 2500;
- best = {
- x: null,
- y: null,
- dist2: Infinity,
- who: null,
- v1: null,
- v2: null
- };
- const look = {
- x: this.position.x + seeRange * Math.cos(this.angle),
- y: this.position.y + seeRange * Math.sin(this.angle)
- };
- vertexCollision(this.position, look, map);
- vertexCollision(this.position, look, body);
- vertexCollision(this.position, look, [player]);
- // hitting player
- if (best.who === player) {
- dmg = 0.004 * game.dmgScale;
- mech.damage(dmg);
- //draw damage
- ctx.fillStyle = color;
- ctx.beginPath();
- ctx.arc(best.x, best.y, dmg * 2000, 0, 2 * Math.PI);
- ctx.fill();
- }
- //draw beam
- if (best.dist2 === Infinity) {
- best = look;
- }
- ctx.beginPath();
- ctx.moveTo(this.position.x, this.position.y);
- ctx.lineTo(best.x, best.y);
- ctx.strokeStyle = "#f00"; // Purple path
- ctx.lineWidth = 1;
- ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
- ctx.stroke(); // Draw it
- ctx.setLineDash([0, 0]);
- }
- },
- searchSpring() {
- ctx.beginPath();
- ctx.arc(this.cons.pointA.x, this.cons.pointA.y, 6, 0, 2 * Math.PI);
- ctx.arc(this.cons2.pointA.x, this.cons2.pointA.y, 6, 0, 2 * Math.PI);
- // ctx.arc(this.cons.bodyB.position.x, this.cons.bodyB.position.y,6,0,2*Math.PI);
- ctx.fillStyle = "#222";
- ctx.fill();
-
- if (!(game.cycle % this.seePlayerFreq)) {
- if (
- (this.seePlayer.recall || this.isLookingAtPlayer(this.lookRange)) &&
- this.distanceToPlayer2() < this.seeAtDistance2 &&
- Matter.Query.ray(map, this.position, player.position).length === 0 &&
- Matter.Query.ray(body, this.position, player.position).length === 0
- ) {
- this.foundPlayer();
- if (!(game.cycle % (this.seePlayerFreq * 2))) {
- this.springTarget.x = this.seePlayer.position.x;
- this.springTarget.y = this.seePlayer.position.y;
- this.cons.length = -200;
- this.cons2.length = 100 + 1.5 * this.radius;
- } else {
- this.springTarget2.x = this.seePlayer.position.x;
- this.springTarget2.y = this.seePlayer.position.y;
- this.cons.length = 100 + 1.5 * this.radius;
- this.cons2.length = -200;
- }
- } else if (this.seePlayer.recall) {
- this.lostPlayer();
- }
- }
- //if you don't recall player location rotate and draw to show where you are looking
- if (!this.seePlayer.recall) {
- this.torque = this.lookTorque * this.inertia;
- //draw
- const range = Math.PI * this.lookRange;
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, this.radius * 2.5, this.angle - range, this.angle + range);
- ctx.arc(this.position.x, this.position.y, this.radius * 1.4, this.angle + range, this.angle - range, true);
- ctx.fillStyle = "rgba(0,0,0,0.07)";
- ctx.fill();
- //spring to random place on map
- 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) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
- const seeRange = 3000;
- if (!(game.cycle % (this.seePlayerFreq * 10))) {
- best = {
- x: null,
- y: null,
- dist2: Infinity,
- who: null,
- v1: null,
- v2: null
- };
- const look = {
- x: this.position.x + seeRange * Math.cos(this.angle),
- y: this.position.y + seeRange * Math.sin(this.angle)
- };
- vertexCollision(this.position, look, map);
- if (best.dist2 != Infinity) {
- this.springTarget.x = best.x;
- this.springTarget.y = best.y;
- this.cons.length = 100 + 1.5 * this.radius;
- this.cons2.length = 100 + 1.5 * this.radius;
- }
- }
- if (!((game.cycle + this.seePlayerFreq * 5) % (this.seePlayerFreq * 10))) {
- best = {
- x: null,
- y: null,
- dist2: Infinity,
- who: null,
- v1: null,
- v2: null
- };
- const look = {
- x: this.position.x + seeRange * Math.cos(this.angle),
- y: this.position.y + seeRange * Math.sin(this.angle)
- };
- vertexCollision(this.position, look, map);
- if (best.dist2 != Infinity) {
- this.springTarget2.x = best.x;
- this.springTarget2.y = best.y;
- this.cons.length = 100 + 1.5 * this.radius;
- this.cons2.length = 100 + 1.5 * this.radius;
- }
- }
- }
- },
- alertNearByMobs() {
- //this.alertRange2 is set at the very bottom of this mobs, after mob is made
- for (let i = 0; i < mob.length; i++) {
- if (!mob[i].seePlayer.recall && Matter.Vector.magnitudeSquared(Matter.Vector.sub(this.position, mob[i].position)) < this.alertRange2) {
- mob[i].locatePlayer();
- }
- }
- //add alert to draw queue
- // game.drawList.push({
- // x: this.position.x,
- // y: this.position.y,
- // radius: Math.sqrt(this.alertRange2),
- // color: "rgba(0,0,0,0.02)",
- // time: game.drawTime
- // });
- },
- zoom() {
- this.zoomMode--;
- if (this.zoomMode > 150) {
- this.drawTrail();
- if (this.seePlayer.recall) {
- //attraction to player
- const forceMag = this.accelMag * this.mass;
- const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x);
- this.force.x += forceMag * Math.cos(angle);
- this.force.y += forceMag * Math.sin(angle);
- }
- } else if (this.zoomMode < 0) {
- this.zoomMode = 300;
- this.setupTrail();
- }
- },
- setupTrail() {
- this.trail = [];
- for (let i = 0; i < this.trailLength; ++i) {
- this.trail.push({
- x: this.position.x,
- y: this.position.y
- });
- }
- },
- drawTrail() {
- //dont' forget to run setupTrail() after mob spawn
- const t = this.trail;
- const len = t.length;
- t.pop();
- t.unshift({
- x: this.position.x,
- y: this.position.y
- });
- //draw
- ctx.strokeStyle = this.trailFill;
- ctx.beginPath();
- // ctx.moveTo(t[0].x, t[0].y);
- // ctx.lineTo(t[0].x, t[0].y);
- // ctx.globalAlpha = 0.2;
- // ctx.lineWidth = this.radius * 3;
- // ctx.stroke();
- ctx.globalAlpha = 0.5 / len;
- ctx.lineWidth = this.radius * 1.95;
- for (let i = 0; i < len; ++i) {
- // ctx.lineWidth *= 0.96;
- ctx.lineTo(t[i].x, t[i].y);
- ctx.stroke();
- }
- ctx.globalAlpha = 1;
- },
- curl(range = 1000, mag = -10) {
- //cause all mobs, and bodies to rotate in a circle
- applyCurl = function (center, array) {
- for (let i = 0; i < array.length; ++i) {
- const sub = Matter.Vector.sub(center, array[i].position)
- const radius2 = Matter.Vector.magnitudeSquared(sub);
-
- //if too close, like center mob or shield, don't curl // if too far don't curl
- if (radius2 < range * range && radius2 > 10000) {
- const curlVector = Matter.Vector.mult(Matter.Vector.perp(Matter.Vector.normalise(sub)), mag)
- //apply curl force
- Matter.Body.setVelocity(array[i], {
- x: array[i].velocity.x * 0.94 + curlVector.x * 0.06,
- y: array[i].velocity.y * 0.94 + curlVector.y * 0.06
- })
- // //draw curl
- // ctx.beginPath();
- // ctx.moveTo(array[i].position.x, array[i].position.y);
- // ctx.lineTo(array[i].position.x + curlVector.x * 10, array[i].position.y + curlVector.y * 10);
- // ctx.lineWidth = 2;
- // ctx.strokeStyle = "#000";
- // ctx.stroke();
- }
- }
- }
- applyCurl(this.position, mob);
- applyCurl(this.position, body);
- applyCurl(this.position, powerUp);
- // applyCurl(this.position, bullet); // too powerful, just stops all bullets need to write a curl function just for bullets
- // applyCurl(this.position, [player]);
-
- //draw limit
- // ctx.beginPath();
- // ctx.arc(this.position.x, this.position.y, range, 0, 2 * Math.PI);
- // ctx.fillStyle = "rgba(55,255,255, 0.1)";
- // ctx.fill();
- },
- pullPlayer() {
- if (this.seePlayer.yes && Matter.Vector.magnitudeSquared(Matter.Vector.sub(this.position, player.position)) < 1000000) {
- const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x);
- player.force.x -= game.accelScale * 1.13 * Math.cos(angle) * (mech.onGround ? 2 * player.mass * game.g : player.mass * game.g);
- player.force.y -= game.accelScale * 0.84 * player.mass * game.g * Math.sin(angle);
-
- ctx.beginPath();
- ctx.moveTo(this.position.x, this.position.y);
- ctx.lineTo(mech.pos.x, mech.pos.y);
- ctx.lineWidth = Math.min(60, this.radius * 2);
- ctx.strokeStyle = "rgba(0,0,0,0.5)";
- ctx.stroke();
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, 40, 0, 2 * Math.PI);
- ctx.fillStyle = "rgba(0,0,0,0.3)";
- ctx.fill();
- }
- },
- repelBullets() {
- if (this.seePlayer.yes) {
- ctx.lineWidth = "8";
- ctx.strokeStyle = this.fill;
- ctx.beginPath();
- for (let i = 0, len = bullet.length; i < len; ++i) {
- const dx = bullet[i].position.x - this.position.x;
- const dy = bullet[i].position.y - this.position.y;
- const dist = Math.sqrt(dx * dx + dy * dy);
- if (dist < 500) {
- ctx.moveTo(this.position.x, this.position.y);
- ctx.lineTo(bullet[i].position.x, bullet[i].position.y);
- const angle = Math.atan2(dy, dx);
- const mag = (1500 * bullet[i].mass * game.g) / dist;
- bullet[i].force.x += mag * Math.cos(angle);
- bullet[i].force.y += mag * Math.sin(angle);
- }
- }
- ctx.stroke();
- }
- },
- attraction() {
- //accelerate towards the player
- if (this.seePlayer.recall) {
- // && dx * dx + dy * dy < 2000000) {
- const forceMag = this.accelMag * this.mass;
- const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
- this.force.x += forceMag * Math.cos(angle);
- this.force.y += forceMag * Math.sin(angle);
- }
- },
- repulsionRange: 500000,
- repulsion() {
- //accelerate towards the player
- if (this.seePlayer.recall && this.distanceToPlayer2() < this.repulsionRange) {
- // && dx * dx + dy * dy < 2000000) {
- const forceMag = this.accelMag * this.mass;
- const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
- this.force.x -= 2 * forceMag * Math.cos(angle);
- this.force.y -= 2 * forceMag * Math.sin(angle); // - 0.0007 * this.mass; //antigravity
- }
- },
- hop() {
- //accelerate towards the player after a delay
- if (this.cd < game.cycle && this.seePlayer.recall && this.speed < 1) {
- this.cd = game.cycle + this.delay;
- const forceMag = (this.accelMag + this.accelMag * Math.random()) * this.mass;
- const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
- this.force.x += forceMag * Math.cos(angle);
- this.force.y += forceMag * Math.sin(angle) - 0.04 * this.mass; //antigravity
- }
- },
- hoverOverPlayer() {
- if (this.seePlayer.recall) {
- // vertical positioning
- const rangeY = 250;
- if (this.position.y > this.seePlayer.position.y - this.hoverElevation + rangeY) {
- this.force.y -= this.accelMag * this.mass;
- } else if (this.position.y < this.seePlayer.position.y - this.hoverElevation - rangeY) {
- this.force.y += this.accelMag * this.mass;
- }
- // horizontal positioning
- const rangeX = 150;
- if (this.position.x > this.seePlayer.position.x + this.hoverXOff + rangeX) {
- this.force.x -= this.accelMag * this.mass;
- } else if (this.position.x < this.seePlayer.position.x + this.hoverXOff - rangeX) {
- this.force.x += this.accelMag * this.mass;
- }
- }
- // else {
- // this.gravity();
- // }
- },
- grow() {
- if (!mech.isBodiesAsleep) {
- if (this.seePlayer.recall) {
- if (this.radius < 80) {
- const scale = 1.01;
- Matter.Body.scale(this, scale, scale);
- this.radius *= scale;
- // this.torque = -0.00002 * this.inertia;
- this.fill = `hsl(144, ${this.radius}%, 50%)`;
- }
- } else {
- if (this.radius > 15) {
- const scale = 0.99;
- Matter.Body.scale(this, scale, scale);
- this.radius *= scale;
- this.fill = `hsl(144, ${this.radius}%, 50%)`;
- }
- }
- }
- },
- search() {
- //be sure to declare searchTarget in mob spawn
- //accelerate towards the searchTarget
- if (!this.seePlayer.recall) {
- const newTarget = function (that) {
- if (Math.random() < 0.05) {
- that.searchTarget = player.position; //chance to target player
- } else {
- //target random body
- that.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position;
- }
- };
-
- const sub = Matter.Vector.sub(this.searchTarget, this.position);
- if (Matter.Vector.magnitude(sub) > this.radius * 2) {
- // ctx.beginPath();
- // ctx.strokeStyle = "#aaa";
- // ctx.moveTo(this.position.x, this.position.y);
- // ctx.lineTo(this.searchTarget.x,this.searchTarget.y);
- // ctx.stroke();
- //accelerate at 0.1 of normal acceleration
- this.force = Matter.Vector.mult(Matter.Vector.normalise(sub), this.accelMag * this.mass * 0.2);
- } else {
- //after reaching random target switch to new target
- newTarget(this);
- }
- //switch to a new target after a while
- if (!(game.cycle % (this.seePlayerFreq * 15))) {
- newTarget(this);
- }
- }
- },
- strike() {
- //teleport to player when close enough on CD
- if (this.seePlayer.recall && this.cd < game.cycle) {
- const dist = Matter.Vector.sub(this.seePlayer.position, this.position);
- const distMag = Matter.Vector.magnitude(dist);
- if (distMag < 430) {
- this.cd = game.cycle + this.delay;
- ctx.beginPath();
- ctx.moveTo(this.position.x, this.position.y);
- Matter.Body.translate(this, Matter.Vector.mult(Matter.Vector.normalise(dist), distMag - 20 - radius));
- ctx.lineTo(this.position.x, this.position.y);
- ctx.lineWidth = radius * 2;
- ctx.strokeStyle = this.fill; //"rgba(0,0,0,0.5)"; //'#000'
- ctx.stroke();
- }
- }
- },
- blink() {
- //teleport towards player as a way to move
- if (this.seePlayer.recall && !(game.cycle % this.blinkRate)) {
- ctx.beginPath();
- ctx.moveTo(this.position.x, this.position.y);
- const dist = Matter.Vector.sub(this.seePlayer.position, this.position);
- const distMag = Matter.Vector.magnitude(dist);
- const unitVector = Matter.Vector.normalise(dist);
- const rando = (Math.random() - 0.5) * 50;
- if (distMag < this.blinkLength) {
- Matter.Body.translate(this, Matter.Vector.mult(unitVector, distMag + rando));
- } else {
- Matter.Body.translate(this, Matter.Vector.mult(unitVector, this.blinkLength + rando));
- }
- ctx.lineTo(this.position.x, this.position.y);
- ctx.lineWidth = radius * 2;
- ctx.strokeStyle = this.stroke; //"rgba(0,0,0,0.5)"; //'#000'
- ctx.stroke();
- }
- },
- drift() {
- //teleport towards player as a way to move
- if (this.seePlayer.recall && !(game.cycle % this.blinkRate)) {
- // && !mech.lookingAtMob(this,0.5)){
- ctx.beginPath();
- ctx.moveTo(this.position.x, this.position.y);
- const dist = Matter.Vector.sub(this.seePlayer.position, this.position);
- const distMag = Matter.Vector.magnitude(dist);
- const vector = Matter.Vector.mult(Matter.Vector.normalise(dist), this.blinkLength);
- if (distMag < this.blinkLength) {
- Matter.Body.setPosition(this, this.seePlayer.position);
- Matter.Body.translate(this, {
- x: (Math.random() - 0.5) * 50,
- y: (Math.random() - 0.5) * 50
- });
- } else {
- vector.x += (Math.random() - 0.5) * 200;
- vector.y += (Math.random() - 0.5) * 200;
- Matter.Body.translate(this, vector);
- }
- ctx.lineTo(this.position.x, this.position.y);
- ctx.lineWidth = radius * 2;
- ctx.strokeStyle = this.stroke;
- ctx.stroke();
- }
- },
- bomb() {
- //throw a mob/bullet at player
- if (
- !(game.cycle % this.fireFreq) &&
- Math.abs(this.position.x - this.seePlayer.position.x) < 400 && //above player
- Matter.Query.ray(map, this.position, this.mechPosRange()).length === 0 && //see player
- Matter.Query.ray(body, this.position, this.mechPosRange()).length === 0
- ) {
- spawn.bullet(this.position.x, this.position.y + this.radius * 0.5, 10 + Math.ceil(this.radius / 15), 5);
- //add spin and speed
- Matter.Body.setAngularVelocity(mob[mob.length - 1], (Math.random() - 0.5) * 0.5);
- Matter.Body.setVelocity(mob[mob.length - 1], {
- x: this.velocity.x,
- y: this.velocity.y
- });
- //spin for mob as well
- Matter.Body.setAngularVelocity(this, (Math.random() - 0.5) * 0.25);
- }
- },
- fire() {
- 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 = Matter.Vector.normalise(Matter.Vector.sub(this.seePlayer.position, this.position));
- this.fireDir.y -= Math.abs(this.seePlayer.position.x - this.position.x) / 1600; //gives the bullet an arc
- this.fireAngle = Math.atan2(this.fireDir.y, this.fireDir.x);
- }
- //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.000004 * this.inertia;
- } else if (c < -threshold) {
- this.torque -= 0.000004 * this.inertia;
- } else if (this.noseLength > 1.5) {
- //fire
- spawn.bullet(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();
- // }
- }
- },
- turnToFacePlayer() {
- //turn to face player
- const dx = player.position.x - this.position.x;
- const dy = -player.position.y + this.position.y;
- const dist = this.distanceToPlayer();
- const angle = this.angle + Math.PI / 2;
- c = Math.cos(angle) * dx - Math.sin(angle) * dy;
- // if (c > 0.04) {
- // Matter.Body.rotate(this, 0.01);
- // } else if (c < 0.04) {
- // Matter.Body.rotate(this, -0.01);
- // }
- if (c > 0.04 * dist) {
- this.torque += 0.002 * this.mass;
- } else if (c < 0.04) {
- this.torque -= 0.002 * this.mass;
- }
- },
- facePlayer() {
- const unitVector = Matter.Vector.normalise(Matter.Vector.sub(this.seePlayer.position, this.position));
- const angle = Math.atan2(unitVector.y, unitVector.x);
- Matter.Body.setAngle(this, angle - Math.PI);
- },
- explode() {
- mech.damage(Math.min(Math.max(0.02 * Math.sqrt(this.mass), 0.01), 0.35) * game.dmgScale);
- this.dropPowerUp = false;
- this.death(); //death with no power up or body
- },
- timeLimit() {
- if (!mech.isBodiesAsleep) {
- this.timeLeft--;
- if (this.timeLeft < 0) {
- this.dropPowerUp = false;
- this.death(); //death with no power up
- }
- }
- },
- healthBar() {
- //draw health bar
- if (this.seePlayer.recall) {
- // && this.health < 1
- const h = this.radius * 0.3;
- const w = this.radius * 2;
- const x = this.position.x - w / 2;
- const y = this.position.y - w * 0.7;
- ctx.fillStyle = "rgba(100, 100, 100, 0.3)";
- ctx.fillRect(x, y, w, h);
- ctx.fillStyle = "rgba(255,0,0,0.7)";
- ctx.fillRect(x, y, w * this.health, h);
- }
- },
- damage(dmg) {
- this.health -= dmg / Math.sqrt(this.mass);
- //this.fill = this.color + this.health + ')';
- if (this.health < 0.1) this.death();
- this.onDamage(this); //custom damage effects
- if (b.modEnergySiphon) mech.fieldMeter += dmg * b.modEnergySiphon
- if (b.modHealthDrain) mech.addHealth(dmg * b.modHealthDrain)
- },
- onDamage() {
- // a placeholder for custom effects on mob damage
- //to use declare custom method in mob spawn
- },
- onDeath() {
- // a placeholder for custom effects on mob death
- //to use declare custom method in mob spawn
- },
- leaveBody: true,
- dropPowerUp: true,
- death() {
- this.onDeath(this); //custom death effects
- this.removeConsBB();
- this.alive = false;
- if (this.dropPowerUp) powerUps.spawnRandomPowerUp(this.position.x, this.position.y, this.mass, radius);
- },
- removeConsBB() {
- for (let i = 0, len = consBB.length; i < len; ++i) {
- if (consBB[i].bodyA === this) {
- if (consBB[i].bodyB.shield) {
- consBB[i].bodyB.do = function () {
- this.death();
- };
- }
- consBB[i].bodyA = consBB[i].bodyB;
- consBB.splice(i, 1);
- this.removeConsBB();
- break;
- } else if (consBB[i].bodyB === this) {
- if (consBB[i].bodyA.shield) {
- consBB[i].bodyA.do = function () {
- this.death();
- };
- }
- consBB[i].bodyB = consBB[i].bodyA;
- consBB.splice(i, 1);
- this.removeConsBB();
- break;
- }
- }
- },
- removeCons() {
- for (let i = 0, len = cons.length; i < len; ++i) {
- if (cons[i].bodyA === this) {
- cons[i].bodyA = cons[i].bodyB;
- cons.splice(i, 1);
- this.removeCons();
- break;
- } else if (cons[i].bodyB === this) {
- cons[i].bodyB = cons[i].bodyA;
- cons.splice(i, 1);
- this.removeCons();
- break;
- }
- }
- },
- //replace dead mob with a regular body
- replace(i) {
- if (this.leaveBody) {
- const len = body.length;
- body[len] = Matter.Bodies.fromVertices(this.position.x, this.position.y, this.vertices);
- Matter.Body.setVelocity(body[len], this.velocity);
- Matter.Body.setAngularVelocity(body[len], this.angularVelocity);
- body[len].collisionFilter.category = 0x010000;
- body[len].collisionFilter.mask = 0x011111;
- // body[len].collisionFilter.category = body[len].collisionFilter.category //0x000001;
- // body[len].collisionFilter.mask = body[len].collisionFilter.mask //0x011111;
-
- //large mobs or too many bodies go intangible and fall until removed from game to help performance
- if (body[len].mass > 10 || 40 + 30 * Math.random() < body.length) {
- body[len].collisionFilter.mask = 0x001100;
- }
- body[len].classType = "body";
- World.add(engine.world, body[len]); //add to world
- }
- Matter.World.remove(engine.world, this);
- mob.splice(i, 1);
- }
- });
- mob[i].alertRange2 = Math.pow(mob[i].radius * 3 + 200, 2);
- World.add(engine.world, mob[i]); //add to world
- }
-};
\ No newline at end of file
diff --git a/js/player.js b/js/player.js
deleted file mode 100644
index fee16d8..0000000
--- a/js/player.js
+++ /dev/null
@@ -1,1445 +0,0 @@
-//global player variables for use in matter.js physics
-let player, jumpSensor, playerBody, playerHead, headSensor;
-
-// player Object Prototype *********************************************
-const mech = {
- spawn() {
- //load player in matter.js physic engine
- // let vector = Vertices.fromPath("0 40 50 40 50 115 0 115 30 130 20 130"); //player as a series of vertices
- let vector = Vertices.fromPath("0,40, 50,40, 50,115, 30,130, 20,130, 0,115, 0,40"); //player as a series of vertices
- playerBody = Matter.Bodies.fromVertices(0, 0, vector);
- jumpSensor = Bodies.rectangle(0, 46, 36, 6, {
- //this sensor check if the player is on the ground to enable jumping
- sleepThreshold: 99999999999,
- isSensor: true
- });
- vector = Vertices.fromPath("16 -82 2 -66 2 -37 43 -37 43 -66 30 -82");
- playerHead = Matter.Bodies.fromVertices(0, -55, vector); //this part of the player lowers on crouch
- headSensor = Bodies.rectangle(0, -57, 48, 45, {
- //senses if the player's head is empty and can return after crouching
- sleepThreshold: 99999999999,
- isSensor: true
- });
- player = Body.create({
- //combine jumpSensor and playerBody
- parts: [playerBody, playerHead, jumpSensor, headSensor],
- inertia: Infinity, //prevents player rotation
- friction: 0.002,
- frictionAir: 0.001,
- //frictionStatic: 0.5,
- restitution: 0,
- sleepThreshold: Infinity,
- collisionFilter: {
- group: 0,
- category: 0x001000,
- mask: 0x010011
- },
- death() {
- mech.death();
- }
- });
- Matter.Body.setMass(player, mech.mass);
- World.add(engine.world, [player]);
-
- mech.holdConstraint = Constraint.create({
- //holding body constraint
- pointA: {
- x: 0,
- y: 0
- },
- bodyB: jumpSensor, //setting constraint to jump sensor because it has to be on something until the player picks up things
- stiffness: 0.4
- });
- World.add(engine.world, mech.holdConstraint);
- },
- cycle: 0,
- width: 50,
- radius: 30,
- fillColor: "#fff",
- fillColorDark: "#ccc",
- height: 42,
- yOffWhen: {
- crouch: 22,
- stand: 49,
- jump: 70
- },
- mass: 5,
- Fx: 0.015, //run Force on ground
- FxAir: 0.015, //run Force in Air
- definePlayerMass(mass = 5) {
- Matter.Body.setMass(player, mass);
- //reduce air and ground move forces
- this.Fx = 0.075 / mass
- this.FxAir = 0.375 / mass / mass
- //make player stand a bit lower when holding heavy masses
- this.yOffWhen.stand = Math.max(this.yOffWhen.crouch, Math.min(49, 49 - (mass - 5) * 6))
- if (this.onGround && !this.crouch) this.yOffGoal = this.yOffWhen.stand;
- },
- yOff: 70,
- yOffGoal: 70,
- onGround: false, //checks if on ground or in air
- standingOn: undefined,
- numTouching: 0,
- crouch: false,
- isHeadClear: true,
- spawnPos: {
- x: 0,
- y: 0
- },
- spawnVel: {
- x: 0,
- y: 0
- },
- pos: {
- 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);
- },
- Sy: 0, //adds a smoothing effect to vertical only
- Vx: 0,
- Vy: 0,
- jumpForce: 0.38,
- gravity: 0.0019,
- friction: {
- ground: 0.01,
- air: 0.0025
- },
- angle: 0,
- walk_cycle: 0,
- stepSize: 0,
- flipLegs: -1,
- hip: {
- x: 12,
- y: 24
- },
- knee: {
- x: 0,
- y: 0,
- x2: 0,
- y2: 0
- },
- foot: {
- x: 0,
- y: 0
- },
- legLength1: 55,
- legLength2: 45,
- transX: 0,
- transY: 0,
- move() {
- this.pos.x = player.position.x;
- this.pos.y = playerBody.position.y - this.yOff;
- this.Vx = player.velocity.x;
- this.Vy = player.velocity.y;
- },
- transSmoothX: 0,
- transSmoothY: 0,
- lastGroundedPositionY: 0,
- // mouseZoom: 0,
- look() {
- //always on mouse look
- this.angle = Math.atan2(
- game.mouseInGame.y - this.pos.y,
- game.mouseInGame.x - this.pos.x
- );
- //smoothed mouse look translations
- const scale = 0.8;
- this.transSmoothX = canvas.width2 - this.pos.x - (game.mouse.x - canvas.width2) * scale;
- this.transSmoothY = canvas.height2 - this.pos.y - (game.mouse.y - canvas.height2) * scale;
-
- this.transX += (this.transSmoothX - this.transX) * 0.07;
- this.transY += (this.transSmoothY - this.transY) * 0.07;
- },
- doCrouch() {
- if (!this.crouch) {
- this.crouch = true;
- this.yOffGoal = this.yOffWhen.crouch;
- Matter.Body.translate(playerHead, {
- x: 0,
- y: 40
- });
- }
- },
- undoCrouch() {
- if (this.crouch) {
- this.crouch = false;
- this.yOffGoal = this.yOffWhen.stand;
- Matter.Body.translate(playerHead, {
- x: 0,
- y: -40
- });
- }
- },
- hardLandCD: 0,
- enterAir() {
- //triggered in engine.js on collision
- this.onGround = false;
- this.hardLandCD = 0 // disable hard landing
- if (this.isHeadClear) {
- if (this.crouch) {
- this.undoCrouch();
- }
- this.yOffGoal = this.yOffWhen.jump;
- }
- },
- //triggered in engine.js on collision
- enterLand() {
- this.onGround = true;
- if (this.crouch) {
- if (this.isHeadClear) {
- this.undoCrouch();
- } else {
- this.yOffGoal = this.yOffWhen.crouch;
- }
- } else {
- //sets a hard land where player stays in a crouch for a bit and can't jump
- //crouch is forced in keyMove() on ground section below
- const momentum = player.velocity.y * player.mass //player mass is 5 so this triggers at 20 down velocity, unless the player is holding something
- if (momentum > 100) {
- this.doCrouch();
- this.yOff = this.yOffWhen.jump;
- this.hardLandCD = mech.cycle + Math.min(momentum / 6 - 6, 40)
- } else {
- this.yOffGoal = this.yOffWhen.stand;
- }
- }
- },
- buttonCD_jump: 0, //cool down for player buttons
- keyMove() {
- if (this.onGround) { //on ground **********************
- if (this.crouch) {
- if (!(keys[83] || keys[40]) && this.isHeadClear && this.hardLandCD < mech.cycle) this.undoCrouch();
- } else if (keys[83] || keys[40] || this.hardLandCD > mech.cycle) {
- this.doCrouch(); //on ground && not crouched and pressing s or down
- } else if ((keys[87] || keys[38]) && this.buttonCD_jump + 20 < mech.cycle && this.yOffWhen.stand > 23) {
- this.buttonCD_jump = mech.cycle; //can't jump again until 20 cycles pass
-
- //apply a fraction of the jump force to the body the player is jumping off of
- Matter.Body.applyForce(mech.standingOn, mech.pos, {
- x: 0,
- y: this.jumpForce * 0.12 * Math.min(mech.standingOn.mass, 5)
- });
-
- player.force.y = -this.jumpForce; //player jump force
- Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps
- x: player.velocity.x,
- y: 0
- });
- }
-
- //horizontal move on ground
- //apply a force to move
- if (keys[65] || keys[37]) { //left / a
- player.force.x -= this.Fx
- if (player.velocity.x > -2) player.force.x -= this.Fx * 0.5
- } else if (keys[68] || keys[39]) { //right / d
- player.force.x += this.Fx
- if (player.velocity.x < 2) player.force.x += this.Fx * 0.5
- } else {
- const stoppingFriction = 0.92;
- Matter.Body.setVelocity(player, {
- x: player.velocity.x * stoppingFriction,
- y: player.velocity.y * stoppingFriction
- });
- }
- //come to a stop if fast or if no move key is pressed
- if (player.speed > 4) {
- const stoppingFriction = (this.crouch) ? 0.65 : 0.89; // this controls speed when crouched
- Matter.Body.setVelocity(player, {
- x: player.velocity.x * stoppingFriction,
- y: player.velocity.y * stoppingFriction
- });
- }
-
- } else { // in air **********************************
- //check for short jumps
- if (
- this.buttonCD_jump + 60 > mech.cycle && //just pressed jump
- !(keys[87] || keys[38]) && //but not pressing jump key
- this.Vy < 0 //moving up
- ) {
- Matter.Body.setVelocity(player, {
- //reduce player y-velocity every cycle
- x: player.velocity.x,
- y: player.velocity.y * 0.94
- });
- }
- const limit = 125 / player.mass / player.mass
- if (keys[65] || keys[37]) {
- if (player.velocity.x > -limit) player.force.x -= this.FxAir; // move player left / a
- } else if (keys[68] || keys[39]) {
- if (player.velocity.x < limit) player.force.x += this.FxAir; //move player right / d
- }
- }
-
- //smoothly move leg height towards height goal
- this.yOff = this.yOff * 0.85 + this.yOffGoal * 0.15;
- },
- gamepadMove() {
- if (this.onGround) { //on ground **********************
- if (this.crouch) {
- if (game.gamepad.leftAxis.y !== -1 && this.isHeadClear && this.hardLandCD < mech.cycle) this.undoCrouch();
- } else if (game.gamepad.leftAxis.y === -1 || this.hardLandCD > mech.cycle) {
- this.doCrouch(); //on ground && not crouched and pressing s or down
- } else if (game.gamepad.jump && this.buttonCD_jump + 20 < mech.cycle && this.yOffWhen.stand > 23) {
- this.buttonCD_jump = mech.cycle; //can't jump again until 20 cycles pass
-
- //apply a fraction of the jump force to the body the player is jumping off of
- Matter.Body.applyForce(mech.standingOn, mech.pos, {
- x: 0,
- y: this.jumpForce * 0.12 * Math.min(mech.standingOn.mass, 5)
- });
-
- player.force.y = -this.jumpForce; //player jump force
- Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps
- x: player.velocity.x,
- y: 0
- });
- }
-
- //horizontal move on ground
- //apply a force to move
- if (game.gamepad.leftAxis.x === -1) { //left / a
- player.force.x -= this.Fx
- if (player.velocity.x > -2) player.force.x -= this.Fx * 0.5
- } else if (game.gamepad.leftAxis.x === 1) { //right / d
- player.force.x += this.Fx
- if (player.velocity.x < 2) player.force.x += this.Fx * 0.5
- } else {
- const stoppingFriction = 0.92;
- Matter.Body.setVelocity(player, {
- x: player.velocity.x * stoppingFriction,
- y: player.velocity.y * stoppingFriction
- });
- }
- //come to a stop if fast or if no move key is pressed
- if (player.speed > 4) {
- const stoppingFriction = (this.crouch) ? 0.65 : 0.89;
- Matter.Body.setVelocity(player, {
- x: player.velocity.x * stoppingFriction,
- y: player.velocity.y * stoppingFriction
- });
- }
-
- } else { // in air **********************************
- //check for short jumps
- if (
- this.buttonCD_jump + 60 > mech.cycle && //just pressed jump
- !game.gamepad.jump && //but not pressing jump key
- this.Vy < 0 //moving up
- ) {
- Matter.Body.setVelocity(player, {
- //reduce player y-velocity every cycle
- x: player.velocity.x,
- y: player.velocity.y * 0.94
- });
- }
- const limit = 125 / player.mass / player.mass
- if (game.gamepad.leftAxis.x === -1) {
- if (player.velocity.x > -limit) player.force.x -= this.FxAir; // move player left / a
- } else if (game.gamepad.leftAxis.x === 1) {
- if (player.velocity.x < limit) player.force.x += this.FxAir; //move player right / d
- }
- }
-
- //smoothly move leg height towards height goal
- this.yOff = this.yOff * 0.85 + this.yOffGoal * 0.15;
- },
- alive: true,
- death() {
- if (b.modIsImmortal) { //if player has the immortality buff, spawn on the same level with randomized stats
- //remove mods
- b.mod = null
- b.setModDefaults();
- b.modText();
-
- function randomizeField() {
- if (game.levelsCleared > 5) {
- mech.fieldUpgrades[Math.floor(Math.random() * (mech.fieldUpgrades.length))].effect();
- } else {
- mech.fieldUpgrades[0].effect();
- }
- }
-
- mech.addHealth(1);
- spawn.setSpawnList(); //new mob types
- game.clearNow = true; //triggers a map reset
-
- //randomize guns
- function randomizeGuns() {
- b.activeGun = null;
- b.inventory = []; //removes guns and ammo
- for (let i = 0, len = b.guns.length; i < len; ++i) {
- b.guns[i].have = false;
- if (b.guns[i].ammo !== Infinity) b.guns[i].ammo = 0;
- }
- if (game.levelsCleared > 0) powerUps.gun.effect();
- if (game.levelsCleared > 1) powerUps.gun.effect();
- if (game.levelsCleared > 3) powerUps.gun.effect();
- if (game.levelsCleared > 6) powerUps.gun.effect();
- //randomize ammo
- for (let i = 0, len = b.inventory.length; i < len; i++) {
- if (b.guns[b.inventory[i]].ammo !== Infinity) {
- b.guns[b.inventory[i]].ammo = Math.max(0, Math.floor(2.2 * b.guns[b.inventory[i]].ammo * (Math.random() - 0.15)))
- }
- }
- game.makeGunHUD(); //update gun HUD
- }
-
- game.wipe = function () { //set wipe to have trails
- ctx.fillStyle = "rgba(255,255,255,0)";
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- }
-
- randomizeGuns()
- for (let i = 0; i < 7; i++) {
- setTimeout(function () {
- randomizeGuns()
- randomizeField()
- game.makeTextLog(`probability amplitude will synchronize in ${7-i} seconds`, 1000);
- game.wipe = function () { //set wipe to have trails
- ctx.fillStyle = `rgba(255,255,255,${(i+1)*(i+1)*0.003})`;
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- }
- }, (i + 1) * 1000);
- }
-
- setTimeout(function () {
- game.wipe = function () { //set wipe to normal
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- }
- game.makeTextLog("your quantum probability has stabilized", 1000);
- document.title = "n-gon: L" + (game.levelsCleared) + " " + level.levels[level.onLevel];
- }, 8000);
-
- } else if (this.alive) { //normal death code here
- this.alive = false;
- game.paused = true;
- this.health = 0;
- this.displayHealth();
- document.getElementById("text-log").style.opacity = 0; //fade out any active text logs
- document.getElementById("fade-out").style.opacity = 1; //slowly fades out
- setTimeout(function () {
- game.splashReturn();
- }, 5000);
- }
- },
- health: 0,
- // regen() {
- // if (this.health < 1 && mech.cycle % 15 === 0) {
- // this.addHealth(0.01);
- // }
- // },
- drawHealth() {
- if (this.health < 1) {
- ctx.fillStyle = "rgba(100, 100, 100, 0.5)";
- ctx.fillRect(this.pos.x - this.radius, this.pos.y - 50, 60, 10);
- ctx.fillStyle = "#f00";
- ctx.fillRect(
- this.pos.x - this.radius,
- this.pos.y - 50,
- 60 * this.health,
- 10
- );
- }
- },
- displayHealth() {
- id = document.getElementById("health");
- id.style.width = Math.floor(300 * this.health) + "px";
- //css animation blink if health is low
- if (this.health < 0.3) {
- id.classList.add("low-health");
- } else {
- id.classList.remove("low-health");
- }
- },
- addHealth(heal) {
- this.health += heal;
- if (this.health > 1) this.health = 1;
- this.displayHealth();
- },
- defaultFPSCycle: 0, //tracks when to return to normal fps
- damage(dmg) {
- this.health -= dmg;
- if (this.health < 0) {
- this.health = 0;
- this.death();
- return;
- }
- this.displayHealth();
- document.getElementById("dmg").style.transition = "opacity 0s";
- document.getElementById("dmg").style.opacity = 0.1 + Math.min(0.6, dmg * 4);
-
- //drop block if holding
- if (dmg > 0.07) {
- this.drop();
- }
-
- // freeze game and display a full screen red color
- if (dmg > 0.05) {
- game.fpsCap = 4 //40 - Math.min(25, 100 * dmg)
- game.fpsInterval = 1000 / game.fpsCap;
- } else {
- game.fpsCap = game.fpsCapDefault
- game.fpsInterval = 1000 / game.fpsCap;
- }
- mech.defaultFPSCycle = mech.cycle
-
- const normalFPS = function () {
- if (mech.defaultFPSCycle < mech.cycle) { //back to default values
- game.fpsCap = game.fpsCapDefault
- game.fpsInterval = 1000 / game.fpsCap;
- document.getElementById("dmg").style.transition = "opacity 1s";
- document.getElementById("dmg").style.opacity = "0";
- } else {
- requestAnimationFrame(normalFPS);
- }
- };
- requestAnimationFrame(normalFPS);
- },
- damageImmune: 0,
- hitMob(i, dmg) {
- //prevents damage happening too quick
- },
- buttonCD: 0, //cooldown for player buttons
- usePowerUp(i) {
- powerUp[i].effect();
- Matter.World.remove(engine.world, powerUp[i]);
- powerUp.splice(i, 1);
- },
- // *********************************************
- // **************** holding ********************
- // *********************************************
- closest: {
- dist: 1000,
- index: 0
- },
- isHolding: false,
- isStealth: false,
- throwCharge: 0,
- fireCDcycle: 0,
- fieldCDcycle: 0,
- fieldMode: 0, //basic field mode before upgrades
- // these values are set on reset by setHoldDefaults()
- fieldMeter: 0,
- fieldRegen: 0,
- fieldMode: 0,
- fieldFire: false,
- holdingMassScale: 0,
- throwChargeRate: 0,
- throwChargeMax: 0,
- fieldFireCD: 0,
- fieldDamage: 0,
- fieldShieldingScale: 0,
- grabRange: 0,
- fieldArc: 0,
- fieldThreshold: 0,
- calculateFieldThreshold() {
- this.fieldThreshold = Math.cos(this.fieldArc * Math.PI)
- },
- setHoldDefaults() {
- this.fieldMeter = 1;
- this.fieldRegen = 0.001;
- this.fieldFire = false;
- this.fieldCDcycle = 0;
- this.isStealth = false;
- player.collisionFilter.mask = 0x010011 //0x010011 is normal
- this.holdingMassScale = 0.5;
- this.throwChargeRate = 2;
- this.throwChargeMax = 50;
- this.fieldFireCD = 15;
- this.fieldDamage = 0; // a value of 1.0 kills a small mob in 2-3 hits on level 1
- this.fieldShieldingScale = 1; //scale energy loss after collision with mob
- this.grabRange = 175;
- this.fieldArc = 0.2;
- this.calculateFieldThreshold();
- this.jumpForce = 0.38;
- this.Fx = 0.015; //run Force on ground
- this.FxAir = 0.015; //run Force in Air
- this.gravity = 0.0019;
- mech.isBodiesAsleep = true;
- mech.wakeCheck();
- // this.phaseBlocks(0x011111)
- },
- drawFieldMeter(range = 60) {
- if (this.fieldMeter < 1) {
- mech.fieldMeter += mech.fieldRegen;
- ctx.fillStyle = "rgba(0, 0, 0, 0.4)";
- ctx.fillRect(this.pos.x - this.radius, this.pos.y - 50, range, 10);
- ctx.fillStyle = "rgb(50,220,255)";
- ctx.fillRect(this.pos.x - this.radius, this.pos.y - 50, range * this.fieldMeter, 10);
- } else {
- mech.fieldMeter = 1
- }
- },
- lookingAt(who) {
- //calculate a vector from body to player and make it length 1
- const diff = Matter.Vector.normalise(Matter.Vector.sub(who.position, mech.pos));
- //make a vector for the player's direction of length 1
- const dir = {
- x: Math.cos(mech.angle),
- y: Math.sin(mech.angle)
- };
- //the dot product of diff and dir will return how much over lap between the vectors
- // console.log(Matter.Vector.dot(dir, diff))
- if (Matter.Vector.dot(dir, diff) > this.fieldThreshold) {
- return true;
- }
- return false;
- },
- drop() {
- if (this.isHolding) {
- this.isHolding = false;
- this.definePlayerMass()
- this.holdingTarget.collisionFilter.category = 0x010000;
- this.holdingTarget.collisionFilter.mask = 0x011111;
- this.holdingTarget = null;
- this.throwCharge = 0;
- }
- },
- drawHold(target, stroke = true) {
- const eye = 15;
- const len = target.vertices.length - 1;
- ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
- ctx.lineWidth = 1;
- ctx.strokeStyle = "#000";
- ctx.beginPath();
- ctx.moveTo(
- mech.pos.x + eye * Math.cos(this.angle),
- mech.pos.y + eye * Math.sin(this.angle)
- );
- ctx.lineTo(target.vertices[len].x, target.vertices[len].y);
- ctx.lineTo(target.vertices[0].x, target.vertices[0].y);
- ctx.fill();
- if (stroke) ctx.stroke();
- for (let i = 0; i < len; i++) {
- ctx.beginPath();
- ctx.moveTo(
- mech.pos.x + eye * Math.cos(this.angle),
- mech.pos.y + eye * Math.sin(this.angle)
- );
- ctx.lineTo(target.vertices[i].x, target.vertices[i].y);
- ctx.lineTo(target.vertices[i + 1].x, target.vertices[i + 1].y);
- ctx.fill();
- if (stroke) ctx.stroke();
- }
- },
- holding() {
- this.fieldMeter -= this.fieldRegen;
- if (this.fieldMeter < 0) this.fieldMeter = 0;
- Matter.Body.setPosition(this.holdingTarget, {
- x: mech.pos.x + 70 * Math.cos(this.angle),
- y: mech.pos.y + 70 * Math.sin(this.angle)
- });
- Matter.Body.setVelocity(this.holdingTarget, player.velocity);
- Matter.Body.rotate(this.holdingTarget, 0.01 / this.holdingTarget.mass); //gently spin the block
- },
- throw () {
- if ((keys[32] || game.mouseDownRight)) {
- if (this.fieldMeter > 0.002) {
- this.fieldMeter -= 0.002;
- this.throwCharge += this.throwChargeRate;;
- //draw charge
- const x = mech.pos.x + 15 * Math.cos(this.angle);
- const y = mech.pos.y + 15 * Math.sin(this.angle);
- const len = this.holdingTarget.vertices.length - 1;
- const edge = this.throwCharge * this.throwCharge * 0.02;
- const grd = ctx.createRadialGradient(x, y, edge, x, y, edge + 5);
- grd.addColorStop(0, "rgba(255,50,150,0.3)");
- grd.addColorStop(1, "transparent");
- ctx.fillStyle = grd;
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.lineTo(this.holdingTarget.vertices[len].x, this.holdingTarget.vertices[len].y);
- ctx.lineTo(this.holdingTarget.vertices[0].x, this.holdingTarget.vertices[0].y);
- ctx.fill();
- for (let i = 0; i < len; i++) {
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.lineTo(this.holdingTarget.vertices[i].x, this.holdingTarget.vertices[i].y);
- ctx.lineTo(this.holdingTarget.vertices[i + 1].x, this.holdingTarget.vertices[i + 1].y);
- ctx.fill();
- }
- } else {
- this.drop()
- }
- } else if (this.throwCharge > 0) {
- //throw the body
- this.fireCDcycle = mech.cycle + this.fieldFireCD;
- this.isHolding = false;
- //bullet-like collisions
- this.holdingTarget.collisionFilter.category = 0x000100;
- this.holdingTarget.collisionFilter.mask = 0x110111;
- //check every second to see if player is away from thrown body, and make solid
- const solid = function (that) {
- const dx = that.position.x - player.position.x;
- const dy = that.position.y - player.position.y;
- if (dx * dx + dy * dy > 10000 && that.speed < 3 && that !== mech.holdingTarget) {
- that.collisionFilter.category = 0x010000; //make solid
- that.collisionFilter.mask = 0x011111;
- } else {
- setTimeout(solid, 50, that);
- }
- };
- setTimeout(solid, 400, this.holdingTarget);
- //throw speed scales a bit with mass
- const speed = Math.min(85, Math.min(54 / this.holdingTarget.mass + 5, 48) * Math.min(this.throwCharge, this.throwChargeMax) / 50);
-
- this.throwCharge = 0;
- Matter.Body.setVelocity(this.holdingTarget, {
- x: player.velocity.x + Math.cos(this.angle) * speed,
- y: player.velocity.y + Math.sin(this.angle) * speed
- });
- //player recoil //stronger in x-dir to prevent jump hacking
- Matter.Body.setVelocity(player, {
- x: player.velocity.x - Math.cos(this.angle) * speed / 20 * Math.sqrt(this.holdingTarget.mass),
- y: player.velocity.y - Math.sin(this.angle) * speed / 80 * Math.sqrt(this.holdingTarget.mass)
- });
- this.definePlayerMass() //return to normal player mass
- }
- },
- drawField() {
- //draw field
- const range = this.grabRange - 20;
- ctx.beginPath();
- ctx.arc(this.pos.x, this.pos.y, range, this.angle - Math.PI * this.fieldArc, this.angle + Math.PI * this.fieldArc, false);
- let eye = 13;
- ctx.lineTo(mech.pos.x + eye * Math.cos(this.angle), mech.pos.y + eye * Math.sin(this.angle));
- if (this.holdingTarget) {
- ctx.fillStyle = "rgba(110,170,200," + (0.05 + 0.1 * Math.random()) + ")";
- } else {
- ctx.fillStyle = "rgba(110,170,200," + (0.15 + 0.15 * Math.random()) + ")";
- }
- ctx.fill();
- //draw random lines in field for cool effect
- let offAngle = this.angle + 2 * Math.PI * this.fieldArc * (Math.random() - 0.5);
- ctx.beginPath();
- eye = 15;
- ctx.moveTo(mech.pos.x + eye * Math.cos(this.angle), mech.pos.y + eye * Math.sin(this.angle));
- ctx.lineTo(this.pos.x + range * Math.cos(offAngle), this.pos.y + range * Math.sin(offAngle));
- ctx.strokeStyle = "rgba(120,170,255,0.4)";
- ctx.lineWidth = 1;
- ctx.stroke();
- },
- grabPowerUp() {
- //look for power ups to grab
- if (mech.fieldCDcycle < mech.cycle) {
- const grabPowerUpRange2 = (this.grabRange + 220) * (this.grabRange + 220)
- for (let i = 0, len = powerUp.length; i < len; ++i) {
- const dxP = mech.pos.x - powerUp[i].position.x;
- const dyP = mech.pos.y - powerUp[i].position.y;
- const dist2 = dxP * dxP + dyP * dyP;
- // float towards player if looking at and in range or if very close to player
- if (dist2 < grabPowerUpRange2 && this.lookingAt(powerUp[i]) || dist2 < 16000) {
- if (dist2 < 5000) { //use power up if it is close enough
- Matter.Body.setVelocity(player, { //player knock back, after grabbing power up
- x: player.velocity.x + ((powerUp[i].velocity.x * powerUp[i].mass) / player.mass) * 0.3,
- y: player.velocity.y + ((powerUp[i].velocity.y * powerUp[i].mass) / player.mass) * 0.3
- });
- mech.usePowerUp(i);
- return;
- }
- this.fieldMeter -= this.fieldRegen * 0.5;
- powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass;
- powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity
- //extra friction
- Matter.Body.setVelocity(powerUp[i], {
- x: powerUp[i].velocity.x * 0.11,
- y: powerUp[i].velocity.y * 0.11
- });
- }
- }
- }
- },
- pushMobs() {
- // push all mobs in range
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (this.lookingAt(mob[i]) && Matter.Vector.magnitude(Matter.Vector.sub(mob[i].position, this.pos)) < this.grabRange && Matter.Query.ray(map, mob[i].position, this.pos).length === 0) {
- const fieldBlockCost = Math.max(0.02, mob[i].mass * 0.012) //0.012
- if (this.fieldMeter > fieldBlockCost) {
- this.fieldMeter -= fieldBlockCost * this.fieldShieldingScale;
- if (this.fieldMeter < 0) this.fieldMeter = 0;
- if (this.fieldDamage) mob[i].damage(b.dmgScale * this.fieldDamage);
- mob[i].locatePlayer();
- this.drawHold(mob[i]);
- //mob and player knock back
- const angle = Math.atan2(player.position.y - mob[i].position.y, player.position.x - mob[i].position.x);
- const mass = Math.min(Math.sqrt(mob[i].mass), 4);
- Matter.Body.setVelocity(mob[i], {
- x: player.velocity.x - (15 * Math.cos(angle)) / mass,
- y: player.velocity.y - (15 * Math.sin(angle)) / mass
- });
- Matter.Body.setVelocity(player, {
- x: player.velocity.x + 5 * Math.cos(angle) * mass,
- y: player.velocity.y + 5 * Math.sin(angle) * mass
- });
- }
- }
- }
- },
- pushMobs360(range = this.grabRange * 0.75) {
- // push all mobs in range
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (Matter.Vector.magnitude(Matter.Vector.sub(mob[i].position, this.pos)) < range && Matter.Query.ray(map, mob[i].position, this.pos).length === 0) {
- const fieldBlockCost = Math.max(0.02, mob[i].mass * 0.012)
- if (this.fieldMeter > fieldBlockCost) {
- this.fieldMeter -= fieldBlockCost * this.fieldShieldingScale;
- if (this.fieldMeter < 0) this.fieldMeter = 0
-
- if (this.fieldDamage) mob[i].damage(b.dmgScale * this.fieldDamage);
- mob[i].locatePlayer();
- this.drawHold(mob[i]);
- //mob and player knock back
- const angle = Math.atan2(player.position.y - mob[i].position.y, player.position.x - mob[i].position.x);
- const mass = Math.min(Math.sqrt(mob[i].mass), 4);
- // console.log(mob[i].mass, Math.sqrt(mob[i].mass), mass)
- Matter.Body.setVelocity(mob[i], {
- x: player.velocity.x - (15 * Math.cos(angle)) / mass,
- y: player.velocity.y - (15 * Math.sin(angle)) / mass
- });
- Matter.Body.setVelocity(player, {
- x: player.velocity.x + 5 * Math.cos(angle) * mass,
- y: player.velocity.y + 5 * Math.sin(angle) * mass
- });
- }
- }
- }
- },
- lookForPickUp(range = this.grabRange) { //find body to pickup
- this.fieldMeter -= this.fieldRegen;
- const grabbing = {
- targetIndex: null,
- targetRange: range,
- // lookingAt: false //false to pick up object in range, but not looking at
- };
- for (let i = 0, len = body.length; i < len; ++i) {
- if (Matter.Query.ray(map, body[i].position, this.pos).length === 0) {
- //is this next body a better target then my current best
- const dist = Matter.Vector.magnitude(Matter.Vector.sub(body[i].position, this.pos));
- const looking = this.lookingAt(body[i]);
- // if (dist < grabbing.targetRange && (looking || !grabbing.lookingAt) && !body[i].isNotHoldable) {
- if (dist < grabbing.targetRange && looking && !body[i].isNotHoldable) {
- grabbing.targetRange = dist;
- grabbing.targetIndex = i;
- // grabbing.lookingAt = looking;
- }
- }
- }
- // set pick up target for when mouse is released
- if (body[grabbing.targetIndex]) {
- this.holdingTarget = body[grabbing.targetIndex];
- //
- ctx.beginPath(); //draw on each valid body
- let vertices = this.holdingTarget.vertices;
- ctx.moveTo(vertices[0].x, vertices[0].y);
- for (let j = 1; j < vertices.length; j += 1) {
- ctx.lineTo(vertices[j].x, vertices[j].y);
- }
- ctx.lineTo(vertices[0].x, vertices[0].y);
- ctx.fillStyle = "rgba(190,215,230," + (0.3 + 0.7 * Math.random()) + ")";
- ctx.fill();
-
- ctx.globalAlpha = 0.2;
- this.drawHold(this.holdingTarget);
- ctx.globalAlpha = 1;
- } else {
- this.holdingTarget = null;
- }
- },
- pickUp() {
- //triggers when a hold target exits and field button is released
- this.isHolding = true;
- this.definePlayerMass(5 + this.holdingTarget.mass * this.holdingMassScale)
- //collide with nothing
- this.holdingTarget.collisionFilter.category = 0x000000;
- this.holdingTarget.collisionFilter.mask = 0x000000;
- // if (this.holdingTarget) {
- // this.holdingTarget.collisionFilter.category = 0x010000;
- // this.holdingTarget.collisionFilter.mask = 0x011111;
- // }
- // combine momentum // this doesn't feel right in game
- // const px = player.velocity.x * player.mass + this.holdingTarget.velocity.x * this.holdingTarget.mass;
- // const py = player.velocity.y * player.mass + this.holdingTarget.velocity.y * this.holdingTarget.mass;
- // Matter.Body.setVelocity(player, {
- // x: px / (player.mass + this.holdingTarget.mass),
- // y: py / (player.mass + this.holdingTarget.mass)
- // });
- },
- wakeCheck() {
- if (mech.isBodiesAsleep) {
- mech.isBodiesAsleep = false;
-
- function wake(who) {
- for (let i = 0, len = who.length; i < len; ++i) {
- Matter.Sleeping.set(who[i], false)
- if (who[i].storeVelocity) {
- Matter.Body.setVelocity(who[i], {
- x: who[i].storeVelocity.x,
- y: who[i].storeVelocity.y
- })
- Matter.Body.setAngularVelocity(who[i], who[i].storeAngularVelocity)
- }
- }
- }
- wake(mob);
- wake(body);
- wake(bullet);
- for (let i = 0, len = cons.length; i < len; i++) {
- if (cons[i].stiffness === 0) {
- cons[i].stiffness = cons[i].storeStiffness
- }
- }
- // wake(powerUp);
- }
- },
- hold() {},
- fieldText() {
- game.makeTextLog(`${mech.fieldUpgrades[mech.fieldMode].name} (right click or space bar)
${mech.fieldUpgrades[mech.fieldMode].description}
`, 1200);
- game.updateModHUD()
- },
- fieldUpgrades: [{
- name: "Field Emitter",
- description: "lets you pick up and throw objects shields you from damage",
- effect: () => {
- mech.fieldMode = 0;
- mech.fieldText();
- // game.makeTextLog(" (right click or space bar)", 1200);
- mech.setHoldDefaults();
- mech.hold = function () {
- if (mech.isHolding) {
- mech.drawHold(mech.holdingTarget);
- mech.holding();
- mech.throw();
- } else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed
- mech.drawField();
- mech.grabPowerUp();
- mech.pushMobs();
- mech.lookForPickUp();
- } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
- mech.pickUp();
- } else {
- mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- mech.drawFieldMeter()
- }
- }
- },
- {
- name: "Time Dilation Field",
- description: "stop time while field is active can fire while field is active",
- effect: () => {
- mech.fieldMode = 1;
- mech.fieldText();
- mech.setHoldDefaults();
- mech.fieldFire = true;
- mech.grabRange = 130
- mech.isBodiesAsleep = false;
- mech.hold = function () {
- if (mech.isHolding) {
- mech.wakeCheck();
- mech.drawHold(mech.holdingTarget);
- mech.holding();
- mech.throw();
- } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) {
- const DRAIN = 0.0027
- if (mech.fieldMeter > DRAIN) {
- mech.fieldMeter -= DRAIN;
-
- //draw field everywhere
- ctx.fillStyle = "rgba(110,170,200," + (0.19 + 0.16 * Math.random()) + ")";
- ctx.fillRect(-100000, -100000, 200000, 200000)
-
- //stop time
- mech.isBodiesAsleep = true;
-
- function sleep(who) {
- for (let i = 0, len = who.length; i < len; ++i) {
- if (!who[i].isSleeping) {
- who[i].storeVelocity = who[i].velocity
- who[i].storeAngularVelocity = who[i].angularVelocity
- }
- Matter.Sleeping.set(who[i], true)
- }
- }
- sleep(mob);
- sleep(body);
- sleep(bullet);
- //doesn't really work, just slows down constraints
- for (let i = 0, len = cons.length; i < len; i++) {
- if (cons[i].stiffness !== 0) {
- cons[i].storeStiffness = cons[i].stiffness;
- cons[i].stiffness = 0;
- }
- }
- game.cycle--; //pause all functions that depend on game cycle increasing
-
- mech.grabPowerUp();
- mech.lookForPickUp(180);
- } else {
- mech.wakeCheck();
- mech.fieldCDcycle = mech.cycle + 120;
- }
- } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
- mech.wakeCheck();
- mech.pickUp();
- } else {
- mech.wakeCheck();
- mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- mech.drawFieldMeter()
- if (mech.fieldMode !== 1) {
- //wake up if this is no longer the current field mode, like after a new power up
- mech.wakeCheck();
-
- }
- }
- }
- },
- {
- name: "Electrostatic Field",
- description: "field does damage on contact blocks are thrown at a higher velocity increased field regeneration",
- effect: () => {
- mech.fieldMode = 2;
- mech.fieldText();
- mech.setHoldDefaults();
- //throw quicker and harder
- mech.grabRange = 225;
- mech.fieldShieldingScale = 2;
- mech.fieldRegen *= 2;
- mech.throwChargeRate = 3;
- mech.throwChargeMax = 140;
- mech.fieldDamage = 5; //passive field does extra damage
- // mech.fieldArc = 0.11
- // mech.calculateFieldThreshold(); //run after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
-
- mech.hold = function () {
- if (mech.isHolding) {
- mech.drawHold(mech.holdingTarget);
- mech.holding();
- mech.throw();
- } else if ((keys[32] || game.mouseDownRight) && mech.fieldMeter > 0.15) { //not hold but field button is pressed
- //draw electricity
- const Dx = Math.cos(mech.angle);
- const Dy = Math.sin(mech.angle);
- let x = mech.pos.x + 20 * Dx;
- let y = mech.pos.y + 20 * Dy;
- ctx.beginPath();
- ctx.moveTo(x, y);
- for (let i = 0; i < 8; i++) {
- x += 18 * (Dx + 2 * (Math.random() - 0.5))
- y += 18 * (Dy + 2 * (Math.random() - 0.5))
- ctx.lineTo(x, y);
- }
- ctx.lineWidth = 1 //0.5 + 2 * Math.random();
- ctx.strokeStyle = `rgba(100,20,50,${0.5+0.5*Math.random()})`;
- ctx.stroke();
-
- //draw field
- const range = 170;
- const arc = Math.PI * 0.11
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, range, mech.angle - arc, mech.angle + arc, false);
- ctx.lineTo(mech.pos.x + 13 * Math.cos(mech.angle), mech.pos.y + 13 * Math.sin(mech.angle));
- if (mech.holdingTarget) {
- ctx.fillStyle = "rgba(255,50,150," + (0.05 + 0.1 * Math.random()) + ")";
- } else {
- ctx.fillStyle = "rgba(255,50,150," + (0.13 + 0.18 * Math.random()) + ")";
- }
- ctx.fill();
-
- //draw random lines in field for cool effect
- // eye = 15;
- // ctx.beginPath();
- // ctx.moveTo(mech.pos.x + eye * Math.cos(mech.angle), mech.pos.y + eye * Math.sin(mech.angle));
- // const offAngle = mech.angle + 2 * Math.PI * mech.fieldArc * (Math.random() - 0.5);
- // ctx.lineTo(mech.pos.x + range * Math.cos(offAngle), mech.pos.y + range * Math.sin(offAngle));
- // ctx.strokeStyle = "rgba(100,20,50,0.2)";
- // ctx.stroke();
-
- mech.grabPowerUp();
- mech.pushMobs();
- mech.lookForPickUp();
- } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
- mech.pickUp();
- } else {
- mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- mech.drawFieldMeter()
- }
- }
- },
- {
- name: "Negative Mass Field",
- description: "field nullifies gravity player can hold more massive objects can fire while field is active",
- effect: () => {
- mech.fieldMode = 3;
- mech.fieldText();
- // decreased field shielding efficiency
- mech.setHoldDefaults();
- mech.fieldFire = true;
- mech.holdingMassScale = 0.05; //can hold heavier blocks with lower cost to jumping
- mech.fieldShieldingScale = 2;
-
- mech.hold = function () {
- if (mech.isHolding) {
- mech.drawHold(mech.holdingTarget);
- mech.holding();
- mech.throw();
- } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //push away
- const DRAIN = 0.0006
- if (mech.fieldMeter > DRAIN) {
- mech.pushMobs360(170);
- mech.grabPowerUp();
- mech.lookForPickUp(170);
- //look for nearby objects to make zero-g
- function zeroG(who) {
- for (let i = 0, len = who.length; i < len; ++i) {
- sub = Matter.Vector.sub(who[i].position, mech.pos);
- dist = Matter.Vector.magnitude(sub);
- if (dist < mech.grabRange) {
- who[i].force.y -= who[i].mass * (game.g * 1.06); //add a bit more then standard gravity
- }
- }
- }
- zeroG(powerUp);
- zeroG(body);
- // zeroG(bullet); //works fine, but not that noticeable and maybe not worth the possible performance hit
- // zeroG(mob); //mobs are too irregular to make this work?
-
- Matter.Body.setVelocity(player, {
- x: player.velocity.x,
- y: player.velocity.y * 0.97
- });
-
- if (keys[83] || keys[40]) { //down
- player.force.y -= 0.8 * player.mass * mech.gravity;
- mech.grabRange = mech.grabRange * 0.97 + 400 * 0.03;
- } else if (keys[87] || keys[38]) { //up
- mech.fieldMeter -= 3 * DRAIN;
- mech.grabRange = mech.grabRange * 0.97 + 750 * 0.03;
- player.force.y -= 1.2 * player.mass * mech.gravity;
- } else {
- mech.fieldMeter -= DRAIN;
- mech.grabRange = mech.grabRange * 0.97 + 650 * 0.03;
- player.force.y -= 1.07 * player.mass * mech.gravity; // slow upward drift
- }
-
- //add extra friction for horizontal motion
- if (keys[65] || keys[68] || keys[37] || keys[39]) {
- Matter.Body.setVelocity(player, {
- x: player.velocity.x * 0.85,
- y: player.velocity.y
- });
- }
-
- //draw zero-G range
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, mech.grabRange, 0, 2 * Math.PI);
- ctx.fillStyle = "#f5f5ff";
- ctx.globalCompositeOperation = "difference";
- ctx.fill();
- ctx.globalCompositeOperation = "source-over";
- } else {
- //trigger cool down
- mech.fieldCDcycle = mech.cycle + 120;
- }
- } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
- mech.pickUp();
- mech.grabRange = 0
- } else {
- mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- mech.grabRange = 0
- }
- mech.drawFieldMeter()
- }
- }
- },
- {
- name: "Standing Wave Harmonics",
- description: "oscillating shields always surround player decreased field regeneration",
- effect: () => {
- mech.fieldMode = 4;
- mech.fieldText();
- mech.setHoldDefaults();
- // mech.fieldShieldingScale = 0.5;
- mech.fieldRegen *= 0.2;
-
- mech.hold = function () {
- if (mech.isHolding) {
- mech.drawHold(mech.holdingTarget);
- mech.holding();
- mech.throw();
- } else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed
- mech.grabPowerUp();
- mech.lookForPickUp(180);
- } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle) { //holding, but field button is released
- mech.pickUp();
- } else {
- mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- if (mech.fieldMeter > 0.1) {
- const grabRange1 = 90 + 60 * Math.sin(mech.cycle / 23)
- const grabRange2 = 85 + 70 * Math.sin(mech.cycle / 37)
- const grabRange3 = 80 + 80 * Math.sin(mech.cycle / 47)
- const netGrabRange = Math.max(grabRange1, grabRange2, grabRange3)
- ctx.fillStyle = "rgba(110,170,200," + (0.15 + 0.15 * Math.random()) + ")";
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, grabRange1, 0, 2 * Math.PI);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, grabRange2, 0, 2 * Math.PI);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, grabRange3, 0, 2 * Math.PI);
- ctx.fill();
- mech.pushMobs360(netGrabRange);
- }
- mech.drawFieldMeter()
- }
- }
- },
- {
- name: "Nano-Scale Manufacturing",
- description: "excess field energy used to build drones increased field regeneration",
- effect: () => {
- mech.fieldMode = 5;
- mech.fieldText();
- mech.setHoldDefaults();
- mech.fieldRegen *= 3.5;
- mech.hold = function () {
- if (mech.fieldMeter === 1) {
- mech.fieldMeter -= 0.5;
- b.guns[12].fire() //spawn drone
- }
- if (mech.isHolding) {
- mech.drawHold(mech.holdingTarget);
- mech.holding();
- mech.throw();
- } else if ((keys[32] || game.mouseDownRight && mech.fieldMeter > 0.1)) { //not hold but field button is pressed
- mech.pushMobs();
- mech.drawField();
- mech.grabPowerUp();
- mech.lookForPickUp();
- } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
- mech.pickUp();
- } else {
- mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- mech.drawFieldMeter()
- }
- }
- },
- {
- name: "Phase Decoherence Field",
- description: "intangible while field is active can't see or be seen outside field",
- effect: () => {
- mech.fieldMode = 6;
- mech.fieldText();
- mech.setHoldDefaults();
- // mech.grabRange = 230
- mech.hold = function () {
- mech.isStealth = false //isStealth is checked in mob foundPlayer()
- player.collisionFilter.mask = 0x010011 //0x010011 is normal
- if (mech.isHolding) {
- mech.drawHold(mech.holdingTarget);
- mech.holding();
- mech.throw();
- } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) {
- const DRAIN = 0.002
- if (mech.fieldMeter > DRAIN) {
- mech.fieldMeter -= DRAIN;
-
- mech.isStealth = true //isStealth is checked in mob foundPlayer()
- player.collisionFilter.mask = 0x000001 //0x010011 is normals
-
- ctx.beginPath();
- ctx.arc(mech.pos.x, mech.pos.y, mech.grabRange, 0, 2 * Math.PI);
- ctx.globalCompositeOperation = "destination-in"; //in or atop
- ctx.fillStyle = "rgba(255,255,255,0.25)";
- ctx.fill();
- ctx.globalCompositeOperation = "source-over";
- ctx.strokeStyle = "#000"
- ctx.lineWidth = 2;
- ctx.stroke();
-
- mech.grabPowerUp();
- mech.lookForPickUp(110);
- } else {
- mech.fieldCDcycle = mech.cycle + 120;
- }
- } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
- mech.pickUp();
- } else {
- mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- }
- mech.drawFieldMeter()
- }
- }
- },
- // () => {
- // mech.fieldMode = 7;
- // game.makeTextLog("Thermal Radiation Field (right click or space bar)
field grows while active damages all targets within range, including player decreased field shielding efficiency
", 1200);
- // mech.setHoldDefaults();
- // mech.fieldShieldingScale = 10;
- // mech.rangeSmoothing = 0
- // mech.hold = function () {
- // if (mech.isHolding) {
- // mech.drawHold(mech.holdingTarget);
- // mech.holding();
- // mech.throw();
- // } else if ((keys[32] || game.mouseDownRight && mech.fieldCDcycle < mech.cycle)) { //not hold but field button is pressed
- // mech.grabPowerUp();
- // mech.lookForPickUp(Math.max(180, mech.grabRange));
- // mech.pushMobs360(140);
-
- // if (mech.health > 0.1) {
- // const DRAIN = 0.0008
- // if (mech.fieldMeter > DRAIN) {
- // mech.fieldMeter -= DRAIN;
- // mech.damage(0.00005 + 0.00000012 * mech.grabRange)
- // //draw damage field
- // mech.grabRange = mech.grabRange * 0.997 + (1350 + 150 * Math.cos(mech.cycle / 30)) * 0.003
- // let gradient = ctx.createRadialGradient(this.pos.x, this.pos.y, 0, this.pos.x, this.pos.y, mech.grabRange);
- // gradient.addColorStop(0, 'rgba(255,255,255,0.7)');
- // gradient.addColorStop(1, 'rgba(255,0,50,' + (0.6 + 0.2 * Math.random()) + ')');
-
- // const angleOff = 2 * Math.PI * Math.random()
- // ctx.beginPath();
- // ctx.arc(this.pos.x, this.pos.y, mech.grabRange + Math.sqrt(mech.grabRange) * 0.7 * (Math.random() - 0.5), angleOff, 1.8 * Math.PI + angleOff);
- // ctx.fillStyle = gradient //rgba(255,0,0,0.2)
- // ctx.fill();
-
- // //damage and push away mobs in range
- // for (let i = 0, len = mob.length; i < len; ++i) {
- // if (mob[i].alive) {
- // sub = Matter.Vector.sub(this.pos, mob[i].position);
- // dist = Matter.Vector.magnitude(sub);
- // if (dist < mech.grabRange) {
- // mob[i].damage(0.01);
- // mob[i].locatePlayer();
- // mob[i].force = Matter.Vector.mult(Matter.Vector.normalise(sub), -0.0001 * mob[i].mass) //gently push mobs back
- // }
- // }
- // }
- // } else {
- // mech.fieldCDcycle = mech.cycle + 120;
- // }
- // } else {
- // mech.grabRange = 180;
- // mech.drawField();
- // mech.grabPowerUp();
- // mech.lookForPickUp();
- // }
- // } else if (mech.holdingTarget && mech.fireCDcycle < mech.cycle && mech.fieldMeter > 0.05) { //holding, but field button is released
- // mech.grabRange = 0
- // mech.pickUp();
- // } else {
- // mech.grabRange = 0
- // mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
- // }
- // mech.drawFieldMeter()
- // }
- // },
- ],
- drawLeg(stroke) {
- // if (game.mouseInGame.x > this.pos.x) {
- if (mech.angle > -Math.PI / 2 && mech.angle < Math.PI / 2) {
- this.flipLegs = 1;
- } else {
- this.flipLegs = -1;
- }
- ctx.save();
- ctx.scale(this.flipLegs, 1); //leg lines
- ctx.beginPath();
- ctx.moveTo(this.hip.x, this.hip.y);
- ctx.lineTo(this.knee.x, this.knee.y);
- ctx.lineTo(this.foot.x, this.foot.y);
- ctx.strokeStyle = stroke;
- ctx.lineWidth = 7;
- ctx.stroke();
-
- //toe lines
- ctx.beginPath();
- ctx.moveTo(this.foot.x, this.foot.y);
- ctx.lineTo(this.foot.x - 15, this.foot.y + 5);
- ctx.moveTo(this.foot.x, this.foot.y);
- ctx.lineTo(this.foot.x + 15, this.foot.y + 5);
- ctx.lineWidth = 4;
- ctx.stroke();
-
- //hip joint
- ctx.beginPath();
- ctx.arc(this.hip.x, this.hip.y, 11, 0, 2 * Math.PI);
- //knee joint
- ctx.moveTo(this.knee.x + 7, this.knee.y);
- ctx.arc(this.knee.x, this.knee.y, 7, 0, 2 * Math.PI);
- //foot joint
- ctx.moveTo(this.foot.x + 6, this.foot.y);
- ctx.arc(this.foot.x, this.foot.y, 6, 0, 2 * Math.PI);
- ctx.fillStyle = this.fillColor;
- ctx.fill();
- ctx.lineWidth = 2;
- ctx.stroke();
- ctx.restore();
- },
- calcLeg(cycle_offset, offset) {
- this.hip.x = 12 + offset;
- this.hip.y = 24 + offset;
- //stepSize goes to zero if Vx is zero or not on ground (make this transition cleaner)
- this.stepSize = 0.8 * this.stepSize + 0.2 * (7 * Math.sqrt(Math.min(9, Math.abs(this.Vx))) * this.onGround);
- //changes to stepsize are smoothed by adding only a percent of the new value each cycle
- const stepAngle = 0.034 * this.walk_cycle + cycle_offset;
- this.foot.x = 2.2 * this.stepSize * Math.cos(stepAngle) + offset;
- this.foot.y = offset + 1.2 * this.stepSize * Math.sin(stepAngle) + this.yOff + this.height;
- const Ymax = this.yOff + this.height;
- if (this.foot.y > Ymax) this.foot.y = Ymax;
-
- //calculate knee position as intersection of circle from hip and foot
- const d = Math.sqrt((this.hip.x - this.foot.x) * (this.hip.x - this.foot.x) + (this.hip.y - this.foot.y) * (this.hip.y - this.foot.y));
- const l = (this.legLength1 * this.legLength1 - this.legLength2 * this.legLength2 + d * d) / (2 * d);
- const h = Math.sqrt(this.legLength1 * this.legLength1 - l * l);
- this.knee.x = (l / d) * (this.foot.x - this.hip.x) - (h / d) * (this.foot.y - this.hip.y) + this.hip.x + offset;
- this.knee.y = (l / d) * (this.foot.y - this.hip.y) + (h / d) * (this.foot.x - this.hip.x) + this.hip.y;
- },
- draw() {
- ctx.fillStyle = this.fillColor;
- this.walk_cycle += this.flipLegs * this.Vx;
-
- //draw body
- ctx.save();
- ctx.translate(this.pos.x, this.pos.y);
- this.calcLeg(Math.PI, -3);
- this.drawLeg("#4a4a4a");
- this.calcLeg(0, 0);
- this.drawLeg("#333");
- ctx.rotate(this.angle);
-
- ctx.beginPath();
- ctx.arc(0, 0, 30, 0, 2 * Math.PI);
- let grd = ctx.createLinearGradient(-30, 0, 30, 0);
- grd.addColorStop(0, this.fillColorDark);
- grd.addColorStop(1, this.fillColor);
- ctx.fillStyle = grd;
- ctx.fill();
- ctx.arc(15, 0, 4, 0, 2 * Math.PI);
- ctx.strokeStyle = "#333";
- ctx.lineWidth = 2;
- ctx.stroke();
- // ctx.beginPath();
- // ctx.arc(15, 0, 3, 0, 2 * Math.PI);
- // ctx.fillStyle = '#9cf' //'#0cf';
- // ctx.fill()
- ctx.restore();
- }
-};
\ No newline at end of file
diff --git a/js/powerups.js b/js/powerups.js
deleted file mode 100644
index 6100163..0000000
--- a/js/powerups.js
+++ /dev/null
@@ -1,233 +0,0 @@
-let powerUp = [];
-
-const powerUps = {
- heal: {
- name: "heal",
- color: "#0f9",
- size() {
- return 40 * Math.sqrt(0.1 + Math.random() * 0.5);
- },
- effect() {
- let heal = (this.size / 40) ** 2
- heal = Math.min(1 - mech.health, heal)
- mech.addHealth(heal);
- if (!game.lastLogTime && heal > 0) game.makeTextLog('heal for ' + (heal * 100).toFixed(0) + '%', 180)
- }
- },
- field: {
- name: "field",
- color: "#f9f",
- size() {
- return 40;
- },
- effect() {
- const previousMode = mech.fieldMode
-
- if (!this.mode) { //this.mode is set if the power up has been ejected from player
- mode = mech.fieldMode
- while (mode === mech.fieldMode) {
- mode = Math.ceil(Math.random() * (mech.fieldUpgrades.length - 1))
- }
- mech.fieldUpgrades[mode].effect(); //choose random field upgrade that you don't already have
- } else {
- mech.fieldUpgrades[this.mode].effect(); //set a predetermined power up
- }
- //pop the old field out in case player wants to swap back
- if (previousMode !== 0) {
- mech.fieldCDcycle = mech.cycle + 40; //trigger fieldCD to stop power up grab automatic pick up of spawn
- powerUps.spawn(mech.pos.x, mech.pos.y - 15, "field", false, previousMode);
- }
- }
- },
- mod: {
- name: "mod",
- color: "#479",
- size() {
- return 42;
- },
- effect() {
- const previousMode = b.mod
- if (this.mode === null) { //this.mode is set if the power up has been ejected from player
- mode = b.mod //start with current mob
- while (mode === b.mod) {
- mode = Math.floor(Math.random() * b.mods.length)
- }
- b.mods[mode].effect(); //choose random upgrade that you don't already have
- } else {
- b.mods[this.mode].effect(); //set a predetermined power up
- }
- if (previousMode != null) { //pop the old field out in case player wants to swap back
- mech.fieldCDcycle = mech.cycle + 40; //trigger fieldCD to stop power up grab automatic pick up of spawn
- powerUps.spawn(mech.pos.x, mech.pos.y - 15, "mod", false, previousMode);
- }
- }
- },
- ammo: {
- name: "ammo",
- color: "#467",
- size() {
- return 17;
- },
- effect() {
- //only get ammo for guns player has
- let target;
- // console.log(b.inventory.length)
- if (b.inventory.length > 0) {
- //add ammo to a gun in inventory
- target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]];
- //try 3 more times to give ammo to a gun with ammo, not Infinity
- if (target.ammo === Infinity) {
- target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]]
- if (target.ammo === Infinity) {
- target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]]
- if (target.ammo === Infinity) target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]]
- }
- }
- } else {
- //if you don't have any guns just add ammo to a random gun you don't have yet
- target = b.guns[Math.floor(Math.random() * b.guns.length)];
- }
- if (target.ammo === Infinity) {
- mech.fieldMeter = 1;
- if (!game.lastLogTime) game.makeTextLog("+energy", 180);
- } else {
- //ammo given scales as mobs take more hits to kill
- const ammo = Math.ceil((target.ammoPack * (0.5 + 0.04 * Math.random())) / b.dmgScale);
- target.ammo += ammo;
- game.updateGunHUD();
- if (!game.lastLogTime) game.makeTextLog("+" + ammo + " ammo: " + target.name, 180);
- }
- }
- },
- gun: {
- name: "gun",
- color: "#0bf",
- size() {
- return 30;
- },
- effect() {
- //find what guns I don't have
- let options = [];
- if (b.activeGun === null) { //the first gun is good for the early game
- options = [0, 1, 2, 3, 4, 5, 6, 8, 9, 12]
- } else {
- for (let i = 0; i < b.guns.length; ++i) {
- if (!b.guns[i].have) options.push(i);
- }
- }
- //give player a gun they don't already have if possible
- if (options.length > 0) {
- let newGun = options[Math.floor(Math.random() * options.length)];
- // newGun = 4; //makes every gun you pick up this type //enable for testing one gun
- if (b.activeGun === null) {
- b.activeGun = newGun //if no active gun switch to new gun
- game.makeTextLog(
- // "
left mouse: fire weapon
️
",
- "Use left mouse to fire weapon.",
- Infinity
- );
- }
- if (b.inventory.length === 1) { //on the second gun pick up tell player how to change guns
- game.makeTextLog(`(Q, E, and mouse wheel change weapons)