mines are even more sticky, fixed quantum immortality

This commit is contained in:
landgreen
2020-01-12 11:05:47 -08:00
parent 69b7035a0b
commit c6afd8982c
5 changed files with 161 additions and 159 deletions

View File

@@ -31,7 +31,7 @@ const b = {
modNailBotCount: null, modNailBotCount: null,
modCollisionImmuneCycles: null, modCollisionImmuneCycles: null,
modBlockDmg: null, modBlockDmg: null,
modPiezo: null, isModPiezo: null,
setModDefaults() { setModDefaults() {
b.modCount = 0; b.modCount = 0;
b.modFireRate = 1; b.modFireRate = 1;
@@ -60,7 +60,7 @@ const b = {
b.modNailBotCount = 0; b.modNailBotCount = 0;
b.modCollisionImmuneCycles = 30; b.modCollisionImmuneCycles = 30;
b.modBlockDmg = 0; b.modBlockDmg = 0;
b.modPiezo = 0; b.isModPiezo = false;
mech.Fx = 0.015; mech.Fx = 0.015;
mech.jumpForce = 0.38; mech.jumpForce = 0.38;
mech.maxHealth = 1; mech.maxHealth = 1;
@@ -262,11 +262,12 @@ const b = {
}, },
{ {
name: "piezoelectricity", //17 name: "piezoelectricity", //17
description: "after <strong>colliding</strong> with enemies gain 50% <strong class='color-f'>energy</strong>", description: "<strong>colliding</strong> with enemies fills your <strong class='color-f'>energy</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { effect() {
b.modPiezo = 0.50 b.isModPiezo = true;
mech.fieldMeter = mech.fieldEnergyMax;
} }
}, },
{ {
@@ -355,6 +356,7 @@ const b = {
powerUps.spawn(mech.pos.x, mech.pos.y, "mod"); powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
} }
b.setModDefaults(); // remove all mods b.setModDefaults(); // remove all mods
//have state is checked in mech.death()
} }
}, },
{ {
@@ -714,8 +716,134 @@ const b = {
} }
} }
} }
},
mine(where, velocity, angle = 0) {
const bIndex = bullet.length;
bullet[bIndex] = Bodies.rectangle(where.x, where.y, 45 * b.modBulletSize, 16 * b.modBulletSize, {
angle: angle,
friction: 1,
frictionAir: 0,
restitution: 0,
dmg: 0, //damage done in addition to the damage from momentum
classType: "bullet",
collisionFilter: {
category: cat.bullet,
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.bullet
},
minDmgSpeed: 5,
stillCount: 0,
isArmed: false,
endCycle: game.cycle + 2000 + 360 * Math.random(),
lookFrequency: 41 + Math.floor(23 * Math.random()),
range: 700,
onDmg() {},
do() {
this.force.y += this.mass * 0.002; //extra gravity
let collide = Matter.Query.collides(this, map) //check if collides with map
if (collide.length > 0) {
for (let i = 0; i < collide.length; i++) {
if (collide[i].bodyA.collisionFilter.category === cat.map || collide[i].bodyB.collisionFilter.category === cat.map) {
// console.log(collide)
const angle = Matter.Vector.angle(collide[i].normal, {
x: 1,
y: 0
})
if (angle > -0.2 || angle < -1.5) { //don't stick to level ground
Matter.Body.setAngle(this, Math.atan2(collide[i].tangent.y, collide[i].tangent.x))
//move until touching map again after rotation
for (let j = 0; j < 10; j++) {
if (Matter.Query.collides(this, map).length > 0) {
Matter.Body.setStatic(this, true) //don't set to static if not touching map
this.arm();
// Vector.magnitudeSquared(Vector.sub(bullet[me].position, mob[i].position)) //sometimes the mine can't attach to map and it just needs to explode
const that = this
setTimeout(function () {
if (Matter.Query.collides(that, map).length === 0) {
that.endCycle = 0 // if not touching map explode
that.isArmed = false
b.mine(that.position, that.velocity, that.angle)
}
}, 100, that);
break
}
//move until you are touching the wall
Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(collide[i].normal, 2)))
}
} else if (this.speed < 1 && this.angularSpeed < 0.01 && !mech.isBodiesAsleep) {
this.stillCount += 2
}
}
}
} else {
if (this.speed < 1 && this.angularSpeed < 0.01 && !mech.isBodiesAsleep) {
this.stillCount++
}
}
if (this.stillCount > 35) this.arm();
},
arm() {
this.isArmed = true
game.drawList.push({
//add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: 10,
color: "#f00",
time: 4
});
this.do = function () { //overwrite the do method for this bullet
this.force.y += this.mass * 0.002; //extra gravity
if (!(game.cycle % this.lookFrequency)) { //find mob targets
for (let i = 0, len = mob.length; i < len; ++i) {
if (Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) < 500000 &&
mob[i].dropPowerUp &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
this.endCycle = 0 //end life if mob is near and visible
}
}
}
}
},
onEnd() {
if (this.isArmed) {
const targets = [] //target nearby mobs
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].dropPowerUp) {
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
if (dist < 1440000 && //1200*1200
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
targets.push(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60))) //predict where the mob will be in a few cycles
}
}
}
for (let i = 0; i < 16; i++) {
const speed = 53 + 10 * Math.random()
if (targets.length > 0) { // aim near a random target in array
const index = Math.floor(Math.random() * targets.length)
const SPREAD = 150 / targets.length
const WHERE = {
x: targets[index].x + SPREAD * (Math.random() - 0.5),
y: targets[index].y + SPREAD * (Math.random() - 0.5)
}
b.nail(this.position, Vector.mult(Vector.normalise(Vector.sub(WHERE, this.position)), speed), 1)
} else { // aim in random direction
const ANGLE = 2 * Math.PI * Math.random()
b.nail(this.position, {
x: speed * Math.cos(ANGLE),
y: speed * Math.sin(ANGLE)
})
}
}
}
}
});
bullet[bIndex].torque += bullet[bIndex].inertia * 0.0001 * (0.5 - Math.random())
Matter.Body.setVelocity(bullet[bIndex], velocity);
World.add(engine.world, bullet[bIndex]); //add bullet to world
}, },
spore(who) { //used with the mod upgrade in mob.death() spore(who) { //used with the mod upgrade in mob.death()
const bIndex = bullet.length; const bIndex = bullet.length;
@@ -1730,153 +1858,21 @@ const b = {
} }
}, { }, {
name: "mine", //10 name: "mine", //10
description: "drop a <strong>proximity</strong> mine that <strong>sticks</strong> to walls<br>fires <strong>nails</strong> at enemies within range", description: "toss a <strong>proximity</strong> mine that <strong>sticks</strong> to walls<br>fires <strong>nails</strong> at enemies within range",
ammo: 0, ammo: 0,
ammoPack: 4, ammoPack: 3,
have: false, have: false,
isStarterGun: false, isStarterGun: false,
fire() { fire() {
const me = bullet.length; const speed = mech.crouch ? 34 : 20
const dir = mech.angle; b.mine({
if (mech.crouch) { x: mech.pos.x + 30 * Math.cos(mech.angle),
bullet[me] = Bodies.rectangle(mech.pos.x + 35 * Math.cos(mech.angle), mech.pos.y + 35 * Math.sin(mech.angle), 45 * b.modBulletSize, 16 * b.modBulletSize, { y: mech.pos.y + 30 * Math.sin(mech.angle)
angle: 0, }, {
friction: 1, x: speed * Math.cos(mech.angle),
frictionAir: 0, y: speed * Math.sin(mech.angle)
dmg: 0, //damage done in addition to the damage from momentum })
classType: "bullet", mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 60 : 40) * b.modFireRate); // cool down
collisionFilter: {
category: cat.bullet,
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.bullet
},
minDmgSpeed: 5,
onDmg() {},
onEnd() {}
});
mech.fireCDcycle = mech.cycle + Math.floor(35 * b.modFireRate); // cool down
Matter.Body.setVelocity(bullet[me], {
x: mech.Vx / 2 + 26 * Math.cos(dir),
y: mech.Vy / 2 + 26 * Math.sin(dir)
});
bullet[me].torque += bullet[me].inertia * 0.0001 * (0.5 - Math.random())
} else {
bullet[me] = Bodies.rectangle(mech.pos.x, mech.pos.y + 25, 45 * b.modBulletSize, 16 * b.modBulletSize, {
angle: 0,
friction: 1,
frictionAir: 0,
dmg: 0, //damage done in addition to the damage from momentum
classType: "bullet",
collisionFilter: {
category: cat.bullet,
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.bullet
},
minDmgSpeed: 5,
onDmg() {},
onEnd() {}
});
mech.fireCDcycle = mech.cycle + Math.floor(20 * b.modFireRate); // cool down
Matter.Body.setVelocity(bullet[me], {
x: mech.Vx,
y: mech.Vy
});
}
World.add(engine.world, bullet[me]); //add bullet to world
bullet[me].endCycle = game.cycle + 2000 + 360 * Math.random();
bullet[me].restitution = 0;
bullet[me].lookFrequency = 41 + Math.floor(23 * Math.random())
bullet[me].range = 700
bullet[me].arm = function () {
this.do = function () { //overwrite the do method for this bullet
this.force.y += this.mass * 0.002; //extra gravity
if (!(game.cycle % this.lookFrequency)) { //find mob targets
for (let i = 0, len = mob.length; i < len; ++i) {
if (Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) < 500000 &&
mob[i].dropPowerUp &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
this.endCycle = 0 //end life if mob is near and visible
}
}
}
}
}
bullet[me].do = function () {
this.force.y += this.mass * 0.002; //extra gravity
let collide = Matter.Query.collides(this, map) //check if collides with map
if (collide.length > 0) {
for (let i = 0; i < collide.length; i++) {
if (collide[i].bodyA.collisionFilter.category === cat.map || collide[i].bodyB.collisionFilter.category === cat.map) {
// console.log(collide)
const angle = Matter.Vector.angle(collide[i].normal, {
x: 1,
y: 0
})
if (angle > -0.2 || angle < -1.5) { //don't stick to level ground
Matter.Body.setAngle(this, Math.atan2(collide[i].tangent.y, collide[i].tangent.x))
//move until touching map again after rotation
for (let j = 0; j < 10; j++) {
if (Matter.Query.collides(this, map).length > 0) {
Matter.Body.setStatic(this, true) //don't set to static if not touching map
this.arm();
//sometimes the mine can't attach to map and it just needs to explode
const who = this
setTimeout(function () {
if (Matter.Query.collides(who, map).length === 0) who.endCycle = 0 // if not touching map explode
}, 100, who);
break
}
//move until you are touching the wall
Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(collide[i].normal, 2)))
}
} else if (this.speed < 1) {
this.arm();
}
}
}
} else if (this.speed < 1) { //check if collides with a body
collide = Matter.Query.collides(this, body)
if (collide.length > 0) {
for (let i = 0; i < collide.length; i++) {
if (collide[i].bodyA.collisionFilter.category === cat.body || collide[i].bodyB.collisionFilter.category === cat.body) {
this.arm();
}
}
}
}
}
bullet[me].onEnd = function () {
const targets = [] //target nearby mobs
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].dropPowerUp) {
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
if (dist < 1440000 && //1200*1200
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
targets.push(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60))) //predict where the mob will be in a few cycles
}
}
}
for (let i = 0; i < 16; i++) {
const speed = 53 + 10 * Math.random()
if (targets.length > 0) { // aim near a random target in array
const index = Math.floor(Math.random() * targets.length)
const SPREAD = 150 / targets.length
const WHERE = {
x: targets[index].x + SPREAD * (Math.random() - 0.5),
y: targets[index].y + SPREAD * (Math.random() - 0.5)
}
b.nail(this.position, Vector.mult(Vector.normalise(Vector.sub(WHERE, this.position)), speed), 0.8)
} else { // aim in random direction
const ANGLE = 2 * Math.PI * Math.random()
b.nail(this.position, {
x: speed * Math.cos(ANGLE),
y: speed * Math.sin(ANGLE)
})
}
}
}
} }
}, },
{ {

View File

@@ -138,7 +138,7 @@ function collisionChecks(event) {
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
mech.damage(dmg); mech.damage(dmg);
if (mob[k].onHit) mob[k].onHit(k); if (mob[k].onHit) mob[k].onHit(k);
mech.fieldMeter += b.modPiezo if (b.isModPiezo) mech.fieldMeter = mech.fieldEnergyMax;
if (b.isModAnnihilation && mob[k].dropPowerUp && !mob[k].isShielded) { if (b.isModAnnihilation && mob[k].dropPowerUp && !mob[k].isShielded) {
mob[k].death(); mob[k].death();
game.drawList.push({ game.drawList.push({

View File

@@ -4,13 +4,6 @@
add setting for random drops instead of choosing add setting for random drops instead of choosing
mines: move targeting position to be perpendicular to stuck wall
mines change shape of mine (maybe a octagon?)
mines: collide with bots
probably don't have to fix...
mines: add high friction, like vacuum bomb and trigger static mode after not moving for a bit
no need to watch collisions
rework custom mode rework custom mode
custom mode grey out mods that are bad, like selection based mods custom mode grey out mods that are bad, like selection based mods
enable recursive mods enable recursive mods

View File

@@ -14,7 +14,7 @@ const level = {
start() { start() {
if (level.levelsCleared === 0) { if (level.levelsCleared === 0) {
// game.difficulty = 6; //for testing to simulate possible mobs spawns // game.difficulty = 6; //for testing to simulate possible mobs spawns
b.giveGuns(10) // b.giveGuns(10)
// mech.setField(3) // mech.setField(3)
// b.giveMod(3); // b.giveMod(3);
@@ -1569,7 +1569,17 @@ const level = {
} }
}, },
levelAnnounce() { levelAnnounce() {
document.title = "n-gon: L" + (level.levelsCleared) + " " + level.levels[level.onLevel]; let mode = document.getElementById("difficulty-select").value
if (mode === "0") {
mode = "(easy)"
} else if (mode === "1") {
mode = "(normal)"
} else if (mode === "2") {
mode = "(hard)"
} else if (mode === "6") {
mode = "(why)"
}
document.title = "n-gon: L" + (level.levelsCleared) + " " + level.levels[level.onLevel] + " " + mode;
// game.makeTextLog(`<div style='font-size: 25px;'>level ${game.difficulty} </div> <div style='font-size: 32px;'>${level.levels[level.onLevel]} </div>`, 300); // game.makeTextLog(`<div style='font-size: 25px;'>level ${game.difficulty} </div> <div style='font-size: 32px;'>${level.levels[level.onLevel]} </div>`, 300);
// if (game.difficulty === 0) text = ""; // if (game.difficulty === 0) text = "";
// text = "Level " + (game.difficulty + 1) + ": " + spawn.pickList[0] + "s + " + spawn.pickList[1] + "s"; // text = "Level " + (game.difficulty + 1) + ": " + spawn.pickList[0] + "s + " + spawn.pickList[1] + "s";

View File

@@ -307,13 +307,16 @@ const mech = {
function randomizeMods() { function randomizeMods() {
b.setModDefaults(); //remove all mods b.setModDefaults(); //remove all mods
//remove all bullets
for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]);
bullet = [];
for (let i = 0; i < totalMods; i++) { for (let i = 0; i < totalMods; i++) {
//find what mods I don't have //find what mods I don't have
let options = []; let options = [];
for (let i = 0, len = b.mods.length; i < len; i++) { for (let i = 0, len = b.mods.length; i < len; i++) {
//can't get quantum immortality or multiverse //can't get quantum immortality or multiverse
if (b.mods[i].name !== "quantum immortality" && if (b.mods[i].name !== "quantum immortality" &&
b.mods[i].name !== "level II multiverse" && b.mods[i].name !== "Born rule" &&
b.mods[i].count < b.mods[i].maxCount) options.push(i); b.mods[i].count < b.mods[i].maxCount) options.push(i);
} }
//add a new mod //add a new mod