diff --git a/js/bullets.js b/js/bullets.js index d3bfc13..efdabd6 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -14,11 +14,15 @@ const b = { modBulletsLastLonger: null, modIsImmortal: null, modSpores: null, + AoEImmunity: null, + makeDroneOnDamage: null, setModDefaults() { b.modCount = 0; b.modFireRate = 1; b.modExplosionRadius = 1; + b.AoEImmunity = false; b.modBulletSize = 1; + b.makeDroneOnDamage = false; b.modEnergySiphon = 0; b.modHealthDrain = 0; b.modNoAmmo = 0; @@ -31,7 +35,7 @@ const b = { }, mods: [{ name: "depleted uranium rounds", - description: "your bullets are larger and do more physical damage", + description: "your bullets are larger and do more physical damage", have: false, effect: () => { //good for guns that do mostly projectile damage: @@ -43,7 +47,7 @@ const b = { }, { name: "auto-loading heuristics", - description: "your rate of fire is 15% faster", + description: "your rate of fire is 15% higher", have: false, effect: () => { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls @@ -53,7 +57,7 @@ const b = { }, { name: "desublimated ammunition", - description: "use 50% less ammo when crouching", + description: "use 50% less ammo when crouching", have: false, effect: () => { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray @@ -62,7 +66,7 @@ const b = { }, { name: "corrosion resistant topology", - description: "your bullets last 40% longer", + description: "your bullets last 40% longer", have: false, effect: () => { //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range) @@ -76,12 +80,28 @@ const b = { effect: () => { //at 1.4 gives a flat 40% increase, and increased range, balanced by limited guns and self damage //testing at 1.3: grenade(+0.3), missiles, flak, M80 - b.modExplosionRadius = 1.8; //good for guns with explosions: + b.modExplosionRadius = 1.8; //good for guns with explosions } }, { - name: "energy siphon", - description: "regenerate energy proportional to your damage done", + name: "ceramic plating", + description: "you take no damage from area effects
immune to explosions and enemy fields", + have: false, + effect: () => { + b.AoEImmunity = true; //good for guns with explosions + } + }, + { + name: "ablative synthesis", + description: "your damaged parts are rebuilt as drones", + have: false, + effect: () => { + b.makeDroneOnDamage = true; //makes dangerous situations more survivable + } + }, + { + name: "field siphon", + description: "regenerate field energy proportional to your damage done", have: false, effect: () => { //good with laser, and all fields @@ -302,7 +322,7 @@ const b = { sub = Matter.Vector.sub(bullet[me].position, player.position); dist = Matter.Vector.magnitude(sub); if (dist < radius) { - mech.damage(radius * 0.0002); + if (!b.AoEImmunity) mech.damage(radius * 0.0002); knock = Matter.Vector.mult(Matter.Vector.normalise(sub), -Math.sqrt(dmg) * player.mass / 30); player.force.x += knock.x; player.force.y += knock.y; @@ -370,7 +390,7 @@ const b = { }, spore(who) { //used with the mod upgrade in mob.death() const bIndex = bullet.length; - const RADIUS = (4 + 2 * Math.random()) * b.modBulletSize; + const RADIUS = 3 * b.modBulletSize; bullet[bIndex] = Bodies.circle(who.position.x, who.position.y, RADIUS, { // density: 0.0015, //frictionAir: 0.01, inertia: Infinity, @@ -378,7 +398,7 @@ const b = { angle: Math.random() * 2 * Math.PI, friction: 0, frictionAir: 0.01, - dmg: 1.65, //damage done in addition to the damage from momentum + dmg: 1.8, //damage done in addition to the damage from momentum classType: "bullet", collisionFilter: { category: 0x000100, @@ -615,7 +635,7 @@ const b = { }, { name: "minigun", - description: "rapidly fire a stream of small bullets", + description: "rapidly fire a stream of small bullets", ammo: 0, ammoPack: 105, have: false, @@ -786,7 +806,7 @@ const b = { bullet[me].force.y += 0.00045; //a small push down at first to make it seem like the missile is briefly falling bullet[me].frictionAir = 0 bullet[me].endCycle = game.cycle + Math.floor((265 + Math.random() * 20) * b.modBulletsLastLonger); - bullet[me].explodeRad = 165 + 40 * Math.random(); + bullet[me].explodeRad = 170 + 60 * Math.random(); bullet[me].lookFrequency = Math.floor(8 + Math.random() * 7); bullet[me].onEnd = b.explode; //makes bullet do explosive damage at end bullet[me].onDmg = function () { @@ -817,7 +837,7 @@ const b = { } } //explode when bullet is close enough to target - if (this.closestTarget && closeDist < this.explodeRad * 0.7) { + if (this.closestTarget && closeDist < this.explodeRad) { this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion } @@ -944,7 +964,7 @@ const b = { }, { name: "vacuum bomb", - description: "fire a huge bomb that sucks before it explodes
click left mouse again to detonate", + description: "fire a huge bomb that sucks before it explodes
click left mouse again to detonate", ammo: 0, ammoPack: 4, have: false, @@ -1093,7 +1113,7 @@ const b = { const NUM = 9; for (let i = 0; i < NUM; i++) { const bIndex = bullet.length; - const RADIUS = (4 + 2 * Math.random()) * b.modBulletSize; + const RADIUS = 3 * b.modBulletSize; bullet[bIndex] = Bodies.circle(this.position.x, this.position.y, RADIUS, { // density: 0.0015, //frictionAir: 0.01, inertia: Infinity, @@ -1101,7 +1121,7 @@ const b = { angle: dir, friction: 0, frictionAir: 0.01, - dmg: 1.65, //damage done in addition to the damage from momentum + dmg: 1.8, //damage done in addition to the damage from momentum classType: "bullet", collisionFilter: { category: 0x000100, @@ -1157,8 +1177,8 @@ const b = { } }, { - name: "hunter drones", - description: "release drones that seek out targets
if no targets are found, drones move towards mouse
", + name: "drones", + description: "release drones that seek out targets for 16 seconds
follows mouse if no targets are found", ammo: 0, ammoPack: 20, have: false, @@ -1166,7 +1186,7 @@ const b = { const THRUST = 0.0015 const dir = mech.angle + 0.2 * (Math.random() - 0.5); const me = bullet.length; - const RADIUS = (4 + 4 * Math.random()) * b.modBulletSize + const RADIUS = (4.5 + 3 * Math.random()) * b.modBulletSize bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), RADIUS, { angle: dir, inertia: Infinity, @@ -1251,35 +1271,37 @@ const b = { } }, { - name: "defense drones", - description: "release drones that defend the space around the player", + //draw a halo, since there will only be 1-3 balls + name: "hornets", + description: "release large drones that defend the space around the player for 5 seconds", ammo: 0, - ammoPack: 3, + ammoPack: 20, have: false, fire() { - const THRUST = 0.0015 + const THRUST = 0.004 const dir = mech.angle + 0.2 * (Math.random() - 0.5); const me = bullet.length; - const RADIUS = (10 + 6 * Math.random()) * b.modBulletSize + const RADIUS = (10 + 5 * Math.random()) * b.modBulletSize bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), RADIUS, { + isOrb: true, angle: dir, inertia: Infinity, friction: 0, - frictionAir: 0.001, + frictionAir: 0.06, restitution: 1, - dmg: 0.14, //damage done in addition to the damage from momentum - lookFrequency: 27 + Math.floor(37 * Math.random()), - endCycle: game.cycle + Math.floor((2400 + 1800 * Math.random()) * b.modBulletsLastLonger), + dmg: 0, // 0.14 //damage done in addition to the damage from momentum + minDmgSpeed: 2, + lookFrequency: 37 + Math.floor(37 * Math.random()), + endCycle: game.cycle + Math.floor((300 + 140 * Math.random()) * b.modBulletsLastLonger), classType: "bullet", collisionFilter: { category: 0x000100, - mask: 0x000110 //self collide + mask: 0x010111 //self, mob,map,body collide }, - minDmgSpeed: 0, - range: 450 + 150 * Math.random(), + range: 500 + 150 * Math.random(), lockedOn: null, - isFollowMouse: true, onDmg() { + // this.endCycle = 0; this.lockedOn = null }, onEnd() {}, @@ -1290,7 +1312,7 @@ const b = { for (let i = 0, len = mob.length; i < len; ++i) { const TARGET_VECTOR = Matter.Vector.sub(mech.pos, mob[i].position) const DIST = Matter.Vector.magnitude(TARGET_VECTOR); - if (DIST < this.range && DIST < closeDist) { + if (DIST < this.range && DIST < closeDist && Matter.Query.ray(map, this.position, mob[i].position).length === 0) { closeDist = DIST; this.lockedOn = mob[i] } @@ -1300,20 +1322,23 @@ const b = { const distanceToPlayer = Matter.Vector.magnitude(Matter.Vector.sub(this.position, mech.pos)) if (this.lockedOn) { //accelerate towards mobs this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, this.lockedOn.position)), -this.mass * THRUST) + this.frictionAir = 0.06 } else if (distanceToPlayer > 0.2 * this.range) { - this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, mech.pos)), -this.mass * THRUST * 0.5) - } - - // speed cap instead of friction to give more agility - if (this.speed > 12) { - Matter.Body.setVelocity(this, { - x: this.velocity.x * 0.97, - y: this.velocity.y * 0.97 - }); + this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, mech.pos)), -this.mass * THRUST * 0.3) + this.frictionAir = 0.02 + // // speed cap instead of friction to give more agility + // if (this.speed > 14) { + // Matter.Body.setVelocity(this, { + // x: this.velocity.x * 0.97, + // y: this.velocity.y * 0.97 + // }); + // } + } else { //must be close to player //add some random motion + this.frictionAir = 0 } } }) - b.fireProps(mech.crouch ? 80 : 60, mech.crouch ? 35 : 10, dir, me); //cd , speed + b.fireProps(mech.crouch ? 40 : 10, mech.crouch ? 40 : 10, dir, me); //cd , speed b.drawOneBullet(bullet[me].vertices); } }, diff --git a/js/game.js b/js/game.js index 26288ee..108eb8d 100644 --- a/js/game.js +++ b/js/game.js @@ -304,25 +304,18 @@ const game = { } } if (keys[71]) { // give all guns with G - b.giveGuns("all", 1000) + // b.giveGuns("all", 1000) + powerUps.gun.effect() } if (keys[72]) { // power ups with H - powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "gun"); powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "gun"); powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "ammo"); powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "field"); powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "heal"); - powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "heal"); powerUps.spawn(game.mouseInGame.x, game.mouseInGame.y, "mod"); } if (keys[89]) { //add all mods with y - for (let i = 0; i < b.mods.length; i++) { - if (!b.mods[i].have) { - b.mods[i].effect() - b.mods[i].have = true - } - } - game.updateModHUD(); + powerUps.mod.effect() } if (keys[82]) { // teleport to mouse with R Matter.Body.setPosition(player, this.mouseInGame); diff --git a/js/index.js b/js/index.js index 08e703c..b935947 100644 --- a/js/index.js +++ b/js/index.js @@ -2,7 +2,17 @@ /* TODO: ******************************************* ***************************************************** -Boss level +diegetic field meter + show as the player head filling with teal color + +atmosphere levels + give the user a rest, between combat + low combat + nonaggressive mobs + one mob attacking the passive mobs + more graphics + +Boss levels boss grows and spilt, if you don't kill it fast sensor that locks you in after you enter the boss room boss that eats other mobs and gains stats from them diff --git a/js/level.js b/js/level.js index 9dbe94d..01e0875 100644 --- a/js/level.js +++ b/js/level.js @@ -14,12 +14,12 @@ const level = { if (game.levelsCleared === 0) { // game.levelsCleared = 16; //for testing to simulate possible mobs spawns // b.giveGuns("all", 1000) - b.giveGuns(13) // set a starting gun for testing - // mech.fieldUpgrades[2].effect(); //give a field power up for testing - // b.giveMod(7) + // b.giveGuns(13) // set a starting gun for testing + // mech.fieldUpgrades[6].effect(); //give a field power up for testing + b.giveMod(6) - // this.intro(); //starting level - this.testingMap(); + this.intro(); //starting level + // this.testingMap(); // this.bosses(); // this.aerie(); // this.rooftops(); diff --git a/js/mobs.js b/js/mobs.js index 268f92c..8fb7439 100644 --- a/js/mobs.js +++ b/js/mobs.js @@ -231,8 +231,10 @@ const mobs = { // ctx.lineDashOffset = 6*(game.cycle % 215); if (this.distanceToPlayer() < this.laserRange) { //if (Math.random()>0.2 && this.seePlayer.yes && this.distanceToPlayer2()<800000) { - mech.damage(0.0003 * game.dmgScale); - if (mech.fieldMeter > 0.1) mech.fieldMeter -= 0.005 + if (!b.AoEImmunity) { + mech.damage(0.0003 * game.dmgScale); + if (mech.fieldMeter > 0.1) mech.fieldMeter -= 0.005 + } ctx.beginPath(); ctx.moveTo(this.position.x, this.position.y); ctx.lineTo(mech.pos.x, mech.pos.y); diff --git a/js/player.js b/js/player.js index 5d6a59a..8968b30 100644 --- a/js/player.js +++ b/js/player.js @@ -374,9 +374,10 @@ const mech = { //find what mods I don't have let options = []; for (let i = 0; i < b.mods.length; i++) { - if (!b.mods[i].have) options.push(i); + //can't get quantum immortality again + if (i !== 7 && !b.mods[i].have) options.push(i); } - //add a new mods + //add a new mod if (options.length > 0) { const choose = Math.floor(Math.random() * options.length) let newMod = options[choose] @@ -388,7 +389,7 @@ const mech = { } function randomizeField() { - if (game.levelsCleared > 5 && Math.random() < 0.9) { + if (game.levelsCleared * (Math.random() + 0.27) > 2) { mech.fieldUpgrades[Math.floor(Math.random() * (mech.fieldUpgrades.length))].effect(); } else { mech.fieldUpgrades[0].effect(); @@ -402,7 +403,7 @@ const mech = { } function randomizeGuns() { - const length = b.inventory.length + const length = Math.round(b.inventory.length * (1 + 0.4 * (Math.random() - 0.5))) //removes guns and ammo b.inventory = []; b.activeGun = null; @@ -432,16 +433,16 @@ const mech = { randomizeGuns() randomizeField() randomizeHealth() - for (let i = 0; i < 6; i++) { + for (let i = 0, len = 7; i < len; i++) { setTimeout(function () { randomizeMods() randomizeGuns() randomizeField() randomizeHealth() game.replaceTextLog = true; - game.makeTextLog(`probability amplitude will synchronize in ${6-i} seconds`, 1000); + game.makeTextLog(`probability amplitude will synchronize in ${len-i-1} seconds`, 1000); game.wipe = function () { //set wipe to have trails - ctx.fillStyle = `rgba(255,255,255,${(i+1)*(i+1)*0.003})`; + ctx.fillStyle = `rgba(255,255,255,${(i+1)*(i+1)*0.006})`; ctx.fillRect(0, 0, canvas.width, canvas.height); } }, (i + 1) * 1000); @@ -514,13 +515,17 @@ const mech = { document.getElementById("dmg").style.transition = "opacity 0s"; document.getElementById("dmg").style.opacity = 0.1 + Math.min(0.6, dmg * 4); - //drop block if holding - if (dmg > 0.07) { - this.drop(); + //chance to build a drone on damage from mod + if (b.makeDroneOnDamage) { + const len = (dmg - 0.08 + 0.05 * Math.random()) / 0.05 + for (let i = 0; i < len; i++) { + if (Math.random() < 0.6) b.guns[12].fire() //spawn drone + } } // freeze game and display a full screen red color if (dmg > 0.05) { + this.drop(); //drop block if holding game.fpsCap = 4 //40 - Math.min(25, 100 * dmg) game.fpsInterval = 1000 / game.fpsCap; } else { @@ -540,17 +545,133 @@ const mech = { } }; requestAnimationFrame(normalFPS); + + // // freeze game and display a full screen red color + // if (dmg > 0.05) { + // if (dmg > 0.07) { + // this.drop(); //drop block if holding + // } + + // game.fpsCap = 4 //40 - Math.min(25, 100 * dmg) + // game.fpsInterval = 1000 / game.fpsCap; + // } else { + // game.fpsCap = game.fpsCapDefault + // game.fpsInterval = 1000 / game.fpsCap; + // } + // mech.defaultFPSCycle = mech.cycle + + // const normalFPS = function () { + // if (mech.defaultFPSCycle < mech.cycle) { //back to default values + // game.fpsCap = game.fpsCapDefault + // game.fpsInterval = 1000 / game.fpsCap; + // document.getElementById("dmg").style.transition = "opacity 1s"; + // document.getElementById("dmg").style.opacity = "0"; + // } else { + // requestAnimationFrame(normalFPS); + // } + // }; + // requestAnimationFrame(normalFPS); }, damageImmune: 0, hitMob(i, dmg) { //prevents damage happening too quick }, - buttonCD: 0, //cooldown for player buttons + buttonCD: 0, //cool down for player buttons usePowerUp(i) { powerUp[i].effect(); Matter.World.remove(engine.world, powerUp[i]); powerUp.splice(i, 1); }, + drawLeg(stroke) { + // if (game.mouseInGame.x > this.pos.x) { + if (mech.angle > -Math.PI / 2 && mech.angle < Math.PI / 2) { + this.flipLegs = 1; + } else { + this.flipLegs = -1; + } + ctx.save(); + ctx.scale(this.flipLegs, 1); //leg lines + ctx.beginPath(); + ctx.moveTo(this.hip.x, this.hip.y); + ctx.lineTo(this.knee.x, this.knee.y); + ctx.lineTo(this.foot.x, this.foot.y); + ctx.strokeStyle = stroke; + ctx.lineWidth = 7; + ctx.stroke(); + + //toe lines + ctx.beginPath(); + ctx.moveTo(this.foot.x, this.foot.y); + ctx.lineTo(this.foot.x - 15, this.foot.y + 5); + ctx.moveTo(this.foot.x, this.foot.y); + ctx.lineTo(this.foot.x + 15, this.foot.y + 5); + ctx.lineWidth = 4; + ctx.stroke(); + + //hip joint + ctx.beginPath(); + ctx.arc(this.hip.x, this.hip.y, 11, 0, 2 * Math.PI); + //knee joint + ctx.moveTo(this.knee.x + 7, this.knee.y); + ctx.arc(this.knee.x, this.knee.y, 7, 0, 2 * Math.PI); + //foot joint + ctx.moveTo(this.foot.x + 6, this.foot.y); + ctx.arc(this.foot.x, this.foot.y, 6, 0, 2 * Math.PI); + ctx.fillStyle = this.fillColor; + ctx.fill(); + ctx.lineWidth = 2; + ctx.stroke(); + ctx.restore(); + }, + calcLeg(cycle_offset, offset) { + this.hip.x = 12 + offset; + this.hip.y = 24 + offset; + //stepSize goes to zero if Vx is zero or not on ground (make this transition cleaner) + this.stepSize = 0.8 * this.stepSize + 0.2 * (7 * Math.sqrt(Math.min(9, Math.abs(this.Vx))) * this.onGround); + //changes to stepsize are smoothed by adding only a percent of the new value each cycle + const stepAngle = 0.034 * this.walk_cycle + cycle_offset; + this.foot.x = 2.2 * this.stepSize * Math.cos(stepAngle) + offset; + this.foot.y = offset + 1.2 * this.stepSize * Math.sin(stepAngle) + this.yOff + this.height; + const Ymax = this.yOff + this.height; + if (this.foot.y > Ymax) this.foot.y = Ymax; + + //calculate knee position as intersection of circle from hip and foot + const d = Math.sqrt((this.hip.x - this.foot.x) * (this.hip.x - this.foot.x) + (this.hip.y - this.foot.y) * (this.hip.y - this.foot.y)); + const l = (this.legLength1 * this.legLength1 - this.legLength2 * this.legLength2 + d * d) / (2 * d); + const h = Math.sqrt(this.legLength1 * this.legLength1 - l * l); + this.knee.x = (l / d) * (this.foot.x - this.hip.x) - (h / d) * (this.foot.y - this.hip.y) + this.hip.x + offset; + this.knee.y = (l / d) * (this.foot.y - this.hip.y) + (h / d) * (this.foot.x - this.hip.x) + this.hip.y; + }, + draw() { + ctx.fillStyle = this.fillColor; + this.walk_cycle += this.flipLegs * this.Vx; + + //draw body + ctx.save(); + ctx.translate(this.pos.x, this.pos.y); + this.calcLeg(Math.PI, -3); + this.drawLeg("#4a4a4a"); + this.calcLeg(0, 0); + this.drawLeg("#333"); + ctx.rotate(this.angle); + + ctx.beginPath(); + ctx.arc(0, 0, 30, 0, 2 * Math.PI); + let grd = ctx.createLinearGradient(-30, 0, 30, 0); + grd.addColorStop(0, this.fillColorDark); + grd.addColorStop(1, this.fillColor); + ctx.fillStyle = grd; + ctx.fill(); + ctx.arc(15, 0, 4, 0, 2 * Math.PI); + ctx.strokeStyle = "#333"; + ctx.lineWidth = 2; + ctx.stroke(); + // ctx.beginPath(); + // ctx.arc(15, 0, 3, 0, 2 * Math.PI); + // ctx.fillStyle = '#9cf' //'#0cf'; + // ctx.fill() + ctx.restore(); + }, // ********************************************* // **************** holding ******************** // ********************************************* @@ -1264,6 +1385,7 @@ const mech = { name: "nano-scale manufacturing", description: "excess field energy used to build drones
increased energy regeneration", effect: () => { + let gunIndex = Math.random() < 0.5 ? 13 : 12 mech.fieldMode = 5; mech.fieldText(); mech.setHoldDefaults(); @@ -1271,7 +1393,7 @@ const mech = { mech.hold = function () { if (mech.fieldMeter === 1) { mech.fieldMeter -= 0.5; - b.guns[12].fire() //spawn drone + b.guns[gunIndex].fire() //spawn drone } if (mech.isHolding) { mech.drawHold(mech.holdingTarget); @@ -1315,9 +1437,9 @@ const mech = { player.collisionFilter.mask = 0x000001 //0x010011 is normals ctx.beginPath(); - ctx.arc(mech.pos.x, mech.pos.y, mech.grabRange / (0.3 + 0.7 * mech.fieldMeter), 0, 2 * Math.PI); + ctx.arc(mech.pos.x, mech.pos.y, mech.grabRange, 0, 2 * Math.PI); ctx.globalCompositeOperation = "destination-in"; //in or atop - ctx.fillStyle = "rgba(255,255,255,0.25)"; + ctx.fillStyle = `rgba(255,255,255,${mech.fieldMeter*0.5})`; ctx.fill(); ctx.globalCompositeOperation = "source-over"; ctx.strokeStyle = "#000" @@ -1403,94 +1525,4 @@ const mech = { // } // }, ], - drawLeg(stroke) { - // if (game.mouseInGame.x > this.pos.x) { - if (mech.angle > -Math.PI / 2 && mech.angle < Math.PI / 2) { - this.flipLegs = 1; - } else { - this.flipLegs = -1; - } - ctx.save(); - ctx.scale(this.flipLegs, 1); //leg lines - ctx.beginPath(); - ctx.moveTo(this.hip.x, this.hip.y); - ctx.lineTo(this.knee.x, this.knee.y); - ctx.lineTo(this.foot.x, this.foot.y); - ctx.strokeStyle = stroke; - ctx.lineWidth = 7; - ctx.stroke(); - - //toe lines - ctx.beginPath(); - ctx.moveTo(this.foot.x, this.foot.y); - ctx.lineTo(this.foot.x - 15, this.foot.y + 5); - ctx.moveTo(this.foot.x, this.foot.y); - ctx.lineTo(this.foot.x + 15, this.foot.y + 5); - ctx.lineWidth = 4; - ctx.stroke(); - - //hip joint - ctx.beginPath(); - ctx.arc(this.hip.x, this.hip.y, 11, 0, 2 * Math.PI); - //knee joint - ctx.moveTo(this.knee.x + 7, this.knee.y); - ctx.arc(this.knee.x, this.knee.y, 7, 0, 2 * Math.PI); - //foot joint - ctx.moveTo(this.foot.x + 6, this.foot.y); - ctx.arc(this.foot.x, this.foot.y, 6, 0, 2 * Math.PI); - ctx.fillStyle = this.fillColor; - ctx.fill(); - ctx.lineWidth = 2; - ctx.stroke(); - ctx.restore(); - }, - calcLeg(cycle_offset, offset) { - this.hip.x = 12 + offset; - this.hip.y = 24 + offset; - //stepSize goes to zero if Vx is zero or not on ground (make this transition cleaner) - this.stepSize = 0.8 * this.stepSize + 0.2 * (7 * Math.sqrt(Math.min(9, Math.abs(this.Vx))) * this.onGround); - //changes to stepsize are smoothed by adding only a percent of the new value each cycle - const stepAngle = 0.034 * this.walk_cycle + cycle_offset; - this.foot.x = 2.2 * this.stepSize * Math.cos(stepAngle) + offset; - this.foot.y = offset + 1.2 * this.stepSize * Math.sin(stepAngle) + this.yOff + this.height; - const Ymax = this.yOff + this.height; - if (this.foot.y > Ymax) this.foot.y = Ymax; - - //calculate knee position as intersection of circle from hip and foot - const d = Math.sqrt((this.hip.x - this.foot.x) * (this.hip.x - this.foot.x) + (this.hip.y - this.foot.y) * (this.hip.y - this.foot.y)); - const l = (this.legLength1 * this.legLength1 - this.legLength2 * this.legLength2 + d * d) / (2 * d); - const h = Math.sqrt(this.legLength1 * this.legLength1 - l * l); - this.knee.x = (l / d) * (this.foot.x - this.hip.x) - (h / d) * (this.foot.y - this.hip.y) + this.hip.x + offset; - this.knee.y = (l / d) * (this.foot.y - this.hip.y) + (h / d) * (this.foot.x - this.hip.x) + this.hip.y; - }, - draw() { - ctx.fillStyle = this.fillColor; - this.walk_cycle += this.flipLegs * this.Vx; - - //draw body - ctx.save(); - ctx.translate(this.pos.x, this.pos.y); - this.calcLeg(Math.PI, -3); - this.drawLeg("#4a4a4a"); - this.calcLeg(0, 0); - this.drawLeg("#333"); - ctx.rotate(this.angle); - - ctx.beginPath(); - ctx.arc(0, 0, 30, 0, 2 * Math.PI); - let grd = ctx.createLinearGradient(-30, 0, 30, 0); - grd.addColorStop(0, this.fillColorDark); - grd.addColorStop(1, this.fillColor); - ctx.fillStyle = grd; - ctx.fill(); - ctx.arc(15, 0, 4, 0, 2 * Math.PI); - ctx.strokeStyle = "#333"; - ctx.lineWidth = 2; - ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(15, 0, 3, 0, 2 * Math.PI); - // ctx.fillStyle = '#9cf' //'#0cf'; - // ctx.fill() - ctx.restore(); - } }; \ No newline at end of file diff --git a/js/powerups.js b/js/powerups.js index 9a2e271..55c6118 100644 --- a/js/powerups.js +++ b/js/powerups.js @@ -44,7 +44,7 @@ const powerUps = { if (!game.lastLogTime) game.makeTextLog("+energy", 300); } else { //ammo given scales as mobs take more hits to kill - const ammo = Math.ceil((target.ammoPack * (0.5 + 0.08 * Math.random())) / b.dmgScale); + const ammo = Math.ceil((target.ammoPack * (0.55 + 0.08 * Math.random())) / b.dmgScale); target.ammo += ammo; game.updateGunHUD(); game.makeTextLog("+" + ammo + " ammo for " + target.name + "", 300); @@ -140,7 +140,7 @@ const powerUps = { powerUps.spawn(x, y, "heal"); return; } - if (Math.random() < 0.19) { + if (Math.random() < 0.2) { if (b.inventory.length > 0) powerUps.spawn(x, y, "ammo"); return; } diff --git a/js/spawn.js b/js/spawn.js index 6ab1a6e..7ab698c 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -457,8 +457,10 @@ const spawn = { this.healthBar(); //when player is inside event horizon if (Matter.Vector.magnitude(Matter.Vector.sub(this.position, player.position)) < eventHorizon) { - mech.damage(0.00015 * game.dmgScale); - if (mech.fieldMeter > 0.1) mech.fieldMeter -= 0.01 + if (!b.AoEImmunity) { + mech.damage(0.00015 * game.dmgScale); + if (mech.fieldMeter > 0.1) mech.fieldMeter -= 0.01 + } const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x); player.force.x -= 1.25 * Math.cos(angle) * player.mass * game.g * (mech.onGround ? 1.8 : 1); player.force.y -= 0.96 * player.mass * game.g * Math.sin(angle); @@ -544,8 +546,10 @@ const spawn = { ctx.fill(); //when player is inside event horizon if (Matter.Vector.magnitude(Matter.Vector.sub(this.position, player.position)) < eventHorizon) { - mech.damage(0.00015 * game.dmgScale); - if (mech.fieldMeter > 0.1) mech.fieldMeter -= 0.01 + if (!b.AoEImmunity) { + mech.damage(0.00015 * game.dmgScale); + if (mech.fieldMeter > 0.1) mech.fieldMeter -= 0.01 + } const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x); player.force.x -= 1.3 * Math.cos(angle) * player.mass * game.g * (mech.onGround ? 1.7 : 1); player.force.y -= 1.2 * Math.sin(angle) * player.mass * game.g;