diff --git a/js/bullets.js b/js/bullets.js index 4059719..6184ae3 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -111,7 +111,7 @@ const b = { }, { name: "kinetic bombardment", //3 - description: "do up to 33% more damage at a distance
increase starts at about 6 steps away", + description: "do up to 33% more damage at a distance
increase maxes out at about 40 steps away", maxCount: 1, count: 0, effect() { @@ -139,11 +139,11 @@ const b = { }, { name: "auto-loading heuristics", //5 - description: "your delay after firing is +12% shorter", - maxCount: 5, + description: "your delay after firing is +14% shorter", + maxCount: 3, count: 0, effect() { - b.modFireRate *= 0.88 + b.modFireRate *= 0.86 } }, { @@ -239,11 +239,11 @@ const b = { }, { name: "Pauli exclusion", //12 - description: "unable to collide with enemies for +1 second
activates after being harmed from a collision", + description: "unable to collide with enemies for +2 second
activates after being harmed from a collision", maxCount: 9, count: 0, effect() { - b.modCollisionImmuneCycles += 60; + b.modCollisionImmuneCycles += 120; mech.collisionImmune = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles } }, @@ -307,7 +307,7 @@ const b = { }, { name: "recursive healing", //22 - description: "healing power ups trigger an extra time.", + description: "healing power ups trigger one extra time.", maxCount: 9, count: 0, effect() { @@ -1191,7 +1191,7 @@ const b = { name: "super balls", //2 description: "fire five balls in a wide arc
balls bounce with no momentum loss", ammo: 0, - ammoPack: 5, + ammoPack: 6, have: false, isStarterGun: true, fire() { @@ -1317,7 +1317,7 @@ const b = { name: "missiles", //5 description: "fire missiles that accelerate towards enemies
explodes when near target", ammo: 0, - ammoPack: 3, + ammoPack: 4, have: false, isStarterGun: false, fireCycle: 0, @@ -1327,7 +1327,7 @@ const b = { const me = bullet.length; bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle) - 3, 30 * b.modBulletSize, 4 * b.modBulletSize, b.fireAttributes(dir)); const thrust = 0.00417 * bullet[me].mass; - b.fireProps(mech.crouch ? 55 : 30, -3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8), dir, me); //cd , speed + b.fireProps(mech.crouch ? 50 : 25, -3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8), dir, me); //cd , speed // bullet[me].collisionFilter.mask = cat.map | cat.body | cat.mobBullet // Matter.Body.setDensity(bullet[me], 0.01) //doesn't help with reducing explosion knock backs bullet[me].force.y += 0.0005; //a small push down at first to make it seem like the missile is briefly falling @@ -1458,7 +1458,7 @@ const b = { name: "grenades", //7 description: "lob a single bouncy projectile
explodes on contact or after one second", ammo: 0, - ammoPack: 6, + ammoPack: 7, have: false, isStarterGun: false, fire() { @@ -1500,7 +1500,7 @@ const b = { bullet[me].restitution = 0.2; bullet[me].friction = 0.3; bullet[me].endCycle = Infinity - bullet[me].explodeRad = 380 + Math.floor(Math.random() * 60); + bullet[me].explodeRad = 400 + Math.floor(Math.random() * 60); bullet[me].onEnd = function () { b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end } @@ -1844,10 +1844,10 @@ const b = { } else if (mech.fieldMeter > 0.005) { // charging on mouse down mech.fireCDcycle = Infinity //can't fire until mouse is released const lastCharge = this.charge - let chargeRate = (mech.crouch) ? 0.965 : 0.985 + let chargeRate = (mech.crouch) ? 0.975 : 0.987 chargeRate *= Math.pow(b.modFireRate, 0.04) this.charge = this.charge * chargeRate + (1 - chargeRate) // this.charge converges to 1 - mech.fieldMeter -= (this.charge - lastCharge) * 0.25 //energy drain is proportional to charge gained, but doesn't stop normal mech.fieldRegen + mech.fieldMeter -= (this.charge - lastCharge) * 0.28 //energy drain is proportional to charge gained, but doesn't stop normal mech.fieldRegen //draw laser targeting let best; @@ -1970,7 +1970,7 @@ const b = { have: false, isStarterGun: true, fire() { - const FIELD_DRAIN = 0.002 //laser drains energy as well as bullets + const FIELD_DRAIN = 0.0018 //laser drains energy as well as bullets const damage = 0.05 if (mech.fieldMeter < FIELD_DRAIN) { mech.fireCDcycle = mech.cycle + 100; // cool down if out of energy @@ -2217,7 +2217,7 @@ const b = { //use energy to explode const energy = 0.3 * Math.min(mech.fieldMeter, 1.75) mech.fieldMeter -= energy - if (best.who) b.explosion(path[1], 950 * energy) + if (best.who) b.explosion(path[1], 1000 * energy) mech.fireCDcycle = mech.cycle + Math.floor(60 * b.modFireRate); // cool down //draw laser beam diff --git a/js/game.js b/js/game.js index 0e9c923..cb194f7 100644 --- a/js/game.js +++ b/js/game.js @@ -180,7 +180,7 @@ const game = { replaceTextLog: true, // - SVGleftMouse: ' ', + SVGleftMouse: ' ', SVGrightMouse: ' ', makeTextLog(text, time = 180) { if (game.replaceTextLog) { diff --git a/js/index.js b/js/index.js index de2bb33..59d02f4 100644 --- a/js/index.js +++ b/js/index.js @@ -2,6 +2,11 @@ /* TODO: ******************************************* ***************************************************** +gun/field: portals + use the code from mines to get them to stick to walls + or lasers + alternate red and blue portals + missiles don't explode reliably enough they can bounce, which is cool, but they should still explode right after a bounce @@ -249,7 +254,14 @@ const build = { }, pauseGrid() { // let text = `
` - let text = `
PAUSED               Press P to unpause
`; + let text = ` +
+ PAUSED               press P to resume +
`; + //
+ // ${game.SVGleftMouse} fire gun + // ${game.SVGrightMouse} use field + //
let countGuns = 0 let countMods = 0 for (let i = 0, len = b.guns.length; i < len; i++) { diff --git a/js/level.js b/js/level.js index 2ecc03c..b734d44 100644 --- a/js/level.js +++ b/js/level.js @@ -74,7 +74,7 @@ const level = { //****************************************************************************************************************** testingMap() { //start with all guns - level.difficultyIncrease(9) //level 7 on normal, level 4 on hard, level 1.2 on why? + // level.difficultyIncrease(9) //level 7 on normal, level 4 on hard, level 1.2 on why? game.zoomScale = 1700 //1400 is normal spawn.setSpawnList(); mech.setPosToSpawn(-75, -60); //normal spawn @@ -126,8 +126,9 @@ const level = { // powerUps.spawn(450, -400, "mod", false); // spawn.bodyRect(-45, -100, 40, 50); // spawn.bomber(800, -450); - spawn.hopper(400, -1050); - // spawn.starter(1200, -1050); + spawn.laserBoss(400, -750); + // spawn.laser(400, -550); + spawn.starter(1200, -1050); // spawn.nodeBoss(-600, -550, "starter"); // spawn.starter(800, -150); // spawn.beamer(800, -150); diff --git a/js/mobs.js b/js/mobs.js index ffcbcad..5e0d2e4 100644 --- a/js/mobs.js +++ b/js/mobs.js @@ -359,7 +359,7 @@ const mobs = { dmg = 0.002 * game.dmgScale; mech.damage(dmg); //draw damage - ctx.fillStyle = color; + ctx.fillStyle = "#f00"; ctx.beginPath(); ctx.arc(best.x, best.y, dmg * 2000, 0, 2 * Math.PI); ctx.fill(); diff --git a/js/player.js b/js/player.js index 4a982f4..080bdc7 100644 --- a/js/player.js +++ b/js/player.js @@ -865,39 +865,27 @@ const mech = { const dyP = mech.pos.y - powerUp[i].position.y; const dist2 = dxP * dxP + dyP * dyP; // float towards player if looking at and in range or if very close to player - if (dist2 < grabPowerUpRange2 && (mech.lookingAt(powerUp[i]) || dist2 < 16000)) { - // mech.fieldMeter -= mech.fieldRegen * 0.5; - if (mech.health === mech.maxHealth && powerUp[i].name === "heal" && dist2 < 16000) { - mech.fieldCDcycle = mech.cycle + 30; - //push away - Matter.Body.setVelocity(powerUp[i], { - x: powerUp[i].velocity.x * 0, - y: powerUp[i].velocity.y * 0 - }); - powerUp[i].force.x -= 0.0005 * dxP * powerUp[i].mass; - powerUp[i].force.y -= 0.0005 * dyP * powerUp[i].mass; - } else { - powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass; - powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity - //extra friction - Matter.Body.setVelocity(powerUp[i], { - x: powerUp[i].velocity.x * 0.11, - y: powerUp[i].velocity.y * 0.11 - }); - if (dist2 < 5000) { //use power up if it is close enough - if (b.isModMassEnergy) { - mech.fieldMeter = mech.fieldEnergyMax; - mech.addHealth(0.05); - } - Matter.Body.setVelocity(player, { //player knock back, after grabbing power up - x: player.velocity.x + ((powerUp[i].velocity.x * powerUp[i].mass) / player.mass) * 0.3, - y: player.velocity.y + ((powerUp[i].velocity.y * powerUp[i].mass) / player.mass) * 0.3 - }); - powerUp[i].effect(); - Matter.World.remove(engine.world, powerUp[i]); - powerUp.splice(i, 1); - return; //because the array order is messed up after splice + if (dist2 < grabPowerUpRange2 && (mech.lookingAt(powerUp[i]) || dist2 < 16000) && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) { + powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass; + powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity + //extra friction + Matter.Body.setVelocity(powerUp[i], { + x: powerUp[i].velocity.x * 0.11, + y: powerUp[i].velocity.y * 0.11 + }); + if (dist2 < 5000) { //use power up if it is close enough + if (b.isModMassEnergy) { + mech.fieldMeter = mech.fieldEnergyMax; + mech.addHealth(0.05); } + Matter.Body.setVelocity(player, { //player knock back, after grabbing power up + x: player.velocity.x + ((powerUp[i].velocity.x * powerUp[i].mass) / player.mass) * 0.3, + y: player.velocity.y + ((powerUp[i].velocity.y * powerUp[i].mass) / player.mass) * 0.3 + }); + powerUp[i].effect(); + Matter.World.remove(engine.world, powerUp[i]); + powerUp.splice(i, 1); + return; //because the array order is messed up after splice } } } diff --git a/js/powerups.js b/js/powerups.js index 1022b2d..dfaf450 100644 --- a/js/powerups.js +++ b/js/powerups.js @@ -4,19 +4,19 @@ const powerUps = { choose(type, index) { if (type === "gun") { b.giveGuns(index) - game.replaceTextLog = true; - game.makeTextLog(`${game.SVGleftMouse} ${b.guns[index].name}

${b.guns[index].description}`, 500); - game.replaceTextLog = false; + // game.replaceTextLog = true; + // game.makeTextLog(`${game.SVGleftMouse} ${b.guns[index].name}

${b.guns[index].description}`, 500); + // game.replaceTextLog = false; } else if (type === "field") { mech.setField(index) - game.replaceTextLog = true; - game.makeTextLog(`${game.SVGrightMouse} ${mech.fieldUpgrades[mech.fieldMode].name}

${mech.fieldUpgrades[mech.fieldMode].description}`, 600); - game.replaceTextLog = false; + // game.replaceTextLog = true; + // game.makeTextLog(`${game.SVGrightMouse} ${mech.fieldUpgrades[mech.fieldMode].name}

${mech.fieldUpgrades[mech.fieldMode].description}`, 600); + // game.replaceTextLog = false; } else if (type === "mod") { b.giveMod(index) - game.replaceTextLog = true; - game.makeTextLog(`
  ${b.mods[index].name}

${b.mods[index].description}`, 500); - game.replaceTextLog = false; + // game.replaceTextLog = true; + // game.makeTextLog(`
  ${b.mods[index].name}

${b.mods[index].description}`, 500); + // game.replaceTextLog = false; } document.body.style.cursor = "none"; document.getElementById("choose-grid").style.display = "none" @@ -139,7 +139,12 @@ const powerUps = { function doNotHave(who, skip1 = -1, skip2 = -1, skip3 = -1) { let options = []; for (let i = 0; i < who.length; i++) { - if (who[i].count < who[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3) options.push(i); + if (who[i].count < who[i].maxCount && + i !== skip1 && i !== skip2 && i !== skip3 && + (b.modCount > 4 || who[i].name !== "Born rule") + ) { + options.push(i); + } } if (options.length > 0) return options[Math.floor(Math.random() * options.length)] } diff --git a/js/spawn.js b/js/spawn.js index 4c89d2c..da2ca39 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -650,7 +650,6 @@ const spawn = { } }, laser(x, y, radius = 30) { - //only on level 1 mobs.spawn(x, y, 3, radius, "#f00"); let me = mob[mob.length - 1]; me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front @@ -666,6 +665,128 @@ const spawn = { this.laser(); }; }, + laserBoss(x, y, radius = 130) { + mobs.spawn(x, y, 3, radius, "#f00"); + let me = mob[mob.length - 1]; + me.startingPosition = { + x: x, + y: y + } + // me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front + // Matter.Body.rotate(me, Math.random() * Math.PI * 2); + Matter.Body.setDensity(me, 0.004 + 0.001 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger + // spawn.shield(me, x, y, 1); + me.onDeath = function () { + powerUps.spawnBossPowerUp(this.position.x, this.position.y) + }; + me.laser = function (where, angle) { + const vertexCollision = function (v1, v1End, domain) { + for (let i = 0; i < domain.length; ++i) { + let vertices = domain[i].vertices; + const len = vertices.length - 1; + for (let j = 0; j < len; j++) { + results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]); + if (results.onLine1 && results.onLine2) { + const dx = v1.x - results.x; + const dy = v1.y - results.y; + const dist2 = dx * dx + dy * dy; + if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { + x: results.x, + y: results.y, + dist2: dist2, + who: domain[i], + v1: vertices[j], + v2: vertices[j + 1] + }; + } + } + results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]); + if (results.onLine1 && results.onLine2) { + const dx = v1.x - results.x; + const dy = v1.y - results.y; + const dist2 = dx * dx + dy * dy; + if (dist2 < best.dist2) best = { + x: results.x, + y: results.y, + dist2: dist2, + who: domain[i], + v1: vertices[0], + v2: vertices[len] + }; + } + } + }; + + const seeRange = 4000; + best = { + x: null, + y: null, + dist2: Infinity, + who: null, + v1: null, + v2: null + }; + const look = { + x: where.x + seeRange * Math.cos(angle), + y: where.y + seeRange * Math.sin(angle) + }; + vertexCollision(where, look, mob); + vertexCollision(where, look, map); + vertexCollision(where, look, body); + if (!mech.isStealth) vertexCollision(where, look, [player]); + //hitting mob + if (best.who) { + if (best.who.mob) { + // dmg = 0.03 * game.dmgScale; + best.who.damage(0.1); + //draw damage + game.drawList.push({ //add dmg to draw queue + x: best.x, + y: best.y, + radius: Math.sqrt(dmg) * 50, + color: game.playerDmgColor, + time: game.drawTime + }); + } + // hitting player + if (best.who === player) { + dmg = 0.03 * game.dmgScale; + mech.damage(dmg); + //draw damage + game.drawList.push({ //add dmg to draw queue + x: best.x, + y: best.y, + radius: dmg * 2000, + color: game.mobDmgColor, + time: game.drawTime + }); + } + } + //draw beam + if (best.dist2 === Infinity) best = look; + ctx.moveTo(where.x, where.y); + ctx.lineTo(best.x, best.y); + } + me.do = function () { + this.torque = this.lookTorque * this.inertia * 0.2; + Matter.Body.setVelocity(this, { + x: 0, + y: 0 + }); + Matter.Body.setPosition(this, this.startingPosition); + + ctx.beginPath(); + this.laser(this.vertices[0], this.angle + Math.PI / 3); + this.laser(this.vertices[1], this.angle + Math.PI); + this.laser(this.vertices[2], this.angle - Math.PI / 3); + ctx.strokeStyle = "#f00"; // Purple path + ctx.lineWidth = 3; + ctx.setLineDash([50 + 120 * Math.random(), 55 * Math.random()]); + ctx.stroke(); // Draw it + ctx.setLineDash([0, 0]); + // this.laser(this.vertices[2], this.angle + Math.PI / 3); + }; + }, striker(x, y, radius = 14 + Math.ceil(Math.random() * 25)) { mobs.spawn(x, y, 5, radius, "rgb(221,102,119)"); let me = mob[mob.length - 1];