pilot wave rework
  it's easier to surf on blocks controlled by pilot wave
    pilot wave secret combo spawns blocks that are easier to surf on: long and thin
  pilot wave location resets to player when off
  pilot wave hitting map no longer shrinks, it just will not enter map
  field speed slows down with total block mass in field
  energy drain
    1x energy regen disabled when field is active
    2x passive regen drained when out of line of sight of player
    energy drain that scales with size and acceleration of blocks in field
  added graphical flicker when field is out of line of sight
  a few more bosses now interact with blocks and can take damage
  prevented field from disabling when mouse goes off screen
    I don't expect any bugs from this, but maybe...

ghoster mobs have 2x->1.5x extra density and health
exploder mobs no longer have a chance for a shield
  2.5x explode damage, 1.3x health
  added a red aura to show they explode on contact
spawnerBossCulture changed visual look to be a flashing transparent red outline
  2x explode damage
laser mobs no longer explode, 1.5x density/mass
This commit is contained in:
landgreen
2025-02-02 21:16:10 -08:00
parent 77e484c3d2
commit b2426cd7be
8 changed files with 276 additions and 222 deletions

View File

@@ -2619,14 +2619,14 @@ const b = {
}
}
},
spore(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death()
spore(where, velocity = null) { //used with the tech upgrade in mob.death()
const bIndex = bullet.length;
const size = 4
if (bIndex < 500) { //can't make over 500 spores
bullet[bIndex] = Bodies.polygon(where.x, where.y, size, size, {
// density: 0.0015, //frictionAir: 0.01,
inertia: Infinity,
isFreeze: isFreeze,
isFreeze: tech.isSporeFreeze,
restitution: 0.5,
angle: Math.random() * 2 * Math.PI,
friction: 0,
@@ -2693,57 +2693,19 @@ const b = {
}
}
// if (!this.lockedOn && !(simulation.cycle % this.lookFrequency)) { //find mob targets
// this.closestTarget = null;
// this.lockedOn = null;
// let closeDist = Infinity;
// for (let i = 0, len = mob.length; i < len; ++i) {
// if (mob[i].isDropPowerUp && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
// // Matter.Query.ray(body, this.position, mob[i].position).length === 0
// const targetVector = Vector.sub(this.position, mob[i].position)
// const dist = Vector.magnitude(targetVector);
// if (dist < closeDist) {
// this.closestTarget = mob[i].position;
// closeDist = dist;
// this.lockedOn = mob[i] //Vector.normalise(targetVector);
// if (0.3 > Math.random()) break //doesn't always target the closest mob
// }
// }
// }
// }
// if (this.lockedOn && this.lockedOn.alive) { //accelerate towards mobs
// this.force = Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), this.mass * this.thrust)
// } else if (tech.isSporeFollow && this.lockedOn !== undefined) { //move towards player
// //checking for undefined means that the spores don't go after the player until it has looked and not found a target
// const dx = this.position.x - m.pos.x;
// const dy = this.position.y - m.pos.y;
// if (dx * dx + dy * dy > 10000) {
// this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, Vector.add(this.playerOffPosition, this.position))), this.mass * this.thrust)
// }
// // this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), this.mass * this.thrust)
// } else {
// this.force.y += this.mass * 0.0001; //gravity
// }
// if (this.nextPortCycle < simulation.cycle) { //teleport around if you have tech.isBulletTeleport
// this.nextPortCycle = simulation.cycle + this.portFrequency
// const range = 50 * Math.random()
// Matter.Body.setPosition(this, Vector.add(this.position, Vector.rotate({ x: range, y: 0 }, 2 * Math.PI * Math.random())))
// }
},
});
// if (tech.isBulletTeleport) {
// bullet[bIndex].portFrequency = 10 + Math.floor(5 * Math.random())
// bullet[bIndex].nextPortCycle = simulation.cycle + bullet[bIndex].portFrequency
// }
if (velocity) {
Matter.Body.setVelocity(bullet[bIndex], velocity);
} else {
const SPEED = 4 + 8 * Math.random();
const ANGLE = 2 * Math.PI * Math.random()
Matter.Body.setVelocity(bullet[bIndex], {
x: SPEED * Math.cos(ANGLE),
y: SPEED * Math.sin(ANGLE)
});
}
const SPEED = 4 + 8 * Math.random();
const ANGLE = 2 * Math.PI * Math.random()
Matter.Body.setVelocity(bullet[bIndex], {
x: SPEED * Math.cos(ANGLE),
y: SPEED * Math.sin(ANGLE)
});
Composite.add(engine.world, bullet[bIndex]); //add bullet to world
if (tech.isMutualism && m.health > 0.01) {

View File

@@ -1206,6 +1206,7 @@ const input = {
left: false,
right: false,
isPauseKeyReady: true,
// isMouseInside: true,
// lastDown: null,
key: {
fire: "KeyF",
@@ -1736,11 +1737,12 @@ document.body.addEventListener("mouseenter", (e) => { //prevents mouse getting s
input.fire = false;
}
if (e.button === 3) {
input.field = true;
} else {
input.field = false;
}
// if (e.button === 3) {
// input.field = true;
// } else {
// input.field = false;
// }
// input.isMouseInside = true
});
document.body.addEventListener("mouseleave", (e) => { //prevents mouse getting stuck when leaving the window
if (e.button === 1) {
@@ -1749,11 +1751,12 @@ document.body.addEventListener("mouseleave", (e) => { //prevents mouse getting s
input.fire = false;
}
if (e.button === 3) {
input.field = true;
} else {
input.field = false;
}
// if (e.button === 3) {
// input.field = true;
// } else {
// input.field = false;
// }
// input.isMouseInside = false
});
document.body.addEventListener("wheel", (e) => {

View File

@@ -34,6 +34,16 @@ const level = {
// tech.addJunkTechToPool(0.5)
// m.couplingChange(10)
// m.setField("pilot 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 10 grappling hook
// spawn.bodyRect(625, -100, 100, 75);
// spawn.bodyRect(750, -125, 250, 100);
// spawn.bodyRect(500, -150, 75, 100);
// spawn.bodyRect(1150, -125, 225, 75);
// spawn.bodyRect(1425, -250, 25, 150);
// spawn.bodyRect(1525, -100, 75, 25);
// spawn.bodyRect(1550, -200, 150, 100);
// m.energy = 0
// powerUps.research.count = 3
// tech.isHookWire = true
@@ -54,7 +64,7 @@ const level = {
// for (let i = 0; i < 1; ++i) tech.giveTech("Higgs mechanism")
// m.skin.egg();
// for (let i = 0; i < 1; ++i) tech.giveTech("many-worlds")
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("quasiparticles") });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("surfing") });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("interest") });
// for (let i = 0; i < 1; i++) tech.giveTech("interest")
// m.lastKillCycle = m.cycle
@@ -63,11 +73,12 @@ const level = {
// spawn.bodyRect(575, -700, 150, 150); //block mob line of site on testing
// level.testing();
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
// for (let i = 0; i < 10; ++i) spawn.starter(1900, -500)
// for (let i = 0; i < 1; i++) spawn.softBoss(1900, -500)
// for (let i = 0; i < 10; ++i) spawn.exploder(1900, -500)
// for (let i = 0; i < 1; i++) spawn.snakeBoss(1900, -500)
// for (let i = 0; i < 1; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "entanglement");
// for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 450, m.pos.y + 50 * Math.random(), "gun");
// for (let i = 0; i < 100; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "ammo");
@@ -2798,7 +2809,7 @@ const level = {
testing() {
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
document.body.style.backgroundColor = "#fff";
document.body.style.backgroundColor = "#ddd";
// color.map = "#444" //custom map color
level.defaultZoom = 1500
simulation.zoomTransition(level.defaultZoom)
@@ -2824,8 +2835,8 @@ const level = {
ctx.fillStyle = "#d4d4d4"
ctx.fillRect(2500, -475, 200, 300)
ctx.fillStyle = "#ddd"
ctx.fillRect(-150, -1000, 6875, 1000);
// ctx.fillStyle = "#ddd"
// ctx.fillRect(-150, -1000, 6875, 1000);
ctx.fillStyle = "rgba(0,255,255,0.1)";
ctx.fillRect(6400, -550, 300, 350);
level.exit.drawAndCheck();
@@ -6901,7 +6912,7 @@ const level = {
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
level.setPosToSpawn(900, 225); //normal spawn
level.custom = () => {
ctx.fillStyle = "#d0d3d9"
ctx.fillStyle = "rgba(0, 10, 30, 0.04)"//"#d0d3d9"
ctx.fillRect(-2500, -1800, 3575, 2100);
ctx.fillStyle = "#c0c3c9"
ctx.fillRect(-2075, -1475, 25, 1800);
@@ -6929,7 +6940,7 @@ const level = {
} else {
level.custom = () => {
ctx.fillStyle = "#d0d3d9"
ctx.fillStyle = "rgba(0, 10, 30, 0.04)"//"#d0d3d9"
ctx.fillRect(-1075, -1800, 3575, 2100);
ctx.fillStyle = "#c0c3c9"
ctx.fillRect(2050, -1475, 25, 1800);

View File

@@ -981,7 +981,7 @@ const mobs = {
},
explode(mass = this.mass) {
if (m.immuneCycle < m.cycle) {
m.damage(Math.min(Math.max(0.02 * Math.sqrt(mass), 0.01), 0.35) * simulation.dmgScale);
m.damage(Math.min(Math.max(0.03 * Math.sqrt(mass), 0.01), 0.4) * simulation.dmgScale);
this.isDropPowerUp = false;
this.death(); //death with no power up or body
}

View File

@@ -3629,6 +3629,10 @@ const m = {
setField(index) {
// console.log("field mode: ", index)
window.removeEventListener("keydown", m.fieldEvent);
if (m.fieldUpgrades[8].collider) {
Matter.Composite.remove(engine.world, m.fieldUpgrades[8].collider);
m.fieldUpgrades[8].collider = null
}
if (isNaN(index)) { //find index by name
let found = false
@@ -4267,7 +4271,8 @@ const m = {
for (let i = 0, len = 5; i < len; i++) {
if (m.energy > 3 * drain) {
m.energy -= drain
b.spore(m.pos)
const unit = Vector.rotate({ x: 1, y: 0 }, 6.28 * Math.random())
b.spore(Vector.add(m.pos, Vector.mult(unit, 25)), Vector.mult(unit, 10))
} else {
break
}
@@ -5163,7 +5168,19 @@ const m = {
name: "pilot wave",
description: `use <strong class='color-f'>energy</strong> to guide <strong class='color-block'>blocks</strong><em style ="float: right; font-family: monospace;font-size:1rem;color:#fff;">↓↓→↘↓↙←↓↓</em><br><div class="circle-grid tech"></div>, <div class="circle-grid gun"></div>, and <div class="circle-grid field"></div> have <strong>+3</strong> <strong class='color-choice'><span>ch</span><span>oi</span><span>ces</span></strong><br><strong>10</strong> <strong class='color-f'>energy</strong> per second`,
keyLog: [null, null, null, null, null, null, null],
collider: null,
fieldMass: 1,
effect: () => {
m.fieldUpgrades[8].collider = Matter.Bodies.polygon(m.pos.x, m.pos.y, 8, 35, {
friction: 0,
frictionAir: 0.12,
collisionFilter: { category: cat.player, mask: cat.map }, //no collision because player is holding
classType: "field",
lastSpeed: 0,
isPLayerInField: false,
});
Composite.add(engine.world, m.fieldUpgrades[8].collider); //add to world
//store event function so it can be found and removed in m.setField()
m.fieldEvent = function (event) {
m.fieldUpgrades[4].keyLog.shift() //remove first element
@@ -5171,27 +5188,30 @@ const m = {
const patternA = ["ArrowDown", "ArrowDown", "ArrowRight", "ArrowDown", "ArrowLeft", "ArrowDown", "ArrowDown"]
const patternB = [input.key.down, input.key.down, input.key.right, input.key.down, input.key.left, input.key.down, input.key.down]
const arraysEqual = (a, b) => a.length === b.length && a.every((val, i) => val === b[i]);
const where = {
x: m.pos.x,
y: m.pos.y - 75
const width = 90 + Math.floor(30 * Math.random())
const height = 11 + Math.floor(7 * Math.random())
const yOff = 60
const blockRegion = {
min: {
x: m.pos.x - width,
y: m.pos.y + yOff - height
},
max: {
x: m.pos.x + width,
y: m.pos.y + yOff + height
}
}
if (
(arraysEqual(m.fieldUpgrades[4].keyLog, patternA) || arraysEqual(m.fieldUpgrades[4].keyLog, patternB))
&& !Matter.Query.point(map, where).length
&& !Matter.Query.region(map, blockRegion).length
&& !m.crouch
) {
//remove old blocks
// for (let i = 0; i < body.length; i++) {
// if (body[i].isPilotWave) {
// Matter.Composite.remove(engine.world, body[i]);
// body.splice(i, 1);
// break
// }
// }
//move player up away from block
Matter.Body.setPosition(player, { x: player.position.x, y: player.position.y - height })
//spawn a block
const radius = 25 + Math.floor(15 * Math.random())
// body[body.length] = Matter.Bodies.polygon(simulation.mouseInGame.x, simulation.mouseInGame.y, 4, radius, {
body[body.length] = Matter.Bodies.polygon(where.x, where.y, 4 + Math.floor(4 * Math.random()), radius, {
body[body.length] = Matter.Bodies.rectangle(m.pos.x, blockRegion.max.y, width * 2, height * 2, {
friction: 0.05,
frictionAir: 0.001,
collisionFilter: {
@@ -5201,38 +5221,20 @@ const m = {
classType: "body",
isPilotWave: true,
});
const block = body[body.length - 1]
//mess with the block shape (this code is horrible)
Composite.add(engine.world, block); //add to world
const r1 = radius * (0.85 + 0.6 * Math.random())
const r2 = radius * (0.85 + 0.6 * Math.random())
let angle = Math.PI / 4
const vertices = []
for (let i = 0, len = block.vertices.length; i < len; i++) {
angle += 2 * Math.PI / len + 0.06 * Math.random()
vertices.push({ x: block.position.x + r1 * Math.cos(angle), y: block.position.y + r2 * Math.sin(angle) })
}
Matter.Body.setVertices(block, vertices)
/* <em style ="float: right; font-family: monospace;font-size:1rem;color:#fff;">↓↘→↓↙←↑↑↓</em> */
Composite.add(engine.world, body[body.length - 1]); //add to world
simulation.inGameConsole(`Composite<span class='color-symbol'>.</span>add<span class='color-symbol'>(</span>engine.world<span class='color-symbol'>,</span> block<span class='color-symbol'>)</span> &nbsp; &nbsp; <em style ="float: right; font-family: monospace;font-size:1rem;color:#fff;">//↓↓→↘↓↙←↓↓</em>`);
}
}
window.addEventListener("keydown", m.fieldEvent);
m.fieldMeterColor = "#333"
m.eyeFillColor = m.fieldMeterColor
m.fieldPhase = 0;
m.fieldPosition = {
x: simulation.mouseInGame.x,
y: simulation.mouseInGame.y
}
m.lastFieldPosition = {
x: simulation.mouseInGame.x,
y: simulation.mouseInGame.y
}
m.fieldPosition = { x: simulation.mouseInGame.x, y: simulation.mouseInGame.y }
m.lastFieldPosition = { x: simulation.mouseInGame.x, y: simulation.mouseInGame.y }
m.fieldOn = false;
// m.fieldFire = true;
m.fieldRadius = 0;
m.drop();
m.hold = function () {
@@ -5268,45 +5270,36 @@ const m = {
}
if (input.field) {
if (m.fieldCDcycle < m.cycle) {
const scale = 25
const bounds = {
min: {
x: m.fieldPosition.x - scale,
y: m.fieldPosition.y - scale
},
max: {
x: m.fieldPosition.x + scale,
y: m.fieldPosition.y + scale
}
}
const isInMap = Matter.Query.region(map, bounds).length
// const isInMap = Matter.Query.point(map, m.fieldPosition).length
if (!m.fieldOn) { // if field was off, and it starting up, teleport to new mouse location
if (!m.fieldOn) { // if field was off, teleport to player
m.fieldOn = true;
// m.fieldPosition = { //smooth the mouse position, set to starting at player
// x: m.pos.x,
// y: m.pos.y
// }
m.fieldPosition = { //smooth the mouse position, set to mouse's current location
x: simulation.mouseInGame.x,
y: simulation.mouseInGame.y
}
m.lastFieldPosition = { //used to find velocity of field changes
x: m.fieldPosition.x,
y: m.fieldPosition.y
}
} else { //when field is on it smoothly moves towards the mouse
m.lastFieldPosition = { //used to find velocity of field changes
x: m.fieldPosition.x,
y: m.fieldPosition.y
}
const smooth = isInMap ? 0.985 : 0.96;
m.fieldPosition = { //smooth the mouse position
x: m.fieldPosition.x * smooth + simulation.mouseInGame.x * (1 - smooth),
y: m.fieldPosition.y * smooth + simulation.mouseInGame.y * (1 - smooth),
}
Matter.Body.setPosition(m.fieldUpgrades[8].collider, m.pos);
m.fieldPosition.x = m.pos.x
m.fieldPosition.y = m.pos.y
}
//when field is on it smoothly moves towards the mouse
const sub = Vector.sub(simulation.mouseInGame, m.fieldUpgrades[8].collider.position)
const mag = Vector.magnitude(sub)
//adjust speed of field here, and with friction and mass above where the collier is spawned
const fieldMassScale = Math.max(1.5, Math.pow(m.fieldUpgrades[8].fieldMass, 0.35)) //how much mass inside the field slows the push and cap
const scaledMag = 0.00000017 / fieldMassScale * Math.pow(mag, 2) //having the mag squared makes the effect weaker in close for fine movement
let push = Vector.mult(Vector.normalise(sub), scaledMag)
const cap = 0.17 / fieldMassScale //acts like a "speed limit"
if (Vector.magnitude(push) > cap) push = Vector.mult(Vector.normalise(push), cap)
m.fieldUpgrades[8].collider.force = push
//check for map collisions
if (Matter.Query.ray(map, m.fieldPosition, m.fieldUpgrades[8].collider.position).length) {
Matter.Body.setVelocity(m.fieldUpgrades[8].collider, Vector.mult(m.fieldUpgrades[8].collider.velocity, 0.6))
m.fieldRadius *= 0.6
}
m.fieldPosition.x = m.fieldUpgrades[8].collider.position.x
m.fieldPosition.y = m.fieldUpgrades[8].collider.position.y
//check if player is inside field
// if (tech.isSurfing) {
// }
//grab power ups into the field
for (let i = 0, len = powerUp.length; i < len; ++i) {
@@ -5340,42 +5333,57 @@ const m = {
}
}
}
//grab power ups normally too
//grab power ups normally at player too
m.grabPowerUp();
if (m.energy > 0.01) {
//find mouse velocity
const diff = Vector.sub(m.fieldPosition, m.lastFieldPosition)
const speed = Vector.magnitude(diff)
const velocity = Vector.mult(Vector.normalise(diff), Math.min(speed, 60)) //limit velocity
let radius, radiusSmooth
if (Matter.Query.ray(map, m.fieldPosition, player.position).length) { //is there something block the player's view of the field
radius = 0
radiusSmooth = Math.max(0, isInMap ? 0.96 - 0.02 * speed : 0.995); //0.99
} else {
radius = Math.max(50, 250 - 2 * speed)
radiusSmooth = 0.97
}
m.fieldRadius = m.fieldRadius * radiusSmooth + radius * (1 - radiusSmooth)
let radiusGoal, radiusSmooth, drainPassive
if (Matter.Query.ray(map, m.fieldPosition, player.position).length) { //is there something blocking the player's view of the field
radiusGoal = 0
radiusSmooth = 0.995
drainPassive = 1.5 * m.fieldRegen //* (tech.isSurfing && m.fieldUpgrades[8].collider.isPLayerInField ? 0 : 1)
} else {
radiusGoal = Math.max(50, 250 - 2 * m.fieldUpgrades[8].collider.speed) //* (tech.isSurfing && m.fieldUpgrades[8].collider.isPLayerInField ? 1.5 : 1)
radiusSmooth = 0.97
drainPassive = m.fieldRegen //* (tech.isSurfing && m.fieldUpgrades[8].collider.isPLayerInField ? 0 : 1)
}
m.fieldRadius = m.fieldRadius * radiusSmooth + radiusGoal * (1 - radiusSmooth)
//track velocity change for calculating block energy drain
const speedChange = Math.max(0, m.fieldUpgrades[8].collider.speed - m.fieldUpgrades[8].collider.lastSpeed)
m.fieldUpgrades[8].collider.lastSpeed = m.fieldUpgrades[8].collider.speed
if (m.energy > drainPassive) {
m.energy -= drainPassive;
m.fieldUpgrades[8].fieldMass = 1
for (let i = 0, len = body.length; i < len; ++i) {
if (Vector.magnitude(Vector.sub(body[i].position, m.fieldPosition)) < m.fieldRadius && !body[i].isNotHoldable) {
const DRAIN = speed * body[i].mass * 0.0000035 // * (1 + m.energy * m.energy) //drain more energy when you have more energy
if (m.energy > DRAIN) {
m.energy -= DRAIN;
Matter.Body.setVelocity(body[i], velocity); //give block mouse velocity
// const drainBlock = m.fieldUpgrades[8].collider.speed * body[i].mass * 0.0000013
const drainBlock = speedChange * body[i].mass * 0.000095 //* (tech.isSurfing && m.fieldUpgrades[8].collider.isPLayerInField ? 0 : 1)
if (m.energy > drainBlock) {
m.energy -= drainBlock;
Matter.Body.setVelocity(body[i], m.fieldUpgrades[8].collider.velocity); //give block mouse velocity
Matter.Body.setAngularVelocity(body[i], body[i].angularVelocity * 0.8)
// body[i].force.y -= body[i].mass * simulation.g; //remove gravity effects
m.fieldUpgrades[8].fieldMass += body[i].mass
//blocks drift towards center of pilot wave
const sub = Vector.sub(m.fieldPosition, body[i].position)
const push = Vector.mult(Vector.normalise(sub), 0.0001 * body[i].mass * Vector.magnitude(sub))
body[i].force.x += push.x
body[i].force.y += push.y - body[i].mass * simulation.g //remove gravity effects
// if (body[i].collisionFilter.category !== cat.bullet) {
// body[i].collisionFilter.category = cat.bullet;
// }
if (m.standingOn === body[i] && m.onGround) {
//try to stop the walk animation
m.walk_cycle -= m.flipLegs * m.Vx
m.stepSize *= 0
//extra stability
Matter.Body.setAngularVelocity(body[i], body[i].angularVelocity * 0)
//match velocity upto a change of 10 per cycle
const limit = 10
const deltaV = Math.max(-limit, Math.min((m.fieldUpgrades[8].collider.velocity.x - player.velocity.x), limit))
Matter.Body.setVelocity(player, { x: player.velocity.x + deltaV, y: player.velocity.y });
}
} else {
m.fieldCDcycle = m.cycle + 120;
m.fieldCDcycle = m.cycle + 60;
m.fieldOn = false
m.fieldRadius = 0
break
@@ -5383,24 +5391,6 @@ const m = {
}
}
// m.holdingTarget.collisionFilter.category = cat.bullet;
// m.holdingTarget.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield;
// //check every second to see if player is away from thrown body, and make solid
// const solid = function(that) {
// const dx = that.position.x - player.position.x;
// const dy = that.position.y - player.position.y;
// if (that.speed < 3 && dx * dx + dy * dy > 10000 && that !== m.holdingTarget) {
// that.collisionFilter.category = cat.body; //make solid
// that.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet; //can hit player now
// } else {
// setTimeout(solid, 40, that);
// }
// };
// setTimeout(solid, 200, m.holdingTarget);
// if (tech.isFreezeMobs) {
// for (let i = 0, len = mob.length; i < len; ++i) {
// if (!mob[i].isMobBullet && !mob[i].shield && !mob[i].isShielded && Vector.magnitude(Vector.sub(mob[i].position, m.fieldPosition)) < m.fieldRadius + mob[i].radius) {
@@ -5418,17 +5408,22 @@ const m = {
const off2 = 1 - 0.06 * Math.sin(m.fieldPhase);
ctx.beginPath();
ctx.ellipse(m.fieldPosition.x, m.fieldPosition.y, 1.2 * m.fieldRadius * off1, 1.2 * m.fieldRadius * off2, rotate, 0, 2 * Math.PI);
ctx.globalCompositeOperation = "exclusion"; //"exclusion" "difference";
ctx.fillStyle = "#fff"; //"#eef";
ctx.globalCompositeOperation = "exclusion";
ctx.fillStyle = "#fff";
ctx.fill();
ctx.globalCompositeOperation = "source-over";
ctx.beginPath();
ctx.ellipse(m.fieldPosition.x, m.fieldPosition.y, 1.2 * m.fieldRadius * off1, 1.2 * m.fieldRadius * off2, rotate, 0, 2 * Math.PI * m.energy / m.maxEnergy);
ctx.strokeStyle = "#000";
if (radiusGoal || m.cycle % 5) {
ctx.strokeStyle = "#000";
} else {
ctx.strokeStyle = "#fff";
}
ctx.lineWidth = 4;
ctx.stroke();
} else {
m.fieldCDcycle = m.cycle + 120;
m.fieldCDcycle = m.cycle + 60;
m.fieldOn = false
m.fieldRadius = 0
}
@@ -5440,6 +5435,16 @@ const m = {
m.fieldRadius = 0
}
m.drawRegenEnergy("rgba(0,0,0,0.2)")
// //draw physics collider
// ctx.beginPath();
// const vertices = m.fieldUpgrades[8].collider.vertices;
// ctx.moveTo(vertices[0].x, vertices[0].y);
// for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y);
// ctx.lineTo(vertices[0].x, vertices[0].y);
// ctx.strokeStyle = "#000";
// ctx.lineWidth = 2;
// ctx.stroke();
}
}
},

View File

@@ -1498,7 +1498,7 @@ const spawn = {
for (let i = 0; i < num; i++) spawn.spawnerBoss(x, y, radius, spawnID)
},
spawnerBoss(x, y, radius, spawnID) {
mobs.spawn(x + Math.random(), y + Math.random(), 4, radius, "rgba(255,60,0,0.3)") //);
mobs.spawn(x + Math.random(), y + Math.random(), 4, radius, "rgba(255,0,70,1)") //);
let me = mob[mob.length - 1];
me.isBoss = true;
@@ -1518,10 +1518,24 @@ const spawn = {
// spawn.shield(me, x, y, 1);
me.onHit = function () { //run this function on hitting player
this.explode();
this.explode(2 * this.mass);
};
me.damageReduction = 0.14
me.doAwake = function () {
//draw aura
ctx.beginPath();
const vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.strokeStyle = `rgba(255,0,70,${0.2 + 0.4 * Math.random()})`
ctx.lineWidth = Math.floor(5 + 30 * this.health)
ctx.stroke();
// ctx.strokeStyle = "rgba(255,60,0,0.1)"
// ctx.lineWidth = 70
// ctx.stroke();
// this.fill = `rgba(255,0,70,${0.1 + 0.1 * Math.random()})`
this.alwaysSeePlayer();
this.checkStatus();
this.attraction();
@@ -1546,6 +1560,7 @@ const spawn = {
this.checkStatus();
if (this.seePlayer.recall) {
this.do = this.doAwake
this.fill = `transparent`
//awaken other spawnBosses
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isSpawnBoss && mob[i].spawnID === this.spawnID) mob[i].seePlayer.recall = 1
@@ -1601,7 +1616,7 @@ const spawn = {
me.seePlayerFreq = Math.floor(11 + 7 * Math.random())
me.seeAtDistance2 = 200000 //1400000;
me.stroke = "transparent"
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body //| cat.map //"rgba(255,60,0,0.3)"
me.collisionFilter.mask = cat.player | cat.bullet | cat.body //| cat.map //"rgba(255,60,0,0.3)"
me.buffCount = 0
me.accelMag = 0.00005 //* simulation.accelScale;
@@ -2030,7 +2045,7 @@ const spawn = {
// Matter.Body.setStatic(me, true); //make static (disables taking damage)
me.frictionAir = 1
me.damageReduction = 2
me.collisionFilter.mask = cat.bullet //| cat.body
me.collisionFilter.mask = cat.bullet | cat.body
// me.collisionFilter.category = cat.mobBullet;
// me.collisionFilter.mask = cat.bullet | cat.body // | cat.player
me.isMine = true
@@ -3930,7 +3945,7 @@ const spawn = {
me.nextBlinkCycle = me.delay;
me.JumpDistance = 0//set in redMode()
// spawn.shield(me, x, y, 1);
me.collisionFilter.mask = cat.bullet | cat.map //| cat.body //cat.player |
me.collisionFilter.mask = cat.bullet | cat.map | cat.body //cat.player |
me.powerUpNames = []
me.redMode = function () {
this.color = `rgba(255,0,200,`
@@ -4711,10 +4726,11 @@ const spawn = {
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0001 * simulation.accelScale;
me.laserInterval = 100
Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y);
me.onHit = function () {
//run this function on hitting player
this.explode();
// this.explode();
};
me.do = function () {
this.torque = this.lookTorque * this.inertia * 0.5;
@@ -6184,7 +6200,7 @@ const spawn = {
me.seeAtDistance2 = 500000;
me.accelMag = 0.0002 + 0.0001 * simulation.accelScale;
if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
Matter.Body.setDensity(me, 0.0002); //normal is 0.001
Matter.Body.setDensity(me, 0.00015); //normal is 0.001
me.damageReduction = 0.1
me.stroke = "transparent"; //used for drawGhost
me.alpha = 1; //used in drawGhost
@@ -6324,7 +6340,7 @@ const spawn = {
me.friction = 0;
me.frictionAir = 0.01;
me.memory = Infinity;
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
me.collisionFilter.mask = cat.player | cat.bullet | cat.body
spawn.shield(me, x, y, 1);
const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty)))
@@ -7429,13 +7445,27 @@ const spawn = {
exploder(x, y, radius = 40 + Math.ceil(Math.random() * 50)) {
mobs.spawn(x, y, 4, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.0013); //normal is 0.001
me.onHit = function () {
//run this function on hitting player
this.explode();
this.explode(2.5 * this.mass);
};
me.g = 0.0004; //required if using this.gravity
spawn.shield(me, x, y);
// spawn.shield(me, x, y);
me.do = function () {
//draw aura
ctx.beginPath();
const vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.strokeStyle = `rgba(255,0,50,${0.13 + 0.45 * Math.random()})`
ctx.lineWidth = 30
ctx.stroke();
ctx.strokeStyle = "rgba(255,0,50,0.1)"
ctx.lineWidth = 70
ctx.stroke();
this.gravity();
this.seePlayerCheck();
this.checkStatus();

View File

@@ -5551,7 +5551,7 @@ const tech = {
},
{
name: "super ball",
description: "fire just <strong>1 large</strong> super <strong>ball</strong><br>that <strong>stuns</strong> mobs for <strong>2</strong> second",
description: "fire just <strong>1 large</strong> super <strong>ball</strong><br>that <strong>stuns</strong> mobs for <strong>2</strong> seconds",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -8828,6 +8828,25 @@ const tech = {
tech.isDamageFieldTech = false
}
},
// {
// name: "surfing",
// description: `while player is inside the pilot wave field<br><strong>1.5x</strong> field radius and no field energy drain`,
// isFieldTech: true,
// maxCount: 1,
// count: 0,
// frequency: 4,
// frequencyDefault: 4,
// allowed() {
// return m.fieldMode === 8
// },
// requires: "pilot wave",
// effect() {
// tech.isSurfing = true
// },
// remove() {
// tech.isSurfing = false
// }
// },
{
name: "WIMPs",
description: `at the exit to each <strong>level</strong> spawn ${powerUps.orb.research(4)}<br>and a dangerous particle that slowly <strong>chases</strong> you`,
@@ -12350,4 +12369,5 @@ const tech = {
mineralDamage: null,
negativeMassCost: null,
beamCollimator: null,
isSurfing: null,
}

View File

@@ -1,22 +1,28 @@
******************************************************** NEXT PATCH **************************************************
tech: collimator - add 1 laser beam and align your diverging beams to be parallel
requires diffraction grating
pilot wave effect rework
it's easier to surf on blocks controlled by pilot wave
pilot wave secret combo spawns blocks that are easier to surf on: long and thin
pilot wave location resets to player when off
pilot wave hitting map no longer shrinks, it just will not enter map
field speed slows down with total block mass in field
energy drain
1x energy regen disabled when field is active
2x passive regen drained when out of line of sight of player
energy drain that scales with size and acceleration of blocks in field
added graphical flicker when field is out of line of sight
a few more bosses now interact with blocks and can take damage
prevented field from disabling when mouse goes off screen
I don't expect any bugs from this, but maybe...
added secret pilot wave combo to make blocks
rewrote combo test algorithm to be more forgiving with pattern matching
also extended combos test to arrow keys, not just WASD
ghoster mobs have 2x->1.5x extra density and health
exploder mobs no longer have a chance for a shield
2.5x explode damage, 1.3x health
added a red aura to show they explode on contact
spawnerBossCulture changed visual look to be a flashing transparent red outline
2x explode damage
laser mobs no longer explode, 1.5x density/mass
cache 17->15x ammo
metamaterial cloaking 0.3->0.4x damage reduction while cloaked
boson composite drains more energy when passing through mobs
scales with difficulty
subway level has 6->4 (5 on hard difficulty) stations
subway gives 1/3->1/5 interest per station
bug fixes
Higgs skin removal fixed
diaphragm skin removal fixed
******************************************************** BUGS ********************************************************
@@ -24,6 +30,22 @@ player can become crouched while not touching the ground if they exit the ground
*********************************************************** TODO *****************************************************
tech - while player is in field increase field radius and no energy drain
check if player is inside field
m.fieldUpgrades[8].collider.isPLayerInField = false
fix tech.isSurfing && m.fieldUpgrades[8].collider.isPLayerInField
tech - get a benefit while surfing on a block inside the pilot wave field
defense? damage?
tech - benefit if you haven't killed any mobs on this level
tech - benefit in the first 20 seconds of the level
plasma globe - it should not explode on map contact, but instead shrink?
only explode on mouse release
mob - moves around, but then stops and makes porcupine spikes for 2 seconds, then moves again.
maybe use hopper movement?
soft body boss?
search softBody(x, y, angle = 0, isAttached = true, len = 15, radius = 20, stiffness = 1, damping = 1) {
@@ -44,10 +66,14 @@ use ←↑→↓↖↗↘↙ combos to allow fields to have special actions
negative mass
molecular assembler - done
plasma torch
move around like you have recoil, move kinda fast so it's hard to control
like form recoil but fast
time dilation
metamaterial cloaking
pilot wave - done
wormhole
toggle bullets entering with wormholes
and player??
shoot out all the blocks that were sucked in this level (maybe cap at like 10?, cap with energy spent to fire)
are block sizes stored properly? because they shrink before they get eaten...
store vertices on the body object if one does already exists
@@ -81,8 +107,6 @@ new level idea: escort mission
make the style look like substructure, that level looks great
use the motion sense lasers
tech synergy ideas
a tech that spawns mobs that the player can use to trigger mob death tech
tech: - remove the research costs of all tech
there's about 15 tech with a research cost
@@ -91,12 +115,10 @@ tech: - remove the research costs of all tech
when far away from your wormhole regenerate 1% of your max energy per second
when far away from your wormhole reduce damage taken
heal last hit damage after enter wormhole
!!quasar - plasma torch from both ends
!!quasar - plasma torch from both ends of wormhole
only after wormhole eats a block fire?
or just increase plasma length after eating block?
make a text orb for JUNK text to make JUNK more clear
procedural animation
https://www.youtube.com/watch?v=qlfh_rv6khY
@@ -1274,6 +1296,7 @@ possible names for tech
active optics - something with lasers? maybe something with diffuse beam getting smaller
Quintessence - related to dark energy
biofilm - something defensive? related to spores?
Thermogalvanic - makes things cold, for no energy
******************************************************* DESIGN ******************************************************