n-gon phase graphics

n-gon phase graphics
timeskipBoss written
build sharing with URL variables
This commit is contained in:
landgreen
2020-04-02 12:54:28 -07:00
parent b52f5f7748
commit 26fbb7bad6
7 changed files with 231 additions and 99 deletions

View File

@@ -150,7 +150,8 @@ const b = {
}
},
{
name: "fluoroantimonic acid<span id='mod-acid'></span>",
name: "fluoroantimonic acid",
nameInfo: "<span id='mod-acid'></span>",
description: "each <strong>bullet</strong> does instant <strong class='color-p'>acid</strong> <strong class='color-d'>damage</strong><br><strong>active</strong> when you are above <strong>80%</strong> base health",
maxCount: 1,
count: 0,
@@ -169,7 +170,8 @@ const b = {
}
},
{
name: "negative feedback<span id='mod-low-health-damage'></span>",
name: "negative feedback",
nameInfo: "<span id='mod-low-health-damage'></span>",
description: "do extra <strong class='color-d'>damage</strong> at low health<br><em>up to <strong>50%</strong> increase when near death</em>",
maxCount: 1,
count: 0,
@@ -576,7 +578,8 @@ const b = {
}
},
{
name: "entanglement <span id = 'mod-entanglement'></span>",
name: "entanglement",
nameInfo: "<span id = 'mod-entanglement'></span>",
description: "<strong>16%</strong> less <strong>harm</strong> for each gun in your <strong>inventory</strong><br> while your <strong>first gun</strong> is equipped",
maxCount: 1,
count: 0,

View File

@@ -61,14 +61,19 @@ const game = {
game.isTimeSkipping = true;
for (let i = 0; i < cycles; i++) {
game.cycle++;
// mech.cycle++;
mech.cycle++;
game.gravity();
Engine.update(engine, game.delta);
level.checkZones();
level.checkQuery();
mech.move();
game.checks();
mobs.loop();
// mech.draw();
mech.walk_cycle += mech.flipLegs * mech.Vx;
mech.hold();
b.fire();
b.bulletActions();
}
game.isTimeSkipping = false;
@@ -106,6 +111,7 @@ const game = {
accelScale: null, //set in levels.setDifficulty
CDScale: null, //set in levels.setDifficulty
lookFreqScale: null, //set in levels.setDifficulty
mouseDown: false,
// dropFPS(cap = 40, time = 15) {
// game.fpsCap = cap
// game.fpsInterval = 1000 / game.fpsCap;
@@ -202,6 +208,7 @@ const game = {
if (b.mods[i].count > 0) {
if (text) text += "<br>" //add a new line, but not on the first line
text += b.mods[i].name
if (b.mods[i].nameInfo) text += b.mods[i].nameInfo
if (b.mods[i].count > 1) text += ` (${b.mods[i].count}x)`
}
}

View File

@@ -12,6 +12,38 @@ const cat = {
mobShield: 0x10000000,
}
//example https://landgreen.github.io/sidescroller/index.html?
// &gun1=minigun&gun2=laser
// &mod1=laser-bot&mod2=mass%20driver&mod3=overcharge&mod4=laser-bot&mod5=laser-bot&field=phase%20decoherence%20field&difficulty=2
//add ? to end of url then for each power up add
// &gun1=name&gun2=name
// &mod1=laser-bot&mod2=mass%20driver&mod3=overcharge&mod4=laser-bot&mod5=laser-bot
// &field=phase%20decoherence%20field
// &difficulty=2
//use %20 for spaces
//difficulty is 0 easy, 1 normal, 2 hard, 4 why
function onLoadPowerUps() {
function getUrlVars() {
let vars = {};
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, k, v) {
vars[k] = v;
});
return vars;
}
const set = getUrlVars()
for (const property in set) {
// console.log(`${property}: ${give[property]}`);
set[property] = set[property].replace(/%20/g, " ")
if (property.substring(0, 3) === "gun") b.giveGuns(set[property])
if (property.substring(0, 3) === "mod") b.giveMod(set[property])
if (property === "field") mech.setField(set[property])
if (property === "difficulty") {
game.difficultyMode = Number(set[property])
document.getElementById("difficulty-select").value = Number(set[property])
}
}
}
//build build grid display
const build = {
pauseGrid() {
@@ -148,9 +180,14 @@ const build = {
<text x="18" y="38">start</text>
</g>
</svg>
<svg class="SVG-button" onclick="build.reset()" width="70" height="35">
<g stroke='none' fill='#333' stroke-width="2" font-size="22px" font-family="Ariel, sans-serif">
<text x="10" y="24">reset</text>
<svg class="SVG-button" onclick="build.reset()" width="50" height="25">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<text x="5" y="18">reset</text>
</g>
</svg>
<svg class="SVG-button" onclick="build.shareURL()" width="52" height="25">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<text x="5" y="18">share</text>
</g>
</svg>
</div>
@@ -207,7 +244,63 @@ const build = {
document.getElementById("field-0").classList.add("build-field-selected");
document.getElementById("build-grid").style.display = "grid"
},
shareURL() {
// Create a fake textarea
const textAreaEle = document.createElement('textarea');
// Reset styles
textAreaEle.style.border = '0';
textAreaEle.style.padding = '0';
textAreaEle.style.margin = '0';
// Set the absolute position
// User won't see the element
textAreaEle.style.position = 'absolute';
textAreaEle.style.left = '-9999px';
textAreaEle.style.top = `0px`;
// Set the value
textAreaEle.value = build.generateURL();
// Append the textarea to body
document.body.appendChild(textAreaEle);
// Focus and select the text
textAreaEle.focus();
textAreaEle.select();
// Execute the "copy" command
try {
document.execCommand('copy');
} catch (err) {
// Unable to copy
} finally {
// Remove the textarea
document.body.removeChild(textAreaEle);
}
alert('n-gon build URL copied to clip board.\nPaste it into your browser address bar.')
},
generateURL() {
let url = "https://landgreen.github.io/sidescroller/index.html?"
let count = 0;
for (let i = 0; i < b.guns.length; i++) {
if (b.guns[i].have) {
url += `&gun${count}=${encodeURIComponent(b.guns[i].name.trim())}`
count++
}
}
count = 0;
for (let i = 0; i < b.mods.length; i++) {
for (let j = 0; j < b.mods[i].count; j++) {
url += `&mod${count}=${encodeURIComponent(b.mods[i].name.trim())}`
count++
}
}
url += `&field=${encodeURIComponent(mech.fieldUpgrades[mech.fieldMode].name.trim())}`
url += `&difficulty=${game.difficultyMode}`
console.log(url)
return url
},
startBuildRun() {
build.isCustomSelection = false;
b.modOnHealthChange()

View File

@@ -15,13 +15,14 @@ const level = {
if (level.levelsCleared === 0) {
// level.difficultyIncrease(9)
// b.giveGuns("vacuum bomb")
// mech.setField("time dilation field")
// mech.setField("phase decoherence field")
// mech.energy = 0.1;
// b.giveMod("ground state");
// b.giveMod("negative feedback");
// b.giveMod("photovoltaics");
onLoadPowerUps();
// level.intro(); //starting level
level.testingMap();
level.intro(); //starting level
// level.testing();
// level.stronghold()
// level.bosses();
// level.satellite();
@@ -75,8 +76,7 @@ const level = {
if (game.difficulty < 1) game.difficulty = 0;
game.healScale = 1 / (1 + game.difficulty * 0.09)
},
difficultyText() {
let mode = document.getElementById("difficulty-select").value
difficultyText(mode = document.getElementById("difficulty-select").value) {
if (mode === "0") {
return "easy"
} else if (mode === "1") {
@@ -97,7 +97,7 @@ const level = {
//******************************************************************************************************************
//******************************************************************************************************************
testingMap() {
testing() {
// level.difficultyIncrease(9) //level 7 on normal, level 4 on hard, level 1.2 on why?
spawn.setSpawnList();
level.defaultZoom = 1500
@@ -137,14 +137,15 @@ const level = {
spawn.mapRect(2500, -1200, 200, 750); //right wall
blockDoor(2585, -210)
spawn.mapRect(2500, -200, 200, 300); //right wall
spawn.mapRect(4500, -1200, 200, 750); //right wall
blockDoor(4585, -210)
spawn.mapRect(4500, -200, 200, 300); //right wall
spawn.mapRect(4500, -1200, 200, 650); //right wall
blockDoor(4585, -310)
spawn.mapRect(4500, -300, 200, 400); //right wall
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
spawn.timeSkipBoss(2900, -500)
spawn.randomMob(3200, -500)
},
bosses() {
@@ -193,23 +194,16 @@ const level = {
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.blockDoor(710, -710);
spawn[spawn.pickList[0]](1500, -200, 150 + Math.random() * 30);
spawn.mapRect(2500, -1200, 200, 750); //right wall
blockDoor(2585, -210)
spawn.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.blockDoor(4585, -210)
spawn.mapRect(4500, -200, 200, 300); //right wall
spawn.lineBoss(5000, -200, spawn.allowedBossList[Math.floor(Math.random() * spawn.allowedBossList.length)]);

View File

@@ -1584,7 +1584,7 @@ const mech = {
zeroG(powerUp, this.fieldDrawRadius);
zeroG(body, this.fieldDrawRadius);
}
if (mech.energy < 0) {
if (mech.energy < 0.001) {
mech.fieldCDcycle = mech.cycle + 120;
mech.energy = 0;
}
@@ -1761,25 +1761,33 @@ const mech = {
mech.grabPowerUp();
mech.lookForPickUp();
const DRAIN = 0.0001 + 0.00017 * player.speed
const DRAIN = 0.00004 + 0.00009 * player.speed
if (mech.energy > DRAIN) {
mech.energy -= DRAIN;
if (mech.energy < 0) {
if (mech.energy < 0.001) {
mech.fieldCDcycle = mech.cycle + 120;
mech.energy = 0;
}
mech.isStealth = true //isStealth disables most uses of foundPlayer()
player.collisionFilter.mask = cat.map
if (!game.isTimeSkipping) {
// game.timeSkip(1)
const drawRadius = 125
ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y, mech.fieldRange, 0, 2 * Math.PI);
ctx.globalCompositeOperation = "destination-in"; //in or atop
ctx.arc(mech.pos.x, mech.pos.y, drawRadius, 0, 2 * Math.PI);
ctx.fillStyle = `rgba(255,255,255,${mech.energy*0.5})`;
ctx.globalCompositeOperation = "destination-in"; //in or atop
ctx.fill();
ctx.globalCompositeOperation = "source-over";
ctx.strokeStyle = "#000"
ctx.lineWidth = 2;
ctx.stroke();
ctx.beginPath();
ctx.arc(mech.pos.x, mech.pos.y, drawRadius, 0, 2 * Math.PI);
ctx.clip();
let inPlayer = Matter.Query.region(mob, player.bounds)
if (inPlayer.length > 0) {
@@ -1816,6 +1824,7 @@ const mech = {
}
}
}
}
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
mech.pickUp();
} else {

View File

@@ -641,52 +641,68 @@ const spawn = {
let me = mob[mob.length - 1];
// me.stroke = "transparent"; //used for drawSneaker
me.timeSkipLastCycle = 0
me.eventHorizon = 1600; //required for black hole
me.eventHorizon = 1300; //required for black hole
me.seeAtDistance2 = (me.eventHorizon + 1000) * (me.eventHorizon + 1000); //vision limit is event horizon
me.accelMag = 0.0001 * game.accelScale;
me.accelMag = 0.00013 * game.accelScale;
// me.collisionFilter.mask = cat.player | cat.bullet
// me.frictionAir = 0.005;
// me.memory = 1600;
Matter.Body.setDensity(me, 0.02); //extra dense //normal is 0.001 //makes effective life much larger
Matter.Body.setDensity(me, 0.018); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function () {
//applying forces to player doesn't seem to work inside this method, not sure why
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
me.do = function () {
//keep it slow, to stop issues from explosion knock backs
this.seePlayerByDistOrLOS();
if (this.seePlayer.recall) {
//accelerate towards the player
const forceMag = this.accelMag * this.mass;
const dx = this.seePlayer.position.x - this.position.x
const dy = this.seePlayer.position.y - this.position.y
const mag = Math.sqrt(dx * dx + dy * dy)
this.force.x += forceMag * dx / mag;
this.force.y += forceMag * dy / mag;
this.seePlayerCheck();
this.attraction()
if (!game.isTimeSkipping) {
this.fill = `rgba(0,0,0,${0.1+0.1*Math.random()})`
const compress = 3
if (this.timeSkipLastCycle < game.cycle - compress &&
Vector.magnitude(Vector.sub(this.position, player.position)) < this.eventHorizon) {
this.timeSkipLastCycle = game.cycle
game.timeSkip(compress)
this.fill = `rgba(0,0,0,${0.1+0.1*Math.random()})`
this.stroke = "#000"
this.isShielded = false;
this.dropPowerUp = true;
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
ctx.fillStyle = `rgba(255,255,255,${mech.energy*0.5})`;
ctx.globalCompositeOperation = "destination-in"; //in or atop
ctx.fill();
ctx.strokeStyle = "#000";
ctx.stroke();
ctx.globalCompositeOperation = "source-over";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
ctx.clip();
// ctx.beginPath();
// ctx.arc(this.position.x, this.position.y, 9999, 0, 2 * Math.PI);
// ctx.fillStyle = "#000";
// ctx.fill();
// ctx.strokeStyle = "#000";
// ctx.stroke();
// ctx.beginPath();
// ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
// ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
// ctx.fill();
// ctx.strokeStyle = "#000";
// ctx.stroke();
} else {
this.isShielded = true;
this.dropPowerUp = false;
this.seePlayer.recall = false
this.fill = "transparent"
this.stroke = "transparent"
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
ctx.fillStyle = this.fill;
ctx.fillStyle = `rgba(0,0,0,${0.1*Math.random()})`;
ctx.fill();
}
}
}
this.checkStatus();
}
},
@@ -1857,6 +1873,13 @@ const spawn = {
color: "#f0f0f3"
});
},
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);
}
},
debris(x, y, width, number = Math.floor(2 + Math.random() * 9)) {
for (let i = 0; i < number; ++i) {
if (Math.random() < 0.15) {

View File

@@ -2,6 +2,9 @@ mod - electromagnetic pulse - vacuum bomb removes shields and does 20% extra dam
************** TODO - n-gon **************
mod - spores with no target hang out about player
mod - status effects last 1 second longer
cryonics : a mod that increases the freezing time of mobs.
wait until you have more status effects written