added laser bot

This commit is contained in:
landgreen
2019-12-07 13:38:39 -08:00
committed by GitHub
parent 53b7cf7bc6
commit 7508b52d91
9 changed files with 9615 additions and 9596 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,233 +1,233 @@
//matter.js *********************************************************** //matter.js ***********************************************************
// module aliases // module aliases
const Engine = Matter.Engine, const Engine = Matter.Engine,
World = Matter.World, World = Matter.World,
Events = Matter.Events, Events = Matter.Events,
Composites = Matter.Composites, Composites = Matter.Composites,
Composite = Matter.Composite, Composite = Matter.Composite,
Constraint = Matter.Constraint, Constraint = Matter.Constraint,
Vertices = Matter.Vertices, Vertices = Matter.Vertices,
Query = Matter.Query, Query = Matter.Query,
Body = Matter.Body, Body = Matter.Body,
Bodies = Matter.Bodies; Bodies = Matter.Bodies;
// create an engine // create an engine
const engine = Engine.create(); const engine = Engine.create();
engine.world.gravity.scale = 0; //turn off gravity (it's added back in later) engine.world.gravity.scale = 0; //turn off gravity (it's added back in later)
// engine.velocityIterations = 100 // engine.velocityIterations = 100
// engine.positionIterations = 100 // engine.positionIterations = 100
// engine.enableSleeping = true // engine.enableSleeping = true
// matter events ********************************************************* // matter events *********************************************************
//************************************************************************ //************************************************************************
//************************************************************************ //************************************************************************
//************************************************************************ //************************************************************************
function playerOnGroundCheck(event) { function playerOnGroundCheck(event) {
//runs on collisions events //runs on collisions events
function enter() { function enter() {
mech.numTouching++; mech.numTouching++;
if (!mech.onGround) mech.enterLand(); if (!mech.onGround) mech.enterLand();
} }
const pairs = event.pairs; const pairs = event.pairs;
for (let i = 0, j = pairs.length; i != j; ++i) { for (let i = 0, j = pairs.length; i != j; ++i) {
let pair = pairs[i]; let pair = pairs[i];
if (pair.bodyA === jumpSensor) { if (pair.bodyA === jumpSensor) {
mech.standingOn = pair.bodyB; //keeping track to correctly provide recoil on jump mech.standingOn = pair.bodyB; //keeping track to correctly provide recoil on jump
if (mech.standingOn.alive !== true) enter(); if (mech.standingOn.alive !== true) enter();
} else if (pair.bodyB === jumpSensor) { } else if (pair.bodyB === jumpSensor) {
mech.standingOn = pair.bodyA; //keeping track to correctly provide recoil on jump mech.standingOn = pair.bodyA; //keeping track to correctly provide recoil on jump
if (mech.standingOn.alive !== true) enter(); if (mech.standingOn.alive !== true) enter();
} }
} }
mech.numTouching = 0; mech.numTouching = 0;
} }
function playerOffGroundCheck(event) { function playerOffGroundCheck(event) {
//runs on collisions events //runs on collisions events
function enter() { function enter() {
if (mech.onGround && mech.numTouching === 0) mech.enterAir(); if (mech.onGround && mech.numTouching === 0) mech.enterAir();
} }
const pairs = event.pairs; const pairs = event.pairs;
for (let i = 0, j = pairs.length; i != j; ++i) { for (let i = 0, j = pairs.length; i != j; ++i) {
if (pairs[i].bodyA === jumpSensor) { if (pairs[i].bodyA === jumpSensor) {
enter(); enter();
} else if (pairs[i].bodyB === jumpSensor) { } else if (pairs[i].bodyB === jumpSensor) {
enter(); enter();
} }
} }
} }
function playerHeadCheck(event) { function playerHeadCheck(event) {
//runs on collisions events //runs on collisions events
if (mech.crouch) { if (mech.crouch) {
mech.isHeadClear = true; mech.isHeadClear = true;
const pairs = event.pairs; const pairs = event.pairs;
for (let i = 0, j = pairs.length; i != j; ++i) { for (let i = 0, j = pairs.length; i != j; ++i) {
if (pairs[i].bodyA === headSensor) { if (pairs[i].bodyA === headSensor) {
mech.isHeadClear = false; mech.isHeadClear = false;
} else if (pairs[i].bodyB === headSensor) { } else if (pairs[i].bodyB === headSensor) {
mech.isHeadClear = false; mech.isHeadClear = false;
} }
} }
} }
} }
function mobCollisionChecks(event) { function mobCollisionChecks(event) {
const pairs = event.pairs; const pairs = event.pairs;
for (let i = 0, j = pairs.length; i != j; i++) { for (let i = 0, j = pairs.length; i != j; i++) {
//body + player collision //body + player collision
if (game.isBodyDamage && mech.damageImmune < mech.cycle) { if (game.isBodyDamage && mech.damageImmune < mech.cycle) {
if (pairs[i].bodyA === playerBody || pairs[i].bodyA === playerHead) { if (pairs[i].bodyA === playerBody || pairs[i].bodyA === playerHead) {
collidePlayer(pairs[i].bodyB) collidePlayer(pairs[i].bodyB)
} else if (pairs[i].bodyB === playerBody || pairs[i].bodyB === playerHead) { } else if (pairs[i].bodyB === playerBody || pairs[i].bodyB === playerHead) {
collidePlayer(pairs[i].bodyA) collidePlayer(pairs[i].bodyA)
} }
} }
function collidePlayer(obj, speedThreshold = 12, massThreshold = 2) { function collidePlayer(obj, speedThreshold = 12, massThreshold = 2) {
if (obj.classType === "body" && obj.speed > speedThreshold && obj.mass > massThreshold) { //dmg from hitting a body if (obj.classType === "body" && obj.speed > speedThreshold && obj.mass > massThreshold) { //dmg from hitting a body
const v = Matter.Vector.magnitude(Matter.Vector.sub(player.velocity, obj.velocity)); const v = Matter.Vector.magnitude(Matter.Vector.sub(player.velocity, obj.velocity));
if (v > speedThreshold) { if (v > speedThreshold) {
mech.damageImmune = mech.cycle + 30; //player is immune to collision damage for 30 cycles mech.damageImmune = mech.cycle + 30; //player is immune to collision damage for 30 cycles
let dmg = Math.sqrt((v - speedThreshold + 0.1) * (obj.mass - massThreshold)) * 0.01; let dmg = Math.sqrt((v - speedThreshold + 0.1) * (obj.mass - massThreshold)) * 0.01;
dmg = Math.min(Math.max(dmg, 0.02), 0.15); dmg = Math.min(Math.max(dmg, 0.02), 0.15);
mech.damage(dmg); mech.damage(dmg);
game.drawList.push({ //add dmg to draw queue game.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y, y: pairs[i].activeContacts[0].vertex.y,
radius: dmg * 500, radius: dmg * 500,
color: game.mobDmgColor, color: game.mobDmgColor,
time: game.drawTime time: game.drawTime
}); });
return; return;
} }
} }
// else if (obj.isStatic && player.speed > speedThreshold * 2) { //falling dmg / hitting map dmg // else if (obj.isStatic && player.speed > speedThreshold * 2) { //falling dmg / hitting map dmg
// mech.damageImmune = mech.cycle + 30; // mech.damageImmune = mech.cycle + 30;
// console.log(player.speed) // console.log(player.speed)
// let dmg = Math.min(Math.max(player.speed * 0.001, 0.02), 0.2); // let dmg = Math.min(Math.max(player.speed * 0.001, 0.02), 0.2);
// mech.damage(dmg); // mech.damage(dmg);
// game.drawList.push({ // game.drawList.push({
// //add dmg to draw queue // //add dmg to draw queue
// x: pairs[i].activeContacts[0].vertex.x, // x: pairs[i].activeContacts[0].vertex.x,
// y: pairs[i].activeContacts[0].vertex.y, // y: pairs[i].activeContacts[0].vertex.y,
// radius: dmg * 500, // radius: dmg * 500,
// color: game.mobDmgColor, // color: game.mobDmgColor,
// time: game.drawTime // time: game.drawTime
// }); // });
// return; // return;
// } // }
} }
//mob + (player,bullet,body) collisions //mob + (player,bullet,body) collisions
for (let k = 0; k < mob.length; k++) { for (let k = 0; k < mob.length; k++) {
if (mob[k].alive && mech.alive) { if (mob[k].alive && mech.alive) {
if (pairs[i].bodyA === mob[k]) { if (pairs[i].bodyA === mob[k]) {
collideMob(pairs[i].bodyB); collideMob(pairs[i].bodyB);
break; break;
} else if (pairs[i].bodyB === mob[k]) { } else if (pairs[i].bodyB === mob[k]) {
collideMob(pairs[i].bodyA); collideMob(pairs[i].bodyA);
break; break;
} }
function collideMob(obj) { function collideMob(obj) {
//player + mob collision //player + mob collision
if (obj === playerBody || obj === playerHead) { if (obj === playerBody || obj === playerHead) {
if (mech.damageImmune < mech.cycle) { if (mech.damageImmune < mech.cycle) {
mech.damageImmune = mech.cycle + 30; //player is immune to collision damage for 30 cycles mech.damageImmune = mech.cycle + 30; //player is immune to collision damage for 30 cycles
mob[k].foundPlayer(); mob[k].foundPlayer();
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
mech.damage(dmg); mech.damage(dmg);
if (mob[k].onHit) mob[k].onHit(k); if (mob[k].onHit) mob[k].onHit(k);
if (b.modAnnihilation && mob[k].dropPowerUp) { if (b.modAnnihilation && mob[k].dropPowerUp) {
mob[k].death(); mob[k].death();
game.drawList.push({ game.drawList.push({
//add dmg to draw queue //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y, y: pairs[i].activeContacts[0].vertex.y,
radius: dmg * 2000, radius: dmg * 2000,
color: "rgba(255,0,255,0.2)", color: "rgba(255,0,255,0.2)",
time: game.drawTime time: game.drawTime
}); });
} else { } else {
game.drawList.push({ game.drawList.push({
//add dmg to draw queue //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y, y: pairs[i].activeContacts[0].vertex.y,
radius: dmg * 500, radius: dmg * 500,
color: game.mobDmgColor, color: game.mobDmgColor,
time: game.drawTime time: game.drawTime
}); });
} }
} }
//extra kick between player and mob //this section would be better with forces but they don't work... //extra kick between player and mob //this section would be better with forces but they don't work...
let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x); let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, {
x: player.velocity.x + 8 * Math.cos(angle), x: player.velocity.x + 8 * Math.cos(angle),
y: player.velocity.y + 8 * Math.sin(angle) y: player.velocity.y + 8 * Math.sin(angle)
}); });
Matter.Body.setVelocity(mob[k], { Matter.Body.setVelocity(mob[k], {
x: mob[k].velocity.x - 8 * Math.cos(angle), x: mob[k].velocity.x - 8 * Math.cos(angle),
y: mob[k].velocity.y - 8 * Math.sin(angle) y: mob[k].velocity.y - 8 * Math.sin(angle)
}); });
return; return;
} }
//mob + bullet collisions //mob + bullet collisions
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) {
// const dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity))); // const dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity)));
let dmg = b.dmgScale * (obj.dmg + b.modExtraDmg + 0.15 * obj.mass * Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity))) let dmg = b.dmgScale * (obj.dmg + b.modExtraDmg + 0.15 * obj.mass * Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity)))
if (b.modIsCrit && !mob[k].seePlayer.recall) dmg *= 5 if (b.modIsCrit && !mob[k].seePlayer.recall) dmg *= 5
mob[k].foundPlayer(); mob[k].foundPlayer();
mob[k].damage(dmg); mob[k].damage(dmg);
obj.onDmg(); //some bullets do actions when they hits things, like despawn obj.onDmg(); //some bullets do actions when they hits things, like despawn
game.drawList.push({ game.drawList.push({
//add dmg to draw queue //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y, y: pairs[i].activeContacts[0].vertex.y,
// radius: Math.sqrt(dmg) * 40, // radius: Math.sqrt(dmg) * 40,
radius: Math.log(2 * dmg + 1.1) * 40, radius: Math.log(2 * dmg + 1.1) * 40,
color: game.playerDmgColor, color: game.playerDmgColor,
time: game.drawTime time: game.drawTime
}); });
return; return;
} }
//mob + body collisions //mob + body collisions
if (obj.classType === "body" && obj.speed > 5) { if (obj.classType === "body" && obj.speed > 5) {
const v = Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity)); const v = Matter.Vector.magnitude(Matter.Vector.sub(mob[k].velocity, obj.velocity));
if (v > 8) { if (v > 8) {
let dmg = b.dmgScale * v * Math.sqrt(obj.mass) * 0.05; let dmg = b.dmgScale * v * Math.sqrt(obj.mass) * 0.05;
mob[k].damage(dmg); mob[k].damage(dmg);
if (mob[k].distanceToPlayer2() < 1000000) mob[k].foundPlayer(); if (mob[k].distanceToPlayer2() < 1000000) mob[k].foundPlayer();
game.drawList.push({ game.drawList.push({
//add dmg to draw queue //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y, y: pairs[i].activeContacts[0].vertex.y,
radius: Math.sqrt(dmg) * 40, radius: Math.sqrt(dmg) * 40,
color: game.playerDmgColor, color: game.playerDmgColor,
time: game.drawTime time: game.drawTime
}); });
return; return;
} }
} }
} }
} }
} }
} }
} }
//determine if player is on the ground //determine if player is on the ground
Events.on(engine, "collisionStart", function (event) { Events.on(engine, "collisionStart", function (event) {
playerOnGroundCheck(event); playerOnGroundCheck(event);
playerHeadCheck(event); playerHeadCheck(event);
mobCollisionChecks(event); mobCollisionChecks(event);
}); });
Events.on(engine, "collisionActive", function (event) { Events.on(engine, "collisionActive", function (event) {
playerOnGroundCheck(event); playerOnGroundCheck(event);
playerHeadCheck(event); playerHeadCheck(event);
}); });
Events.on(engine, "collisionEnd", function (event) { Events.on(engine, "collisionEnd", function (event) {
playerOffGroundCheck(event); playerOffGroundCheck(event);
}); });

