"use strict";
//collision groups
// cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet | cat.mobShield | cat.phased
const cat = {
player: 0x1,
map: 0x10,
body: 0x100,
bullet: 0x1000,
powerUp: 0x10000,
mob: 0x100000,
mobBullet: 0x1000000,
mobShield: 0x10000000,
phased: 0x100000000,
}
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;
}
// shrink power up selection menu to find window height
if (screen.height < 800) {
document.getElementById("choose-grid").style.fontSize = "1em"; //1.3em is normal
if (screen.height < 600) document.getElementById("choose-grid").style.fontSize = "0.8em"; //1.3em is normal
}
//**********************************************************************
// check for URL parameters to load an experimental game
//**********************************************************************
//example https://landgreen.github.io/sidescroller/index.html?
// &gun1=minigun&gun2=laser
// &tech1=laser-bot&tech2=mass%20driver&tech3=overcharge&tech4=laser-bot&tech5=laser-bot&field=phase%20decoherence%20field&difficulty=2
//add ? to end of url then for each power up add
// &gun1=name&gun2=name
// &tech1=laser-bot&tech2=mass%20driver&tech3=overcharge&tech4=laser-bot&tech5=laser-bot
// &field=phase%20decoherence%20field
// &difficulty=2
//use %20 for spaces
//difficulty is 0 easy, 1 normal, 2 hard, 4 why
function getUrlVars() {
let vars = {};
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m, k, v) {
vars[k] = v;
});
return vars;
}
window.addEventListener('load', (event) => {
const set = getUrlVars()
if (Object.keys(set).length !== 0) {
openExperimentMenu();
//add experimental selections based on url
for (const property in set) {
set[property] = set[property].replace(/%20/g, " ")
set[property] = set[property].replace(/%27/g, "'")
set[property] = set[property].replace(/%CE%A8/g, "Ψ")
if (property === "field") {
let found = false
let index
for (let i = 0; i < m.fieldUpgrades.length; i++) {
if (set[property] === m.fieldUpgrades[i].name) {
index = i;
found = true;
break;
}
}
if (found) build.choosePowerUp(document.getElementById(`field-${index}`), index, 'field')
}
if (property.substring(0, 3) === "gun") {
let found = false
let index
for (let i = 0; i < b.guns.length; i++) {
if (set[property] === b.guns[i].name) {
index = i;
found = true;
break;
}
}
if (found) build.choosePowerUp(document.getElementById(`gun-${index}`), index, 'gun')
}
if (property.substring(0, 4) === "tech") {
for (let i = 0; i < tech.tech.length; i++) {
if (set[property] === tech.tech[i].name) {
build.choosePowerUp(document.getElementById(`tech-${i}`), i, 'tech', true)
break;
}
}
}
if (property === "difficulty") {
simulation.difficultyMode = Number(set[property])
document.getElementById("difficulty-select-experiment").value = Number(set[property])
}
if (property === "level") {
document.getElementById("starting-level").value = Number(set[property])
}
if (property === "noPower") {
document.getElementById("no-power-ups").checked = Number(set[property])
}
}
}
});
//**********************************************************************
//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 = "18px Arial";
// ctx.textAlign = "center";
ctx.font = "25px Arial";
ctx.lineJoin = "round";
ctx.lineCap = "round";
// ctx.lineCap='square';
simulation.setZoom();
}
setupCanvas();
window.onresize = () => {
setupCanvas();
};
//**********************************************************************
// experimental build grid display and pause
//**********************************************************************
const build = {
onLoadPowerUps() {
const set = getUrlVars()
if (Object.keys(set).length !== 0) {
for (const property in set) {
set[property] = set[property].replace(/%20/g, " ")
if (property.substring(0, 3) === "gun") b.giveGuns(set[property])
if (property.substring(0, 3) === "tech") tech.giveTech(set[property])
if (property === "field") m.setField(set[property])
if (property === "difficulty") {
simulation.difficultyMode = Number(set[property])
document.getElementById("difficulty-select").value = Number(set[property])
}
if (property === "level") {
level.levelsCleared += Number(set[property]);
level.difficultyIncrease(Number(set[property]) * simulation.difficultyMode) //increase difficulty based on modes
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
level.onLevel++
}
}
for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]);
bullet = []; //remove any bullets that might have spawned from tech
if (b.inventory.length > 0) {
b.activeGun = b.inventory[0] //set first gun to active gun
simulation.makeGunHUD();
}
}
},
pauseGrid() {
const harm = (1 - m.harmReduction()) * 100
let text = ""
if (!simulation.isChoosing) text += `
`
}
let el = document.getElementById("pause-grid-left")
el.style.display = "grid"
el.innerHTML = text
text = "";
text += `
${m.fieldUpgrades[m.fieldMode].name}
${m.fieldUpgrades[m.fieldMode].description}
`
let countTech = 0
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].count > 0) {
const isCount = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
if (tech.tech[i].isFieldTech) {
text += `
${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
} else if (tech.tech[i].isGunTech) {
text += `
${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
} else if (tech.tech[i].isLore) {
text += `
${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
} else {
text += `
${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
}
countTech++
}
}
el = document.getElementById("pause-grid-right")
el.style.display = "grid"
el.innerHTML = text
if (countTech > 5 || b.inventory.length > 6) {
document.body.style.overflowY = "scroll";
document.body.style.overflowX = "hidden";
}
},
unPauseGrid() {
document.body.style.overflow = "hidden"
document.getElementById("pause-grid-left").style.display = "none"
document.getElementById("pause-grid-right").style.display = "none"
window.scrollTo(0, 0);
},
isExperimentSelection: true,
choosePowerUp(who, index, type, isAllowed = false) {
if (type === "gun") {
let isDeselect = false
for (let i = 0, len = b.inventory.length; i < len; i++) { //look for selection in inventory
if (b.guns[b.inventory[i]].name === b.guns[index].name) { //if already clicked, remove gun
isDeselect = true
who.classList.remove("build-gun-selected");
//remove gun
b.inventory.splice(i, 1)
b.guns[index].count = 0;
b.guns[index].have = false;
if (b.guns[index].ammo != Infinity) b.guns[index].ammo = 0;
if (b.inventory.length === 0) b.activeGun = null;
simulation.makeGunHUD();
break
}
}
if (!isDeselect) { //add gun
who.classList.add("build-gun-selected");
b.giveGuns(index)
}
} else if (type === "field") {
if (m.fieldMode !== index) {
document.getElementById("field-" + m.fieldMode).classList.remove("build-field-selected");
m.setField(index)
who.classList.add("build-field-selected");
}
} else if (type === "tech") { //remove tech if you have too many
if (tech.tech[index].count < tech.tech[index].maxCount) {
if (!who.classList.contains("build-tech-selected")) who.classList.add("build-tech-selected");
tech.giveTech(index)
} else {
tech.removeTech(index);
who.classList.remove("build-tech-selected");
}
}
//update tech text //disable not allowed tech
for (let i = 0, len = tech.tech.length; i < len; i++) {
const techID = document.getElementById("tech-" + i)
if (!tech.tech[i].isCustomHide) {
if (tech.tech[i].allowed() || isAllowed || tech.tech[i].count > 0) {
const isCount = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
if (tech.tech[i].isFieldTech) {
techID.innerHTML = `