From ff613dc2cf6014fa395c968cd8b50573c0f5e2d1 Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 15 Oct 2023 19:59:47 -0700 Subject: [PATCH] free falling after falling off most open maps you don't take damage you fall down into the level again above the entrance disabled smooth camera tracking for portals falling off map added a once every 7 seconds check to see if the player is suck inside the map if stuck you teleport to the level entrance catches about 90% of the ways to get stuck from falling too fast this might causing problems after more testing, not sure bug fixes --- js/bullet.js | 22 +++----- js/level.js | 141 +++++++++++++++++++++++++++++------------------ js/player.js | 10 ++-- js/powerup.js | 4 +- js/simulation.js | 102 ++++++++++++++++++++++++---------- js/spawn.js | 4 +- js/tech.js | 32 +++++------ todo.txt | 19 +++++-- 8 files changed, 205 insertions(+), 129 deletions(-) diff --git a/js/bullet.js b/js/bullet.js index 294f84a..fae5e81 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -4612,19 +4612,18 @@ const b = { this.force.y += this.mass * tech.foamGravity; //gravity if (tech.isFoamAttract) { for (let i = 0, len = mob.length; i < len; i++) { + const range = Vector.magnitude(Vector.sub(mob[i].position, this.position)) if ( !mob[i].isBadTarget && - Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 && mob[i].alive && - Matter.Query.ray(map, this.position, mob[i].position).length === 0 && - !mob[i].isInvulnerable + !mob[i].isInvulnerable && + range < 500 && + Matter.Query.ray(map, this.position, mob[i].position).length === 0 ) { - this.force = Vector.mult(Vector.normalise(Vector.sub(mob[i].position, this.position)), this.mass * 0.004) - const slow = 0.9 - Matter.Body.setVelocity(this, { - x: this.velocity.x * slow, - y: this.velocity.y * slow - }); + const mag = 0.001 * Math.min(1, 200 / range) + this.force = Vector.mult(Vector.normalise(Vector.sub(mob[i].position, this.position)), this.mass * mag) + const slow = 0.98 + Matter.Body.setVelocity(this, { x: this.velocity.x * slow, y: this.velocity.y * slow }); break } } @@ -7509,10 +7508,7 @@ const b = { bullet[me].do = function () { function onCollide(that) { that.collisionFilter.mask = 0; //non collide with everything - Matter.Body.setVelocity(that, { - x: 0, - y: 0 - }); + Matter.Body.setVelocity(that, { x: 0, y: 0 }); that.do = that.grow; } const mobCollisions = Matter.Query.collides(this, mob) diff --git a/js/level.js b/js/level.js index 1f9928b..208cc30 100644 --- a/js/level.js +++ b/js/level.js @@ -4,6 +4,7 @@ let cons = []; //all constraints between a point and a body let consBB = []; //all constraints between two bodies let composite = [] //rotors and other map elements that don't fit const level = { + isEndlessFall: false, defaultZoom: 1400, onLevel: -1, levelsCleared: 0, @@ -15,27 +16,27 @@ const level = { levels: [], start() { if (level.levelsCleared === 0) { //this code only runs on the first level - // simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode + simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode // simulation.isHorizontalFlipped = true // tech.giveTech("performance") // level.difficultyIncrease(3 * 4) //30 is near max on hard //60 is near max on why // spawn.setSpawnList(); // spawn.setSpawnList(); - // m.maxHealth = m.health = 100 + m.maxHealth = m.health = 100 // tech.isRerollDamage = true // powerUps.research.changeRerolls(99999) // m.immuneCycle = Infinity //you can't take damage // tech.tech[297].frequency = 100 // m.couplingChange(10) - // m.setField("standing wave") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole + // m.setField("wormhole") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole // m.energy = 0 // simulation.molecularMode = 2 // m.damage(0.1); // b.giveGuns("super balls") //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("drones") //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[3].ammo = 100000000 + // b.giveGuns("foam") //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[8].ammo = 100000000 // requestAnimationFrame(() => { tech.giveTech("MACHO") }); - // for (let i = 0; i < 1; ++i) tech.giveTech("additive manufacturing") + // for (let i = 0; i < 1; ++i) tech.giveTech("electrostatic induction") // for (let i = 0; i < 1; ++i) tech.giveTech("flatland") // for (let i = 0; i < 1; ++i) tech.giveTech("foam-bot") // for (let i = 0; i < 1; ++i) tech.giveTech("nail-bot") @@ -49,7 +50,7 @@ const level = { // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); - // level.testing(); + level.skyscrapers(); // for (let i = 0; i < 4; ++i) spawn.hopMother(1900, -500) // for (let i = 0; i < 0; ++i) spawn.hopper(1900, -500) // for (let i = 0; i < 1; ++i) spawn.shooterBoss(1900, -2500) @@ -62,7 +63,7 @@ const level = { // spawn.tetherBoss(1900, -500, { x: 1900, y: -500 }) // for (let i = 0; i < 40; ++i) tech.giveTech() - level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************** + // level[simulation.isTraining ? "walk" : "intro"]() //normal starting level ************************************************** // simulation.isAutoZoom = false; //look in close // simulation.zoomScale *= 0.5; @@ -100,7 +101,7 @@ const level = { } } if (!simulation.isTraining) level.levelAnnounce(); - simulation.noCameraScroll(); + simulation.setupCamera(player.position); simulation.setZoom(); level.addToWorld(); //add bodies to game engine simulation.draw.setPaths(); @@ -1345,10 +1346,12 @@ const level = { //teleport if (this.portalPair.angle % (Math.PI / 2)) { //if left, right up or down if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles - Matter.Body.setPosition(player, this.portalPair.portal.position); + // Matter.Body.setPosition(player, this.portalPair.portal.position); + simulation.translatePlayerAndCamera(this.portalPair.portal.position) } else { //if at some odd angle if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles - Matter.Body.setPosition(player, this.portalPair.position); + // Matter.Body.setPosition(player, this.portalPair.position); + simulation.translatePlayerAndCamera(this.portalPair.position) } //rotate velocity let mag @@ -5347,6 +5350,7 @@ const level = { powerUps.addResearchToLevel() //needs to run after mobs are spawned }, pavilion() { + level.isEndlessFall = true; const vanish = [] level.exit.x = -850; level.exit.y = -1485; @@ -5375,6 +5379,7 @@ const level = { vanish.push(level.vanish(-350, -450, 150, 223)) spawn.mapRect(2475, -1800, 250, 2300); + spawn.mapRect(1200, -750, 100, 450); spawn.mapRect(1200, -375, 250, 75); powerUps.spawnStartingPowerUps(550, -100); @@ -5403,7 +5408,6 @@ const level = { } // vanish.push(level.vanish(575, -1575, 375, 225)) - spawn.bodyRect(225, -850, 50, 100, 0.4); spawn.mapRect(600, -1800, 325, 225); spawn.mapRect(1900, -1500, 325, 25); @@ -5421,9 +5425,11 @@ const level = { vanish.push(level.vanish(-50, -1800, 450, 25)) //exit - spawn.mapRect(-1050, -1450, 700, 25); - spawn.mapRect(-1050, -1800, 525, 25); - spawn.mapRect(-550, -1800, 25, 200); + // spawn.mapRect(-1050, -1450, 700, 25); + // spawn.mapRect(-1050, -1800, 525, 25); + spawn.mapRect(-575, -1800, 50, 200); + spawn.mapRect(-1050, -1800, 525, 75); + spawn.mapRect(-1050, -1450, 700, 75); spawn.randomMob(-1175, -1975, -0.4); spawn.randomMob(275, -1500, -0.3); @@ -6193,6 +6199,7 @@ const level = { }, satellite() { + level.isEndlessFall = true; const boost1 = level.boost(5825, 235, 1400) const elevator = level.elevator(4210, -1265, 380, 50, -3450) //, 0.003, { up: 0.01, down: 0.2 } level.custom = () => { @@ -6368,6 +6375,8 @@ const level = { } }, rooftops() { + level.isEndlessFall = true; + // level.fallPosition = { x: 5000, y:-4000} const elevator = level.elevator(1450, -990, 235, 45, -2000) const boost1 = level.boost(4950, 0, 1100) @@ -6554,6 +6563,7 @@ const level = { } }, aerie() { + level.isEndlessFall = true; const boost1 = level.boost(-425, 100, 1400) const boost2 = level.boost(5350, 275, 2850); @@ -6782,6 +6792,7 @@ const level = { } }, skyscrapers() { + level.isEndlessFall = true; const boost1 = level.boost(475, 0, 1300) const boost2 = level.boost(4450, 0, 1300); level.custom = () => { @@ -6919,6 +6930,7 @@ const level = { } }, highrise() { + level.isEndlessFall = true; const elevator1 = level.elevator(-790, -190, 180, 25, -1150, 0.0025, { up: 0.01, down: 0.2 @@ -7203,6 +7215,7 @@ const level = { } }, warehouse() { + level.isEndlessFall = true; level.custom = () => { ctx.fillStyle = "#444" //light fixtures ctx.fillRect(-920, -505, 40, 10) @@ -18205,8 +18218,8 @@ const level = { spawn.mapRect(1350, -325, 100, 50); spawn.mapRect(1400, -1500, 325, 1600); spawn.mapRect(1400, -1500, 1550, 50); - spawn.mapRect(1400, -1900, 900, 50); - spawn.mapRect(1400, -2900, 100, 1050); + spawn.mapRect(1250, -1900, 1050, 50); + spawn.mapRect(1250, -2900, 100, 1050); spawn.mapRect(-600, -2900, 3550, 100); spawn.mapRect(2850, -2900, 100, 700); @@ -18243,6 +18256,28 @@ const level = { const piston7 = horizontalDoor(-2000, -2600, 300, 100, 300, 20); const hand1 = clockHand(400, -3700, 75, 600); const elevator1 = level.elevator(3200, 0, 150, 50, -1750, 0.0025, { up: 0.05, down: 0.2 }); + const lightButton = level.button(1400, -1900); + lightButton.isUp = true; + var lightOn = false; + simulation.ephemera.push({ + name: "lightWire", + do() { + if (level.levels[level.onLevel] == "clock") { + // light wire + ctx.beginPath(); + ctx.moveTo(1460, -1887); + ctx.lineTo(1300, -1887); + ctx.lineTo(1300, -2860); + ctx.lineTo(400, -2860); + ctx.lineTo(400, -2800); + ctx.lineWidth = 6; + ctx.strokeStyle = lightOn ? "#ffd700" : "000"; + ctx.stroke(); + } else { + simulation.removeEphemera(this.name); + } + }, + }) spawn.debris(-300, 0, 1300, 6); spawn.debris(0, -2900, 2500, 8); @@ -18299,7 +18334,7 @@ const level = { } var circleHead = Matter.Bodies.polygon(m.pos.x, m.pos.y, 0, 31); - var losDomain = generateIntersectMap().concat(mob.filter((obj) => { return obj.isNotCloaked == null && (obj.isBoss || obj.label != 'Circle Body') }), [pendulum1, gear1, gear2, piston1, player, circleHead]); + var losDomain = generateIntersectMap().concat(mob.filter((obj) => { return obj.isNotCloaked == null && (obj.isBoss || obj.label != 'Circle Body') }), [pendulum1, gear1, gear2, player, circleHead]); var oldMap = [...map]; var oldMob = [...mob]; var spawnGearMobCycle = 0; @@ -18313,12 +18348,12 @@ const level = { var startCycle = simulation.cycle; // used to offset simulation.cycle to avoid the swing starting halfway through at the start of the level and messing up syncronization level.custom = () => { - Matter.Body.setPosition(circleHead, m.pos) - if (!(compareArrays(oldMap, map) && compareArrays(oldMob, mob))) { - losDomain = generateIntersectMap().concat(mob.filter((obj) => { return obj.isNotCloaked == null && (obj.isBoss || obj.label != 'Circle Body') }), [pendulum1, gear1, gear2, piston1, player, circleHead]); + if (lightOn) { + Matter.Body.setPosition(circleHead, m.pos) + if (!(compareArrays(oldMap, map) && compareArrays(oldMob, mob))) losDomain = generateIntersectMap().concat(mob.filter((obj) => { return obj.isNotCloaked == null && (obj.isBoss || obj.label != 'Circle Body') }), [pendulum1, gear1, gear2, player, circleHead]); + oldMap = [...map]; + oldMob = [...mob]; } - oldMap = [...map]; - oldMob = [...mob]; ctx.fillStyle = "#b0b0b2"; ctx.fillRect(-600, -1700, 2000, 1700); ctx.fillRect(1350, -1851, 1550, 350); @@ -18330,39 +18365,41 @@ const level = { ctx.fillStyle = "#000"; ctx.fillRect(350, -2800, 100, 25); // light - var lightPos = { x: 400, y: -2775 }; - var lightRadius = 2950; - const vertices = circleLoS(lightPos, lightRadius, map.concat(mob.filter((obj) => { return obj.isNotCloaked == null && (obj.isBoss || obj.label != 'Circle Body') }), [pendulum1, gear1, gear2, piston1, player, circleHead])); if (vertices.length > 0 && vertices[0].x) { - ctx.beginPath(); - ctx.moveTo(vertices[0].x, vertices[0].y); - for (var i = 1; i < vertices.length; i++) { - var currentDistance = Math.sqrt((vertices[i - 1].x - lightPos.x) ** 2 + (vertices[i - 1].y - lightPos.y) ** 2); - var newDistance = Math.sqrt((vertices[i].x - lightPos.x) ** 2 + (vertices[i].y - lightPos.y) ** 2); + if (lightOn) { + var lightPos = { x: 400, y: -2775 }; + var lightRadius = 2950; + const vertices = circleLoS(lightPos, lightRadius, map.concat(mob.filter((obj) => { return obj.isNotCloaked == null && (obj.isBoss || obj.label != 'Circle Body') }), [pendulum1, gear1, gear2, player, circleHead])); if (vertices.length > 0 && vertices[0].x) { + ctx.beginPath(); + ctx.moveTo(vertices[0].x, vertices[0].y); + for (var i = 1; i < vertices.length; i++) { + var currentDistance = Math.sqrt((vertices[i - 1].x - lightPos.x) ** 2 + (vertices[i - 1].y - lightPos.y) ** 2); + var newDistance = Math.sqrt((vertices[i].x - lightPos.x) ** 2 + (vertices[i].y - lightPos.y) ** 2); + if (Math.abs(currentDistance - lightRadius) < 1 && Math.abs(newDistance - lightRadius) < 1) { + const currentAngle = Math.atan2(vertices[i - 1].y - lightPos.y, vertices[i - 1].x - lightPos.x); + const newAngle = Math.atan2(vertices[i].y - lightPos.y, vertices[i].x - lightPos.x); + ctx.arc(lightPos.x, lightPos.y, lightRadius, currentAngle, newAngle); + } else { + ctx.lineTo(vertices[i].x, vertices[i].y) + } + } + newDistance = Math.sqrt((vertices[0].x - lightPos.x) ** 2 + (vertices[0].y - lightPos.y) ** 2); + currentDistance = Math.sqrt((vertices[vertices.length - 1].x - lightPos.x) ** 2 + (vertices[vertices.length - 1].y - lightPos.y) ** 2); if (Math.abs(currentDistance - lightRadius) < 1 && Math.abs(newDistance - lightRadius) < 1) { - const currentAngle = Math.atan2(vertices[i - 1].y - lightPos.y, vertices[i - 1].x - lightPos.x); - const newAngle = Math.atan2(vertices[i].y - lightPos.y, vertices[i].x - lightPos.x); + const currentAngle = Math.atan2(vertices[vertices.length - 1].y - lightPos.y, vertices[vertices.length - 1].x - lightPos.x); + const newAngle = Math.atan2(vertices[0].y - lightPos.y, vertices[0].x - lightPos.x); ctx.arc(lightPos.x, lightPos.y, lightRadius, currentAngle, newAngle); } else { - ctx.lineTo(vertices[i].x, vertices[i].y) + ctx.lineTo(vertices[0].x, vertices[0].y) } + ctx.fillStyle = "rgba(216, 218, 223, 0.5)"; + ctx.fill(); } - newDistance = Math.sqrt((vertices[0].x - lightPos.x) ** 2 + (vertices[0].y - lightPos.y) ** 2); - currentDistance = Math.sqrt((vertices[vertices.length - 1].x - lightPos.x) ** 2 + (vertices[vertices.length - 1].y - lightPos.y) ** 2); - if (Math.abs(currentDistance - lightRadius) < 1 && Math.abs(newDistance - lightRadius) < 1) { - const currentAngle = Math.atan2(vertices[vertices.length - 1].y - lightPos.y, vertices[vertices.length - 1].x - lightPos.x); - const newAngle = Math.atan2(vertices[0].y - lightPos.y, vertices[0].x - lightPos.x); - ctx.arc(lightPos.x, lightPos.y, lightRadius, currentAngle, newAngle); - } else { - ctx.lineTo(vertices[0].x, vertices[0].y) - } - ctx.fillStyle = "rgba(216, 218, 223, 0.5)"; - ctx.fill(); } ctx.beginPath(); ctx.moveTo(425, -2775); ctx.arc(400, -2775, 25, 0, Math.PI); - ctx.fillStyle = "#c6aa12"; + ctx.fillStyle = lightOn ? "#ffe245" : "transparent"; ctx.fill(); ctx.strokeStyle = "#000000"; ctx.lineWidth = 1; @@ -18473,7 +18510,6 @@ const level = { if (!finishedGearFight && !pistonsLocked && m.pos.x > 2100 && m.pos.x < 2900 && m.pos.y > -1850 && m.pos.y < -1500) { pistonsLocked = true; - roofFallCycle = simulation.cycle + 250; roofReadyToFall = true; } @@ -18627,10 +18663,6 @@ const level = { distanceToIntersection = (circle3.radius * distance) / (circle3.radius + circle2.radius); slopeAngle = Math.atan((circle2.y - circle3.y) / (circle2.x - circle3.x)); angleToTangent = Math.acos(circle3.radius / distanceToIntersection); - const tangentPoint2 = { - x: Math.cos(angleToTangent + slopeAngle) * circle3.radius + circle3.x, - y: Math.sin(angleToTangent + slopeAngle) * circle3.radius + circle3.y - } const invertedTangentPoint2 = { x: Math.cos(-angleToTangent + slopeAngle) * circle3.radius + circle3.x, y: Math.sin(-angleToTangent + slopeAngle) * circle3.radius + circle3.y @@ -18640,10 +18672,6 @@ const level = { x: Math.cos(angleToTangent + slopeAngle) * -circle2.radius + circle2.x, y: Math.sin(angleToTangent + slopeAngle) * -circle2.radius + circle2.y } - const invertedTangentPoint3 = { - x: Math.cos(-angleToTangent + slopeAngle) * -circle2.radius + circle2.x, - y: Math.sin(-angleToTangent + slopeAngle) * -circle2.radius + circle2.y - } distance = Math.sqrt((piston2.position.y - 175 - circle3.y) ** 2 + (piston2.position.x - 50 - circle3.x) ** 2); slopeAngle = Math.atan((piston2.position.y - 175 - circle3.y) / (piston2.position.x - 50 - circle3.x)); @@ -18894,6 +18922,9 @@ const level = { var lastBlock = Math.sin(simulation.cycle / 50) < 0; level.customTopLayer = () => { + if (!lightOn) lightButton.query(); + if (!lightButton.isUp) lightOn = true; + lightButton.draw(); elevator1.move(); ctx.beginPath(); diff --git a/js/player.js b/js/player.js index f295e38..1643ce2 100644 --- a/js/player.js +++ b/js/player.js @@ -196,14 +196,11 @@ const m = { look() { }, //set to lookDefault() lookDefault() { //always on mouse look - m.angle = Math.atan2( - simulation.mouseInGame.y - m.pos.y, - simulation.mouseInGame.x - m.pos.x - ); + 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.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) * m.lookSmoothing; m.transY += (m.transSmoothY - m.transY) * m.lookSmoothing; @@ -4609,6 +4606,7 @@ const m = { m.hole.isReady = false; m.fieldRange = 0 Matter.Body.setPosition(player, simulation.mouseInGame); + // simulation.translatePlayerAndCamera(simulation.mouseInGame) //too jerky m.buttonCD_jump = 0 //this might fix a bug with jumping const velocity = Vector.mult(Vector.normalise(sub), 20) Matter.Body.setVelocity(player, { diff --git a/js/powerup.js b/js/powerup.js index 8fef7cb..9f1e6dd 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -245,7 +245,7 @@ const powerUps = { dupExplode() { for (let i = 0, len = powerUp.length; i < len; ++i) { if (powerUp[i].isDuplicated) { - if (Math.random() < 0.003) { // (1-0.003)^240 = chance to be removed after 4 seconds, 240 = 4 seconds * 60 cycles per second + if (Math.random() < 0.003 && !m.isBodiesAsleep) { // (1-0.003)^240 = chance to be removed after 4 seconds, 240 = 4 seconds * 60 cycles per second b.explosion(powerUp[i].position, 175 + (11 + 3 * Math.random()) * powerUp[i].size); Matter.Composite.remove(engine.world, powerUp[i]); powerUp.splice(i, 1); @@ -1070,7 +1070,7 @@ const powerUps = { const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options if (tech.isBanish) { tech.tech[choose].isBanished = true - if (i === 0) simulation.makeTextLog(`options.length = ${optionLengthNoDuplicates}`) + if (i === 0) simulation.makeTextLog(`options.length = ${optionLengthNoDuplicates} //tech removed from pool by decoherence`) } removeOption(choose) //move from future options pool to avoid repeats on this selection tech.tech[choose].isRecentlyShown = true //this flag prevents this option from being shown the next time you pick up a tech power up diff --git a/js/simulation.js b/js/simulation.js index a89422e..0a254ab 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -548,15 +548,31 @@ const simulation = { } } }, - noCameraScroll() { //makes the camera not scroll after changing locations - //only works if velocity is zero + translatePlayerAndCamera(where) { + //infinite falling. teleport to sky after falling + const before = { x: player.position.x, y: player.position.y, } + Matter.Body.setPosition(player, { x: where.x, y: where.y }); + const change = { x: before.x - player.position.x, y: before.y - player.position.y } + // translate camera to preserve illusion to endless fall + m.transX += change.x + m.transY += change.y + simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX; + simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY; + m.angle = Math.atan2(simulation.mouseInGame.y - m.pos.y, simulation.mouseInGame.x - m.pos.x); + + //is there a reason to update m.pos here? + // m.pos.x = player.position.x; + // m.pos.y = playerBody.position.y - m.yOff; + }, + setupCamera() { //makes the camera not scroll after changing locations + // //only works if velocity is zero m.pos.x = player.position.x; m.pos.y = playerBody.position.y - m.yOff; 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) * 1; - m.transY += (m.transSmoothY - m.transY) * 1; + m.transX += (m.transSmoothX - m.transX); + m.transY += (m.transSmoothY - m.transY); }, edgeZoomOutSmooth: 1, camera() { @@ -570,6 +586,7 @@ const simulation = { ctx.translate(canvas.width2, canvas.height2); //center ctx.scale(simulation.zoom / simulation.edgeZoomOutSmooth, simulation.zoom / simulation.edgeZoomOutSmooth); //zoom in once centered ctx.translate(-canvas.width2 + m.transX, -canvas.height2 + m.transY); //translate + // ctx.translate(-canvas.width2 + m.transX - player.velocity.x, -canvas.height2 + m.transY + player.velocity.y); //translate //calculate in game mouse position by undoing the zoom and translations simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX; simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY; @@ -909,29 +926,51 @@ const simulation = { } if (m.pos.y > simulation.fallHeight) { // if 4000px deep - Matter.Body.setVelocity(player, { - x: 0, - y: 0 - }); - Matter.Body.setPosition(player, { - x: level.enter.x + 50, - y: level.enter.y - 20 - }); - // move bots - for (let i = 0; i < bullet.length; i++) { - if (bullet[i].botType) { - Matter.Body.setPosition(bullet[i], Vector.add(player.position, { - x: 250 * (Math.random() - 0.5), - y: 250 * (Math.random() - 0.5) - })); - Matter.Body.setVelocity(bullet[i], { - x: 0, - y: 0 - }); + if (level.isEndlessFall) { + //infinite falling. teleport to sky after falling + + simulation.ephemera.push({ + name: "slow player", + count: 130, //cycles before it self removes + do() { + this.count-- + if (this.count < 0 || m.onGround) simulation.removeEphemera(this.name) + // console.log(player.velocity.y) + if (player.velocity.y > 70) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 }); + if (player.velocity.y > 90) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 }); + }, + }) + + const before = { x: player.position.x, y: player.position.y, } + Matter.Body.setPosition(player, { x: level.enter.x, y: level.enter.y - 3000 }); + // Matter.Body.setPosition(player, level.fallPosition); + + const change = { x: before.x - player.position.x, y: before.y - player.position.y } + // translate camera smoothly to preserve illusion to endless fall + m.transX += change.x + m.transY += change.y + simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX; + simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY; + m.angle = Math.atan2(simulation.mouseInGame.y - m.pos.y, simulation.mouseInGame.x - m.pos.x); + + } else { + Matter.Body.setVelocity(player, { x: 0, y: 0 }); + Matter.Body.setPosition(player, { x: level.enter.x + 50, y: level.enter.y - 20 }); + m.damage(0.05 * simulation.difficultyMode); + m.energy -= 0.05 * simulation.difficultyMode + // move bots + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType) { + Matter.Body.setPosition(bullet[i], Vector.add(player.position, { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) })); + Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 }); + } } } - m.damage(0.1 * simulation.difficultyMode); - m.energy -= 0.1 * simulation.difficultyMode + + + + + } if (isNaN(player.position.x)) m.death(); if (m.lastKillCycle + 300 > m.cycle) { //effects active for 5 seconds after killing a mob @@ -959,6 +998,13 @@ const simulation = { } if (!(m.cycle % 420)) { //once every 7 seconds + //check if player is inside the map + if (Matter.Query.point(map, m.pos).length > 0 || Matter.Query.point(map, player.position).length > 0) { + // console.log('halp', Matter.Query.point(map, m.pos)) + Matter.Body.setVelocity(player, { x: 0, y: 0 }); + Matter.Body.setPosition(player, { x: level.enter.x + 50, y: level.enter.y - 20 }); + } + if (tech.isZeno) { if (tech.isEnergyHealth) { m.energy *= 0.95 @@ -975,10 +1021,7 @@ const simulation = { while (i--) { if (who[i].position.y > simulation.fallHeight) { if (save) { - Matter.Body.setVelocity(who[i], { - x: 0, - y: 0 - }); + Matter.Body.setVelocity(who[i], { x: 0, y: 0 }); Matter.Body.setPosition(who[i], { x: level.exit.x + 30 * (Math.random() - 0.5), y: level.exit.y + 30 * (Math.random() - 0.5) @@ -1016,6 +1059,7 @@ const simulation = { clearNow: false, clearMap() { level.isProcedural = false; + level.isEndlessFall = false; ctx.setTransform(1, 0, 0, 1, 0, 0); if (m.alive) { if (tech.isLongitudinal) b.guns[3].waves = []; //empty array of wave bullets diff --git a/js/spawn.js b/js/spawn.js index 01ef73c..fe8834b 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -1510,10 +1510,10 @@ const spawn = { // } // } me.do = function () { + this.checkStatus(); this.zombieHealthBar(); this.lookForMobTargets(); this.attack(); - this.checkStatus(); }; me.mobSearchIndex = 0; me.target = null @@ -1560,7 +1560,7 @@ const spawn = { } me.hitCD = 0 me.attack = function () { //hit non zombie mobs - if (this.hitCD < simulation.cycle) { + if (this.hitCD < simulation.cycle && !this.isStunned && !this.isSlowed) { if (this.target) { this.force = Vector.mult(Vector.normalise(Vector.sub(this.target.position, this.position)), this.accelMag * this.mass) } else { //wonder around diff --git a/js/tech.js b/js/tech.js index 2a32bcf..7e7cc17 100644 --- a/js/tech.js +++ b/js/tech.js @@ -3361,7 +3361,7 @@ const tech = { }, { name: "decoherence", - description: `tech options you don't choose won't reoccur
spawn ${powerUps.orb.research(6)}`, + description: `tech options you don't choose won't reoccur
spawn ${powerUps.orb.research(7)}`, maxCount: 1, count: 0, frequency: 1, @@ -3370,7 +3370,7 @@ const tech = { return !tech.isSuperDeterminism }, requires: "not superdeterminism", - bonusResearch: 6, + bonusResearch: 7, effect() { tech.isBanish = true for (let i = 0; i < this.bonusResearch; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); @@ -5662,19 +5662,19 @@ const tech = { }, { name: "shaped charge", - description: `use ${powerUps.orb.research(3)} to dynamically reduce
all explosions to prevent health loss`, + description: `use ${powerUps.orb.research(2)} to dynamically reduce
all explosions to prevent health loss`, isGunTech: true, maxCount: 1, count: 0, frequency: 2, frequencyDefault: 2, allowed() { - return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 2) && (tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)) + return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 1) && (tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)) }, requires: "an explosive damage source, not rocket propelled grenade", effect() { tech.isSmartRadius = true; - for (let i = 0; i < 3; i++) { + for (let i = 0; i < 2; i++) { if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) } }, @@ -5731,9 +5731,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("grenades") && !tech.isVacuumBomb + return tech.haveGunCheck("grenades") && !tech.isVacuumBomb && !tech.isSmartRadius }, - requires: "grenades, not vacuum bomb", + requires: "grenades, not vacuum bomb, shaped charges", effect() { tech.isImmuneExplosion = true; tech.isRPG = true; @@ -6615,12 +6615,12 @@ const tech = { isGunTech: true, maxCount: 1, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, allowed() { - return !tech.isBulletTeleport && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall || tech.isFoamMine) + return tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall || tech.isFoamMine }, - requires: "foam, not uncertainty", + requires: "foam", effect() { tech.isFoamAttract = true }, @@ -6637,9 +6637,9 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return (!tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall || tech.isFoamMine)) || (tech.haveGunCheck("wave") && !tech.is360Longitudinal) || (tech.haveGunCheck("super balls") && !tech.isSuperHarm) || tech.isSoundBotUpgrade + return (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall || tech.isFoamMine) || (tech.haveGunCheck("wave") && !tech.is360Longitudinal) || (tech.haveGunCheck("super balls") && !tech.isSuperHarm) || tech.isSoundBotUpgrade }, - requires: "foam, wave, super balls, not isotropic, electrostatic induction, Zectron", + requires: "foam, wave, super balls, not isotropic, Zectron", effect() { tech.isBulletTeleport = true }, @@ -7179,7 +7179,7 @@ const tech = { }, { name: "compound lens", - description: "+50% laser lens damage
+15° lens arc", + description: "+40% laser lens damage
+25° lens arc", isGunTech: true, maxCount: 9, count: 0, @@ -7190,8 +7190,8 @@ const tech = { }, requires: "lens", effect() { - b.guns[11].arcRange += 15 * Math.PI / 180 / 2 - b.guns[11].lensDamageOn += 0.5 + b.guns[11].arcRange += 25 * Math.PI / 180 / 2 + b.guns[11].lensDamageOn += 0.4 }, remove() { b.guns[11].arcRange = 90 * Math.PI / 180 / 2 //0.78 divded by 2 because of how it's drawn diff --git a/todo.txt b/todo.txt index 010889f..246090e 100644 --- a/todo.txt +++ b/todo.txt @@ -1,14 +1,21 @@ ******************************************************** NEXT PATCH ************************************************** -new mob type: hopMother - hoppers that drop eggs that explode on contact and after several seconds they hatch into baby hoppers - regular hopper mobs have more life and more damage +after falling off most open maps you don't take damage + you fall down into the level again above the entrance -a few bug fixes +disabled smooth camera tracking for + portals + falling off map + +added a once every 7 seconds check to see if the player is suck inside the map + if stuck you teleport to the level entrance + catches about 90% of the ways to get stuck from falling too fast + this might causing problems after more testing, not sure + +bug fixes *********************************************************** TODO ***************************************************** -a mob/boss? that drops the mines from reactor and final boss - more (all) bosses need to be made of parts good examples: spiderBoss, dragonFlyBoss, beetleBoss methods: @@ -1108,7 +1115,7 @@ possible names for tech magnetorquers - produce spin by pushing on earth's magnetic field Josephson junction - superconducting junction Pyroelectricity - voltage from temp changes - upgrade from piezoelectricity - dark star - upgrade to WIMPs + perturbation ******************************************************** CARS IMAGES ********************************************************