2098
js/game.js

File diff suppressed because it is too large Load Diff

View File

@@ -1,347 +1,347 @@
"use strict"; "use strict";
/* TODO: ******************************************* /* TODO: *******************************************
***************************************************** *****************************************************
add builds with combinations of gun, field and mobs add builds with combinations of gun, field and mobs
use the pull down menu use the pull down menu
dynamically generate html about fields, guns and mods dynamically generate html about fields, guns and mods
add grid check to improve queries over large body arrays add grid check to improve queries over large body arrays
something about broad phase something about broad phase
having trouble with this, might give up having trouble with this, might give up
gun: like drones, but fast moving and short lived gun: like drones, but fast moving and short lived
dies after doing damage dies after doing damage
gun: Spirit Bomb (singularity) gun: Spirit Bomb (singularity)
use charge up like rail gun use charge up like rail gun
electricity graphics like plasma torch electricity graphics like plasma torch
suck in nearby mobs, power ups?, blocks? suck in nearby mobs, power ups?, blocks?
sucked in stuff increase size sucked in stuff increase size
uses energy uses energy
mod: auto pick up guns, heals, ammo mod: auto pick up guns, heals, ammo
use the same rule for drones use the same rule for drones
maybe give some other bonus too? maybe give some other bonus too?
rework junk bot rework junk bot
it's behavior is too unpredictable it's behavior is too unpredictable
range is unclear range is unclear
having the bullets last long after doing dmg isn't fun having the bullets last long after doing dmg isn't fun
we want a fun gun that acts like a melee weapon we want a fun gun that acts like a melee weapon
atmosphere levels atmosphere levels
large rotating fan that the player has to move through large rotating fan that the player has to move through
give the user a rest, between combat give the user a rest, between combat
low combat low combat
nonaggressive mobs nonaggressive mobs
one mob attacking the passive mobs one mob attacking the passive mobs
more graphics more graphics
Boss levels Boss levels
boss grows and spilt, if you don't kill it fast boss grows and spilt, if you don't kill it fast
sensor that locks you in after you enter the boss room sensor that locks you in after you enter the boss room
boss that eats other mobs and gains stats from them boss that eats other mobs and gains stats from them
chance to spawn on any level (past level 5) chance to spawn on any level (past level 5)
boss that knows how to shoot (player) bullets that collide with player boss that knows how to shoot (player) bullets that collide with player
overwrite custom engine collision bullet mob function. overwrite custom engine collision bullet mob function.
add a key that player picks up and needs to set on the exit door to open it add a key that player picks up and needs to set on the exit door to open it
make power ups keep moving to player if the pickup field is turned off before they get picked up make power ups keep moving to player if the pickup field is turned off before they get picked up
not sure how to do this without adding a constant check not sure how to do this without adding a constant check
animate new level spawn by having the map aspects randomly fly into place animate new level spawn by having the map aspects randomly fly into place
new map with repeating endlessness new map with repeating endlessness
get ideas from Manifold Garden game get ideas from Manifold Garden game
if falling, get teleported above the map if falling, get teleported above the map
I tried it, but had trouble getting the camera to adjust to the teleportation I tried it, but had trouble getting the camera to adjust to the teleportation
this can apply to blocks mobs, and power ups as well this can apply to blocks mobs, and power ups as well
field power up effects field power up effects
field allows player to hold and throw living mobs field allows player to hold and throw living mobs
mod power ups ideas mod power ups ideas
double jump double jump
bullet on mob damage effects bullet on mob damage effects
add to the array mob.do new mob behaviors add to the array mob.do new mob behaviors
add a damage over time add a damage over time
add a freeze add a freeze
give mobs more animal-like behaviors give mobs more animal-like behaviors
like rain world like rain world
give mobs something to do when they don't see player give mobs something to do when they don't see player
explore map explore map
eat power ups eat power ups
drop power up (if killed after eating one) drop power up (if killed after eating one)
mobs some times aren't aggressive mobs some times aren't aggressive
when low on life or after taking a large hit when low on life or after taking a large hit
mobs can fight each other mobs can fight each other
this might be hard to code this might be hard to code
isolated mobs try to group up. isolated mobs try to group up.
game mechanics game mechanics
mechanics that support the physics engine mechanics that support the physics engine
add rope/constraint add rope/constraint
get ideas from game: limbo / inside get ideas from game: limbo / inside
environmental hazards environmental hazards
laser laser
lava lava
button / switch button / switch
door door
fizzler fizzler
moving platform moving platform
map zones map zones
water water
low friction ground low friction ground
bouncy ground bouncy ground
// collision info: // collision info:
category mask category mask
powerUp: 0x100000 0x100001 powerUp: 0x100000 0x100001
body: 0x010000 0x011111 body: 0x010000 0x011111
player: 0x001000 0x010011 player: 0x001000 0x010011
bullet: 0x000100 0x010011 bullet: 0x000100 0x010011
mob: 0x000010 0x011111 mob: 0x000010 0x011111
mobBullet: 0x000010 0x011101 mobBullet: 0x000010 0x011101
mobShield: 0x000010 0x001100 mobShield: 0x000010 0x001100
map: 0x000001 0x111111 map: 0x000001 0x111111
*/ */
//build build grid display //build build grid display
const build = { const build = {
isShowingBuilds: false, isShowingBuilds: false,
list: [], list: [],
choosePowerUp(who, index, type) { choosePowerUp(who, index, type) {
//check if matching a current power up //check if matching a current power up
for (let i = 0; i < build.list.length; i++) { for (let i = 0; i < build.list.length; i++) {
if (build.list[i].index === index && build.list[i].type === type) { //if already click, toggle off if (build.list[i].index === index && build.list[i].type === type) { //if already click, toggle off
build.list.splice(i, 1); build.list.splice(i, 1);
who.style.backgroundColor = "#fff" who.style.backgroundColor = "#fff"
return return
} }
} }
//check if trying to get a second field //check if trying to get a second field
if (type === "field") { if (type === "field") {
for (let i = 0; i < build.list.length; i++) { for (let i = 0; i < build.list.length; i++) {
if (build.list[i].type === "field") { //if already click, toggle off if (build.list[i].type === "field") { //if already click, toggle off
build.list[i].who.style.backgroundColor = "#fff" build.list[i].who.style.backgroundColor = "#fff"
build.list.splice(i, 1); build.list.splice(i, 1);
} }
} }
} }
if (build.list.length < 5) { //add to build array if (build.list.length < 5) { //add to build array
// who.style.border = "2px solid #333" // who.style.border = "2px solid #333"
who.style.backgroundColor = "#919ba8" //"#868f9a" who.style.backgroundColor = "#919ba8" //"#868f9a"
build.list[build.list.length] = { build.list[build.list.length] = {
who: who, who: who,
index: index, index: index,
type: type type: type
} }
} }
}, },
startBuildRun() { startBuildRun() {
spawn.setSpawnList(); spawn.setSpawnList();
spawn.setSpawnList(); spawn.setSpawnList();
game.startGame(); game.startGame();
game.difficulty = 6; game.difficulty = 6;
level.isBuildRun = true; level.isBuildRun = true;
for (let i = 0; i < build.list.length; i++) { for (let i = 0; i < build.list.length; i++) {
if (build.list[i].type === "field") { if (build.list[i].type === "field") {
mech.fieldUpgrades[build.list[i].index].effect(); mech.fieldUpgrades[build.list[i].index].effect();
} else if (build.list[i].type === "gun") { } else if (build.list[i].type === "gun") {
b.giveGuns(build.list[i].index) b.giveGuns(build.list[i].index)
} else if (build.list[i].type === "mod") { } else if (build.list[i].type === "mod") {
b.giveMod(build.list[i].index) b.giveMod(build.list[i].index)
} }
} }
} }
} }
document.getElementById("build-button").addEventListener("click", () => { document.getElementById("build-button").addEventListener("click", () => {
document.getElementById("build-button").style.display = "none"; document.getElementById("build-button").style.display = "none";
const el = document.getElementById("build-grid") const el = document.getElementById("build-grid")
if (build.isShowingBuilds) { if (build.isShowingBuilds) {
el.style.display = "none" el.style.display = "none"
build.isShowingBuilds = false build.isShowingBuilds = false
document.body.style.overflow = "hidden" document.body.style.overflow = "hidden"
document.getElementById("controls").style.display = 'inline' document.getElementById("controls").style.display = 'inline'
document.getElementById("settings").style.display = 'inline' document.getElementById("settings").style.display = 'inline'
} else { } else {
build.list = [] build.list = []
// let text = '<p>choose up to 5 powers<br> <button type="button" id="build-begin-button" onclick="build.startBuildRun()">Begin Run</button></p>' // let text = '<p>choose up to 5 powers<br> <button type="button" id="build-begin-button" onclick="build.startBuildRun()">Begin Run</button></p>'
let text = let text =
`<div style="display: flex; justify-content: center; align-items: center;"> `<div style="display: flex; justify-content: center; align-items: center;">
<svg class="SVG-button" onclick="build.startBuildRun()" width="90" height="40"> <svg class="SVG-button" onclick="build.startBuildRun()" width="90" height="40">
<g stroke='none' fill='#333' stroke-width="2" font-size="30px" font-family="Ariel, sans-serif"> <g stroke='none' fill='#333' stroke-width="2" font-size="30px" font-family="Ariel, sans-serif">
<text x="15" y="31">start</text> <text x="15" y="31">start</text>
</g> </g>
</svg> </svg>
</div> </div>
<div class="build-grid-module" style="font-size: 19px; line-height: 110%;"> <div class="build-grid-module" style="font-size: 19px; line-height: 110%;">
Choose up to five power ups. Once you start, only health and ammo will drop, so pick carefully. Choose up to five power ups. Once you start, only health and ammo will drop, so pick carefully.
</div>` </div>`
for (let i = 1, len = mech.fieldUpgrades.length; i < len; i++) { for (let i = 1, len = mech.fieldUpgrades.length; i < len; i++) {
text += `<div class="build-grid-module" onclick="build.choosePowerUp(this,${i},'field')" ><div class="circle-grid field"></div> &nbsp; <strong style='font-size:1.3em;'>${mech.fieldUpgrades[i].name}</strong><br> ${mech.fieldUpgrades[i].description}</div>` text += `<div class="build-grid-module" onclick="build.choosePowerUp(this,${i},'field')" ><div class="circle-grid field"></div> &nbsp; <strong style='font-size:1.3em;'>${mech.fieldUpgrades[i].name}</strong><br> ${mech.fieldUpgrades[i].description}</div>`
} }
for (let i = 0, len = b.guns.length; i < len; i++) { for (let i = 0, len = b.guns.length; i < len; i++) {
text += `<div class="build-grid-module" onclick="build.choosePowerUp(this,${i},'gun')"><div class="circle-grid gun"></div> &nbsp; <strong style='font-size:1.3em;'>${b.guns[i].name}</strong><br> ${b.guns[i].description}</div>` text += `<div class="build-grid-module" onclick="build.choosePowerUp(this,${i},'gun')"><div class="circle-grid gun"></div> &nbsp; <strong style='font-size:1.3em;'>${b.guns[i].name}</strong><br> ${b.guns[i].description}</div>`
} }
for (let i = 0, len = b.mods.length; i < len; i++) { for (let i = 0, len = b.mods.length; i < len; i++) {
text += `<div class="build-grid-module" onclick="build.choosePowerUp(this,${i},'mod')"><div class="circle-grid mod"></div> &nbsp; <strong style='font-size:1.3em;'>${b.mods[i].name}</strong><br> ${b.mods[i].description}</div>` text += `<div class="build-grid-module" onclick="build.choosePowerUp(this,${i},'mod')"><div class="circle-grid mod"></div> &nbsp; <strong style='font-size:1.3em;'>${b.mods[i].name}</strong><br> ${b.mods[i].description}</div>`
} }
el.innerHTML = text el.innerHTML = text
el.style.display = "grid" el.style.display = "grid"
build.isShowingBuilds = true build.isShowingBuilds = true
document.body.style.overflowY = "scroll"; document.body.style.overflowY = "scroll";
document.body.style.overflowX = "hidden"; document.body.style.overflowX = "hidden";
document.getElementById("controls").style.display = 'none' document.getElementById("controls").style.display = 'none'
document.getElementById("settings").style.display = 'none' document.getElementById("settings").style.display = 'none'
} }
}); });
//set up canvas //set up canvas
var canvas = document.getElementById("canvas"); var canvas = document.getElementById("canvas");
//using "const" causes problems in safari when an ID shares the same name. //using "const" causes problems in safari when an ID shares the same name.
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
document.body.style.backgroundColor = "#fff"; document.body.style.backgroundColor = "#fff";
//disable pop up menu on right click //disable pop up menu on right click
document.oncontextmenu = function () { document.oncontextmenu = function () {
return false; return false;
} }
function setupCanvas() { function setupCanvas() {
canvas.width = window.innerWidth; canvas.width = window.innerWidth;
canvas.height = window.innerHeight; canvas.height = window.innerHeight;
canvas.width2 = canvas.width / 2; //precalculated because I use this often (in mouse look) canvas.width2 = canvas.width / 2; //precalculated because I use this often (in mouse look)
canvas.height2 = canvas.height / 2; canvas.height2 = canvas.height / 2;
canvas.diagonal = Math.sqrt(canvas.width2 * canvas.width2 + canvas.height2 * canvas.height2); canvas.diagonal = Math.sqrt(canvas.width2 * canvas.width2 + canvas.height2 * canvas.height2);
ctx.font = "15px Arial"; ctx.font = "15px Arial";
ctx.lineJoin = "round"; ctx.lineJoin = "round";
ctx.lineCap = "round"; ctx.lineCap = "round";
// ctx.lineCap='square'; // ctx.lineCap='square';
game.setZoom(); game.setZoom();
} }
setupCanvas(); setupCanvas();
window.onresize = () => { window.onresize = () => {
setupCanvas(); setupCanvas();
}; };
//mouse move input //mouse move input
document.body.addEventListener("mousemove", (e) => { document.body.addEventListener("mousemove", (e) => {
game.mouse.x = e.clientX; game.mouse.x = e.clientX;
game.mouse.y = e.clientY; game.mouse.y = e.clientY;
}); });
document.body.addEventListener("mouseup", (e) => { document.body.addEventListener("mouseup", (e) => {
// game.buildingUp(e); //uncomment when building levels // game.buildingUp(e); //uncomment when building levels
// game.mouseDown = false; // game.mouseDown = false;
// console.log(e) // console.log(e)
if (e.which === 3) { if (e.which === 3) {
game.mouseDownRight = false; game.mouseDownRight = false;
} else { } else {
game.mouseDown = false; game.mouseDown = false;
} }
}); });
document.body.addEventListener("mousedown", (e) => { document.body.addEventListener("mousedown", (e) => {
if (e.which === 3) { if (e.which === 3) {
game.mouseDownRight = true; game.mouseDownRight = true;
} else { } else {
game.mouseDown = true; game.mouseDown = true;
} }
}); });
//keyboard input //keyboard input
const keys = []; const keys = [];
document.body.addEventListener("keydown", (e) => { document.body.addEventListener("keydown", (e) => {
keys[e.keyCode] = true; keys[e.keyCode] = true;
game.keyPress(); game.keyPress();
}); });
document.body.addEventListener("keyup", (e) => { document.body.addEventListener("keyup", (e) => {
keys[e.keyCode] = false; keys[e.keyCode] = false;
}); });
document.body.addEventListener("wheel", (e) => { document.body.addEventListener("wheel", (e) => {
if (e.deltaY > 0) { if (e.deltaY > 0) {
game.nextGun(); game.nextGun();
} else { } else {
game.previousGun(); game.previousGun();
} }
}, { }, {
passive: true passive: true
}); });
document.getElementById("fps-select").addEventListener("input", () => { document.getElementById("fps-select").addEventListener("input", () => {
let value = document.getElementById("fps-select").value let value = document.getElementById("fps-select").value
if (value === 'max') { if (value === 'max') {
game.fpsCapDefault = 999999999; game.fpsCapDefault = 999999999;
} else if (value === '72') { } else if (value === '72') {
game.fpsCapDefault = 72 game.fpsCapDefault = 72
} else if (value === '60') { } else if (value === '60') {
game.fpsCapDefault = 60 game.fpsCapDefault = 60
} else if (value === '45') { } else if (value === '45') {
game.fpsCapDefault = 45 game.fpsCapDefault = 45
} else if (value === '30') { } else if (value === '30') {
game.fpsCapDefault = 30 game.fpsCapDefault = 30
} else if (value === '15') { } else if (value === '15') {
game.fpsCapDefault = 15 game.fpsCapDefault = 15
} }
}); });
document.getElementById("body-damage").addEventListener("input", () => { document.getElementById("body-damage").addEventListener("input", () => {
game.isBodyDamage = document.getElementById("body-damage").checked game.isBodyDamage = document.getElementById("body-damage").checked
}); });
// function playSound(id) { // function playSound(id) {
// //play sound // //play sound
// if (false) { // if (false) {
// //sounds are turned off for now // //sounds are turned off for now
// // if (document.getElementById(id)) { // // if (document.getElementById(id)) {
// var sound = document.getElementById(id); //setup audio // var sound = document.getElementById(id); //setup audio
// sound.currentTime = 0; //reset position of playback to zero //sound.load(); // sound.currentTime = 0; //reset position of playback to zero //sound.load();
// sound.play(); // sound.play();
// } // }
// } // }
function shuffle(array) { function shuffle(array) {
var currentIndex = array.length, var currentIndex = array.length,
temporaryValue, temporaryValue,
randomIndex; randomIndex;
// While there remain elements to shuffle... // While there remain elements to shuffle...
while (0 !== currentIndex) { while (0 !== currentIndex) {
// Pick a remaining element... // Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex); randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1; currentIndex -= 1;
// And swap it with the current element. // And swap it with the current element.
temporaryValue = array[currentIndex]; temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex]; array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue; array[randomIndex] = temporaryValue;
} }
return array; return array;
} }
//main loop ************************************************************ //main loop ************************************************************
//********************************************************************** //**********************************************************************
function cycle() { function cycle() {
if (!game.paused) requestAnimationFrame(cycle); if (!game.paused) requestAnimationFrame(cycle);
const now = Date.now(); const now = Date.now();
const elapsed = now - game.then; // calc elapsed time since last loop const elapsed = now - game.then; // calc elapsed time since last loop
if (elapsed > game.fpsInterval) { // if enough time has elapsed, draw the next frame 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.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(); game.loop();
} }
} }

