some tech come with a skin - but only 1 at a time
  tech aperture -  skin, damage cycles between -25% and +125%
  tungsten carbide - skin, +100->150 max health
  mass-energy equivalence - skin, gets a bit more benefit from defense
  CPT symmetry - skin, costs a bit less energy
  flip-flop, and relay switch and a few JUNK tech are also skins

some new images
bug fixes
This commit is contained in:
landgreen
2023-02-04 06:54:08 -08:00
parent 74f569b836
commit c9f355b225
26 changed files with 960 additions and 473 deletions

BIN
img/aperture.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -83,6 +83,7 @@
<input list="ban-suggest" id="banned" name="banned" placeholder="list levels by name" autocomplete="off" spellcheck="false" style="width: 182px;" /> <input list="ban-suggest" id="banned" name="banned" placeholder="list levels by name" autocomplete="off" spellcheck="false" style="width: 182px;" />
<datalist id="ban-suggest"> <datalist id="ban-suggest">
<option value="testChamber"> <option value="testChamber">
<option value="lock">
<option value="sewers"> <option value="sewers">
<option value="satellite"> <option value="satellite">
<option value="aerie"> <option value="aerie">
@@ -103,6 +104,7 @@
<option value="vats"> <option value="vats">
<option value="basement"> <option value="basement">
<option value="stronghold"> <option value="stronghold">
<option value="stereo madness">
<option value="house"> <option value="house">
<option value="dripp"> <option value="dripp">
<option value="crossfire"> <option value="crossfire">

View File

@@ -109,7 +109,7 @@ function collisionChecks(event) {
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.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) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
if (m.isCloak) dmg *= 0.75 if (m.isCloak) dmg *= 0.75
mob[k].foundPlayer(); mob[k].foundPlayer();
if (tech.isRewindAvoidDeath && m.energy > 0.66 && dmg > 0.01) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too if (tech.isRewindAvoidDeath && (m.energy + 0.05) > Math.min(1, m.maxEnergy) && dmg > 0.01) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too
m.damage(dmg); m.damage(dmg);
return return
} }

View File

