diff --git a/.DS_Store b/.DS_Store index cf66128..49bb66f 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/js/level.js b/js/level.js index 614c2dd..03f5767 100644 --- a/js/level.js +++ b/js/level.js @@ -379,6 +379,71 @@ const level = { World.add(engine.world, constraint); return constraint }, + elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { + x += width / 2 + y += height / 2 + maxHeight += height / 2 + const yTravel = maxHeight - y + force += simulation.g + const who = body[body.length] = Bodies.rectangle(x, y, width, height, { + collisionFilter: { + category: cat.body, + mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + }, + inertia: Infinity, //prevents rotation + isNotHoldable: true, + friction: 1, + frictionStatic: 1, + restitution: 0, + frictionAir: 0.001, + move() { + if (!m.isBodiesAsleep) { + if (this.isUp) { //moving up still with high air friction + this.force.y -= force * this.mass //hard force propels up, even with high friction + + if (this.position.y < maxHeight) { //switch to down mode + this.isUp = false + this.frictionAir = friction.down + //adds a hard jerk at the top of vertical motion because it's fun + Matter.Body.setPosition(this, { + x: x, + y: maxHeight + }); + Matter.Body.setVelocity(this, { + x: 0, + y: 0 + }); + } + } else if (this.position.y + 10 * this.velocity.y > y) { //free falling down, with only air friction + Matter.Body.setVelocity(this, { //slow down early to avoid a jerky stop that can pass through blocks + x: 0, + y: this.velocity.y * 0.7 + }); + if (this.position.y + this.velocity.y > y) { //switch to up mode + this.isUp = true + this.frictionAir = friction.up + } + } + + } + // hold horizontal position + Matter.Body.setPosition(this, { + x: x, + y: this.position.y + }); + Matter.Body.setVelocity(this, { + x: 0, + y: this.velocity.y + }); + }, + drawTrack() { + ctx.fillStyle = "#ccc" + ctx.fillRect(x, y, 5, yTravel) + } + }); + Matter.Body.setDensity(who, 0.01) //10x density for added stability + return who + }, platform(x, y, width, height, speed = 0, density = 0.001) { x = x + width / 2 y = y + height / 2 @@ -410,6 +475,7 @@ const level = { speed: speed, } constraint.pauseUntilCycle = 0 //to to pause platform at top and bottom + return constraint }, rotor(x, y, rotate = 0, radius = 800, width = 40, density = 0.0005) { @@ -1866,7 +1932,7 @@ const level = { if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275); }, satellite() { - const elevator = level.platform(4210, -1325, 380, 30, -10) + const elevator = level.elevator(4210, -1297, 380, 85, -3450) //, 0.003, { up: 0.01, down: 0.2 } level.custom = () => { ctx.fillStyle = "#d4f4f4" ctx.fillRect(-250, -750, 420, 450) @@ -1894,19 +1960,21 @@ const level = { ctx.fillStyle = "rgba(0,20,40,0.1)" ctx.fillRect(4000, -1200, 1050, 1500) ctx.fillRect(4100, -3450, 600, 2250) - if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { //elevator move - if (elevator.pointA.y > -1275) { //bottom - elevator.plat.speed = -10 - elevator.pauseUntilCycle = simulation.cycle + 90 - } else if (elevator.pointA.y < -3455) { //top - elevator.plat.speed = 30 - elevator.pauseUntilCycle = simulation.cycle + 90 - } - elevator.pointA = { - x: elevator.pointA.x, - y: elevator.pointA.y + elevator.plat.speed - } - } + elevator.move() + // elevator.drawTrack() //looks ugly + // if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { //elevator move + // if (elevator.pointA.y > -1275) { //bottom + // elevator.plat.speed = -10 + // elevator.pauseUntilCycle = simulation.cycle + 90 + // } else if (elevator.pointA.y < -3455) { //top + // elevator.plat.speed = 30 + // elevator.pauseUntilCycle = simulation.cycle + 90 + // } + // elevator.pointA = { + // x: elevator.pointA.x, + // y: elevator.pointA.y + elevator.plat.speed + // } + // } }; level.setPosToSpawn(-100, 210); //normal spawn @@ -2025,10 +2093,11 @@ const level = { if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(3950, -850); }, rooftops() { - const elevator = level.platform(1450, -1000, 235, 30, -2) + const elevator = level.elevator(1450, -1000, 235, 50, -2000) level.custom = () => { - ctx.fillStyle = "#ccc" - ctx.fillRect(1567, -1990, 5, 1020) + elevator.move(); + elevator.drawTrack(); + ctx.fillStyle = "#d4f4f4" if (isBackwards) { ctx.fillRect(-650, -2300, 440, 300) @@ -2063,19 +2132,6 @@ const level = { } else { ctx.fillRect(-650, -2300, 440, 300) } - if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { //elevator move - if (elevator.pointA.y > -980) { //bottom - elevator.plat.speed = -2 - elevator.pauseUntilCycle = simulation.cycle + 60 - } else if (elevator.pointA.y < -1980) { //top - elevator.plat.speed = 1 - elevator.pauseUntilCycle = simulation.cycle + 60 - } - elevator.pointA = { - x: elevator.pointA.x, - y: elevator.pointA.y + elevator.plat.speed - } - } }; level.defaultZoom = 1700 @@ -2487,6 +2543,54 @@ const level = { if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(3075, -2050); }, highrise() { + const isBlockMode = false + let slideBlock + if (isBlockMode) { + const x = -2750 + const yMax = -1500 + slideBlock = body[body.length] = Bodies.rectangle(x, -700, 200, 100, { + collisionFilter: { + category: cat.body, + mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + }, + inertia: Infinity, //prevents rotation + isNotHoldable: true, + friction: 1, + frictionStatic: 1, + frictionAir: 0.001, + // restitution: 0, + isUp: true, + move() { + if (this.isUp) { + if (this.position.y > yMax) { + this.force.y -= 0.01 * this.mass + } else { + this.isUp = false + Matter.Body.setPosition(this, { + x: x, + y: yMax + }); + Matter.Body.setVelocity(this, { + x: 0, + y: 0 + }); + } + } else if (this.position.y > -800) { + this.isUp = true + } + }, + holdHorizontal() { + Matter.Body.setPosition(this, { + x: x, + y: this.position.y + }); + Matter.Body.setVelocity(this, { + x: 0, + y: this.velocity.y + }); + } + }); + } level.custom = () => { ctx.fillStyle = "#d0d0d2" ctx.fillRect(-2475, -2450, 25, 750) @@ -2498,24 +2602,43 @@ const level = { level.exit.draw(); level.enter.draw(); }; - level.customTopLayer = () => { - ctx.fillStyle = "rgba(64,64,64,0.97)" //hidden section - ctx.fillRect(-4450, -750, 800, 200) - ctx.fillStyle = "rgba(0,0,0,0.12)" - ctx.fillRect(-1830, -1150, 2030, 1150) - ctx.fillRect(-3410, -2150, 495, 1550) - ctx.fillRect(-2585, -1675, 420, 1125) - ctx.fillRect(-1640, -1575, 540, 425) - ctx.fillStyle = "rgba(200,0,255,0.2)"; //boost - ctx.fillRect(-750, -25, 100, 25); - ctx.fillRect(-2800, -625, 100, 25); - ctx.fillStyle = "rgba(200,0,255,0.1)"; //boost - ctx.fillRect(-750, -55, 100, 55); - ctx.fillRect(-2800, -655, 100, 55); - ctx.fillStyle = "rgba(200,0,255,0.05)"; //boost - ctx.fillRect(-750, -120, 100, 120); - ctx.fillRect(-2800, -720, 100, 120); - }; + if (isBlockMode) { + level.customTopLayer = () => { + ctx.fillStyle = "rgba(64,64,64,0.97)" //hidden section + ctx.fillRect(-4450, -750, 800, 200) + ctx.fillStyle = "rgba(0,0,0,0.12)" + ctx.fillRect(-1830, -1150, 2030, 1150) + ctx.fillRect(-3410, -2150, 495, 1550) + ctx.fillRect(-2585, -1675, 420, 1125) + ctx.fillRect(-1640, -1575, 540, 425) + //move sliding block + slideBlock.move() + slideBlock.holdHorizontal() //keep horizontal position constant + + + + }; + } else { + level.customTopLayer = () => { + ctx.fillStyle = "rgba(64,64,64,0.97)" //hidden section + ctx.fillRect(-4450, -750, 800, 200) + ctx.fillStyle = "rgba(0,0,0,0.12)" + ctx.fillRect(-1830, -1150, 2030, 1150) + ctx.fillRect(-3410, -2150, 495, 1550) + ctx.fillRect(-2585, -1675, 420, 1125) + ctx.fillRect(-1640, -1575, 540, 425) + ctx.fillStyle = "rgba(200,0,255,0.2)"; //boost + ctx.fillRect(-750, -25, 100, 25); + ctx.fillRect(-2800, -625, 100, 25); + ctx.fillStyle = "rgba(200,0,255,0.1)"; //boost + ctx.fillRect(-750, -55, 100, 55); + ctx.fillRect(-2800, -655, 100, 55); + ctx.fillStyle = "rgba(200,0,255,0.05)"; //boost + ctx.fillRect(-750, -120, 100, 120); + ctx.fillRect(-2800, -720, 100, 120); + }; + } + level.setPosToSpawn(-300, -700); //normal spawn spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); @@ -2575,7 +2698,7 @@ const level = { spawn.mapRect(-4450, -600, 2300, 750); spawn.mapRect(-2225, -450, 175, 550); // spawn.mapRect(-2600, -975, 450, 50); - spawn.boost(-2800, -600, 950); + if (!isBlockMode) spawn.boost(-2800, -600, 950); spawn.mapRect(-3425, -1325, 525, 50); spawn.mapRect(-3425, -2200, 525, 50); spawn.mapRect(-2600, -1700, 450, 50); diff --git a/js/player.js b/js/player.js index f2f45d1..2887a2a 100644 --- a/js/player.js +++ b/js/player.js @@ -264,10 +264,11 @@ const m = { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) }); + player.force.y = -m.jumpForce; //player jump force Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps x: player.velocity.x, - y: 0 + y: Math.max(-10, Math.min(m.standingOn.velocity.y, 10)) //cap velocity contribution from blocks you are standing on to 10 in the vertical }); } @@ -1632,14 +1633,14 @@ const m = { // m.fieldMeterColor = "#0c5" // m.eyeFillColor = m.fieldMeterColor m.hold = function() { - if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 200 && (m.cycle % 2)) { + if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 150 && (m.cycle % 2)) { if (tech.isSporeField) { - for (let i = 0; i < 30; i++) { - m.energy -= 0.088 + for (let i = 0, len = Math.random() * 20; i < len; i++) { + m.energy -= 0.085 if (m.energy > 0) { b.spore(m.pos) } else { - m.energy = 0.01 + m.energy = 0.001 break; } } diff --git a/js/tech.js b/js/tech.js index d1f3a14..b877673 100644 --- a/js/tech.js +++ b/js/tech.js @@ -665,6 +665,23 @@ // tech.isOneBullet = false // } // }, + { + name: "fracture analysis", + description: "bullet impacts do 400% damage
to stunned mobs", + maxCount: 1, + count: 0, + frequency: 2, + allowed() { + return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isExplosionStun + }, + requires: "a stun effect", + effect() { + tech.isCrit = true; + }, + remove() { + tech.isCrit = false; + } + }, { name: "microstates", description: "increase damage by 4%
for every 10 active bullets", @@ -1856,20 +1873,25 @@ } }, { - name: "fracture analysis", - description: "bullet impacts do 400% damage
to stunned mobs", + name: "MACHO", + description: "a massive but compact object slowly follows you
take 66% less harm inside it's halo", maxCount: 1, count: 0, - frequency: 2, + frequency: 1, + frequencyDefault: 1, allowed() { - return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isExplosionStun + return true }, - requires: "a stun effect", - effect() { - tech.isCrit = true; + requires: "", + effect: () => { + tech.isMACHO = true; //this harm reduction comes from the particle toggling tech.isHarmMACHO + spawn.MACHO() }, remove() { - tech.isCrit = false; + tech.isMACHO = false; + for (let i = 0, len = mob.length; i < len; i++) { + if (mob[i].isMACHO) mob[i].alive = false; + } } }, { @@ -2735,28 +2757,6 @@ tech.wimpCount = 0 } }, - { - name: "MACHO", - description: "a massive but compact object slowly follows you
take 66% less harm inside it's halo", - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return true - }, - requires: "", - effect: () => { - tech.isMACHO = true; //this harm reduction comes from the particle toggling tech.isHarmMACHO - spawn.MACHO() - }, - remove() { - tech.isMACHO = false; - for (let i = 0, len = mob.length; i < len; i++) { - if (mob[i].isMACHO) mob[i].alive = false; - } - } - }, { name: "bubble fusion", description: "after destroying a mob's natural shield
spawn 1-2 heals, ammo, or research", @@ -2795,7 +2795,7 @@ }, { name: "replication", - description: "8% chance to duplicate spawned power ups
add 14 JUNK tech to the potential pool", + description: "8% chance to duplicate spawned power ups
add 18 JUNK tech to the potential pool", maxCount: 9, count: 0, frequency: 1, @@ -2807,12 +2807,12 @@ effect() { tech.duplicateChance += 0.08 powerUps.setDo(); //needed after adjusting duplication chance - tech.addJunkTechToPool(14) + tech.addJunkTechToPool(18) }, remove() { tech.duplicateChance = 0 powerUps.setDo(); //needed after adjusting duplication chance - if (this.count > 1) tech.removeJunkTechFromPool(14) + if (this.count > 1) tech.removeJunkTechFromPool(18) } }, { @@ -3230,7 +3230,7 @@ }, { name: "dark patterns", - description: "reduce combat difficulty by 1 level
add 18 JUNK tech to the potential pool", + description: "reduce combat difficulty by 1 level
add 21 JUNK tech to the potential pool", maxCount: 1, count: 0, frequency: 1, @@ -3243,12 +3243,12 @@ level.difficultyDecrease(simulation.difficultyMode) // simulation.difficulty-= simulation.makeTextLog(`level.difficultyDecrease(simulation.difficultyMode)`) - tech.addJunkTechToPool(18) + tech.addJunkTechToPool(21) // for (let i = 0; i < tech.junk.length; i++) tech.tech.push(tech.junk[i]) }, remove() { if (this.count > 0) { - tech.removeJunkTechFromPool(18) + tech.removeJunkTechFromPool(21) level.difficultyIncrease(simulation.difficultyMode) } } diff --git a/todo.txt b/todo.txt index b1209a9..63e7c84 100644 --- a/todo.txt +++ b/todo.txt @@ -1,12 +1,14 @@ ******************************************************** NEXT PATCH ******************************************************** -tech: MACHO - an object follows you and gives you harm protection when you are inside it's halo +jump now applies the velocity of the block you jumped off of + it might feel slightly different if you play n-gon often + it could add some bugs so let me know -several nano-scale field tech now require some research, and have been buffed - nano-scale mycelium, ice-IX, missile tech now consume 20% less energy to produce bullets - nano-scale bot tech: spawn an extra bots - -some bug fixes +elevators have more realistic physics + you can jump off them when they get to the top (fun!) + blocks interact with them in a more healthy way (no bleed through) + they can have a wider range of healthy speeds + it can hurt mobs ******************************************************** BUGS ******************************************************** @@ -52,6 +54,23 @@ is there a way to check if the player is stuck inside the map or block ******************************************************** TODO ******************************************************** +platform: jumps a bit before moving up + you can't use set position for y, because blocks drag a bit inside the platform + get delays working right + do something if the force is overwhelmed so much the platform moves backwards, or below lower/upper range + apply a constraint when still and remove it when moving + also apply thr constraint if the block goes outside normal bounds by too much + +should jump velocity add to current velocity? + maybe only add the velocity of what the player is standing on + +mob: molecule shapes - 2 separate mobs joined by a bond + use constraints: just spawn 2x or 3x groupings + low friction so they can spin around + spin when attacking player? + increase constraint length when attacking + + make nano-scale upgrades all cost research, and buff those tech make most future tech for guns / fields