elevators

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

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
This commit is contained in:
landgreen
2021-05-25 17:40:17 -07:00
parent 8727fee15e
commit 39e6ee5dde
5 changed files with 239 additions and 96 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -379,6 +379,71 @@ const level = {
World.add(engine.world, constraint); World.add(engine.world, constraint);
return 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) { platform(x, y, width, height, speed = 0, density = 0.001) {
x = x + width / 2 x = x + width / 2
y = y + height / 2 y = y + height / 2
@@ -410,6 +475,7 @@ const level = {
speed: speed, speed: speed,
} }
constraint.pauseUntilCycle = 0 //to to pause platform at top and bottom constraint.pauseUntilCycle = 0 //to to pause platform at top and bottom
return constraint return constraint
}, },
rotor(x, y, rotate = 0, radius = 800, width = 40, density = 0.0005) { 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); if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275);
}, },
satellite() { 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 = () => { level.custom = () => {
ctx.fillStyle = "#d4f4f4" ctx.fillStyle = "#d4f4f4"
ctx.fillRect(-250, -750, 420, 450) ctx.fillRect(-250, -750, 420, 450)
@@ -1894,19 +1960,21 @@ const level = {
ctx.fillStyle = "rgba(0,20,40,0.1)" ctx.fillStyle = "rgba(0,20,40,0.1)"
ctx.fillRect(4000, -1200, 1050, 1500) ctx.fillRect(4000, -1200, 1050, 1500)
ctx.fillRect(4100, -3450, 600, 2250) ctx.fillRect(4100, -3450, 600, 2250)
if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { //elevator move elevator.move()
if (elevator.pointA.y > -1275) { //bottom // elevator.drawTrack() //looks ugly
elevator.plat.speed = -10 // if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { //elevator move
elevator.pauseUntilCycle = simulation.cycle + 90 // if (elevator.pointA.y > -1275) { //bottom
} else if (elevator.pointA.y < -3455) { //top // elevator.plat.speed = -10
elevator.plat.speed = 30 // elevator.pauseUntilCycle = simulation.cycle + 90
elevator.pauseUntilCycle = simulation.cycle + 90 // } else if (elevator.pointA.y < -3455) { //top
} // elevator.plat.speed = 30
elevator.pointA = { // elevator.pauseUntilCycle = simulation.cycle + 90
x: elevator.pointA.x, // }
y: elevator.pointA.y + elevator.plat.speed // elevator.pointA = {
} // x: elevator.pointA.x,
} // y: elevator.pointA.y + elevator.plat.speed
// }
// }
}; };
level.setPosToSpawn(-100, 210); //normal spawn level.setPosToSpawn(-100, 210); //normal spawn
@@ -2025,10 +2093,11 @@ const level = {
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(3950, -850); if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(3950, -850);
}, },
rooftops() { rooftops() {
const elevator = level.platform(1450, -1000, 235, 30, -2) const elevator = level.elevator(1450, -1000, 235, 50, -2000)
level.custom = () => { level.custom = () => {
ctx.fillStyle = "#ccc" elevator.move();
ctx.fillRect(1567, -1990, 5, 1020) elevator.drawTrack();
ctx.fillStyle = "#d4f4f4" ctx.fillStyle = "#d4f4f4"
if (isBackwards) { if (isBackwards) {
ctx.fillRect(-650, -2300, 440, 300) ctx.fillRect(-650, -2300, 440, 300)
@@ -2063,19 +2132,6 @@ const level = {
} else { } else {
ctx.fillRect(-650, -2300, 440, 300) 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 level.defaultZoom = 1700
@@ -2487,6 +2543,54 @@ const level = {
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(3075, -2050); if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(3075, -2050);
}, },
highrise() { 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 = () => { level.custom = () => {
ctx.fillStyle = "#d0d0d2" ctx.fillStyle = "#d0d0d2"
ctx.fillRect(-2475, -2450, 25, 750) ctx.fillRect(-2475, -2450, 25, 750)
@@ -2498,6 +2602,23 @@ const level = {
level.exit.draw(); level.exit.draw();
level.enter.draw(); level.enter.draw();
}; };
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 = () => { level.customTopLayer = () => {
ctx.fillStyle = "rgba(64,64,64,0.97)" //hidden section ctx.fillStyle = "rgba(64,64,64,0.97)" //hidden section
ctx.fillRect(-4450, -750, 800, 200) ctx.fillRect(-4450, -750, 800, 200)
@@ -2516,6 +2637,8 @@ const level = {
ctx.fillRect(-750, -120, 100, 120); ctx.fillRect(-750, -120, 100, 120);
ctx.fillRect(-2800, -720, 100, 120); ctx.fillRect(-2800, -720, 100, 120);
}; };
}
level.setPosToSpawn(-300, -700); //normal spawn level.setPosToSpawn(-300, -700); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); 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(-4450, -600, 2300, 750);
spawn.mapRect(-2225, -450, 175, 550); spawn.mapRect(-2225, -450, 175, 550);
// spawn.mapRect(-2600, -975, 450, 50); // 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, -1325, 525, 50);
spawn.mapRect(-3425, -2200, 525, 50); spawn.mapRect(-3425, -2200, 525, 50);
spawn.mapRect(-2600, -1700, 450, 50); spawn.mapRect(-2600, -1700, 450, 50);

View File

@@ -264,10 +264,11 @@ const m = {
x: 0, x: 0,
y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5)
}); });
player.force.y = -m.jumpForce; //player jump force player.force.y = -m.jumpForce; //player jump force
Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps
x: player.velocity.x, 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.fieldMeterColor = "#0c5"
// m.eyeFillColor = m.fieldMeterColor // m.eyeFillColor = m.fieldMeterColor
m.hold = function() { 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) { if (tech.isSporeField) {
for (let i = 0; i < 30; i++) { for (let i = 0, len = Math.random() * 20; i < len; i++) {
m.energy -= 0.088 m.energy -= 0.085
if (m.energy > 0) { if (m.energy > 0) {
b.spore(m.pos) b.spore(m.pos)
} else { } else {
m.energy = 0.01 m.energy = 0.001
break; break;
} }
} }

View File

@@ -665,6 +665,23 @@
// tech.isOneBullet = false // tech.isOneBullet = false
// } // }
// }, // },
{
name: "fracture analysis",
description: "bullet impacts do <strong>400%</strong> <strong class='color-d'>damage</strong><br>to <strong>stunned</strong> 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", name: "microstates",
description: "increase <strong class='color-d'>damage</strong> by <strong>4%</strong><br>for every <strong>10</strong> active <strong>bullets</strong>", description: "increase <strong class='color-d'>damage</strong> by <strong>4%</strong><br>for every <strong>10</strong> active <strong>bullets</strong>",
@@ -1856,20 +1873,25 @@
} }
}, },
{ {
name: "fracture analysis", name: "MACHO",
description: "bullet impacts do <strong>400%</strong> <strong class='color-d'>damage</strong><br>to <strong>stunned</strong> mobs", description: "a massive but compact object slowly <strong>follows</strong> you<br>take <strong>66%</strong> less <strong class='color-harm'>harm</strong> inside it's <strong>halo</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 1,
frequencyDefault: 1,
allowed() { allowed() {
return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isExplosionStun return true
}, },
requires: "a stun effect", requires: "",
effect() { effect: () => {
tech.isCrit = true; tech.isMACHO = true; //this harm reduction comes from the particle toggling tech.isHarmMACHO
spawn.MACHO()
}, },
remove() { 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 tech.wimpCount = 0
} }
}, },
{
name: "MACHO",
description: "a massive but compact object slowly <strong>follows</strong> you<br>take <strong>66%</strong> less <strong class='color-harm'>harm</strong> inside it's <strong>halo</strong>",
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", name: "bubble fusion",
description: "after destroying a mob's natural <strong>shield</strong><br>spawn <strong>1-2</strong> <strong class='color-h'>heals</strong>, <strong class='color-g'>ammo</strong>, or <strong class='color-r'>research</strong>", description: "after destroying a mob's natural <strong>shield</strong><br>spawn <strong>1-2</strong> <strong class='color-h'>heals</strong>, <strong class='color-g'>ammo</strong>, or <strong class='color-r'>research</strong>",
@@ -2795,7 +2795,7 @@
}, },
{ {
name: "replication", name: "replication",
description: "<strong>8%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>14</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool", description: "<strong>8%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>18</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2807,12 +2807,12 @@
effect() { effect() {
tech.duplicateChance += 0.08 tech.duplicateChance += 0.08
powerUps.setDo(); //needed after adjusting duplication chance powerUps.setDo(); //needed after adjusting duplication chance
tech.addJunkTechToPool(14) tech.addJunkTechToPool(18)
}, },
remove() { remove() {
tech.duplicateChance = 0 tech.duplicateChance = 0
powerUps.setDo(); //needed after adjusting duplication chance 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", name: "dark patterns",
description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br>add <strong>18</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool", description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br>add <strong>21</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3243,12 +3243,12 @@
level.difficultyDecrease(simulation.difficultyMode) level.difficultyDecrease(simulation.difficultyMode)
// simulation.difficulty<span class='color-symbol'>-=</span> // simulation.difficulty<span class='color-symbol'>-=</span>
simulation.makeTextLog(`level.difficultyDecrease(simulation.difficultyMode)`) 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]) // for (let i = 0; i < tech.junk.length; i++) tech.tech.push(tech.junk[i])
}, },
remove() { remove() {
if (this.count > 0) { if (this.count > 0) {
tech.removeJunkTechFromPool(18) tech.removeJunkTechFromPool(21)
level.difficultyIncrease(simulation.difficultyMode) level.difficultyIncrease(simulation.difficultyMode)
} }
} }

View File

@@ -1,12 +1,14 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** 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 elevators have more realistic physics
nano-scale mycelium, ice-IX, missile tech now consume 20% less energy to produce bullets you can jump off them when they get to the top (fun!)
nano-scale bot tech: spawn an extra bots blocks interact with them in a more healthy way (no bleed through)
they can have a wider range of healthy speeds
some bug fixes it can hurt mobs
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
@@ -52,6 +54,23 @@ is there a way to check if the player is stuck inside the map or block
******************************************************** TODO ******************************************************** ******************************************************** 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 nano-scale upgrades all cost research, and buff those tech
make most future tech for guns / fields make most future tech for guns / fields