File diff suppressed because it is too large Load Diff

2020
js/mobs.js

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,239 +1,239 @@
let powerUp = []; let powerUp = [];
const powerUps = { const powerUps = {
heal: { heal: {
name: "heal", name: "heal",
color: "#0fb", color: "#0fb",
size() { size() {
return 40 * Math.sqrt(0.1 + Math.random() * 0.5); return 40 * Math.sqrt(0.1 + Math.random() * 0.5);
}, },
effect() { effect() {
let heal = (this.size / 40) ** 2 let heal = (this.size / 40) ** 2
if (b.fullHeal) heal = Infinity if (b.fullHeal) heal = Infinity
heal = Math.min(1 - mech.health, heal) heal = Math.min(1 - mech.health, heal)
mech.addHealth(heal); mech.addHealth(heal);
if (heal > 0) game.makeTextLog("<div class='circle heal'></div> &nbsp; <span style='font-size:115%;'> <strong style = 'letter-spacing: 2px;'>heal</strong> " + (heal * 100).toFixed(0) + "%</span>", 300) if (heal > 0) game.makeTextLog("<div class='circle heal'></div> &nbsp; <span style='font-size:115%;'> <strong style = 'letter-spacing: 2px;'>heal</strong> " + (heal * 100).toFixed(0) + "%</span>", 300)
} }
}, },
ammo: { ammo: {
name: "ammo", name: "ammo",
color: "#467", color: "#467",
size() { size() {
return 17; return 17;
}, },
effect() { effect() {
//only get ammo for guns player has //only get ammo for guns player has
let target; let target;
// console.log(b.inventory.length) // console.log(b.inventory.length)
if (b.inventory.length > 0) { if (b.inventory.length > 0) {
//add ammo to a gun in inventory //add ammo to a gun in inventory
target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]]; 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 //try 3 more times to give ammo to a gun with ammo, not Infinity
if (target.ammo === Infinity) { if (target.ammo === Infinity) {
target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]] target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]]
if (target.ammo === Infinity) { if (target.ammo === Infinity) {
target = b.guns[b.inventory[Math.floor(Math.random() * (b.inventory.length))]] 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 { } else {
//if you don't have any guns just add ammo to a random gun you don't have yet //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)]; target = b.guns[Math.floor(Math.random() * b.guns.length)];
} }
if (target.ammo === Infinity) { if (target.ammo === Infinity) {
mech.fieldMeter = 1; mech.fieldMeter = 1;
if (!game.lastLogTime) game.makeTextLog("<span style='font-size:115%;'><span class='color-f'>+energy</span></span>", 300); if (!game.lastLogTime) game.makeTextLog("<span style='font-size:115%;'><span class='color-f'>+energy</span></span>", 300);
} else { } else {
//ammo given scales as mobs take more hits to kill //ammo given scales as mobs take more hits to kill
let ammo = Math.ceil((target.ammoPack * (0.45 + 0.06 * Math.random())) / Math.sqrt(b.dmgScale)); let ammo = Math.ceil((target.ammoPack * (0.45 + 0.06 * Math.random())) / Math.sqrt(b.dmgScale));
if (level.isBuildRun) ammo = Math.floor(ammo * 1.2) if (level.isBuildRun) ammo = Math.floor(ammo * 1.2)
target.ammo += ammo; target.ammo += ammo;
game.updateGunHUD(); game.updateGunHUD();
game.makeTextLog("<div class='circle gun'></div> &nbsp; <span style='font-size:110%;'>+" + ammo + " ammo for " + target.name + "</span>", 300); game.makeTextLog("<div class='circle gun'></div> &nbsp; <span style='font-size:110%;'>+" + ammo + " ammo for " + target.name + "</span>", 300);
} }
} }
}, },
field: { field: {
name: "field", name: "field",
color: "#0cf", color: "#0cf",
size() { size() {
return 45; return 45;
}, },
effect() { effect() {
const previousMode = mech.fieldMode const previousMode = mech.fieldMode
if (!this.mode) { //this.mode is set if the power up has been ejected from player if (!this.mode) { //this.mode is set if the power up has been ejected from player
mode = mech.fieldMode mode = mech.fieldMode
while (mode === mech.fieldMode) { while (mode === mech.fieldMode) {
mode = Math.ceil(Math.random() * (mech.fieldUpgrades.length - 1)) mode = Math.ceil(Math.random() * (mech.fieldUpgrades.length - 1))
} }
mech.fieldUpgrades[mode].effect(); //choose random field upgrade that you don't already have mech.fieldUpgrades[mode].effect(); //choose random field upgrade that you don't already have
} else { } else {
mech.fieldUpgrades[this.mode].effect(); //set a predetermined power up mech.fieldUpgrades[this.mode].effect(); //set a predetermined power up
} }
//pop the old field out in case player wants to swap back //pop the old field out in case player wants to swap back
if (previousMode !== 0) { if (previousMode !== 0) {
mech.fieldCDcycle = mech.cycle + 40; //trigger fieldCD to stop power up grab automatic pick up of spawn 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); powerUps.spawn(mech.pos.x, mech.pos.y - 15, "field", false, previousMode);
} }
} }
}, },
mod: { mod: {
name: "mod", name: "mod",
color: "#a8f", color: "#a8f",
size() { size() {
return 42; return 42;
}, },
effect() { effect() {
//find what mods I don't have //find what mods I don't have
let options = []; let options = [];
for (let i = 0; i < b.mods.length; i++) { for (let i = 0; i < b.mods.length; i++) {
if (!b.mods[i].have) options.push(i); if (!b.mods[i].have) options.push(i);
} }
//give a random mod from the mods I don't have //give a random mod from the mods I don't have
if (options.length > 0) { if (options.length > 0) {
let newMod = options[Math.floor(Math.random() * options.length)] let newMod = options[Math.floor(Math.random() * options.length)]
b.giveMod(newMod) b.giveMod(newMod)
game.replaceTextLog = true; game.replaceTextLog = true;
game.makeTextLog(`<div class="circle mod"></div> &nbsp; <strong style='font-size:30px;'>${b.mods[newMod].name}</strong><br><br> ${b.mods[newMod].description}`, 1000); game.makeTextLog(`<div class="circle mod"></div> &nbsp; <strong style='font-size:30px;'>${b.mods[newMod].name}</strong><br><br> ${b.mods[newMod].description}`, 1000);
game.replaceTextLog = false; game.replaceTextLog = false;
} }
} }
}, },
gun: { gun: {
name: "gun", name: "gun",
color: "#26a", color: "#26a",
size() { size() {
return 35; return 35;
}, },
effect() { effect() {
//find what guns I don't have //find what guns I don't have
let options = []; let options = [];
if (b.activeGun === null && game.difficulty < 3) { if (b.activeGun === null && game.difficulty < 3) {
//choose the first gun to be one that is good for the early game //choose the first gun to be one that is good for the early game
for (let i = 0; i < b.guns.length; ++i) { for (let i = 0; i < b.guns.length; ++i) {
if (!b.guns[i].have && b.guns[i].isStarterGun) options.push(i); if (!b.guns[i].have && b.guns[i].isStarterGun) options.push(i);
} }
} else { } else {
//choose a gun you don't have //choose a gun you don't have
for (let i = 0; i < b.guns.length; ++i) { for (let i = 0; i < b.guns.length; ++i) {
if (!b.guns[i].have) options.push(i); if (!b.guns[i].have) options.push(i);
} }
} }
//give player a gun they don't already have if possible //give player a gun they don't already have if possible
game.replaceTextLog = true; game.replaceTextLog = true;
if (options.length > 0) { if (options.length > 0) {
let newGun = options[Math.floor(Math.random() * options.length)]; let newGun = options[Math.floor(Math.random() * options.length)];
if (b.activeGun === null) b.activeGun = newGun //if no active gun switch to new gun if (b.activeGun === null) b.activeGun = newGun //if no active gun switch to new gun
game.makeTextLog(`${game.SVGleftMouse} <strong style='font-size:30px;'>${b.guns[newGun].name}</strong><br><br>${b.guns[newGun].description}`, 900); game.makeTextLog(`${game.SVGleftMouse} <strong style='font-size:30px;'>${b.guns[newGun].name}</strong><br><br>${b.guns[newGun].description}`, 900);
b.guns[newGun].have = true; b.guns[newGun].have = true;
b.inventory.push(newGun); b.inventory.push(newGun);
b.guns[newGun].ammo += b.guns[newGun].ammoPack * 2; b.guns[newGun].ammo += b.guns[newGun].ammoPack * 2;
game.makeGunHUD(); game.makeGunHUD();
} else { } else {
//if you have all guns then get ammo //if you have all guns then get ammo
const ammoTarget = Math.floor(Math.random() * (b.guns.length)); const ammoTarget = Math.floor(Math.random() * (b.guns.length));
const ammo = Math.ceil(b.guns[ammoTarget].ammoPack * 2); const ammo = Math.ceil(b.guns[ammoTarget].ammoPack * 2);
b.guns[ammoTarget].ammo += ammo; b.guns[ammoTarget].ammo += ammo;
game.updateGunHUD(); game.updateGunHUD();
game.makeTextLog("<span style='font-size:110%;'>+" + ammo + " ammo for " + b.guns[ammoTarget].name + "</span>", 300); game.makeTextLog("<span style='font-size:110%;'>+" + ammo + " ammo for " + b.guns[ammoTarget].name + "</span>", 300);
} }
game.replaceTextLog = false game.replaceTextLog = false
} }
}, },
spawnRandomPowerUp(x, y) { //mostly used after mob dies spawnRandomPowerUp(x, y) { //mostly used after mob dies
if (Math.random() * Math.random() - 0.25 > Math.sqrt(mech.health) || Math.random() < 0.04) { //spawn heal chance is higher at low health if (Math.random() * Math.random() - 0.25 > Math.sqrt(mech.health) || Math.random() < 0.04) { //spawn heal chance is higher at low health
powerUps.spawn(x, y, "heal"); powerUps.spawn(x, y, "heal");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "heal"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "heal");
return; return;
} }
if (Math.random() < 0.2 && b.inventory.length > 0) { if (Math.random() < 0.2 && b.inventory.length > 0) {
powerUps.spawn(x, y, "ammo"); powerUps.spawn(x, y, "ammo");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "ammo"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "ammo");
return; return;
} }
if (Math.random() < 0.004 * (4 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun to drop if (Math.random() < 0.004 * (4 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun to drop
powerUps.spawn(x, y, "gun"); powerUps.spawn(x, y, "gun");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun");
return; return;
} }
if (Math.random() < 0.004 * (7 - b.modCount)) { if (Math.random() < 0.0035 * (7 - b.modCount)) {
powerUps.spawn(x, y, "mod"); powerUps.spawn(x, y, "mod");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod");
return; return;
} }
if (Math.random() < 0.005) { if (Math.random() < 0.005) {
powerUps.spawn(x, y, "field"); powerUps.spawn(x, y, "field");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field");
return; return;
} }
}, },
spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades
if (mech.fieldMode === 0) { if (mech.fieldMode === 0) {
powerUps.spawn(x, y, "field") powerUps.spawn(x, y, "field")
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field") if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field")
} else if (Math.random() < 0.3) { } else if (Math.random() < 0.27) {
powerUps.spawn(x, y, "mod") powerUps.spawn(x, y, "mod")
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod") if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "mod")
} else if (Math.random() < 0.3) { } else if (Math.random() < 0.27) {
powerUps.spawn(x, y, "field"); powerUps.spawn(x, y, "field");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "field");
} else if (Math.random() < 0.3) { } else if (Math.random() < 0.27) {
powerUps.spawn(x, y, "gun") powerUps.spawn(x, y, "gun")
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun") if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "gun")
} else if (mech.health < 0.6) { } else if (mech.health < 0.6) {
powerUps.spawn(x, y, "heal"); powerUps.spawn(x, y, "heal");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "heal"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "heal");
} else { } else {
powerUps.spawn(x, y, "ammo"); powerUps.spawn(x, y, "ammo");
if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "ammo"); if (Math.random() < b.modMoreDrops) powerUps.spawn(x, y, "ammo");
} }
}, },
chooseRandomPowerUp(x, y) { //100% chance to drop a random power up //used in spawn.debris chooseRandomPowerUp(x, y) { //100% chance to drop a random power up //used in spawn.debris
if (Math.random() < 0.5) { if (Math.random() < 0.5) {
powerUps.spawn(x, y, "heal", false); powerUps.spawn(x, y, "heal", false);
} else { } else {
powerUps.spawn(x, y, "ammo", false); powerUps.spawn(x, y, "ammo", false);
} }
}, },
spawnStartingPowerUps(x, y) { //used for map specific power ups, mostly to give player a starting gun spawnStartingPowerUps(x, y) { //used for map specific power ups, mostly to give player a starting gun
if (b.inventory.length < 2 || game.isEasyMode) { if (b.inventory.length < 2 || game.isEasyMode) {
powerUps.spawn(x, y, "gun", false); //starting gun powerUps.spawn(x, y, "gun", false); //starting gun
} else { } else {
powerUps.spawnRandomPowerUp(x, y); powerUps.spawnRandomPowerUp(x, y);
powerUps.spawnRandomPowerUp(x, y); powerUps.spawnRandomPowerUp(x, y);
powerUps.spawnRandomPowerUp(x, y); powerUps.spawnRandomPowerUp(x, y);
powerUps.spawnRandomPowerUp(x, y); powerUps.spawnRandomPowerUp(x, y);
} }
}, },
spawn(x, y, target, moving = true, mode = null) { spawn(x, y, target, moving = true, mode = null) {
if (!level.isBuildRun || target === "heal" || target === "ammo") { if (!level.isBuildRun || target === "heal" || target === "ammo") {
let i = powerUp.length; let i = powerUp.length;
target = powerUps[target]; target = powerUps[target];
size = target.size(); size = target.size();
powerUp[i] = Matter.Bodies.polygon(x, y, 0, size, { powerUp[i] = Matter.Bodies.polygon(x, y, 0, size, {
density: 0.001, density: 0.001,
frictionAir: 0.01, frictionAir: 0.01,
restitution: 0.8, restitution: 0.8,
inertia: Infinity, //prevents rotation inertia: Infinity, //prevents rotation
collisionFilter: { collisionFilter: {
group: 0, group: 0,
category: 0x100000, category: 0x100000,
mask: 0x100001 mask: 0x100001
}, },
color: target.color, color: target.color,
effect: target.effect, effect: target.effect,
mode: mode, mode: mode,
name: target.name, name: target.name,
size: size size: size
}); });
if (moving) { if (moving) {
Matter.Body.setVelocity(powerUp[i], { Matter.Body.setVelocity(powerUp[i], {
x: (Math.random() - 0.5) * 15, x: (Math.random() - 0.5) * 15,
y: Math.random() * -9 - 3 y: Math.random() * -9 - 3
}); });
} }
World.add(engine.world, powerUp[i]); //add to world World.add(engine.world, powerUp[i]); //add to world
} }
}, },
}; };

File diff suppressed because it is too large Load Diff