@@ -335,7 +335,7 @@ const build = {
<span style="float: right;">press ${input.key.pause} to resume</span> <span style="float: right;">press ${input.key.pause} to resume</span>
<br> <br>
<br><strong class='color-d'>damage</strong>: ${((tech.damageFromTech())).toPrecision(4)} &nbsp; &nbsp; difficulty: ${((m.dmgScale)).toPrecision(4)} <br><strong class='color-d'>damage</strong>: ${((tech.damageFromTech())).toPrecision(4)} &nbsp; &nbsp; difficulty: ${((m.dmgScale)).toPrecision(4)}
<br><strong class='color-defense'>defense</strong>: ${tech.isEnergyHealth ? (1-Math.pow(m.harmReduction(), 0.1)).toPrecision(5) : (1-m.harmReduction()).toPrecision(5) } &nbsp; &nbsp; difficulty: ${(1/simulation.dmgScale).toPrecision(4)} <br><strong class='color-defense'>defense</strong>: ${tech.isEnergyHealth ? (1-Math.pow(m.harmReduction(), 0.12)).toPrecision(5) : (1-m.harmReduction()).toPrecision(5) } &nbsp; &nbsp; difficulty: ${(1/simulation.dmgScale).toPrecision(4)}
<br><strong><em>fire rate</em></strong>: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}% <br><strong><em>fire rate</em></strong>: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}%
${tech.duplicationChance() ? `<br><strong class='color-dup'>duplication</strong>: ${(tech.duplicationChance()*100).toFixed(0)}%`: ""} ${tech.duplicationChance() ? `<br><strong class='color-dup'>duplication</strong>: ${(tech.duplicationChance()*100).toFixed(0)}%`: ""}
${m.coupling ? `<br><strong class='color-coupling'>coupling</strong>: ${(m.coupling).toFixed(2)} &nbsp; <span style = 'font-size:90%;'>`+m.couplingDescription()+"</span>": ""} ${m.coupling ? `<br><strong class='color-coupling'>coupling</strong>: ${(m.coupling).toFixed(2)} &nbsp; <span style = 'font-size:90%;'>`+m.couplingDescription()+"</span>": ""}
@@ -358,13 +358,13 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
</span></div>`; </span></div>`;
// deaths: ${mobs.mobDeaths} &nbsp; // deaths: ${mobs.mobDeaths} &nbsp;
if (tech.isPauseSwitchField && !simulation.isChoosing) { if (tech.isPauseSwitchField && !simulation.isChoosing) {
const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? Math.floor(Math.random()*10) : ""}.webp');"` const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"`
text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} > text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} >
<div class="card-text" style = "animation: fieldColorCycle 1s linear infinite alternate;"> <div class="card-text" style = "animation: fieldColorCycle 1s linear infinite alternate;">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div> <div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div>
${m.fieldUpgrades[m.fieldMode].description}</div> </div>` ${m.fieldUpgrades[m.fieldMode].description}</div> </div>`
} else { } else {
const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? Math.floor(Math.random()*10) : ""}.webp');"` const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"`
text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} > text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} >
<div class="card-text"> <div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div> <div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div>
@@ -412,7 +412,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
// } else { // } else {
// text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>` // text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
// } // }
const style = (localSettings.isHideImages || tech.tech[i].isJunk) ? `style="height:auto;"` : `style = "background-image: url('img/${tech.tech[i].name}.webp');"` const style = (localSettings.isHideImages || tech.tech[i].isJunk || tech.tech[i].isLore) ? `style="height:auto;"` : `style = "background-image: url('img/${tech.tech[i].name}.webp');"`
const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""; const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
if (tech.tech[i].isNonRefundable) { if (tech.tech[i].isNonRefundable) {
text += `<div class="pause-grid-module" id ="${i}-pause-tech" style = "border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding: 6px;"><div class="grid-title">${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>` text += `<div class="pause-grid-module" id ="${i}-pause-tech" style = "border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding: 6px;"><div class="grid-title">${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
@@ -629,7 +629,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
</div>` </div>`
const hideStyle = `style="height:auto; border: none; background-color: transparent;"` const hideStyle = `style="height:auto; border: none; background-color: transparent;"`
for (let i = 0, len = m.fieldUpgrades.length; i < len; i++) { for (let i = 0, len = m.fieldUpgrades.length; i < len; i++) {
const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/field/${m.fieldUpgrades[i].name}${i === 0 ? Math.floor(Math.random()*10) : ""}.webp');"` const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/field/${m.fieldUpgrades[i].name}${i === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"`
//original //original
// text += powerUps.fieldText(i, `build.choosePowerUp(this,${i},'field')`) // text += powerUps.fieldText(i, `build.choosePowerUp(this,${i},'field')`)
// text += `<div id ="field-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'field')"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}</div>` // text += `<div id ="field-${i}" class="experiment-grid-module" onclick="build.choosePowerUp(this,${i},'field')"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}</div>`
@@ -1642,7 +1642,7 @@ if (!localSettings.isHideImages) {
for (let i = 0, len = b.guns.length; i < len; i++) urls.push("img/gun/" + b.guns[i].name + ".webp") for (let i = 0, len = b.guns.length; i < len; i++) urls.push("img/gun/" + b.guns[i].name + ".webp")
for (let i = 1, len = m.fieldUpgrades.length; i < len; i++) urls.push("img/field/" + m.fieldUpgrades[i].name + ".webp") for (let i = 1, len = m.fieldUpgrades.length; i < len; i++) urls.push("img/field/" + m.fieldUpgrades[i].name + ".webp")
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (!tech.tech[i].isJunk) urls.push("img/" + tech.tech[i].name + ".webp") if (!tech.tech[i].isJunk && !tech.tech[i].isLore) urls.push("img/" + tech.tech[i].name + ".webp")
} }
let images = new Array() let images = new Array()
for (let i = 0; i < urls.length; i++) { for (let i = 0; i < urls.length; i++) {

View File

@@ -23,7 +23,7 @@ const level = {
// spawn.setSpawnList(); // spawn.setSpawnList();
// m.maxHealth = m.health = 100 // m.maxHealth = m.health = 100
// tech.isRerollDamage = true // tech.isRerollDamage = true
// powerUps.research.changeRerolls(10) // powerUps.research.changeRerolls(6)
// m.immuneCycle = Infinity //you can't take damage // m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// m.couplingChange(5) // m.couplingChange(5)
@@ -33,18 +33,16 @@ const level = {
// b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[0].ammo = 10000 // b.guns[0].ammo = 10000
// tech.giveTech("vacuum bomb") // tech.giveTech("tungsten carbide")
// for (let i = 0; i < 3; ++i) tech.giveTech("collider") // tech.giveTech("ship")
// tech.giveTech("diffuse beam") // for (let i = 0; i < 1; ++i) tech.giveTech("mass-energy equivalence")
// for (let i = 0; i < 1; ++i) tech.giveTech("super ball") // for (let i = 0; i < 1; ++i) tech.giveTech("squirrel-cage rotor")
// tech.isFoamBall = true for (let i = 0; i < 1; i++) tech.giveTech("CPT symmetry")
// for (let i = 0; i < 3; ++i) tech.giveTech("repeater") // for (let i = 0; i < 1; i++) tech.giveTech("Meissner effect")
// for (let i = 0; i < 1; i++) tech.giveTech("irradiated nails") // for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 1; i++) tech.giveTech("colony")
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.lock(); // level.testChamber();
// spawn.nodeGroup(1200, 0, "slasher") // spawn.nodeGroup(1200, 0, "slasher")
// spawn.blinkBoss(1900, -500) // spawn.blinkBoss(1900, -500)
// spawn.sneakBoss(1900, -500) // spawn.sneakBoss(1900, -500)
@@ -61,6 +59,10 @@ const level = {
level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************ level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************
// simulation.isAutoZoom = false;
// simulation.zoomScale *= 0.5;
// simulation.setZoom();
// for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech"); // for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
// for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "gun"); // for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "gun");
// for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false); // for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false);
@@ -422,7 +424,7 @@ const level = {
player.velocity.y < 0.15 player.velocity.y < 0.15
) { ) {
// level.exitCount += input.down ? 8 : 2 // level.exitCount += input.down ? 8 : 2
level.exitCount++ level.exitCount += 2
} else if (level.exitCount > 0) { } else if (level.exitCount > 0) {
level.exitCount -= 2 level.exitCount -= 2
} }
@@ -4520,6 +4522,8 @@ const level = {
spawn.mapVertex(4075, 2079, "-150 30 -120 0 150 0 150 600 -150 600"); spawn.mapVertex(4075, 2079, "-150 30 -120 0 150 0 150 600 -150 600");
//escape ledge when drowning //escape ledge when drowning
spawn.mapRect(2750, 525, 100, 25);
spawn.mapRect(2750, 125, 100, 25);
spawn.mapRect(4425, 800, 75, 25); spawn.mapRect(4425, 800, 75, 25);
spawn.mapRect(4425, 325, 75, 25); spawn.mapRect(4425, 325, 75, 25);
// spawn.mapRect(4425, -100, 75, 25); // spawn.mapRect(4425, -100, 75, 25);
@@ -14246,9 +14250,7 @@ const level = {
ctx.restore(); ctx.restore();
} }
} else { } else {
m.draw = () => { m.resetSkin()
m.drawDefault()
}
m.airControl = () => { m.airControl = () => {
if (input.up && m.buttonCD_jump + 20 < m.cycle && m.yOffWhen.stand > 23 && m.lastOnGroundCycle + 5 > m.cycle) m.jump() if (input.up && m.buttonCD_jump + 20 < m.cycle && m.yOffWhen.stand > 23 && m.lastOnGroundCycle + 5 > m.cycle) m.jump()
if (m.buttonCD_jump + 60 > m.cycle && !(input.up) && m.Vy < 0) { if (m.buttonCD_jump + 60 > m.cycle && !(input.up) && m.Vy < 0) {

View File

@@ -63,14 +63,14 @@ const m = {
grd.addColorStop(1, m.fillColor); grd.addColorStop(1, m.fillColor);
m.bodyGradient = grd m.bodyGradient = grd
}, },
setFillColorsAlpha(alpha = 0.5) { // setFillColorsAlpha(alpha = 0.5) {
m.fillColor = `hsla(${m.color.hue},${m.color.sat}%,${m.color.light}%,${alpha})` // m.fillColor = `hsla(${m.color.hue},${m.color.sat}%,${m.color.light}%,${alpha})`
m.fillColorDark = `hsla(${m.color.hue},${m.color.sat}%,${m.color.light - 25}%,${alpha})` // m.fillColorDark = `hsla(${m.color.hue},${m.color.sat}%,${m.color.light - 25}%,${alpha})`
let grd = ctx.createLinearGradient(-30, 0, 30, 0); // let grd = ctx.createLinearGradient(-30, 0, 30, 0);
grd.addColorStop(0, m.fillColorDark); // grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor); // grd.addColorStop(1, m.fillColor);
m.bodyGradient = grd // m.bodyGradient = grd
}, // },
height: 42, height: 42,
yOffWhen: { yOffWhen: {
crouch: 22, crouch: 22,
@@ -533,7 +533,7 @@ const m = {
}, },
baseHealth: 1, baseHealth: 1,
setMaxHealth() { setMaxHealth() {
m.maxHealth = m.baseHealth + tech.extraMaxHealth + tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth //+ (m.fieldMode === 0 || m.fieldMode === 5) * 0.5 * m.coupling m.maxHealth = m.baseHealth + tech.extraMaxHealth + 1.5 * tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth //+ (m.fieldMode === 0 || m.fieldMode === 5) * 0.5 * m.coupling
document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px` document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px`
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(2)}`) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(2)}`)
if (m.health > m.maxHealth) m.health = m.maxHealth; if (m.health > m.maxHealth) m.health = m.maxHealth;
@@ -706,7 +706,7 @@ const m = {
} }
} }
if (tech.isEnergyHealth) { if (tech.isEnergyHealth) {
dmg *= Math.pow(m.harmReduction(), 0.1) //defense has less effect dmg *= Math.pow(m.harmReduction(), 0.12) //defense has less effect
m.energy -= 0.9 * dmg / Math.sqrt(simulation.healScale) //scale damage with heal reduction difficulty m.energy -= 0.9 * dmg / Math.sqrt(simulation.healScale) //scale damage with heal reduction difficulty
if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage
if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) { if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) {
@@ -810,47 +810,10 @@ const m = {
// } // }
}, },
buttonCD: 0, //cool down for player buttons buttonCD: 0, //cool down for player buttons
drawLeg(stroke) { // *********************************************
// if (simulation.mouseInGame.x > m.pos.x) { // ****** drawing player and skins *************
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) { // *********************************************
m.flipLegs = 1; drawLeg(stroke) {},
} else {
m.flipLegs = -1;
}
ctx.save();
ctx.scale(m.flipLegs, 1); //leg lines
ctx.beginPath();
ctx.moveTo(m.hip.x, m.hip.y);
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke;
ctx.lineWidth = 7;
ctx.stroke();
//toe lines
ctx.beginPath();
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
ctx.lineWidth = 4;
ctx.stroke();
//hip joint
ctx.beginPath();
ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
//knee joint
ctx.moveTo(m.knee.x + 7, m.knee.y);
ctx.arc(m.knee.x, m.knee.y, 7, 0, 2 * Math.PI);
//foot joint
ctx.moveTo(m.foot.x + 6, m.foot.y);
ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = m.fillColor;
ctx.fill();
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
},
calcLeg(cycle_offset, offset) { calcLeg(cycle_offset, offset) {
m.hip.x = 12 + offset; m.hip.x = 12 + offset;
m.hip.y = 24 + offset; m.hip.y = 24 + offset;
@@ -871,61 +834,752 @@ const m = {
m.knee.y = (l / d) * (m.foot.y - m.hip.y) + (h / d) * (m.foot.x - m.hip.x) + m.hip.y; m.knee.y = (l / d) * (m.foot.y - m.hip.y) + (h / d) * (m.foot.x - m.hip.x) + m.hip.y;
}, },
draw() {}, draw() {},
drawFlipFlop() { isAltSkin: false,
ctx.fillStyle = m.fillColor; resetSkin() {
m.walk_cycle += m.flipLegs * m.Vx; m.isAltSkin = false
m.color = {
hue: 0,
sat: 0,
light: 100,
}
m.setFillColors();
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
}
m.drawLeg = function(stroke) {
// if (simulation.mouseInGame.x > m.pos.x) {
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
m.flipLegs = 1;
} else {
m.flipLegs = -1;
}
ctx.save();
ctx.scale(m.flipLegs, 1); //leg lines
ctx.beginPath();
ctx.moveTo(m.hip.x, m.hip.y);
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke;
ctx.lineWidth = 7;
ctx.stroke();
//draw body //toe lines
ctx.save(); ctx.beginPath();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 ctx.moveTo(m.foot.x, m.foot.y);
ctx.translate(m.pos.x, m.pos.y); ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
ctx.lineWidth = 4;
ctx.stroke();
m.calcLeg(Math.PI, -3); //hip joint
m.drawLeg("#4a4a4a"); ctx.beginPath();
m.calcLeg(0, 0); ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
m.drawLeg("#333"); //knee joint
ctx.moveTo(m.knee.x + 7, m.knee.y);
ctx.rotate(m.angle); ctx.arc(m.knee.x, m.knee.y, 7, 0, 2 * Math.PI);
ctx.beginPath(); //foot joint
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.moveTo(m.foot.x + 6, m.foot.y);
ctx.fillStyle = m.bodyGradient ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI);
ctx.fill(); ctx.fillStyle = m.fillColor;
ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.fill();
ctx.strokeStyle = "#333"; ctx.lineWidth = 2;
ctx.lineWidth = 2; ctx.stroke();
ctx.stroke(); ctx.restore();
//draw eye }
ctx.beginPath();
ctx.arc(15, 0, 3.5, 0, 2 * Math.PI);
ctx.fillStyle = m.eyeFillColor;
ctx.fill()
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
}, },
drawDefault() { skin: {
ctx.fillStyle = m.fillColor; none() {
m.walk_cycle += m.flipLegs * m.Vx; m.isAltSkin = true
ctx.save(); },
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20) energy() {
ctx.translate(m.pos.x, m.pos.y); m.isAltSkin = true
m.calcLeg(Math.PI, -3); m.color = {
m.drawLeg("#4a4a4a"); hue: 184,
m.calcLeg(0, 0); sat: 100,
m.drawLeg("#333"); light: 85,
ctx.rotate(m.angle); }
ctx.beginPath(); m.setFillColors();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); m.draw = function() {
ctx.fillStyle = m.bodyGradient ctx.fillStyle = m.fillColor;
ctx.fill(); m.walk_cycle += m.flipLegs * m.Vx;
ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.save();
ctx.strokeStyle = "#333"; ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.lineWidth = 2; ctx.translate(m.pos.x, m.pos.y);
ctx.stroke(); m.calcLeg(Math.PI, -3);
ctx.restore(); m.drawLeg("#4a4a4a");
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal m.calcLeg(0, 0);
powerUps.boost.draw() m.drawLeg("#333");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.strokeStyle = "rgba(0,255,255,0.22)";
ctx.lineWidth = 12;
ctx.stroke();
ctx.fillStyle = 'hsl(184,100%,85%)' //m.fillColor; //"#9ff" //m.bodyGradient
ctx.fill();
ctx.beginPath();
ctx.arc(17, 0, 5.5, 0, 2 * Math.PI);
ctx.fillStyle = "#333"
ctx.fill();
ctx.beginPath();
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
}
m.drawLeg = function(stroke) {
// if (simulation.mouseInGame.x > m.pos.x) {
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
m.flipLegs = 1;
} else {
m.flipLegs = -1;
}
ctx.save();
ctx.scale(m.flipLegs, 1); //leg lines
ctx.beginPath();
ctx.moveTo(m.hip.x, m.hip.y);
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke;
ctx.lineWidth = 7;
ctx.stroke();
//toe lines
ctx.beginPath();
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
ctx.lineWidth = 4;
ctx.stroke();
//hip joint
ctx.beginPath();
ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
//knee joint
ctx.moveTo(m.knee.x + 7, m.knee.y);
ctx.arc(m.knee.x, m.knee.y, 7, 0, 2 * Math.PI);
//foot joint
ctx.moveTo(m.foot.x + 6, m.foot.y);
ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI);
ctx.strokeStyle = "rgba(0,255,255,0.25)";
ctx.lineWidth = 5;
ctx.stroke();
ctx.fillStyle = m.fillColor;
ctx.fill();
ctx.restore();
}
},
tungsten() {
m.isAltSkin = true
m.color = {
hue: 210,
sat: 5,
light: 75,
}
// m.setFillColors();
m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 50}%)`
const grd = ctx.createLinearGradient(-30, -5, 30, 10);
grd.addColorStop(0, `#eee`);
grd.addColorStop(0.3, `#bbb`);
grd.addColorStop(0.4, `#aaa`);
grd.addColorStop(0.5, `#ccc`);
grd.addColorStop(0.65, `#bbb`);
grd.addColorStop(0.7, `#aaa`);
grd.addColorStop(0.75, `#bbb`);
grd.addColorStop(1, `#eee`);
// const grdRad = ctx.createRadialGradient(0, 0, 0, 0, 0, 30);
// grdRad.addColorStop(0, `rgba(0,0,0,0.3)`);
// grdRad.addColorStop(0.5, `rgba(210,210,210,0)`);
m.bodyGradient = grd
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(4.2, -3);
m.drawLeg("#666");
m.calcLeg(2.1, -1);
m.drawLeg("#5f5f5f");
m.calcLeg(0, 1);
m.drawLeg("#555");
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
// ctx.fillStyle = grdRad
// ctx.fill();
ctx.strokeStyle = "#000";
ctx.lineWidth = 1.5;
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.fillStyle = "#fff"
ctx.fill();
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
}
m.drawLeg = function(stroke) {
// if (simulation.mouseInGame.x > m.pos.x) {
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
m.flipLegs = 1;
} else {
m.flipLegs = -1;
}
ctx.save();
ctx.scale(m.flipLegs, 1); //leg lines
ctx.beginPath();
ctx.moveTo(m.hip.x, m.hip.y);
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke;
ctx.lineWidth = 4.5;
ctx.stroke();
//toe lines
ctx.beginPath();
ctx.moveTo(m.foot.x, m.foot.y - 1);
ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
ctx.lineTo(m.foot.x, m.foot.y - 1);
ctx.lineWidth = 4;
ctx.stroke();
//hip joint
ctx.beginPath();
ctx.arc(m.hip.x, m.hip.y - 4, 12, 0, 2 * Math.PI);
//knee joint
ctx.moveTo(m.knee.x + 6, m.knee.y);
ctx.arc(m.knee.x, m.knee.y, 6, 0, 2 * Math.PI);
//foot joint
ctx.moveTo(m.foot.x + 5, m.foot.y);
ctx.arc(m.foot.x, m.foot.y, 5, 0, 2 * Math.PI);
ctx.fillStyle = m.fillColor;
ctx.fill();
ctx.lineWidth = 1;
ctx.strokeStyle = "#000"
ctx.stroke();
ctx.restore();
}
},
anodize() {
m.isAltSkin = true
m.color = {
hue: 210,
sat: 14,
light: 65,
}
// m.setFillColors();
m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 50}%)`
// let grd = ctx.createLinearGradient(-30, 0, 30, 0);
const grd = ctx.createRadialGradient(16, 0, 0, 0, 0, 40);
// grd.addColorStop(0, `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 35}%)`);
// grd.addColorStop(0.25, `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 20}%)`);
// grd.addColorStop(0.5, `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 35}%)`);
// grd.addColorStop(1, `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 10}%)`);
grd.addColorStop(0, `#c78034`);
grd.addColorStop(0.04, `#bd5235`);
grd.addColorStop(0.08, `#ab554d`);
grd.addColorStop(0.12, `#8f5d8f`);
grd.addColorStop(0.16, `#4352ab`);
grd.addColorStop(0.2, `#2058b3`);
grd.addColorStop(0.24, `#1a6fc4`);
grd.addColorStop(0.28, `#1b85cf`);
grd.addColorStop(0.32, `#2d9bd7`);
grd.addColorStop(0.4, `#d2d7b4`);
grd.addColorStop(0.44, `#e1cd87`);
grd.addColorStop(0.48, `#f0b955`);
grd.addColorStop(0.52, `#ffa050`);
grd.addColorStop(0.56, `#ff8269`);
grd.addColorStop(0.6, `#f5697d`);
grd.addColorStop(0.64, `#e65aaf`);
grd.addColorStop(0.68, `#d732d7`);
grd.addColorStop(0.72, `#c846e6`);
grd.addColorStop(0.76, `#c850fa`);
grd.addColorStop(0.8, `#878cf0`);
grd.addColorStop(0.84, `#37beeb`);
grd.addColorStop(0.88, `#00d2be`);
grd.addColorStop(0.92, `#00e19b`);
grd.addColorStop(0.96, `#19f5aa`);
grd.addColorStop(1, `#aaf5af`);
m.bodyGradient = grd
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a5a");
m.calcLeg(0, 0);
m.drawLeg("#445");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
// ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#222";
ctx.lineWidth = 2;
// ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
}
m.drawLeg = function(stroke) {
// if (simulation.mouseInGame.x > m.pos.x) {
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
m.flipLegs = 1;
} else {
m.flipLegs = -1;
}
ctx.save();
ctx.scale(m.flipLegs, 1); //leg lines
ctx.beginPath();
ctx.moveTo(m.hip.x, m.hip.y);
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke;
ctx.lineWidth = 7;
ctx.stroke();
//toe lines
ctx.beginPath();
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
ctx.lineWidth = 4;
ctx.stroke();
//hip joint
ctx.beginPath();
ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
ctx.fillStyle = "#1b85cf";
ctx.fill();
//knee joint
ctx.beginPath();
ctx.arc(m.knee.x, m.knee.y, 7, 0, 2 * Math.PI);
ctx.fillStyle = "#ffa050";
ctx.fill();
//foot joint
ctx.beginPath();
ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = "#878cf0";
ctx.fill();
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
}
},
dilate() {
m.isAltSkin = true
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.beginPath();
ctx.arc(12, 0, 8 + 4 * Math.sin(m.cycle * 0.01), 0, 2 * Math.PI); //big eye
ctx.fillStyle = `hsl(${150+100*Math.sin(m.cycle * 0.01)},100%,50%)`
ctx.fill();
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
}
},
CPT() {
m.isAltSkin = true
m.color = {
hue: 0,
sat: 0,
light: 100,
}
// m.setFillColors();
m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 45}%)`
let grd = ctx.createLinearGradient(-30, 0, 30, 0);
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
m.bodyGradient = grd
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#3a3a3a");
m.calcLeg(0, 0);
m.drawLeg("#222");
ctx.rotate(0.013 * simulation.cycle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.restore();
ctx.beginPath();
ctx.arc(m.pos.x + 15 * Math.cos(m.angle), m.pos.y + 15 * Math.sin(m.angle), 5, 0, 2 * Math.PI);
ctx.fillStyle = "#222"
ctx.fill();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
}
m.drawLeg = function(stroke) {
// if (simulation.mouseInGame.x > m.pos.x) {
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
m.flipLegs = 1;
} else {
m.flipLegs = -1;
}
ctx.save();
ctx.scale(m.flipLegs, 1); //leg lines
ctx.beginPath();
ctx.moveTo(m.hip.x, m.hip.y);
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y);
ctx.strokeStyle = stroke;
ctx.lineWidth = 7;
ctx.stroke();
//toe lines
ctx.beginPath();
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
ctx.moveTo(m.foot.x, m.foot.y);
ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
ctx.lineWidth = 4;
ctx.stroke();
//hip joint
ctx.beginPath();
ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
//knee joint
ctx.moveTo(m.knee.x + 7, m.knee.y);
ctx.arc(m.knee.x, m.knee.y, 7, 0, 2 * Math.PI);
//foot joint
ctx.moveTo(m.foot.x + 6, m.foot.y);
ctx.arc(m.foot.x, m.foot.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = m.fillColor;
ctx.fill();
// ctx.lineWidth = 2;
// ctx.stroke();
ctx.restore();
}
},
stubs() {
m.isAltSkin = true
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#555");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
}
m.drawLeg = function(stroke) {
// if (simulation.mouseInGame.x > m.pos.x) {
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
m.flipLegs = 1;
} else {
m.flipLegs = -1;
}
ctx.save();
ctx.scale(m.flipLegs, 1); //leg lines
ctx.beginPath();
ctx.moveTo(m.hip.x, m.hip.y);
ctx.lineTo(m.knee.x, m.knee.y);
ctx.lineTo(m.foot.x, m.foot.y + 5);
ctx.strokeStyle = stroke;
ctx.lineWidth = 6;
ctx.stroke();
ctx.restore();
}
},
Sleipnir() {
m.isAltSkin = true
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y);
for (let i = 0; i < 16; i++) {
m.calcLeg(Math.PI * i / 8, -3 * i / 16)
m.drawLeg("#444")
}
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
}
},
diegesis() {
m.isAltSkin = true
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle - (m.fireCDcycle !== Infinity ? m.flipLegs * 0.25 * Math.pow(Math.max(m.fireCDcycle - m.cycle, 0), 0.5) : 0));
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
}
},
cat() {
m.isAltSkin = true
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) {
ctx.scale(1, -1);
ctx.rotate(Math.PI);
}
ctx.beginPath();
ctx.moveTo(-30, 0);
ctx.bezierCurveTo(-65, -75,
-5, 150 + (5 * Math.sin(simulation.cycle / 10)),
-70 + (10 * Math.sin(simulation.cycle / 10)), 0 + (10 * Math.sin(simulation.cycle / 10)));
ctx.strokeStyle = "#333";
ctx.lineWidth = 4;
ctx.stroke();
if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) {
ctx.scale(1, -1);
ctx.rotate(0 - Math.PI);
}
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle);
if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) ctx.scale(1, -1);
ctx.beginPath();
ctx.moveTo(5, -30);
ctx.lineTo(20, -40);
ctx.lineTo(20, -20);
ctx.lineWidth = 2;
ctx.fillStyle = "#f3f";
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.stroke();
ctx.moveTo(19, 0);
ctx.arc(15, 0, 4, Math.PI, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(24.3, 6, 5, Math.PI * 2, Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(30, 6);
ctx.lineTo(32, 0);
ctx.lineTo(26, 0);
ctx.lineTo(30, 6);
ctx.fillStyle = "#f3f";
ctx.fill();
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
}
},
pareidolia() {
m.isAltSkin = true
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.7
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) ctx.scale(1, -1); //here is the flip
ctx.stroke();
ctx.beginPath();
ctx.arc(2, -6, 7, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(25, -6, 7, 0.25 * Math.PI, 1.6 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(2, -10, 9, 1.25 * Math.PI, 1.75 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(25, -10, 9, 1.25 * Math.PI, 1.4 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(18, 13, 10, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient;
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(18, 13, 6, 0, 2 * Math.PI);
ctx.fillStyle = "#555";
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(3, -6, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(26, -6, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15;
}
},
flipFlop() {
m.isAltSkin = true
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
//draw body
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
//draw eye
ctx.beginPath();
ctx.arc(15, 0, 3.5, 0, 2 * Math.PI);
ctx.fillStyle = m.eyeFillColor;
ctx.fill()
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
powerUps.boost.draw()
}
}
}, },
// ********************************************* // *********************************************
// **************** fields ********************* // **************** fields *********************
@@ -1699,6 +2353,7 @@ const m = {
}, },
fieldUpgrades: [{ fieldUpgrades: [{
name: "field emitter", name: "field emitter",
imageNumber: Math.floor(Math.random() * 17),
description: `use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs description: `use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs
<br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`, // <br><strong>100</strong> max <strong class='color-f'>energy</strong> <br>generate <strong>6</strong> <strong class='color-f'>energy</strong> per second`, // <br><strong>100</strong> max <strong class='color-f'>energy</strong>
effect: () => { effect: () => {
@@ -1991,12 +2646,10 @@ const m = {
m.throwBlock(); m.throwBlock();
} else if (input.field) { //not hold but field button is pressed } else if (input.field) { //not hold but field button is pressed
//float while field is on //float while field is on
// console.log(m.angle, Math.abs(m.angle + Math.PI / 2)) const angleReduction = 0.5 + 0.7 * (Math.PI / 2 - Math.min(Math.PI / 2, Math.abs(m.angle + Math.PI / 2)))
console.log(angleReduction)
//
const angleReduction = 0.1 + (Math.PI / 2 - Math.min(Math.PI / 2, Math.abs(m.angle + Math.PI / 2)))
if (player.velocity.y > 1) { if (player.velocity.y > 1) {
player.force.y -= angleReduction * (tech.isBigField ? 0.9 : 0.7) * player.mass * simulation.g; player.force.y -= angleReduction * (tech.isBigField ? 0.95 : 0.5) * player.mass * simulation.g;
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, {
x: player.velocity.x, x: player.velocity.x,
y: 0.98 * player.velocity.y y: 0.98 * player.velocity.y
@@ -4226,7 +4879,7 @@ const m = {
} }
//fix collisions //fix collisions
collisionChecks = (event) => { collisionChecks = function(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++) {
//mob + (player,bullet,body) collisions //mob + (player,bullet,body) collisions
@@ -4250,7 +4903,7 @@ const m = {
) { ) {
mob[k].foundPlayer(); mob[k].foundPlayer();
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.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) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
if (tech.isRewindAvoidDeath && m.energy > 0.66) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too if (tech.isRewindAvoidDeath && (m.energy + 0.05) > Math.min(1, m.maxEnergy) && dmg > 0.01) { //CPT reversal runs in m.damage, but it stops the rest of the collision code here too
m.damage(dmg); m.damage(dmg);
return return
} }

View File

@@ -663,7 +663,7 @@ const powerUps = {
// width = "384px" // width = "384px"
// } // }
let text = "" let text = ""
if (localSettings.isHideImages || canvas.width < 1200) { if (totalChoices === 1 || localSettings.isHideImages || canvas.width < 1200) {
document.getElementById("choose-grid").style.gridTemplateColumns = width document.getElementById("choose-grid").style.gridTemplateColumns = width
text += powerUps.cancelText(type) text += powerUps.cancelText(type)
text += powerUps.researchText(type) text += powerUps.researchText(type)
@@ -671,10 +671,6 @@ const powerUps = {
document.getElementById("choose-grid").style.gridTemplateColumns = `repeat(2, ${width})` document.getElementById("choose-grid").style.gridTemplateColumns = `repeat(2, ${width})`
text += powerUps.researchText(type) text += powerUps.researchText(type)
text += powerUps.cancelText(type) text += powerUps.cancelText(type)
} else if (totalChoices === 1) {
document.getElementById("choose-grid").style.gridTemplateColumns = width
text += powerUps.cancelText(type)
text += powerUps.researchText(type)
} else { } else {
document.getElementById("choose-grid").style.gridTemplateColumns = `repeat(3, ${width})` document.getElementById("choose-grid").style.gridTemplateColumns = `repeat(3, ${width})`
text += "<div></div>" text += "<div></div>"
@@ -718,7 +714,7 @@ const powerUps = {
}, },
techText(choose, click) { techText(choose, click) {
const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : ""; const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"` const style = localSettings.isHideImages || tech.tech[choose].isLore ? powerUps.hideStyle : `style="background-image: url('img/${tech.tech[choose].name}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${style}> return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${style}>
<div class="card-text"> <div class="card-text">
<div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div> <div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
@@ -1044,15 +1040,15 @@ const powerUps = {
text += powerUps.fieldText(pick, `powerUps.choose('field',${pick})`) text += powerUps.fieldText(pick, `powerUps.choose('field',${pick})`)
} }
} }
if (tech.isMicroTransactions && powerUps.research.count > 0) { // if (tech.isMicroTransactions && powerUps.research.count > 0) {
const skins = [] //find skins // const skins = [] //find skins
for (let i = 0; i < tech.tech.length; i++) { // for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].isSkin) skins.push(i) // if (tech.tech[i].isSkin) skins.push(i)
} // }
const choose = skins[Math.floor(Math.seededRandom(0, skins.length))] //pick an element from the array of options // const choose = skins[Math.floor(Math.seededRandom(0, skins.length))] //pick an element from the array of options
text += `<div class="choose-grid-module" onclick="tech.giveTech(${choose});powerUps.research.changeRerolls(-1);powerUps.endDraft('tech');powerUps.tech.effect();"><div class="grid-title"><div class="circle-grid research"></div> <span style = 'font-size:90%; font-weight: 100; letter-spacing: -1.5px;'>microtransaction:</span> ${tech.tech[choose].name}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>` // text += `<div class="choose-grid-module" onclick="tech.giveTech(${choose});powerUps.research.changeRerolls(-1);powerUps.endDraft('tech');powerUps.tech.effect();"><div class="grid-title"><div class="circle-grid research"></div> <span style = 'font-size:90%; font-weight: 100; letter-spacing: -1.5px;'>microtransaction:</span> ${tech.tech[choose].name}</div>${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div>`
} // }
if (tech.isBrainstorm && !tech.isBrainstormActive && !simulation.isChoosing) { if (tech.isBrainstorm && !tech.isBrainstormActive && !simulation.isChoosing) {
tech.isBrainstormActive = true tech.isBrainstormActive = true
let count = 0 let count = 0
@@ -1410,13 +1406,13 @@ const powerUps = {
if (bigIndexes.length > 0) { if (bigIndexes.length > 0) {
// console.log("at least 1 big will always spilt") // console.log("at least 1 big will always spilt")
const index = bigIndexes[Math.floor(Math.random() * bigIndexes.length)] const index = bigIndexes[Math.floor(Math.random() * bigIndexes.length)]
for (let i = 0; i < 4; i++) powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false) for (let i = 0; i < 3; i++) powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)
Matter.Composite.remove(engine.world, powerUp[index]); Matter.Composite.remove(engine.world, powerUp[index]);
powerUp.splice(index, 1); powerUp.splice(index, 1);
} else if (smallIndexes.length > 3 && Math.random() < 0.25) { } else if (smallIndexes.length > 2 && Math.random() < 0.33) {
// console.log("no big, at least 4 small can combine") // console.log("no big, at least 3 small can combine")
for (let j = 0; j < 4; j++) { for (let j = 0; j < 3; j++) {
for (let i = 0; i < powerUp.length; i++) { for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "heal" || powerUp[i].name === "research" || powerUp[i].name === "ammo" || powerUp[i].name === "coupling" || powerUp[i].name === "boost") { if (powerUp[i].name === "heal" || powerUp[i].name === "research" || powerUp[i].name === "ammo" || powerUp[i].name === "coupling" || powerUp[i].name === "boost") {
Matter.Composite.remove(engine.world, powerUp[i]); Matter.Composite.remove(engine.world, powerUp[i]);

View File

@@ -676,48 +676,6 @@ const simulation = {
}, },
fpsInterval: 0, //set in startGame fpsInterval: 0, //set in startGame
then: null, then: null,
introPlayer() { //not work, but trying to show player in the intro screen
setTimeout(() => {
document.getElementById("info").style.display = "none";
document.getElementById("splash").style.display = "none"; //hides the element that spawned the function
simulation.clearMap()
m.draw = m.drawDefault //set the play draw to normal, undoing some junk tech
m.spawn(); //spawns the player
m.look = m.lookDefault
//level
level.testing(); //not in rotation, used for testing
//load level
simulation.setZoom();
level.addToWorld(); //add bodies to game engine
simulation.draw.setPaths();
function cycle() {
simulation.gravity();
Engine.update(engine, simulation.delta);
simulation.wipe();
if (m.onGround) {
m.groundControl()
} else {
m.airControl()
}
m.move();
// m.look();
// simulation.camera();
m.draw();
m.hold();
simulation.draw.drawMapPath();
ctx.restore();
if (simulation.onTitlePage) requestAnimationFrame(cycle);
}
requestAnimationFrame(cycle)
}, 1000);
},
startGame(isBuildRun = false, isTrainingRun = false) { startGame(isBuildRun = false, isTrainingRun = false) {
simulation.isTextLogOpen = true simulation.isTextLogOpen = true
simulation.clearMap() simulation.clearMap()
@@ -762,7 +720,7 @@ const simulation = {
}) })
// ctx.shadowColor = '#000'; // ctx.shadowColor = '#000';
if (!m.isShipMode) { if (!m.isShipMode) {
m.draw = m.drawDefault //set the play draw to normal, undoing some junk tech m.resetSkin() //set the play draw to normal, undoing some junk tech
m.spawn(); //spawns the player m.spawn(); //spawns the player
m.look = m.lookDefault m.look = m.lookDefault
} else { } else {

View File

@@ -220,6 +220,7 @@ const tech = {
damage: 1, //used for tech changes to player damage that don't have complex conditions damage: 1, //used for tech changes to player damage that don't have complex conditions
damageFromTech() { damageFromTech() {
let dmg = tech.damage //m.fieldDamage let dmg = tech.damage //m.fieldDamage
if (tech.isDilate) dmg *= 1.25 + Math.sin(m.cycle * 0.01)
if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.31 * b.inventory.length if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.31 * b.inventory.length
if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage
if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.15 * m.coupling if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.15 * m.coupling
@@ -733,10 +734,10 @@ const tech = {
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return true return this.count > 0
}, },
requires: "", requires: "",
effect() { // good with melee builds, content skipping builds effect() {
tech.squirrelFx += 0.25; tech.squirrelFx += 0.25;
tech.squirrelJump += 0.1; tech.squirrelJump += 0.1;
m.setMovement() m.setMovement()
@@ -1008,7 +1009,7 @@ const tech = {
{ {
name: "collider", name: "collider",
descriptionFunction() { descriptionFunction() {
return `after mobs <strong>die</strong> there is a <strong>+33%</strong> chance <br>to change a <strong>power up</strong> into a different <strong>flavor</strong>` return `after mobs <strong>die</strong> there is a <strong>+33%</strong> chance <br>to smash <strong>power ups</strong> into a different <strong>flavor</strong>`
}, },
maxCount: 3, maxCount: 3,
count: 0, count: 0,
@@ -1896,6 +1897,7 @@ const tech = {
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
isSkin: true,
allowed() { allowed() {
return !tech.isRelay return !tech.isRelay
}, },
@@ -1912,7 +1914,7 @@ const tech = {
} }
} }
if (!m.isShipMode) { if (!m.isShipMode) {
m.draw = m.drawFlipFlop m.skin.flipFlop()
} }
}, },
remove() { remove() {
@@ -1927,6 +1929,7 @@ const tech = {
} }
} }
m.eyeFillColor = 'transparent' m.eyeFillColor = 'transparent'
m.resetSkin();
} }
}, },
{ {
@@ -2047,11 +2050,13 @@ const tech = {
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
isSkin: true,
allowed() { allowed() {
return !tech.isFlipFlop return !tech.isFlipFlop
}, },
requires: "not flip-flop", requires: "not flip-flop",
effect() { effect() {
m.isAltSkin = true
tech.isRelay = true //do you have this tech? tech.isRelay = true //do you have this tech?
if (!tech.isFlipFlopOn) { if (!tech.isFlipFlopOn) {
tech.isFlipFlopOn = true //what is the state of flip-Flop? tech.isFlipFlopOn = true //what is the state of flip-Flop?
@@ -2063,7 +2068,7 @@ const tech = {
} }
} }
if (!m.isShipMode) { if (!m.isShipMode) {
m.draw = m.drawFlipFlop m.skin.flipFlop()
} }
}, },
remove() { remove() {
@@ -2078,6 +2083,7 @@ const tech = {
} }
} }
m.eyeFillColor = 'transparent' m.eyeFillColor = 'transparent'
m.resetSkin();
} }
}, },
{ {
@@ -2293,21 +2299,24 @@ const tech = {
// description: "<strong>charge</strong>, <strong>parity</strong>, and <strong>time</strong> invert to undo <strong class='color-defense'>defense</strong><br><strong class='color-rewind'>rewind</strong> <strong>(1.5—5)</strong> seconds for <strong>(66—220)</strong> <strong class='color-f'>energy</strong>", // description: "<strong>charge</strong>, <strong>parity</strong>, and <strong>time</strong> invert to undo <strong class='color-defense'>defense</strong><br><strong class='color-rewind'>rewind</strong> <strong>(1.5—5)</strong> seconds for <strong>(66—220)</strong> <strong class='color-f'>energy</strong>",
// description: "after losing <strong class='color-h'>health</strong>, if you have <strong>full</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>44</strong> <strong class='color-f'>energy</strong> per second", // description: "after losing <strong class='color-h'>health</strong>, if you have <strong>full</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>44</strong> <strong class='color-f'>energy</strong> per second",
descriptionFunction() { descriptionFunction() {
return `after losing <strong class='color-h'>health</strong>, if you have <strong>${(100*Math.min(100,m.maxEnergy)).toFixed(0)}</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>44</strong> <strong class='color-f'>energy</strong> per second` return `after losing <strong class='color-h'>health</strong>, if you have <strong>${(100*Math.min(100,m.maxEnergy)).toFixed(0)}</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>40</strong> <strong class='color-f'>energy</strong> per second`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
isSkin: true,
allowed() { allowed() {
return m.fieldUpgrades[m.fieldMode].name !== "standing wave" && !tech.isRewindField && !tech.isEnergyHealth return !m.isAltSkin && m.fieldUpgrades[m.fieldMode].name !== "standing wave" && !tech.isRewindField && !tech.isEnergyHealth
}, },
requires: "not standing wave, max energy reduction, retrocausality, mass-energy", requires: "not skinned, standing wave, max energy reduction, retrocausality, mass-energy",
effect() { effect() {
tech.isRewindAvoidDeath = true; tech.isRewindAvoidDeath = true;
m.skin.CPT()
}, },
remove() { remove() {
tech.isRewindAvoidDeath = false; tech.isRewindAvoidDeath = false;
m.resetSkin();
} }
}, },
{ {
@@ -2371,13 +2380,14 @@ const tech = {
{ {
name: "mass-energy equivalence", name: "mass-energy equivalence",
// description: "<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br>√ of <strong class='color-defense'>defense</strong> <strong>reduction</strong> reduces max <strong class='color-f'>energy</strong>", // description: "<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br>√ of <strong class='color-defense'>defense</strong> <strong>reduction</strong> reduces max <strong class='color-f'>energy</strong>",
description: "<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br>exponentially <strong>reduced</strong> <strong class='color-defense'>defense</strong> <em>(~ x^0.1)</em>", description: "<strong class='color-f'>energy</strong> protects you instead of <strong class='color-h'>health</strong><br>exponentially <strong>reduced</strong> <strong class='color-defense'>defense</strong> <em>(~ x^0.12)</em>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
isSkin: true,
allowed() { allowed() {
return !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isAnnihilation //&& !tech.isAmmoFromHealth && !tech.isRewindGun return !m.isAltSkin && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isAnnihilation //&& !tech.isAmmoFromHealth && !tech.isRewindGun
}, },
requires: "not piezoelectricity, CPT, annihilation", requires: "not piezoelectricity, CPT, annihilation",
effect() { effect() {
@@ -2386,8 +2396,9 @@ const tech = {
document.getElementById("health-bg").style.display = "none" document.getElementById("health-bg").style.display = "none"
document.getElementById("dmg").style.backgroundColor = "#0cf"; document.getElementById("dmg").style.backgroundColor = "#0cf";
tech.isEnergyHealth = true; tech.isEnergyHealth = true;
simulation.mobDmgColor = "rgba(14, 190, 235,0.7)" //"#0cf" simulation.mobDmgColor = "rgba(0, 255, 255,0.6)" //"#0cf"
m.displayHealth(); m.displayHealth();
m.skin.energy();
}, },
remove() { remove() {
if (tech.isEnergyHealth) { if (tech.isEnergyHealth) {
@@ -2400,6 +2411,7 @@ const tech = {
m.displayHealth(); m.displayHealth();
} }
tech.isEnergyHealth = false; tech.isEnergyHealth = false;
m.resetSkin();
} }
}, },
{ {
@@ -2850,23 +2862,26 @@ const tech = {
}, },
{ {
name: "tungsten carbide", name: "tungsten carbide",
description: "<strong>+100</strong> maximum <strong class='color-h'>health</strong><br><strong>lose</strong> <strong class='color-h'>health</strong> after hard <strong>landings</strong>", description: "<strong>+150</strong> maximum <strong class='color-h'>health</strong><br><strong>lose</strong> <strong class='color-h'>health</strong> after hard <strong>landings</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
isSkin: true,
allowed() { allowed() {
return true return !m.isAltSkin
}, },
requires: "", requires: "not skin",
effect() { effect() {
tech.isFallingDamage = true; tech.isFallingDamage = true;
m.setMaxHealth(); m.setMaxHealth();
m.addHealth(1 / simulation.healScale) m.addHealth(1 / simulation.healScale)
m.skin.tungsten()
}, },
remove() { remove() {
tech.isFallingDamage = false; tech.isFallingDamage = false;
m.setMaxHealth(); m.setMaxHealth();
m.resetSkin();
} }
}, },
{ {
@@ -3495,6 +3510,27 @@ const tech = {
} }
} }
}, },
{
name: "aperture",
description: "your damage cycles every <strong>6</strong> seconds<br>between <strong>-75%</strong> and <strong>+125%</strong> <strong class='color-d'>damage</strong>",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
isSkin: true,
allowed() {
return !m.isAltSkin
},
requires: "not skinned",
effect() {
tech.isDilate = true
m.skin.dilate()
},
remove() {
tech.isDilate = false
m.resetSkin();
}
},
{ {
name: "exciton", name: "exciton",
descriptionFunction() { descriptionFunction() {
@@ -10063,30 +10099,25 @@ const tech = {
}, },
remove() {} remove() {}
}, },
// { {
// name: "inverted input", name: "stubs",
// description: "left input becomes right and up input becomes down", description: "no knees or toes are drawn on the player",
// maxCount: 9, maxCount: 1,
// count: 0, count: 0,
// frequency: 0, frequency: 0,
// isNonRefundable: true, isSkin: true,
// isExperimentHide: true, isJunk: true,
// isJunk: true, allowed() {
// allowed() { return !m.isShipMode
// return true },
// }, requires: "",
// requires: "", effect() {
// effect() { m.skin.stubs()
// const left = input.key.left },
// input.key.left = input.key.right remove() {
// input.key.right = left m.resetSkin();
}
// const up = input.key.up },
// input.key.up = input.key.down
// input.key.down = up
// },
// remove() {}
// },
{ {
name: "Sleipnir", name: "Sleipnir",
description: "grow more legs", description: "grow more legs",
@@ -10094,44 +10125,17 @@ const tech = {
count: 0, count: 0,
frequency: 0, frequency: 0,
isSkin: true, isSkin: true,
isNonRefundable: true,
isJunk: true, isJunk: true,
allowed() { allowed() {
return !m.isShipMode return !m.isShipMode
}, },
requires: "", requires: "",
effect() { effect() {
m.draw = function() { m.skin.Sleipnir()
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
//draw body
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y);
for (let i = 0; i < 16; i++) {
m.calcLeg(Math.PI * i / 8, -3 * i / 16)
m.drawLeg("#444")
}
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
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 = '#0cf';
// ctx.fill()
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
}
}, },
remove() {} remove() {
m.resetSkin();
}
}, },
{ {
name: "diegesis", name: "diegesis",
@@ -10140,39 +10144,17 @@ const tech = {
count: 0, count: 0,
frequency: 0, frequency: 0,
isSkin: true, isSkin: true,
isNonRefundable: true,
isJunk: true, isJunk: true,
allowed() { allowed() {
return !m.isShipMode return !m.isShipMode
}, },
requires: "", requires: "",
effect() { effect() {
m.draw = function() { m.skin.diegesis()
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle - (m.fireCDcycle !== Infinity ? m.flipLegs * 0.25 * Math.pow(Math.max(m.fireCDcycle - m.cycle, 0), 0.5) : 0));
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
}
}, },
remove() {} remove() {
m.resetSkin();
}
}, },
{ {
name: "🐱", name: "🐱",
@@ -10181,80 +10163,17 @@ const tech = {
count: 0, count: 0,
frequency: 0, frequency: 0,
isSkin: true, isSkin: true,
isNonRefundable: true,
isJunk: true, isJunk: true,
allowed() { allowed() {
return !m.isShipMode return !m.isShipMode
}, },
requires: "", requires: "",
effect() { effect() {
m.draw = function() { m.skin.cat();
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) {
ctx.scale(1, -1);
ctx.rotate(Math.PI);
}
ctx.beginPath();
ctx.moveTo(-30, 0);
ctx.bezierCurveTo(-65, -75,
-5, 150 + (5 * Math.sin(simulation.cycle / 10)),
-70 + (10 * Math.sin(simulation.cycle / 10)), 0 + (10 * Math.sin(simulation.cycle / 10)));
ctx.strokeStyle = "#333";
ctx.lineWidth = 4;
ctx.stroke();
if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) {
ctx.scale(1, -1);
ctx.rotate(0 - Math.PI);
}
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle);
if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) ctx.scale(1, -1);
ctx.beginPath();
ctx.moveTo(5, -30);
ctx.lineTo(20, -40);
ctx.lineTo(20, -20);
ctx.lineWidth = 2;
ctx.fillStyle = "#f3f";
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.stroke();
ctx.moveTo(19, 0);
ctx.arc(15, 0, 4, Math.PI, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(24.3, 6, 5, Math.PI * 2, Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(30, 6);
ctx.lineTo(32, 0);
ctx.lineTo(26, 0);
ctx.lineTo(30, 6);
ctx.fillStyle = "#f3f";
ctx.fill();
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
}
}, },
remove() {} remove() {
m.resetSkin();
}
}, },
{ {
name: "n-gone", name: "n-gone",
@@ -10263,7 +10182,6 @@ const tech = {
count: 0, count: 0,
frequency: 0, frequency: 0,
isSkin: true, isSkin: true,
isNonRefundable: true,
isJunk: true, isJunk: true,
allowed() { allowed() {
return true return true
@@ -10272,7 +10190,29 @@ const tech = {
effect() { effect() {
m.draw = () => {} m.draw = () => {}
}, },
remove() {} remove() {
m.resetSkin();
}
},
{
name: "pareidolia",
description: "don't",
maxCount: 1,
count: 0,
frequency: 0,
isSkin: true,
isNonRefundable: true,
isJunk: true,
allowed() {
return !m.isShipMode
},
requires: "",
effect() {
m.skin.pareidolia()
},
remove() {
m.resetSkin();
}
}, },
{ {
name: "posture", name: "posture",
@@ -10280,7 +10220,6 @@ const tech = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 0, frequency: 0,
isSkin: true,
isJunk: true, isJunk: true,
allowed() { allowed() {
return !m.isShipMode return !m.isShipMode
@@ -10299,7 +10238,6 @@ const tech = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 0, frequency: 0,
isSkin: true,
isJunk: true, isJunk: true,
isNonRefundable: true, isNonRefundable: true,
allowed() { allowed() {
@@ -10314,82 +10252,12 @@ const tech = {
}, },
remove() {} remove() {}
}, },
{
name: "pareidolia",
description: "don't",
maxCount: 1,
count: 0,
frequency: 0,
isSkin: true,
isNonRefundable: true,
isJunk: true,
allowed() {
return !m.isShipMode
},
requires: "",
effect() {
m.draw = function() {
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.7
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient
ctx.fill();
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
if (!(m.angle > -Math.PI / 2 && m.angle < Math.PI / 2)) ctx.scale(1, -1); //here is the flip
ctx.stroke();
ctx.beginPath();
ctx.arc(2, -6, 7, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(25, -6, 7, 0.25 * Math.PI, 1.6 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(2, -10, 9, 1.25 * Math.PI, 1.75 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(25, -10, 9, 1.25 * Math.PI, 1.4 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(18, 13, 10, 0, 2 * Math.PI);
ctx.fillStyle = m.bodyGradient;
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(18, 13, 6, 0, 2 * Math.PI);
ctx.fillStyle = "#555";
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(3, -6, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(26, -6, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15;
}
},
remove() {}
},
{ {
name: "prism", name: "prism",
description: "you cycle through different <strong>colors</strong>", description: "you cycle through different <strong>colors</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 0, frequency: 0,
isSkin: true,
isNonRefundable: true, isNonRefundable: true,
isJunk: true, isJunk: true,
allowed() { allowed() {
@@ -10409,24 +10277,24 @@ const tech = {
}, },
remove() {} remove() {}
}, },
{ // {
name: "microtransactions", // name: "microtransactions",
description: `when you choose a <strong class='color-m'>tech</strong> you can<br>use ${powerUps.orb.research(1)} to buy a free in game <strong>skin</strong>`, // description: `when you choose a <strong class='color-m'>tech</strong> you can<br>use ${powerUps.orb.research(1)} to buy a free in game <strong>skin</strong>`,
maxCount: 1, // maxCount: 1,
count: 0, // count: 0,
frequency: 0, // frequency: 0,
isJunk: true, // isJunk: true,
allowed() { // allowed() {
return true // return true
}, // },
requires: "", // requires: "",
effect() { // effect() {
tech.isMicroTransactions = true // tech.isMicroTransactions = true
}, // },
remove() { // remove() {
tech.isMicroTransactions = false // tech.isMicroTransactions = false
} // }
}, // },
{ {
name: "ship", name: "ship",
description: "fly around with no legs<br>reduce combat <strong>difficulty</strong> by <strong>1 level</strong>", description: "fly around with no legs<br>reduce combat <strong>difficulty</strong> by <strong>1 level</strong>",
@@ -10436,10 +10304,11 @@ const tech = {
isNonRefundable: true, isNonRefundable: true,
isJunk: true, isJunk: true,
allowed() { allowed() {
return !m.isShipMode && m.fieldUpgrades[m.fieldMode].name !== "negative mass" return !m.isShipMode && !m.isAltSkin && m.fieldUpgrades[m.fieldMode].name !== "negative mass"
}, },
requires: "", requires: "",
effect() { effect() {
m.isAltSkin = true
m.shipMode() m.shipMode()
level.difficultyDecrease(simulation.difficultyMode) level.difficultyDecrease(simulation.difficultyMode)
//unlock relativistic rotation //unlock relativistic rotation
@@ -11399,7 +11268,7 @@ const tech = {
quantumEraserCount: null, quantumEraserCount: null,
isPhononBlock: null, isPhononBlock: null,
isPhononWave: null, isPhononWave: null,
isMicroTransactions: null, // isMicroTransactions: null,
isLaserLens: null, isLaserLens: null,
laserCrit: null, laserCrit: null,
isSporeColony: null, isSporeColony: null,
@@ -11422,4 +11291,5 @@ const tech = {
isSuperMine: null, isSuperMine: null,
sentryAmmo: null, sentryAmmo: null,
collidePowerUps: null, collidePowerUps: null,
isDilate: null,
} }

View File

@@ -1,38 +1,50 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
exit doors take longer to open some tech come with a skin - but only 1 at a time
it's nice to take a few seconds to relax between levels tech aperture - skin, damage cycles between -25% and +125%
please don't submit a bug report about this tungsten carbide - skin, +100->150 max health
mass-energy equivalence - skin, gets a bit more benefit from defense
CPT symmetry - skin, costs a bit less energy
flip-flop, and relay switch and a few JUNK tech are also skins
plasma torch energy regen 6->10 some new images
perfect diamagnetism energy regen 6->5 bug fixes
a few more new images
tech: collider - after a mob dies smash power ups and change the flavor of one of them
powerUps.randomize(where)
if there is a tech,field,gun it will split into 4 small power ups
else if there are at least 4 small power ups they have a 1/4 chance to combine into a tech, field, gun
else a random small power up will change
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
tech: if a needle hits 2 mobs reset your fire CD
and maybe to 2x damage for each consecutive mob hit?
tech for lens - you can only fire through the lens and some buff? damage or energy?
this was in todo.txt on GitHub. I think it should be 'laser never drains energy, but you can only fire through lens and +90° lens arc, +100% damage (also you can not gain compound lens with this upgrade)
Tech: Von Neuman probes - Drones will consume blocks to replicate themselves
it's a little too similar to the drone repair tech, but I kinda like it better. drones that eat blocks and spit out more drones is cool
new boss level like reactor with a very very big boss
mechanics around a very big boss?
maybe the boss moves into rooms so you have to do platforming to clear the room before the boss enters the room
boss can destroy blocks and smaller map elements
tech - after standing wave runs out of energy from blocking, gain a buff
buff: defense, damage?
aoe damage like railgun
push mobs away
diagetic UI Elements diagetic UI Elements
ammo number? ammo number?
doesn't text look choppy when camera moves? doesn't text look choppy when camera moves?
health bar could be rendered similarly to energy bar health bar could be rendered similarly to energy bar
what about 2 bezier curves on left and right of player head that looks like 1/3 circleRadiusScale what about 2 bezier curves on left and right of player head that looks like 1/3 circleRadiusScale
what about 2 bezier both above player rotate the curves as the head rotates
what about 2 bezier both above player
as the total energy and health increases the curses could asymptotically approach a maximum length as max energy/health goes to infinity as the total energy and health increases the curses could asymptotically approach a maximum length as max energy/health goes to infinity
level: lock level: lock
should there be something in the top part of the map? should there be something in the top part of the map?
add alt versions of left and right sides add alt versions of left and right sides
make flipped L/R version (after everything else is done) make flipped L/R version (after everything else is done)
Tech: Drones always follow you mouse, never going to attack enemies or pick up power ups unless they are close to your mouse
tech: add an selection option to all tech, gun, fields to do something tech: add an selection option to all tech, gun, fields to do something
set all mobs to 30% health, and stun all mobs set all mobs to 30% health, and stun all mobs
50% chance to convert all power ups into research 50% chance to convert all power ups into research
@@ -43,8 +55,6 @@ tech: if you die inside MACHO, heal to full and delete the MACHO for the rest of
tech: after bosses die<br>they spawn a research tech: after bosses die<br>they spawn a research
tech: neutrino oscillation - when a mob dies there is a __% chance to convert a random existing power up to a different type
tech: +8% damage each time you kill a boss tech: +8% damage each time you kill a boss
tech: maybe missiles explode when they hit walls, but explosions only drain energy tech: maybe missiles explode when they hit walls, but explosions only drain energy
@@ -66,11 +76,6 @@ tech: Bose Einstein condensate - freezes enemies in pilot wave, and drains some
super-bot super-bot
tech - after standing wave runs out of energy from blocking, gain a buff
buff: defense, damage?
aoe damage like railgun
push mobs away
make super balls with Zectron deflectable with field make super balls with Zectron deflectable with field
but is there a simple way to do this? but is there a simple way to do this?
@@ -1172,6 +1177,7 @@ if pause is pressed while selecting power ups, display pause menu on top of sele
supercritical fission supercritical fission
***past style themes*** ***past style themes***
field emitter - isometric, clean white robot spherical gun turret on bird legs, blender 3d, style of artstation and behance, Disney Pixar, cute field emitter - isometric, clean white robot spherical gun turret on bird legs, blender 3d, style of artstation and behance, Disney Pixar, cute
damaged dirty white robot spherical gun turret on bird legs in the style of Solarpunk
standing wave - concentric transparent blue geometric circles science standing wave - concentric transparent blue geometric circles science
perfect diamagnetism - physics magnetic field chalk diagram perfect diamagnetism - physics magnetic field chalk diagram
time dilation - graphic of a hyperbolic equation Luminogram time dilation - graphic of a hyperbolic equation Luminogram