1-body problem

tech: 1-body problem - do 100% damage if there is only 1 active bullet

experiment mode and junk tech: random aiming

bug fix - sniper, shooter aiming might be improved (no more firing backwards)
  or maybe I just made it worse, let me know

bug fix - Shift registers

working on rewriting the way backgrounds and foregrounds are drawn on each level (in progress)
This commit is contained in:
landgreen
2021-03-30 05:23:56 -07:00
parent 3ab42884ca
commit 4848cc4e73
11 changed files with 369 additions and 261 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -452,7 +452,7 @@ const b = {
},
pulse(energy, angle = m.angle) {
let best;
let explosionRadius = 1300 * energy
let explosionRadius = 1250 * energy
let range = 3000
const path = [{
x: m.pos.x + 20 * Math.cos(angle),
@@ -2050,7 +2050,7 @@ const b = {
isImproved: false,
beforeDmg(who) {
if (tech.isIncendiary) {
const max = Math.min(this.endCycle - simulation.cycle, 1500)
const max = Math.max(Math.min(this.endCycle - simulation.cycle, 1500), 0)
b.explosion(this.position, max * 0.08 + this.isImproved * 100 + 60 * Math.random()); //makes bullet do explosive damage at end
this.endCycle -= max
} else {
@@ -4550,7 +4550,7 @@ const b = {
x: 7.5 * Math.cos(m.angle - Math.PI / 2),
y: 7.5 * Math.sin(m.angle - Math.PI / 2)
}
const dmg = 0.6 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
const dmg = 0.7 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
const eye = {
x: m.pos.x + 15 * Math.cos(m.angle),
@@ -4630,10 +4630,10 @@ const b = {
},
firePulse() {
m.fireCDcycle = m.cycle + Math.floor((tech.isPulseAim ? 25 : 50) * b.fireCD); // cool down
let energy = 0.27 * Math.min(m.energy, 1.5)
let energy = 0.3 * Math.min(m.energy, 1.5)
m.energy -= energy * tech.isLaserDiode
if (tech.beamSplitter) {
energy *= Math.pow(0.9, tech.beamSplitter)
energy *= Math.pow(0.85, tech.beamSplitter)
b.pulse(energy, m.angle)
for (let i = 1; i < 1 + tech.beamSplitter; i++) {
b.pulse(energy, m.angle - i * 0.27)

View File

@@ -783,6 +783,7 @@ window.addEventListener("keydown", function(event) {
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline'
if (!simulation.isCheating) {
simulation.isCheating = true;
level.levelAnnounce();
lore.techCount = 0;
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isLore) {

View File

@@ -111,7 +111,7 @@ const level = {
// if (tech.isPerpetualStun) {
// for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], 780)
// }
if (tech.isFlipFlopHarm && tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
if (tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
tech.isFlipFlopOn = true
m.eyeFillColor = m.fieldMeterColor
simulation.makeTextLog(`tech.isFlipFlopOn <span class='color-symbol'>=</span> true`);
@@ -155,10 +155,11 @@ const level = {
}
},
levelAnnounce() {
const difficulty = simulation.isCheating ? "testing" : level.difficultyText()
if (level.levelsCleared === 0) {
document.title = "n-gon: (" + level.difficultyText() + ")";
document.title = "n-gon: (" + difficulty + ")";
} else {
document.title = (simulation.isCheating ? "∅ " : "n-gon:") + (level.levelsCleared) + " " + level.levels[level.onLevel] + " (" + level.difficultyText() + ")";
document.title = `n-gon: ${level.levelsCleared} ${level.levels[level.onLevel]} (${difficulty})`
simulation.makeTextLog(`<span class='color-var'>level</span>.onLevel <span class='color-symbol'>=</span> "<span class='color-text'>${level.levels[level.onLevel]}</span>"`);
}
// simulation.makeTextLog(`
@@ -932,7 +933,6 @@ const level = {
radius: 50
}
level.custom = () => {
// level.playerExitCheck();
hazardSlime.query();
//draw wide line
@@ -958,7 +958,10 @@ const level = {
ctx.arc(circle.x, circle.y, circle.radius / 8, 0, 2 * Math.PI);
ctx.fillStyle = lore.talkingColor //"#dff"
ctx.fill();
// ctx.stroke();
level.enter.draw();
// level.exit.draw();
// level.playerExitCheck();
};
let sway = {
x: 0,
@@ -1002,7 +1005,7 @@ const level = {
level.setPosToSpawn(0, -50); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 25, 100, 10);
level.exit.x = 0;
level.exit.y = 200;
level.exit.y = 400;
level.defaultZoom = 1000
simulation.zoomTransition(level.defaultZoom)
// document.body.style.backgroundColor = "#aaa";
@@ -1044,6 +1047,8 @@ const level = {
button.query();
button.draw();
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {};
@@ -1116,11 +1121,11 @@ const level = {
// spawn.streamBoss(1600, -500)
// spawn.orbitalBoss(1600, -500)
// spawn.cellBossCulture(1600, -500)
spawn.shieldingBoss(1600, -500)
// spawn.shieldingBoss(1600, -500)
// spawn.beamer(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);
spawn.nodeGroup(1200, -500, "grower")
spawn.nodeGroup(1200, -500, "sniper")
// spawn.snakeBoss(1200, -500)
// spawn.powerUpBoss(2900, -500)
// spawn.randomMob(1600, -500)
@@ -1128,6 +1133,8 @@ const level = {
template() {
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {};
level.setPosToSpawn(0, -50); //normal spawn
@@ -1139,20 +1146,6 @@ const level = {
document.body.style.backgroundColor = "#dcdcde";
// powerUps.spawnStartingPowerUps(1475, -1175);
// spawn.debris(750, -2200, 3700, 16); //16 debris per level
// level.fill.push({ //foreground
// x: 2500,
// y: -1100,
// width: 450,
// height: 250,
// color: "rgba(0,0,0,0.1)"
// });
// level.fillBG.push({ //background
// x: 1300,
// y: -1800,
// width: 750,
// height: 1800,
// color: "#d4d4d7"
// });
spawn.mapRect(-100, 0, 1000, 100);
// spawn.bodyRect(1540, -1110, 300, 25, 0.9);
@@ -1167,6 +1160,8 @@ const level = {
final() {
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {};
@@ -1178,7 +1173,7 @@ const level = {
level.defaultZoom = 2500
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#ccc";
document.body.style.backgroundColor = "#ddd";
level.fill.push({
x: 5400,
@@ -1219,6 +1214,8 @@ const level = {
gauntlet() {
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {};
@@ -1284,152 +1281,174 @@ const level = {
},
intro() {
level.custom = () => {
level.playerExitCheck();
};
level.customTopLayer = () => {};
//draw binary number
const binary = (localSettings.runCount >>> 0).toString(2)
const height = 25
const thick = 2
const color = "#aaa"
const xOff = -130 //2622
const yOff = -45 //-580
let xLetter = 0
const height = 20
const width = 8
const yOff = -40 //-580
let xOff = -130 //2622
ctx.strokeStyle = "#adf"
ctx.lineWidth = 1.5;
ctx.beginPath()
for (let i = 0; i < binary.length; i++) {
if (binary[i] === "0") {
zero(xOff + xLetter, yOff)
ctx.moveTo(xOff, yOff)
ctx.lineTo(xOff, yOff + height)
ctx.lineTo(xOff + width, yOff + height)
ctx.lineTo(xOff + width, yOff)
ctx.lineTo(xOff, yOff)
xOff += 10 + width
} else {
one(xOff + xLetter, yOff)
ctx.moveTo(xOff, yOff)
ctx.lineTo(xOff, yOff + height)
xOff += 10
}
}
ctx.stroke();
function one(x, y) {
level.fillBG.push({
x: x,
y: y,
width: thick,
height: height,
color: color
});
xLetter += 10
}
//wires
ctx.beginPath()
ctx.moveTo(-150, -275)
ctx.lineTo(80, -275)
ctx.lineTo(80, -1000)
ctx.moveTo(-150, -265)
ctx.lineTo(90, -265)
ctx.lineTo(90, -1000)
ctx.moveTo(-150, -255)
ctx.lineTo(100, -255)
ctx.lineTo(100, -1000)
ctx.moveTo(-150, -245)
ctx.lineTo(1145, -245)
ctx.lineTo(1145, 0)
ctx.moveTo(-150, -235)
ctx.lineTo(1135, -235)
ctx.lineTo(1135, 0)
ctx.moveTo(-150, -225)
ctx.lineTo(1125, -225)
ctx.lineTo(1125, 0)
ctx.moveTo(-150, -215)
ctx.lineTo(460, -215)
ctx.lineTo(460, 0)
ctx.moveTo(-150, -205)
ctx.lineTo(450, -205)
ctx.lineTo(450, 0)
ctx.moveTo(-150, -195)
ctx.lineTo(440, -195)
ctx.lineTo(440, 0)
ctx.moveTo(1155, 0)
ctx.lineTo(1155, -450)
ctx.lineTo(1000, -450)
ctx.lineTo(1000, -1000)
ctx.moveTo(1165, 0)
ctx.lineTo(1165, -460)
ctx.lineTo(1010, -460)
ctx.lineTo(1010, -1000)
ctx.moveTo(1175, 0)
ctx.lineTo(1175, -470)
ctx.lineTo(1020, -470)
ctx.lineTo(1020, -1000)
ctx.moveTo(1185, 0)
ctx.lineTo(1185, -480)
ctx.lineTo(1030, -480)
ctx.lineTo(1030, -1000)
ctx.moveTo(1195, 0)
ctx.lineTo(1195, -490)
ctx.lineTo(1040, -490)
ctx.lineTo(1040, -1000)
ctx.moveTo(1625, -1000)
ctx.lineTo(1625, 0)
ctx.moveTo(1635, -1000)
ctx.lineTo(1635, 0)
ctx.moveTo(1645, -1000)
ctx.lineTo(1645, 0)
ctx.moveTo(1655, -1000)
ctx.lineTo(1655, 0)
ctx.moveTo(1665, -1000)
ctx.lineTo(1665, 0)
ctx.moveTo(1675, -465)
ctx.lineTo(2325, -465)
ctx.lineTo(2325, 0)
ctx.moveTo(1675, -455)
ctx.lineTo(2315, -455)
ctx.lineTo(2315, 0)
ctx.moveTo(1675, -445)
ctx.lineTo(2305, -445)
ctx.lineTo(2305, 0)
ctx.moveTo(1675, -435)
ctx.lineTo(2295, -435)
ctx.lineTo(2295, 0)
ctx.moveTo(2335, 0)
ctx.lineTo(2335, -710)
ctx.lineTo(2600, -710)
ctx.moveTo(2345, 0)
ctx.lineTo(2345, -700)
ctx.lineTo(2600, -700)
ctx.moveTo(2355, 0)
ctx.lineTo(2355, -690)
ctx.lineTo(2600, -690)
ctx.strokeStyle = "#ccc"
ctx.lineWidth = 5;
ctx.stroke();
//squares that look like they keep the wires in place
ctx.beginPath()
ctx.rect(1600, -500, 90, 100)
ctx.rect(-55, -285, 12, 100)
ctx.rect(1100, -497, 8, 54)
ctx.rect(2285, -200, 80, 10)
ctx.rect(1110, -70, 100, 10)
ctx.fillStyle = "#ccc"
ctx.fill()
//power up dispenser
// ctx.beginPath()
// for (let i = 2; i < 10; i++) {
// ctx.moveTo(2000, -100 * i)
// ctx.lineTo(2080, -100 * i)
// }
// ctx.strokeStyle = "#ddd"
// ctx.lineWidth = 5;
// ctx.stroke();
// ctx.beginPath()
// for (let i = 2; i < 10; i++) {
// ctx.arc(2040, -100 * i, 30, 0, 2 * Math.PI);
// ctx.moveTo(2040, -100 * i)
// }
// ctx.fillStyle = "rgba(0,0,0,0.3)"
// ctx.fill()
// ctx.fillStyle = "rgba(240,255,255,0.5)"
// ctx.fillRect(2000, -1000, 80, 700)
//exit room
ctx.fillStyle = "#f2f2f2"
ctx.fillRect(2600, -600, 400, 300)
level.exit.draw();
// level.enter.draw();
level.playerExitCheck();
};
level.customTopLayer = () => {
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(2600, -600, 400, 300)
};
function zero(x, y) {
const width = 10
level.fillBG.push({
x: x,
y: y,
width: thick,
height: height,
color: color
});
level.fillBG.push({
x: x + width,
y: y,
width: thick,
height: height,
color: color
});
level.fillBG.push({
x: x,
y: y,
width: width,
height: thick,
color: color
});
level.fillBG.push({
x: x,
y: y + height - thick,
width: width,
height: thick,
color: color
});
xLetter += 10 + width
}
level.setPosToSpawn(460, -100); //normal spawn
level.enter.x = -1000000; //hide enter graphic for first level by moving to the far left
// level.enter.x = -1000000; //hide enter graphic for first level by moving to the far left
level.exit.x = 2800;
level.exit.y = -335;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
simulation.zoomScale = 1000 //1400 is normal
level.defaultZoom = 1600
simulation.zoomTransition(level.defaultZoom, 1)
document.body.style.backgroundColor = "#ddd";
level.fill.push({
x: 2600,
y: -600,
width: 400,
height: 500,
color: "rgba(0,255,255,0.05)"
});
level.fillBG.push({
x: 2600,
y: -600,
width: 400,
height: 500,
color: "#fff"
});
const lineColor = "#ccc"
level.fillBG.push({
x: 1600,
y: -500,
width: 100,
height: 100,
color: lineColor
});
level.fillBG.push({
x: -55,
y: -283,
width: 12,
height: 100,
color: lineColor
});
document.body.style.backgroundColor = "#e1e1e1";
//faster way to draw a wire
function wallWire(x, y, width, height, front = false) {
if (front) {
level.fill.push({
x: x,
y: y,
width: width,
height: height,
color: lineColor
});
} else {
level.fillBG.push({
x: x,
y: y,
width: width,
height: height,
color: lineColor
});
}
}
for (let i = 0; i < 3; i++) {
wallWire(100 - 10 * i, -1050 - 10 * i, 5, 800);
wallWire(100 - 10 * i, -255 - 10 * i, -300, 5);
}
for (let i = 0; i < 5; i++) {
wallWire(1000 + 10 * i, -1050 - 10 * i, 5, 600);
wallWire(1000 + 10 * i, -450 - 10 * i, 150, 5);
wallWire(1150 + 10 * i, -450 - 10 * i, 5, 500);
}
for (let i = 0; i < 3; i++) {
wallWire(2650 - 10 * i, -700 - 10 * i, -300, 5);
wallWire(2350 - 10 * i, -700 - 10 * i, 5, 800);
}
for (let i = 0; i < 5; i++) {
wallWire(1625 + 10 * i, -1050, 5, 1200);
}
for (let i = 0; i < 4; i++) {
wallWire(1650, -470 + i * 10, 670 - i * 10, 5);
wallWire(1650 + 670 - i * 10, -470 + i * 10, 5, 600);
}
for (let i = 0; i < 3; i++) {
wallWire(-200 - i * 10, -245 + i * 10, 1340, 5);
wallWire(1140 - i * 10, -245 + i * 10, 5, 300);
wallWire(-200 - i * 10, -215 + i * 10, 660, 5);
wallWire(460 - i * 10, -215 + i * 10, 5, 300);
}
spawn.mapRect(-250, 0, 3600, 1800); //ground
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
spawn.mapRect(3000, -2800, 2600, 4600); //right wall
@@ -1563,6 +1582,8 @@ const level = {
button.query();
button.draw();
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
door.draw();
@@ -1754,6 +1775,8 @@ const level = {
hazard.level(button.isUp)
rotor.rotate();
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
ctx.fillStyle = "#233"
@@ -1888,6 +1911,8 @@ const level = {
const elevator = level.platform(4210, -1325, 380, 30, -10)
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { //elevator move
@@ -2096,6 +2121,8 @@ const level = {
ctx.fillStyle = "#ccc"
ctx.fillRect(1567, -1990, 5, 1020)
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
@@ -2321,6 +2348,8 @@ const level = {
// simulation.g = 0.0012 //0.0024
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
// elevator.move()
@@ -2523,6 +2552,8 @@ const level = {
skyscrapers() {
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {};
@@ -2686,6 +2717,8 @@ const level = {
highrise() {
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {};
@@ -2888,6 +2921,8 @@ const level = {
warehouse() {
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {};
@@ -3138,6 +3173,8 @@ const level = {
}
door.openClose();
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
door.draw();
@@ -3291,6 +3328,8 @@ const level = {
stronghold() { // player made level by Francois 👑 from discord
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {};
@@ -3594,6 +3633,8 @@ const level = {
doorPlateform.openClose();
}
hazard.level(button.isUp)
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
@@ -3978,6 +4019,8 @@ const level = {
level.playerExitCheck();
rotor.rotate();
// rotor2.rotate()
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
doorSortieSalle.draw();
@@ -3994,6 +4037,8 @@ const level = {
rotor.rotate();
doorSortieSalle.openClose();
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
// //////////////////////////////////////
level.customTopLayer = () => {
@@ -4216,6 +4261,8 @@ const level = {
chair2.force.y += chair2.mass * simulation.g;
person.force.y += person.mass * simulation.g;
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
hazard.draw();
@@ -4731,6 +4778,8 @@ const level = {
portal2[2].query(true)
portal2[3].query(true)
rotor.rotate();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
@@ -4977,6 +5026,8 @@ const level = {
coliseum() {
level.custom = () => {
level.playerExitCheck();
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {};
level.defaultZoom = 1800

View File

@@ -905,14 +905,19 @@ const mobs = {
}
//rotate towards fireAngle
const angle = this.angle + Math.PI / 2;
c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
const dot = Vector.dot({
x: Math.cos(angle),
y: Math.sin(angle)
}, this.fireDir)
// c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
const threshold = 0.1;
if (c > threshold) {
if (dot > threshold) {
this.torque += 0.000004 * this.inertia;
} else if (c < -threshold) {
} else if (dot < -threshold) {
this.torque -= 0.000004 * this.inertia;
} else if (this.noseLength > 1.5) {
} else if (this.noseLength > 1.5 && dot > 0 && dot < 0.03) {
//fire
console.log(dot)
spawn.bullet(this.vertices[1].x, this.vertices[1].y, 9 + Math.ceil(this.radius / 15));
const v = 15;
Matter.Body.setVelocity(mob[mob.length - 1], {

View File

@@ -189,6 +189,20 @@ const m = {
m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07;
},
lookDefault() {
//always on mouse look
m.angle = Math.atan2(
simulation.mouseInGame.y - m.pos.y,
simulation.mouseInGame.x - m.pos.x
);
//smoothed mouse look translations
const scale = 0.8;
m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07;
},
doCrouch() {
if (!m.crouch) {
m.crouch = true;
@@ -272,13 +286,13 @@ const m = {
player.force.x += m.Fx
}
} else {
const stoppingFriction = 0.92;
const stoppingFriction = 0.92; //come to a stop if no move key is pressed
Matter.Body.setVelocity(player, {
x: player.velocity.x * stoppingFriction,
y: player.velocity.y * stoppingFriction
});
}
//come to a stop if fast or if no move key is pressed
//come to a stop if fast
if (player.speed > 4) {
const stoppingFriction = (m.crouch) ? 0.65 : 0.89; // this controls speed when crouched
Matter.Body.setVelocity(player, {
@@ -2711,7 +2725,7 @@ const m = {
m.spin = 0
// m.groundControl = () => {} //disable entering ground
m.onGround = false
playerOnGroundCheck = () => {}
// playerOnGroundCheck = () => {}
m.airControl = () => { //tank controls
player.force.y -= player.mass * simulation.g; //undo gravity
Matter.Body.setVelocity(player, {

View File

@@ -20,8 +20,6 @@ const simulation = {
ctx.save();
simulation.camera();
level.drawFillBGs();
level.exit.draw();
level.enter.draw();
level.custom();
simulation.draw.powerUp();
mobs.draw();
@@ -519,10 +517,10 @@ const simulation = {
} else {
World.add(engine.world, [player])
}
m.look = m.lookDefault
level.levels = level.playableLevels.slice(0) //copy array, not by just by assignment
if (simulation.isCommunityMaps) {
level.levels.push("stronghold");
level.levels.push("basement");
// level.levels.push("detours");

View File

@@ -1550,7 +1550,7 @@ const spawn = {
ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
ctx.lineWidth = 2;
ctx.strokeStyle = "rgba(120,0,255,0.15)";
ctx.strokeStyle = "rgba(120,0,255,0.2)";
ctx.stroke();
ctx.setLineDash([0, 0]);
}
@@ -1600,12 +1600,11 @@ const spawn = {
me.isFiring = false
me.onHit = function() {};
me.canSeeTarget = function() {
const diff = Vector.normalise(Vector.sub(this.fireTarget, this.position)); //make a vector for the mob's direction of length 1
const angle = this.angle + Math.PI / 2;
const dot = Vector.dot({
x: Math.cos(angle),
y: Math.sin(angle)
}, diff); //the dot product of di console.log(dot, 'see')
}, Vector.normalise(Vector.sub(this.fireTarget, this.position)));
//distance between the target and the player's location
if (
dot > 0.03 || // not looking at target
@@ -1670,18 +1669,18 @@ const spawn = {
ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
ctx.lineWidth = 2;
ctx.strokeStyle = "rgba(255,0,100,0.15)";
ctx.strokeStyle = "rgba(255,0,100,0.2)";
ctx.stroke();
ctx.setLineDash([0, 0]);
}
} else { //aim at player
this.fireCycle++
this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position)); //set direction to turn to fire
// this.fireDir = ; //set direction to turn to fire
const angle = this.angle + Math.PI / 2;
const dot = Vector.dot({
x: Math.cos(angle),
y: Math.sin(angle)
}, this.fireDir)
}, Vector.normalise(Vector.sub(this.seePlayer.position, this.position)))
const threshold = 0.04;
if (dot > threshold) { //rotate towards fireAngle
this.torque += 0.0000015 * this.inertia;
@@ -2377,13 +2376,18 @@ const spawn = {
}
//rotate towards fireAngle
const angle = this.angle + Math.PI / 2;
c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
const threshold = 0.2;
if (c > threshold) {
// c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
//rotate towards fireAngle
const dot = Vector.dot({
x: Math.cos(angle),
y: Math.sin(angle)
}, this.fireDir)
const threshold = 0.03;
if (dot > threshold) {
this.torque += 0.000004 * this.inertia;
} else if (c < -threshold) {
} else if (dot < -threshold) {
this.torque -= 0.000004 * this.inertia;
} else if (this.noseLength > 1.5) {
} else if (this.noseLength > 1.5 && dot > 0 && dot < 0.05) {
//fire
spawn.sniperBullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 15), 4);
const v = 20 * simulation.accelScale;

View File

@@ -123,9 +123,10 @@
},
damageFromTech() {
let dmg = m.fieldDamage
if (tech.isOneBullet && bullet.length - b.totalBots() === 1) dmg *= 2 //3 / Math.sqrt(bullet.length + 1) //testing this tech out, seems to have too many negatives though ...
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
if (tech.isDamageAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 1.5 : 0.5
if (tech.isDamageAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 1.5 : 0.66
if (tech.isTechDamage) dmg *= 2
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
if (tech.isLowEnergyDamage) dmg *= 1 + Math.max(0, 1 - m.energy) * 0.5
@@ -614,6 +615,23 @@
b.setFireCD();
}
},
{
name: "1-body problem",
description: "if there is exactly <strong>1</strong> active <strong>bullet</strong><br>increase <strong class='color-d'>damage</strong> by <strong>100%</strong>",
maxCount: 1,
count: 0,
frequency: 2,
allowed() {
return !tech.foamBotCount && !tech.nailBotCount && m.fieldUpgrades[m.fieldMode].name !== "nano-scale manufacturing" && ((tech.haveGunCheck("missiles") && tech.missileCount === 1) || tech.haveGunCheck("rail gun") || tech.haveGunCheck("grenades") || tech.isRivets || tech.isSlugShot || tech.oneSuperBall)
},
requires: "missiles, rail gun, grenades, rivets, slugs, super ball, no foam/nail bots, nano-scale",
effect() {
tech.isOneBullet = true
},
remove() {
tech.isOneBullet = false
}
},
{
name: "microstates",
description: "increase <strong class='color-d'>damage</strong> by <strong>4%</strong><br>for every <strong>10</strong> active <strong>bullets</strong>",
@@ -1982,7 +2000,7 @@
}
}, {
name: "dormancy",
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br><span style = 'font-size:93%;'>increase <strong class='color-d'>damage</strong> by <strong>50%</strong> else decrease it by <strong>50%</strong></span>",
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br><span style = 'font-size:93%;'>increase <strong class='color-d'>damage</strong> by <strong>50%</strong> else decrease it by <strong>33%</strong></span>",
maxCount: 1,
count: 0,
frequency: 2,
@@ -3939,7 +3957,7 @@
count: 0,
frequency: 2,
allowed() {
return tech.haveGunCheck("laser") || tech.laserBotCount > 1
return (tech.haveGunCheck("laser") && !tech.isPulseLaser) || tech.laserBotCount > 1
},
requires: "laser",
effect() {
@@ -3998,7 +4016,7 @@
}
}, {
name: "diffuse beam",
description: "<strong class='color-laser'>laser</strong> beam is <strong>wider</strong> and doesn't <strong>reflect</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>175%</strong>",
description: "<strong class='color-laser'>laser</strong> beam is <strong>wider</strong> and doesn't <strong>reflect</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>200%</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4797,6 +4815,31 @@
},
remove() {}
},
{
name: "aim",
description: "<strong>experiment:</strong> your aiming is random",
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection && !m.isShipMode
},
requires: "not ship",
effect() {
m.look = () => {
m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03)
const scale = 0.8;
m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07;
}
},
remove() {}
},
//**************************************************
//************************************************** JUNK
//************************************************** tech
@@ -4819,6 +4862,32 @@
// },
// remove() {}
// },
{
name: "Fourier analysis",
description: "your aiming is now controlled by this equation:<br>2sin(0.0133t) + sin(0.013t) + 0.5sin(0.031t)+ 0.33sin(0.03t)",
maxCount: 1,
count: 0,
frequency: 0,
isExperimentHide: true,
isJunk: true,
allowed() {
return !m.isShipMode
},
requires: "not ship",
effect() {
m.look = () => {
m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03)
const scale = 0.8;
m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07;
}
},
remove() {
m.look = m.lookDefault
}
},
{
name: "disintegrated armament",
description: "spawn a <strong class='color-g'>gun</strong><br><strong>remove</strong> your active <strong class='color-g'>gun</strong>",

View File

@@ -312,7 +312,7 @@ summary {
}
.experiment-grid-disabled[data-descr]:hover::after {
content: '\a \00a0 \00a0 \00a0 REQUIRES:\a''\00a0 \00a0 \00a0 'attr(data-descr);
content: '\a \00a0 \00a0 \00a0 REQUIRES:\a \00a0 \00a0 \00a0 'attr(data-descr);
white-space: pre-wrap;
position: absolute;
left: 0;

110
todo.txt
View File

@@ -1,9 +1,15 @@
******************************************************** NEXT PATCH ********************************************************
bug fix - grower mob becoming immune to damage when shielded and growing bigger than shield
tech: 1-body problem - do 100% damage if there is only 1 active bullet
relay switch - toggles ON/OFF when you pick up a power up
tech: ice IX condenser - if ON make a couple Ice IX crystals every second
experiment mode and junk tech: random aiming
bug fix - sniper, shooter aiming might be improved (no more firing backwards)
or maybe I just made it worse, let me know
bug fix - Shift registers
working on rewriting the way backgrounds and foregrounds are drawn on each level (in progress)
******************************************************** BUGS ********************************************************
@@ -36,29 +42,35 @@ fix door.isOpen actually meaning isClosed?
******************************************************** TODO ********************************************************
have junk tech drop frequency to 0 after showing up once
but add way more junk tech into the pool
how to communicate that to player?
console message
add water dips to sewers
move power ups in front of blocks, make blocks not transparent?
consider adding canvas path shadows to levels in level.custom for non squared lighting
convert all level.BG into canvas draw in level.custom
draw exit and entrance in level
new level: procedural generation
several small rooms are linked by portals
the portals have a randomized pattern
the rooms can be set out in a grid and linked by physical doors,tunnels,wells
choose bosses that can move though walls, so it can track you while you portal
the map shuffles it's pattern when the player get to a button
shuffle portals or shuffle the physical layout of rooms
and then have the player go back through to get to the end?
gravity room
portal room
endlessly falling blocks down a slide, that the player has to climb
portal + rotor + falling blocks = perpetual motion
laser room
slime radiation room
look into improving mouse lag with pointer lock?
https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API
https://www.vsynctester.com/game.html
https://news.ycombinator.com/item?id=26530272
should blocks block mob vision?
Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 &&
Matter.Query.ray(body, this.position, this.mPosRange()).length === 0 &&
only negative is mobs will attack player in the starting room
maybe make all doors to spawns somehow block vision
maybe start in cloaking mode
disable it a few cycles after level loads?
or disable when player moves?
***maybe just clear spawns away from the starting room***
ok go through each map and find issues on each map
**but first test he game with no block blocking vision**
mob vision: look at player history
build a new type of attraction for mobs
if mobs can't see player, they check to see if they can see where the player was in the history
@@ -103,16 +115,6 @@ bosses should have 2x health, but only do about 50 health damage
boss flag cut damage done to boss by 20x <----
make bosses not have extra density
map: laboratory
rooms with switches that change physics
gravity room
portal room
laser room
radiation room
portal + rotor + falling blocks = perpetual motion room
a button that spawns a heal.
consider adding canvas path shadows to levels in level.custom for non squared lighting
lore: a tutorial / lore intro
needs to be optional so it doesn't slow experienced players
put something on the intro map
@@ -126,8 +128,6 @@ add back in gamepad support
but does anyone care?
https://github.com/landgreen/landgreen.github.io/search?q=gamepadconnected
mechanic: gain damage when there are fewer bullets
rename intro level to something lore related
give undefined tech different effects at different localSettings.loreCount values
@@ -338,9 +338,12 @@ possible names for tech
metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity
stochastic optimization
electrostatic discharge
Gödel's incompleteness
dynamical systems
quantum zeno effect (perturbation of a system prevents some systems from evolving because it scrambles coherence) (apply to lasers, fields)
plot script:
chapter 1: bot can hear audio and learns testing mode
bot uses testing mode to exit room
@@ -384,7 +387,8 @@ chapter 4: no need to fight?
keep fighting
exit the simulation
enter real world
enter console command to close tab?
close tab?
wipes all local storage?
@@ -437,41 +441,3 @@ AI doesn't know about:
modern pop culture
outside the lab
scientist console text:
2 scientists (each one a different color text)
at the start of each level listen to text conversation from the two colors of text strings also
talking about the robot, watching
trying to communicate with the robot? but how
random lines when:
at start of level, about: what mobs types are queued up, and level order
when player gets a cool tech combination
at random times:
I think it's planing to escape
Why is it attacking those shapes?
Are those shapes supposed to be us?
ending outline
testing mode is unlocked when player see the 1st ending
if player chose tech: choosing this tech means the player gets lore after beating the game
count 1:
after final boss is cleared, player enters a level with no mobs
level maybe has some environmental damage, so player has an option to die at any time
player can see text output between two colors of text strings (scientists)
audio.ambient(current time and date)<br> "text"
player reads a conversation between the two colors of text
first time win on east or normal they talk about:
how many runs the player has done
they guess why
player is asked to stand on an in game button to enable the vocoder
they reveal the player is running simulations, and it isn't real
they ask the player to communicate
jump twice if you understand
they ask the player to enter console commands
give ammo or tech or something
They tell the player a console command to permanently enable custom and testing mode (in local storage)
players can use this command in the future to enable custom and testing without beating the game even if local storage is wiped
they then tell the player the command to increase the difficulty and the command to restart the game.
If you win on hard or why:
they give the player and option to exit the simulation and entre the real world
simulation.exit()
This wipes all local storage, and closes the browser tab