JUNK percents
JUNK tech: facsimile - copy current level and insert into level queue JUNK tech: planetesimals - spawn a tech, and play planetesimals, an annoying asteroids like game with realistic physics tech that previously added 1 junk tech now adds 1% (of current non-JUNK tech options) the percent values may seem like more but I actually lowered the JUNK chance about 10% meta-analysis no longer requires replication - (if you choose a JUNK tech get a random tech and 3 research) symbiosis: only gives 1 bonus tech (was 1 or 2) blink boss rebalanced (it's easier, and has two modes) bug fixes
This commit is contained in:
@@ -580,6 +580,10 @@
|
|||||||
<script src="js/lore.js"></script>
|
<script src="js/lore.js"></script>
|
||||||
<script src="js/engine.js"></script>
|
<script src="js/engine.js"></script>
|
||||||
<script src="js/index.js"></script>
|
<script src="js/index.js"></script>
|
||||||
|
|
||||||
|
<!-- code for different game: planetesimals -->
|
||||||
|
<!-- <div id='hud'></div>
|
||||||
|
<script src="js/planetesimals.js"></script> -->
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
18
js/bullet.js
18
js/bullet.js
@@ -1231,7 +1231,7 @@ const b = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (m.energy > 0.005) m.energy -= 0.005
|
if (m.energy > 0.005 && !m.isBodiesAsleep) m.energy -= 0.005
|
||||||
const sub = Vector.sub(this.position, m.pos)
|
const sub = Vector.sub(this.position, m.pos)
|
||||||
const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player
|
const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player
|
||||||
const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * this.thrustMag * this.mass)
|
const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * this.thrustMag * this.mass)
|
||||||
@@ -1478,7 +1478,6 @@ const b = {
|
|||||||
y: Math.sin(this.angle)
|
y: Math.sin(this.angle)
|
||||||
};
|
};
|
||||||
const target = Vector.normalise(Vector.sub(this.position, this.lockedOn.position));
|
const target = Vector.normalise(Vector.sub(this.position, this.lockedOn.position));
|
||||||
// const target = Vector.normalise(Vector.sub(this.position, this.lockedOn.position));
|
|
||||||
const dot = Vector.dot(target, face)
|
const dot = Vector.dot(target, face)
|
||||||
const aim = Math.min(0.08, (1 + dot) * 1)
|
const aim = Math.min(0.08, (1 + dot) * 1)
|
||||||
if (Vector.cross(target, face) > 0) {
|
if (Vector.cross(target, face) > 0) {
|
||||||
@@ -1486,7 +1485,7 @@ const b = {
|
|||||||
} else {
|
} else {
|
||||||
Matter.Body.rotate(this, -aim);
|
Matter.Body.rotate(this, -aim);
|
||||||
}
|
}
|
||||||
this.frictionAir = Math.min(0.1, Math.max(0.04, (1 + dot) * 1)) //0.08; //extra friction if turning
|
this.frictionAir = Math.min(0.1, Math.max(0.04, 1 + dot)) //0.08; //extra friction if turning
|
||||||
}
|
}
|
||||||
//accelerate in direction bullet is facing
|
//accelerate in direction bullet is facing
|
||||||
const dir = this.angle;
|
const dir = this.angle;
|
||||||
@@ -4073,7 +4072,7 @@ const b = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Math.abs(player.velocity.x) < 12) player.force.x -= 0.025 * Math.cos(m.angle)
|
player.force.x -= 0.06 * Math.cos(m.angle) * Math.min(1, 3 / (0.1 + Math.abs(player.velocity.x)))
|
||||||
player.force.y -= 0.006 * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
|
player.force.y -= 0.006 * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -4239,7 +4238,9 @@ const b = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Math.abs(player.velocity.x) < 12) player.force.x -= 0.06 * Math.cos(m.angle)
|
player.force.x -= 0.2 * Math.cos(m.angle) * Math.min(1, 3 / (0.1 + Math.abs(player.velocity.x)))
|
||||||
|
// player.force.x -= 0.06 * Math.cos(m.angle) * Math.min(1, 3 / (0.1 + Math.abs(player.velocity.x)))
|
||||||
|
|
||||||
player.force.y -= 0.02 * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
|
player.force.y -= 0.02 * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -5333,7 +5334,6 @@ const b = {
|
|||||||
m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
|
m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
|
||||||
// }
|
// }
|
||||||
} else if (tech.extraHarpoons) {
|
} else if (tech.extraHarpoons) {
|
||||||
const harpoons = tech.extraHarpoons + 1
|
|
||||||
const range = 450 * (tech.isFilament ? 1 + 0.005 * Math.min(110, this.ammo) : 1)
|
const range = 450 * (tech.isFilament ? 1 + 0.005 * Math.min(110, this.ammo) : 1)
|
||||||
let targetCount = 0
|
let targetCount = 0
|
||||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||||
@@ -5345,15 +5345,15 @@ const b = {
|
|||||||
this.ammo--
|
this.ammo--
|
||||||
b.harpoon(where, mob[i], m.angle, length, true, totalCycles) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 })
|
b.harpoon(where, mob[i], m.angle, length, true, totalCycles) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 })
|
||||||
targetCount++
|
targetCount++
|
||||||
if (targetCount > harpoons) break
|
if (targetCount > tech.extraHarpoons) break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if more harpoons and no targets left
|
//if more harpoons and no targets left
|
||||||
if (targetCount < harpoons) {
|
if (targetCount < tech.extraHarpoons + 1) {
|
||||||
const SPREAD = 0.1
|
const SPREAD = 0.1
|
||||||
const num = harpoons - targetCount
|
const num = tech.extraHarpoons + 1 - targetCount
|
||||||
let dir = m.angle - SPREAD * (num - 1) / 2;
|
let dir = m.angle - SPREAD * (num - 1) / 2;
|
||||||
for (let i = 0; i < num; i++) {
|
for (let i = 0; i < num; i++) {
|
||||||
if (this.ammo > 0) {
|
if (this.ammo > 0) {
|
||||||
|
|||||||
13
js/level.js
13
js/level.js
@@ -22,7 +22,7 @@ const level = {
|
|||||||
// tech.giveTech("rivet gun")
|
// tech.giveTech("rivet gun")
|
||||||
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
|
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
|
||||||
// tech.giveTech("all-stars")
|
// tech.giveTech("all-stars")
|
||||||
// for (let i = 0; i < 9; i++) tech.giveTech("reticulum")
|
// for (let i = 0; i < 1; i++) tech.giveTech("reticulum")
|
||||||
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
|
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
|
||||||
// tech.isCancelDuplication = true
|
// tech.isCancelDuplication = true
|
||||||
|
|
||||||
@@ -2316,7 +2316,7 @@ const level = {
|
|||||||
// spawn.laserBombingBoss(1900, -500)
|
// spawn.laserBombingBoss(1900, -500)
|
||||||
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
|
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
|
||||||
// spawn.slashBoss(1900, -500)
|
// spawn.slashBoss(1900, -500)
|
||||||
spawn.sucker(1900, -500)
|
// spawn.sucker(1900, -500)
|
||||||
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
|
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
|
||||||
// mob[mob.length - 1].isShielded = true
|
// mob[mob.length - 1].isShielded = true
|
||||||
// spawn.growBossCulture(1200, -500)
|
// spawn.growBossCulture(1200, -500)
|
||||||
@@ -2332,7 +2332,7 @@ const level = {
|
|||||||
// spawn.nodeGroup(1200, -500, "grenadier")
|
// spawn.nodeGroup(1200, -500, "grenadier")
|
||||||
// spawn.nodeGroup(1800, -500, "grenadier")
|
// spawn.nodeGroup(1800, -500, "grenadier")
|
||||||
// spawn.nodeGroup(1200, 0, "grenadier")
|
// spawn.nodeGroup(1200, 0, "grenadier")
|
||||||
// spawn.snakeBoss(1200, -500)
|
spawn.blinkBoss(1200, -500)
|
||||||
// spawn.suckerBoss(2900, -500)
|
// spawn.suckerBoss(2900, -500)
|
||||||
// spawn.randomMob(1600, -500)
|
// spawn.randomMob(1600, -500)
|
||||||
},
|
},
|
||||||
@@ -2931,12 +2931,7 @@ const level = {
|
|||||||
spawn.randomMob(-75, -1475, 0);
|
spawn.randomMob(-75, -1475, 0);
|
||||||
spawn.randomGroup(600, -2600, 0);
|
spawn.randomGroup(600, -2600, 0);
|
||||||
}
|
}
|
||||||
if (simulation.difficulty < 10) {
|
if (simulation.difficulty < 1) {
|
||||||
spawn.randomMob(700, -1650, 0);
|
|
||||||
spawn.randomMob(600, -3500, 0.2);
|
|
||||||
spawn.randomMob(-75, -1175, 0.2);
|
|
||||||
powerUps.spawnBossPowerUp(-125, -1760);
|
|
||||||
} else {
|
|
||||||
if (Math.random() < 0.5) {
|
if (Math.random() < 0.5) {
|
||||||
spawn.randomLevelBoss(700, -1550);
|
spawn.randomLevelBoss(700, -1550);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1140,7 +1140,7 @@ const mobs = {
|
|||||||
if (tech.isAddRemoveMaxHealth) {
|
if (tech.isAddRemoveMaxHealth) {
|
||||||
if (this.isBoss && this.isDropPowerUp) {
|
if (this.isBoss && this.isDropPowerUp) {
|
||||||
powerUps.spawn(this.position.x, this.position.y, "tech", false)
|
powerUps.spawn(this.position.x, this.position.y, "tech", false)
|
||||||
if (0.5 < Math.random()) powerUps.spawn(this.position.x, this.position.y, "tech", false)
|
// if (0.5 < Math.random()) powerUps.spawn(this.position.x, this.position.y, "tech", false)
|
||||||
} else {
|
} else {
|
||||||
const amount = 0.01
|
const amount = 0.01
|
||||||
if (tech.isEnergyHealth) {
|
if (tech.isEnergyHealth) {
|
||||||
|
|||||||
807
js/planetesimals.js
Normal file
807
js/planetesimals.js
Normal file
@@ -0,0 +1,807 @@
|
|||||||
|
/* http://brm.io/matter-js/docs/
|
||||||
|
http://brm.io/matter-js/demo/#mixed
|
||||||
|
https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js
|
||||||
|
|
||||||
|
git hub gist:
|
||||||
|
https://gist.github.com/lilgreenland/8f2a2c033fdf3d5546a0ca5d73a2ae11
|
||||||
|
|
||||||
|
todo:
|
||||||
|
can you render bullets a different color? // red?
|
||||||
|
|
||||||
|
maybe add the ability to put up shields to survive collisions?
|
||||||
|
maybe add durability regeneration
|
||||||
|
|
||||||
|
fix new mass spawn so that it will pick a new location if the first spawn location already has a mass
|
||||||
|
|
||||||
|
*/
|
||||||
|
function planetesimals() {
|
||||||
|
|
||||||
|
//pause n-gon
|
||||||
|
// if (!simulation.isChoosing && input.isPauseKeyReady && m.alive) {
|
||||||
|
// input.isPauseKeyReady = false
|
||||||
|
// setTimeout(function() {
|
||||||
|
// input.isPauseKeyReady = true
|
||||||
|
// }, 300);
|
||||||
|
// if (simulation.paused) {
|
||||||
|
// build.unPauseGrid()
|
||||||
|
// simulation.paused = false;
|
||||||
|
// // level.levelAnnounce();
|
||||||
|
// document.body.style.cursor = "none";
|
||||||
|
// requestAnimationFrame(cycle);
|
||||||
|
// } else {
|
||||||
|
// simulation.paused = true;
|
||||||
|
// build.pauseGrid()
|
||||||
|
// document.body.style.cursor = "auto";
|
||||||
|
|
||||||
|
// if (tech.isGunSwitchField || simulation.testing) {
|
||||||
|
// document.getElementById("pause-field").addEventListener("click", () => {
|
||||||
|
// const energy = m.energy
|
||||||
|
// m.setField((m.fieldMode === m.fieldUpgrades.length - 1) ? 1 : m.fieldMode + 1) //cycle to next field
|
||||||
|
// m.energy = energy
|
||||||
|
// document.getElementById("pause-field").innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> ${m.fieldUpgrades[m.fieldMode].name}</div> ${m.fieldUpgrades[m.fieldMode].description}`
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
"use strict"; //strict mode to catch errors
|
||||||
|
//game objects values
|
||||||
|
var game = {
|
||||||
|
cycle: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
scale: 0.5,
|
||||||
|
gravity: 0.00011,
|
||||||
|
totalMass: 0,
|
||||||
|
massSize: 0,
|
||||||
|
level: 1,
|
||||||
|
startingMassValue: 0,
|
||||||
|
massSegment: 0,
|
||||||
|
clearThreshold: 0.2, // there must be less than this percent to move on to the next level
|
||||||
|
currentMass: 0,
|
||||||
|
explodeMin: 8000,
|
||||||
|
HUD: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
function levelScaling() {
|
||||||
|
//game.gravity = 0.00011; // + 0.000012 * game.level;
|
||||||
|
game.width = 2000 * game.level; //shapes walls and spawn locations
|
||||||
|
game.height = 2000 * game.level; //shapes walls and spawn locations
|
||||||
|
game.scale = 1.2 / (Math.log(game.level + 1)); //0.6 + 1.0 / (game.level); //controls map zoom
|
||||||
|
game.totalMass = 3 + game.level * 1; //how many masses to spawn at start of level
|
||||||
|
game.massSize = 3 + game.level * 3; //adds the average length of a segment on a masses's vertices
|
||||||
|
game.massSegment = 0.1 + 0.1 / game.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
//looks for key presses and logs them
|
||||||
|
var keys = [];
|
||||||
|
document.body.addEventListener("keydown", function(e) {
|
||||||
|
keys[e.keyCode] = true;
|
||||||
|
});
|
||||||
|
document.body.addEventListener("keyup", function(e) {
|
||||||
|
keys[e.keyCode] = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// module aliases
|
||||||
|
var Engine = Matter.Engine,
|
||||||
|
World = Matter.World,
|
||||||
|
Events = Matter.Events,
|
||||||
|
Composite = Matter.Composite,
|
||||||
|
Vertices = Matter.Vertices,
|
||||||
|
Body = Matter.Body,
|
||||||
|
Bodies = Matter.Bodies;
|
||||||
|
|
||||||
|
// create an engine
|
||||||
|
var engine = Engine.create();
|
||||||
|
//turn off gravity
|
||||||
|
engine.world.gravity.y = 0;
|
||||||
|
// run the engine
|
||||||
|
// Engine.run(engine);
|
||||||
|
Matter.Runner.run(engine)
|
||||||
|
|
||||||
|
function addWalls() {
|
||||||
|
//add the walls
|
||||||
|
var wallSettings = {
|
||||||
|
size: 200,
|
||||||
|
isStatic: true,
|
||||||
|
render: {
|
||||||
|
restitution: 0,
|
||||||
|
fillStyle: 'rgba(0, 0, 0, 0.0)',
|
||||||
|
strokeStyle: '#00ffff'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
World.add(engine.world, [
|
||||||
|
Bodies.rectangle(game.width * 0.5, -wallSettings.size * 0.5, game.width, wallSettings.size, wallSettings), //top
|
||||||
|
Bodies.rectangle(game.width * 0.5, game.height + wallSettings.size * 0.5, game.width, wallSettings.size, wallSettings), //bottom
|
||||||
|
Bodies.rectangle(-wallSettings.size * 0.5, game.height * 0.5, wallSettings.size, game.height + wallSettings.size * 2, wallSettings), //left
|
||||||
|
Bodies.rectangle(game.width + wallSettings.size * 0.5, game.height * 0.5, wallSettings.size, game.height + wallSettings.size * 2, wallSettings) //right
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
//add the masses
|
||||||
|
var mass = [];
|
||||||
|
|
||||||
|
function addPlayer() {
|
||||||
|
//add the player object as the first mass in the array
|
||||||
|
mass.push();
|
||||||
|
//var arrow = Vertices.fromPath('100 0 75 50 100 100 25 100 0 50 25 0');
|
||||||
|
var arrow = Vertices.fromPath('0 15 -10 -15 10 -15');
|
||||||
|
mass[0] = Matter.Bodies.fromVertices(Math.random() * game.width, Math.random() * game.height, arrow, {
|
||||||
|
//density: 0.001,
|
||||||
|
alive: true,
|
||||||
|
friction: 0,
|
||||||
|
frictionStatic: 0,
|
||||||
|
frictionAir: 0,
|
||||||
|
restitution: 0, //bounce 1 = 100% elastic
|
||||||
|
density: 0.003333,
|
||||||
|
thrust: 0.0004, //forward acceleration, if mass goes up this needs to go up
|
||||||
|
yaw: 0.00133, //angular acceleration, needs to be higher with larger mass
|
||||||
|
rotationLimit: 0.05, //max acceleration for player in radians/cycle
|
||||||
|
angularFriction: 0.98, // 1 = no friction, 0.9 = high friction
|
||||||
|
durability: 1,
|
||||||
|
fireCD: 0,
|
||||||
|
lastPlayerVelocity: { //for keeping track of damamge from too much acceleration
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
},
|
||||||
|
});
|
||||||
|
World.add(engine.world, mass[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function randomConvexPolygon(size) { //returns a string of vectors that make a convex polygon
|
||||||
|
var polyVector = '';
|
||||||
|
var x = 0;
|
||||||
|
var y = 0;
|
||||||
|
var r = 0;
|
||||||
|
var angle = 0;
|
||||||
|
for (var i = 1; i < 60; i++) {
|
||||||
|
angle += 0.1 + Math.random() * game.massSegment; //change in angle in radians
|
||||||
|
if (angle > 2 * Math.PI) {
|
||||||
|
break; //stop before it becomes convex
|
||||||
|
}
|
||||||
|
r = 2 + Math.random() * 2;
|
||||||
|
x = Math.round(x + r * Math.cos(angle));
|
||||||
|
y = Math.round(y + r * Math.sin(angle));
|
||||||
|
polyVector = polyVector.concat(x * size + ' ' + y * size + ' ');
|
||||||
|
}
|
||||||
|
return polyVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMassVector(x, y, Vx, Vy, size) {
|
||||||
|
var verticies = [];
|
||||||
|
var vector = Vertices.fromPath(randomConvexPolygon(size));
|
||||||
|
var i = mass.length;
|
||||||
|
mass.push();
|
||||||
|
mass[i] = Matter.Bodies.fromVertices(x, y, vector, { // x,y,vectors,{options}
|
||||||
|
friction: 0,
|
||||||
|
frictionStatic: 0,
|
||||||
|
frictionAir: 0,
|
||||||
|
restitution: 1,
|
||||||
|
angle: Math.random() * 2 * Math.PI
|
||||||
|
});
|
||||||
|
Matter.Body.setVelocity(mass[i], {
|
||||||
|
x: Vx,
|
||||||
|
y: Vy
|
||||||
|
});
|
||||||
|
Matter.Body.setAngularVelocity(mass[i], (Math.random() - 0.5) * 0.03);
|
||||||
|
World.add(engine.world, mass[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMass(x, y, r, sides, Vx, Vy) {
|
||||||
|
var i = mass.length;
|
||||||
|
mass.push();
|
||||||
|
mass[i] = Bodies.polygon(x, y, sides, r, {
|
||||||
|
friction: 0,
|
||||||
|
frictionStatic: 0,
|
||||||
|
frictionAir: 0,
|
||||||
|
restitution: 1,
|
||||||
|
});
|
||||||
|
Matter.Body.setVelocity(mass[i], {
|
||||||
|
x: Vx,
|
||||||
|
y: Vy
|
||||||
|
});
|
||||||
|
Matter.Body.setAngularVelocity(mass[i], (Math.random() - 0.5) * 0.03);
|
||||||
|
World.add(engine.world, mass[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearMasses() {
|
||||||
|
World.clear(engine.world, false);
|
||||||
|
console.log('clear')
|
||||||
|
mass = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function spawnSetup() {
|
||||||
|
//make the level indicator more clear on a new level
|
||||||
|
// document.getElementById("level").innerHTML = 'system ' + game.level;
|
||||||
|
// document.getElementById("level").style.color = 'white';
|
||||||
|
// document.getElementById("level").style.fontSize = '500%';
|
||||||
|
// document.getElementById("level").style.left = '40%';
|
||||||
|
// document.getElementById("level").style.position = 'absolute';
|
||||||
|
// setTimeout(levelFontSize, 3000);
|
||||||
|
//after 3 seconds return to normal style
|
||||||
|
// function levelFontSize(size) {
|
||||||
|
// document.getElementById("level").style.color = 'grey';
|
||||||
|
// document.getElementById("level").style.position = '';
|
||||||
|
// document.getElementById("level").style.left = '';
|
||||||
|
// document.getElementById("level").style.fontSize = '100%';
|
||||||
|
// }
|
||||||
|
levelScaling();
|
||||||
|
clearMasses();
|
||||||
|
addWalls();
|
||||||
|
addPlayer();
|
||||||
|
//add other masses
|
||||||
|
for (var j = 0; j < game.totalMass; j++) {
|
||||||
|
// addMassVector(x,y,Vx,Vy,size)
|
||||||
|
addMassVector(game.width * 0.2 + Math.random() * game.width * 0.6,
|
||||||
|
game.height * 0.2 + Math.random() * game.height * 0.6,
|
||||||
|
0, //(0.5 - Math.random()) * 4,
|
||||||
|
0,
|
||||||
|
Math.random() * 3 + game.massSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//determine how much mass is in the game at the start
|
||||||
|
game.startingMassValue = 0;
|
||||||
|
for (var i = 0; i < mass.length; i++) {
|
||||||
|
game.startingMassValue += mass[i].mass;
|
||||||
|
}
|
||||||
|
game.currentMass = game.startingMassValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
spawnSetup();
|
||||||
|
|
||||||
|
function repopulateMasses() {
|
||||||
|
game.currentMass = 0;
|
||||||
|
for (var i = 0; i < mass.length; i++) {
|
||||||
|
game.currentMass += mass[i].mass;
|
||||||
|
}
|
||||||
|
if (game.currentMass < game.startingMassValue * game.clearThreshold) {
|
||||||
|
game.level++;
|
||||||
|
spawnSetup();
|
||||||
|
mass[0].durability = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var bullet = [];
|
||||||
|
|
||||||
|
function fireBullet() { //addMass(x, y, r, sides, Vx, Vy)
|
||||||
|
var i = bullet.length;
|
||||||
|
var angle = mass[0].angle + Math.PI * 0.5;
|
||||||
|
var speed = 9;
|
||||||
|
var playerDist = 25;
|
||||||
|
bullet.push();
|
||||||
|
bullet[i] = Bodies.polygon(
|
||||||
|
mass[0].position.x + playerDist * Math.cos(angle),
|
||||||
|
mass[0].position.y + playerDist * Math.sin(angle),
|
||||||
|
3, //sides
|
||||||
|
2, { //radius
|
||||||
|
angle: Math.random() * 6.28,
|
||||||
|
friction: 0,
|
||||||
|
frictionStatic: 0,
|
||||||
|
frictionAir: 0,
|
||||||
|
restitution: 1,
|
||||||
|
endCycle: game.cycle + 90, // life span for a bullet (60 per second)
|
||||||
|
});
|
||||||
|
Matter.Body.setVelocity(bullet[i], {
|
||||||
|
x: mass[0].velocity.x + speed * Math.cos(angle),
|
||||||
|
y: mass[0].velocity.y + speed * Math.sin(angle)
|
||||||
|
});
|
||||||
|
Matter.Body.setAngularVelocity(bullet[i], (Math.random() - 0.5) * 1);
|
||||||
|
World.add(engine.world, bullet[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bulletEndCycle() {
|
||||||
|
for (var i = 0; i < bullet.length; i++) {
|
||||||
|
if (bullet[i].endCycle < game.cycle) {
|
||||||
|
Matter.World.remove(engine.world, bullet[i]);
|
||||||
|
bullet.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function controls() {
|
||||||
|
if (mass[0].alive) {
|
||||||
|
if (keys[32] && mass[0].fireCD < game.cycle) {
|
||||||
|
mass[0].fireCD = game.cycle + 10; // ?/60 seconds of cooldown before you can fire
|
||||||
|
fireBullet();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keys[38] || keys[87]) { //forward thrust
|
||||||
|
mass[0].force.x += mass[0].thrust * Math.cos(mass[0].angle + Math.PI * 0.5);
|
||||||
|
mass[0].force.y += mass[0].thrust * Math.sin(mass[0].angle + Math.PI * 0.5);
|
||||||
|
thrustGraphic();
|
||||||
|
} else if (keys[40] || keys[83]) { //reverse thrust
|
||||||
|
mass[0].force = {
|
||||||
|
x: -mass[0].thrust * 0.5 * Math.cos(mass[0].angle + Math.PI * 0.5),
|
||||||
|
y: -mass[0].thrust * 0.5 * Math.sin(mass[0].angle + Math.PI * 0.5)
|
||||||
|
};
|
||||||
|
torqueGraphic(-1);
|
||||||
|
torqueGraphic(1);
|
||||||
|
}
|
||||||
|
//rotate left and right
|
||||||
|
if ((keys[37] || keys[65])) { //&& mass[0].angularVelocity > -mass[0].rotationLimit) {
|
||||||
|
mass[0].torque = -mass[0].yaw; //counter clockwise
|
||||||
|
torqueGraphic(-1);
|
||||||
|
} else if ((keys[39] || keys[68])) { //&& mass[0].angularVelocity < mass[0].rotationLimit) {
|
||||||
|
mass[0].torque = mass[0].yaw; //clockwise
|
||||||
|
torqueGraphic(1);
|
||||||
|
}
|
||||||
|
//angular friction if spinning too fast
|
||||||
|
if (Math.abs(mass[0].angularVelocity) > mass[0].rotationLimit) {
|
||||||
|
Matter.Body.setAngularVelocity(mass[0], mass[0].angularVelocity * mass[0].angularFriction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function torqueGraphic(dir) { //thrust graphic when holding rotation keys
|
||||||
|
ctx.save();
|
||||||
|
//ctx.translate(0.5 * canvas.width, 0.5 * canvas.height)
|
||||||
|
ctx.rotate(mass[0].angle - Math.PI * 0.6 * dir);
|
||||||
|
ctx.translate(0, -23);
|
||||||
|
var grd = ctx.createLinearGradient(0, 0, 0, 15);
|
||||||
|
grd.addColorStop(0.1, 'rgba(0, 0, 0, 0)');
|
||||||
|
grd.addColorStop(1, 'rgba(160, 192, 255, 1)');
|
||||||
|
ctx.fillStyle = grd;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(dir * 6 * (Math.random() - 0.5) + 12 * dir, 6 * (Math.random() - 0.5));
|
||||||
|
ctx.lineTo(dir * 8, 14);
|
||||||
|
ctx.lineTo(dir * 12, 14);
|
||||||
|
ctx.fill();
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
function thrustGraphic() {
|
||||||
|
//ctx.fillStyle= "#90b0ff";
|
||||||
|
ctx.save();
|
||||||
|
//ctx.translate(0.5 * canvas.width, 0.5 * canvas.height)
|
||||||
|
ctx.rotate(mass[0].angle);
|
||||||
|
ctx.translate(0, -33);
|
||||||
|
var grd = ctx.createLinearGradient(0, 0, 0, 15);
|
||||||
|
grd.addColorStop(0, 'rgba(0, 0, 0, 0)');
|
||||||
|
grd.addColorStop(1, 'rgba(160, 192, 255, 1)');
|
||||||
|
ctx.fillStyle = grd;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(10 * (Math.random() - 0.5), 10 * (Math.random() - 0.5));
|
||||||
|
ctx.lineTo(7, 20);
|
||||||
|
ctx.lineTo(-7, 20);
|
||||||
|
ctx.fill();
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
function gravity() {
|
||||||
|
var length = mass.length;
|
||||||
|
var Dx = 0;
|
||||||
|
var Dy = 0;
|
||||||
|
var force = 0;
|
||||||
|
var angle = 0;
|
||||||
|
var i = 0;
|
||||||
|
var j = 0;
|
||||||
|
//gravity for array masses, but not player: mass[0]
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
for (j = 0; j < length; j++) {
|
||||||
|
if (i != j) {
|
||||||
|
Dx = mass[j].position.x - mass[i].position.x;
|
||||||
|
Dy = mass[j].position.y - mass[i].position.y;
|
||||||
|
force = game.gravity * mass[j].mass * mass[i].mass / (Math.sqrt(Dx * Dx + Dy * Dy));
|
||||||
|
angle = Math.atan2(Dy, Dx);
|
||||||
|
mass[i].force.x += force * Math.cos(angle);
|
||||||
|
mass[i].force.y += force * Math.sin(angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//gravity for bullets
|
||||||
|
var Blength = bullet.length;
|
||||||
|
for (i = 0; i < Blength; i++) {
|
||||||
|
for (j = 0; j < length; j++) { //bullets only feel gravity, they don't create it
|
||||||
|
Dx = mass[j].position.x - bullet[i].position.x;
|
||||||
|
Dy = mass[j].position.y - bullet[i].position.y;
|
||||||
|
force = game.gravity * mass[j].mass * bullet[i].mass / (Math.sqrt(Dx * Dx + Dy * Dy));
|
||||||
|
angle = Math.atan2(Dy, Dx);
|
||||||
|
bullet[i].force.x += force * Math.cos(angle);
|
||||||
|
bullet[i].force.y += force * Math.sin(angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function damage() { //changes player health if velocity changes too much
|
||||||
|
var limit2 = 9; //square of velocity damamge limit
|
||||||
|
var dX = Math.abs(mass[0].lastPlayerVelocity.x - mass[0].velocity.x);
|
||||||
|
var dY = Math.abs(mass[0].lastPlayerVelocity.y - mass[0].velocity.y);
|
||||||
|
var dV2 = dX * dX + dY * dY; //we are skipping the square root
|
||||||
|
if (dV2 > limit2) { //did velocity change enough to take damage
|
||||||
|
mass[0].durability -= Math.sqrt(dV2 - limit2) * 0.02; //player takes damage
|
||||||
|
if (mass[0].durability < 0 && mass[0].alive) { //player dead?
|
||||||
|
mass[0].alive = false;
|
||||||
|
//spawn player explosion debris
|
||||||
|
for (var j = 0; j < 10; j++) { //addMass(x, y, r, sides, Vx, Vy)
|
||||||
|
addMass(mass[0].position.x + 10 * (0.5 - Math.random()),
|
||||||
|
mass[0].position.y + 10 * (0.5 - Math.random()),
|
||||||
|
5,
|
||||||
|
3,
|
||||||
|
(0.5 - Math.random()) * 8 + mass[0].velocity.x,
|
||||||
|
(0.5 - Math.random()) * 8 + mass[0].velocity.y);
|
||||||
|
}
|
||||||
|
//shrink player to match debris size
|
||||||
|
Matter.Body.scale(mass[0], 0.4, 0.4);
|
||||||
|
//reset masses after a few seconds
|
||||||
|
window.setTimeout(spawnSetup, 6000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//keep track of last player velocity to calculate changes in velocity
|
||||||
|
mass[0].lastPlayerVelocity.x = mass[0].velocity.x;
|
||||||
|
mass[0].lastPlayerVelocity.y = mass[0].velocity.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
//bullet collision event
|
||||||
|
Events.on(engine, 'collisionStart', function(event) {
|
||||||
|
|
||||||
|
//slice the polygon up into sections
|
||||||
|
function slicePoly(m, start, end) { //cut a mass into two sectons
|
||||||
|
//build new string vector array that matches some of the reference mass
|
||||||
|
var polyVector = '';
|
||||||
|
for (var i = start; i < end; i++) {
|
||||||
|
polyVector = polyVector.concat(mass[m].vertices[i].x + ' ' + mass[m].vertices[i].y + ' ');
|
||||||
|
}
|
||||||
|
//buggy: making polygons noncolide. not sure why
|
||||||
|
//if (end = mass[m].vertices.length) { //catch the first vertices if the polygon hits the last
|
||||||
|
// polyVector = polyVector.concat(mass[m].vertices[0].x + ' ' + mass[m].vertices[0].y + ' '); }
|
||||||
|
var verticies = []; //build the polygon in matter.js
|
||||||
|
var vector = Vertices.fromPath(polyVector);
|
||||||
|
|
||||||
|
//add string vector array to game as a polygon
|
||||||
|
var len = mass.length;
|
||||||
|
mass.push();
|
||||||
|
mass[len] = Matter.Bodies.fromVertices(0, 0, vector, { // x,y,vectors,{options}
|
||||||
|
friction: 0,
|
||||||
|
frictionStatic: 0,
|
||||||
|
frictionAir: 0,
|
||||||
|
restitution: 1
|
||||||
|
});
|
||||||
|
World.add(engine.world, mass[len]);
|
||||||
|
//scale down the polygon a bit to help with collisions
|
||||||
|
Matter.Body.scale(mass[len], 0.9, 0.9);
|
||||||
|
//move polygon into position
|
||||||
|
var vectorPos = Matter.Vertices.centre(vector); //find the center of new polygon
|
||||||
|
Matter.Body.translate(mass[len], {
|
||||||
|
x: vectorPos.x,
|
||||||
|
y: vectorPos.y
|
||||||
|
});
|
||||||
|
//give a velocity pointed away from the old mass's center so it explodes
|
||||||
|
var angle = Math.atan2(mass[len].position.y - mass[m].position.y, mass[len].position.x - mass[m].position.x);
|
||||||
|
Matter.Body.setVelocity(mass[len], {
|
||||||
|
x: mass[m].velocity.x + 2 * Math.cos(angle),
|
||||||
|
y: mass[m].velocity.y + 2 * Math.sin(angle)
|
||||||
|
});
|
||||||
|
//add some spin
|
||||||
|
Matter.Body.setAngularVelocity(mass[len], (Math.random() - 0.5) * 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hit(i, b, m) {
|
||||||
|
//match the collisions pair id to the mass
|
||||||
|
for (var j = 1; j < mass.length; j++) { //start at 1 to skip the player
|
||||||
|
if (mass[j].id === m.id) {
|
||||||
|
//remove bullet
|
||||||
|
Matter.World.remove(engine.world, bullet[i]);
|
||||||
|
bullet.splice(i, 1);
|
||||||
|
|
||||||
|
// explosion graphics
|
||||||
|
var driftSpeed = 1;
|
||||||
|
var length = mass[j].vertices.length - 1;
|
||||||
|
var dx = (mass[j].vertices[length].x - mass[j].position.x);
|
||||||
|
var dy = (mass[j].vertices[length].y - mass[j].position.y);
|
||||||
|
var r = Math.sqrt(dx * dx + dy * dy) * 1.5; // *1.5 give the explosion outward spread
|
||||||
|
var angle = Math.atan2(dy, dx);
|
||||||
|
boom.push({ //the line form the 1st and last vertex
|
||||||
|
x1: mass[j].vertices[length].x,
|
||||||
|
y1: mass[j].vertices[length].y,
|
||||||
|
x2: mass[j].vertices[0].x,
|
||||||
|
y2: mass[j].vertices[0].y,
|
||||||
|
alpha: 1,
|
||||||
|
driftVx: mass[j].velocity.x + (Math.random() - 0.5) * driftSpeed + r * mass[j].angularSpeed * Math.cos(angle),
|
||||||
|
driftVy: mass[j].velocity.y + (Math.random() - 0.5) * driftSpeed + r * mass[j].angularSpeed * Math.sin(angle),
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var n = 0; n < length; n++) {
|
||||||
|
dx = (mass[j].vertices[n].x - mass[j].position.x);
|
||||||
|
dy = (mass[j].vertices[n].y - mass[j].position.y);
|
||||||
|
r = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
angle = Math.atan2(dy, dx);
|
||||||
|
boom.push({
|
||||||
|
x1: mass[j].vertices[n].x,
|
||||||
|
y1: mass[j].vertices[n].y,
|
||||||
|
x2: mass[j].vertices[n + 1].x,
|
||||||
|
y2: mass[j].vertices[n + 1].y,
|
||||||
|
alpha: 1,
|
||||||
|
driftVx: mass[j].velocity.x + (Math.random() - 0.5) * driftSpeed + r * mass[j].angularSpeed * Math.cos(angle),
|
||||||
|
driftVy: mass[j].velocity.y + (Math.random() - 0.5) * driftSpeed + r * mass[j].angularSpeed * Math.sin(angle),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//choose to slice
|
||||||
|
if (mass[j].vertices.length > 13) {
|
||||||
|
var cut = 6 + Math.floor(Math.random() * 4);
|
||||||
|
slicePoly(j, 0, cut);
|
||||||
|
//sliceChoices(mass.length - 1);
|
||||||
|
slicePoly(j, cut - 1, mass[j].vertices.length);
|
||||||
|
//sliceChoices(mass.length - 1);
|
||||||
|
Matter.World.remove(engine.world, mass[j]);
|
||||||
|
mass.splice(j, 1);
|
||||||
|
} else {
|
||||||
|
Matter.World.remove(engine.world, mass[j]);
|
||||||
|
mass.splice(j, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//check to see if one of the collisison pairs is a bullet
|
||||||
|
var pairs = event.pairs;
|
||||||
|
for (var i = 0, j = pairs.length; i != j; ++i) {
|
||||||
|
var pair = pairs[i];
|
||||||
|
for (var k = 0; k < bullet.length; k++) {
|
||||||
|
if (pair.bodyA === bullet[k]) {
|
||||||
|
hit(k, pair.bodyA, pair.bodyB);
|
||||||
|
repopulateMasses();
|
||||||
|
break;
|
||||||
|
} else if (pair.bodyB === bullet[k]) {
|
||||||
|
hit(k, pair.bodyB, pair.bodyA);
|
||||||
|
repopulateMasses();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var boom = [];
|
||||||
|
|
||||||
|
function explosions() {
|
||||||
|
var i = boom.length;
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
while (i--) {
|
||||||
|
ctx.strokeStyle = 'rgba(255, 255, 255, ' + boom[i].alpha + ')';
|
||||||
|
//drift vector lines around
|
||||||
|
boom[i].x1 += boom[i].driftVx;
|
||||||
|
boom[i].y1 += boom[i].driftVy;
|
||||||
|
boom[i].x2 += boom[i].driftVx;
|
||||||
|
boom[i].y2 += boom[i].driftVy;
|
||||||
|
//draw vector lines
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(boom[i].x1, boom[i].y1);
|
||||||
|
ctx.lineTo(boom[i].x2, boom[i].y2);
|
||||||
|
ctx.stroke();
|
||||||
|
//remove vector lines if they are too old
|
||||||
|
boom[i].alpha -= 0.03;
|
||||||
|
if (boom[i].alpha < 0.01) {
|
||||||
|
boom.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//set up render
|
||||||
|
var canvas = document.createElement('canvas'),
|
||||||
|
ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
//make canvas fill window
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
document.body.appendChild(canvas);
|
||||||
|
window.onresize = function(event) {
|
||||||
|
ctx.canvas.width = window.innerWidth;
|
||||||
|
ctx.canvas.height = window.innerHeight;
|
||||||
|
starsMoveRandom();
|
||||||
|
};
|
||||||
|
|
||||||
|
(function cycle() { //render loop
|
||||||
|
game.cycle++;
|
||||||
|
//ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; //trails simulate a old arcade cathode look
|
||||||
|
//ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height); //clear canvas for new cycle
|
||||||
|
bulletEndCycle();
|
||||||
|
|
||||||
|
damage();
|
||||||
|
gravity();
|
||||||
|
//background graphics
|
||||||
|
drawStars();
|
||||||
|
|
||||||
|
HUD();
|
||||||
|
ctx.save(); //move camera
|
||||||
|
|
||||||
|
ctx.translate(window.innerWidth * 0.5, window.innerHeight * 0.5);
|
||||||
|
ctx.scale(game.scale, game.scale);
|
||||||
|
controls();
|
||||||
|
ctx.translate(-mass[0].position.x, -mass[0].position.y);
|
||||||
|
//primary graphics
|
||||||
|
render();
|
||||||
|
drawVectors();
|
||||||
|
explosions();
|
||||||
|
ctx.restore(); //undo previous translation
|
||||||
|
//foreground graphics
|
||||||
|
miniMap();
|
||||||
|
completionBar();
|
||||||
|
durabilityBar();
|
||||||
|
window.requestAnimationFrame(cycle);
|
||||||
|
})();
|
||||||
|
|
||||||
|
function render() { //draw all the objects from matter.js physics engine
|
||||||
|
var bodies = Composite.allBodies(engine.world); //draw every object
|
||||||
|
//fill and stroke each body
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.strokeStyle = '#ffffff';
|
||||||
|
ctx.fillStyle = '#050505'; //'#111'; //'#0a0606';
|
||||||
|
ctx.beginPath();
|
||||||
|
for (var i = 0; i < bodies.length; i++) {
|
||||||
|
var vertices = bodies[i].vertices;
|
||||||
|
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||||
|
for (var j = 1; j < vertices.length; j++) {
|
||||||
|
ctx.lineTo(vertices[j].x, vertices[j].y);
|
||||||
|
}
|
||||||
|
ctx.lineTo(vertices[0].x, vertices[0].y);
|
||||||
|
}
|
||||||
|
ctx.fill();
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawVectors() { //render force and velocity vectors for each mass
|
||||||
|
if (game.HUD) {
|
||||||
|
var length = mass.length;
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
//velocity vector
|
||||||
|
//ctx.strokeStyle = 'rgba(0, 255, 255, 1)';
|
||||||
|
ctx.strokeStyle = '#00ffff';
|
||||||
|
ctx.beginPath();
|
||||||
|
for (var i = 0; i < length; i++) {
|
||||||
|
ctx.moveTo(mass[i].position.x, mass[i].position.y);
|
||||||
|
ctx.lineTo(mass[i].position.x + 10 * mass[i].velocity.x,
|
||||||
|
mass[i].position.y + 10 * mass[i].velocity.y);
|
||||||
|
}
|
||||||
|
ctx.stroke();
|
||||||
|
//force vector
|
||||||
|
//ctx.strokeStyle = 'rgba(255, 0, 255, 1)';
|
||||||
|
ctx.strokeStyle = '#ff00ff';
|
||||||
|
ctx.beginPath();
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
ctx.moveTo(mass[i].position.x, mass[i].position.y);
|
||||||
|
ctx.lineTo(mass[i].position.x + 600000 * mass[i].force.x / mass[i].mass,
|
||||||
|
mass[i].position.y + 600000 * mass[i].force.y / mass[i].mass);
|
||||||
|
}
|
||||||
|
ctx.stroke();
|
||||||
|
//angular motion vector
|
||||||
|
/* ctx.strokeStyle = 'rgba(255, 255, 00, 0.5)';//'#ff00ff';
|
||||||
|
ctx.beginPath();
|
||||||
|
if (mass[0].angularVelocity>0){
|
||||||
|
ctx.arc(mass[0].position.x,mass[0].position.y,20,Math.PI*0.5,53*mass[0].angularVelocity+Math.PI*0.5);
|
||||||
|
}else{
|
||||||
|
ctx.arc(mass[0].position.x,mass[0].position.y,20,53*mass[0].angularVelocity+Math.PI*0.5,Math.PI*0.5);
|
||||||
|
}
|
||||||
|
ctx.stroke(); */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function HUD() { //player data
|
||||||
|
// document.getElementById("level").innerHTML = 'system ' + game.level
|
||||||
|
if (game.HUD) { //testing and development data
|
||||||
|
document.getElementById("hud").innerHTML = '<table> ' +
|
||||||
|
//'<tr> <td>#:</td> <td>' + mass.length + '</td> </tr>' +
|
||||||
|
//'<tr> <td>level: </td> <td>' + game.level + '</td> </tr>' +
|
||||||
|
'<tr> <td> t:</td> <td>' + engine.timing.timestamp.toFixed(0) + '</td> </tr>' +
|
||||||
|
'<tr> <td style="color:#77f;"> m:</td> <td>' + mass[0].mass.toFixed(2) + '</td> </tr>' +
|
||||||
|
'<tr> <td style="color:#77f;"> θ:</td> <td>' + (Math.abs(mass[0].angle % (Math.PI * 2))).toFixed(2) + '</td> </tr>' +
|
||||||
|
'<tr> <td style="color:#77f;">dθ:</td> <td>' + mass[0].angularVelocity.toFixed(3) + '</td> </tr>' +
|
||||||
|
'<tr> <td style="color:#77f;"> x:</td> <td>' + mass[0].position.x.toFixed(0) + '</td> </tr>' +
|
||||||
|
'<tr> <td style="color:#77f;"> y:</td> <td>' + mass[0].position.y.toFixed(0) + '</td> </tr>' +
|
||||||
|
'<tr> <td style="color:#0dd;">Vx:</td> <td>' + mass[0].velocity.x.toFixed(2) + '</td> </tr>' +
|
||||||
|
'<tr> <td style="color:#0dd;">Vy:</td> <td>' + mass[0].velocity.y.toFixed(2) + '</td> </tr>' +
|
||||||
|
'<tr> <td style="color:#d0d;">Fx:</td> <td>' + mass[0].force.x.toFixed(6) + '</td> </tr>' +
|
||||||
|
'<tr> <td style="color:#d0d;">Fy:</td> <td>' + mass[0].force.y.toFixed(6) + '</td> </tr>' + '</table>';
|
||||||
|
} else {
|
||||||
|
document.getElementById("hud").innerHTML = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function durabilityBar() { // player health bar
|
||||||
|
var size = 200;
|
||||||
|
var x = 6;
|
||||||
|
var y = 6;
|
||||||
|
//ctx.lineWidth = 2;
|
||||||
|
//ctx.strokeStyle = '#999';
|
||||||
|
//ctx.strokeRect(x - 1, y - 1, size + 2, 12); //draw outline
|
||||||
|
//ctx.fillStyle = '#512';
|
||||||
|
ctx.fillStyle = 'rgba(255, 85, 119, 0.3)'
|
||||||
|
ctx.fillRect(x, y, size, 10); //draw bar
|
||||||
|
if (mass[0].alive) { //only draw bar if player is alive
|
||||||
|
ctx.fillStyle = 'rgba(255, 85, 119, 0.9)'
|
||||||
|
ctx.fillRect(x, y, size * mass[0].durability, 10); //draw bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function completionBar() {
|
||||||
|
var size = 152;
|
||||||
|
var x = canvas.width - size - 4;
|
||||||
|
var y = 5;
|
||||||
|
|
||||||
|
//ctx.fillStyle = '#000007';
|
||||||
|
//ctx.fillRect(x, y, size, 5); //draw bar
|
||||||
|
ctx.fillStyle = 'rgba(85, 85, 170, 0.3)'
|
||||||
|
//ctx.fillStyle = '#55a';
|
||||||
|
ctx.fillRect(x, y, size, 5); //draw bar
|
||||||
|
//ctx.fillStyle = '#55a';
|
||||||
|
ctx.fillStyle = 'rgba(85, 85, 170, 0.9)'
|
||||||
|
ctx.fillRect(x, y, size * game.currentMass / game.startingMassValue, 5); //draw bar
|
||||||
|
//goal line
|
||||||
|
ctx.fillStyle = '#ffff00';
|
||||||
|
ctx.fillRect(x + size * game.clearThreshold, y, 1, 5); //draw bar
|
||||||
|
//outline of bar
|
||||||
|
//ctx.lineWidth = 1;
|
||||||
|
//ctx.strokeStyle = '#88f';
|
||||||
|
//ctx.strokeRect(x, y, size, 5); //draw outline
|
||||||
|
}
|
||||||
|
|
||||||
|
function miniMap() {
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.strokeStyle = '#88f';
|
||||||
|
ctx.beginPath();
|
||||||
|
var xOff = canvas.width - 5;
|
||||||
|
var yOff = 10;
|
||||||
|
var size = 150;
|
||||||
|
var scale = size / game.width;
|
||||||
|
ctx.fillStyle = 'rgba(0, 0, 50, 0.5)'
|
||||||
|
ctx.rect(xOff, yOff, -size, size);
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fill();
|
||||||
|
//draw dot for masses
|
||||||
|
ctx.fillStyle = '#aaf';
|
||||||
|
for (var i = 1; i < mass.length; i++) {
|
||||||
|
ctx.fillRect(mass[i].position.x * scale + xOff - size, mass[i].position.y * scale + yOff, 3, 3);
|
||||||
|
}
|
||||||
|
//draw player's dot
|
||||||
|
ctx.fillStyle = '#ffff00';
|
||||||
|
ctx.fillRect(mass[0].position.x * scale + xOff - size, mass[0].position.y * scale + yOff, 5, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
var star = [];
|
||||||
|
var totalStars = 100;
|
||||||
|
for (var i = 0; i < totalStars; i++) {
|
||||||
|
star.push({
|
||||||
|
x: Math.random() * window.innerWidth,
|
||||||
|
y: Math.random() * window.innerHeight
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function starsMoveRandom() {
|
||||||
|
for (var i = 0; i < totalStars; i++) {
|
||||||
|
star[i].x = Math.random() * window.innerWidth;
|
||||||
|
star[i].y = Math.random() * window.innerHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawStars() {
|
||||||
|
ctx.fillStyle = '#ffffff'; //'darkgrey'; //'rgba(255, 255, 255, 0.5)'
|
||||||
|
var parallax = 1;
|
||||||
|
var Vx = mass[0].velocity.x * game.scale;
|
||||||
|
var Vy = mass[0].velocity.y * game.scale;
|
||||||
|
var width = window.innerWidth;
|
||||||
|
var height = window.innerHeight;
|
||||||
|
for (var i = 0; i < totalStars; i++) {
|
||||||
|
star[i].x -= Vx;
|
||||||
|
star[i].y -= Vy;
|
||||||
|
ctx.fillRect(star[i].x, star[i].y, 1, 1);
|
||||||
|
if (star[i].x < 0) {
|
||||||
|
star[i].x = width;
|
||||||
|
star[i].y = Math.random() * height;
|
||||||
|
}
|
||||||
|
if (star[i].x > width) {
|
||||||
|
star[i].x = 0;
|
||||||
|
star[i].y = Math.random() * height;
|
||||||
|
}
|
||||||
|
if (star[i].y < 0) {
|
||||||
|
star[i].y = height;
|
||||||
|
star[i].x = Math.random() * width;
|
||||||
|
}
|
||||||
|
if (star[i].y > height) {
|
||||||
|
star[i].y = 0;
|
||||||
|
star[i].x = Math.random() * width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -949,12 +949,12 @@ const m = {
|
|||||||
},
|
},
|
||||||
setHoldDefaults() {
|
setHoldDefaults() {
|
||||||
if (tech.isFreeWormHole && m.fieldUpgrades[m.fieldMode].name !== "wormhole") {
|
if (tech.isFreeWormHole && m.fieldUpgrades[m.fieldMode].name !== "wormhole") {
|
||||||
tech.removeTech("charmed baryon") //neutronum can get player stuck so it has to be removed if player has wrong field
|
const removed = tech.removeTech("charmed baryon") //neutronum can get player stuck so it has to be removed if player has wrong field
|
||||||
powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
|
if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
|
||||||
}
|
}
|
||||||
if (tech.isNeutronium && m.fieldUpgrades[m.fieldMode].name !== "negative mass") {
|
if (tech.isNeutronium && m.fieldUpgrades[m.fieldMode].name !== "negative mass") {
|
||||||
tech.removeTech("neutronium") //neutronum can get player stuck so it has to be removed if player has wrong field
|
const removed = tech.removeTech("neutronium") //neutronum can get player stuck so it has to be removed if player has wrong field
|
||||||
powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
|
if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
|
||||||
}
|
}
|
||||||
if (m.energy < m.maxEnergy) m.energy = m.maxEnergy;
|
if (m.energy < m.maxEnergy) m.energy = m.maxEnergy;
|
||||||
m.fieldRegen = tech.energyRegen; //0.001
|
m.fieldRegen = tech.energyRegen; //0.001
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ const powerUps = {
|
|||||||
currentRerollCount: 0,
|
currentRerollCount: 0,
|
||||||
use(type) { //runs when you actually research a list of selections, type can be field, gun, or tech
|
use(type) { //runs when you actually research a list of selections, type can be field, gun, or tech
|
||||||
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
|
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
|
||||||
tech.addJunkTechToPool(tech.junkResearchNumber)
|
tech.addJunkTechToPool(tech.junkResearchNumber * 0.01)
|
||||||
} else {
|
} else {
|
||||||
powerUps.research.changeRerolls(-1)
|
powerUps.research.changeRerolls(-1)
|
||||||
}
|
}
|
||||||
|
|||||||
14
js/spawn.js
14
js/spawn.js
@@ -111,7 +111,7 @@ const spawn = {
|
|||||||
powerUps.research.changeRerolls(-4)
|
powerUps.research.changeRerolls(-4)
|
||||||
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 4<br>${powerUps.research.count}`)
|
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 4<br>${powerUps.research.count}`)
|
||||||
} else {
|
} else {
|
||||||
tech.addJunkTechToPool(49)
|
tech.addJunkTechToPool(0.49)
|
||||||
}
|
}
|
||||||
spawn.randomLevelBoss(x, y);
|
spawn.randomLevelBoss(x, y);
|
||||||
return true
|
return true
|
||||||
@@ -2323,11 +2323,15 @@ const spawn = {
|
|||||||
me.friction = 0;
|
me.friction = 0;
|
||||||
me.memory = 240
|
me.memory = 240
|
||||||
me.seePlayerFreq = 60
|
me.seePlayerFreq = 60
|
||||||
me.delay = 25 + 30 * simulation.CDScale;
|
|
||||||
me.nextBlinkCycle = me.delay;
|
|
||||||
me.blinkRange = 235
|
me.blinkRange = 235
|
||||||
me.grenadeDelay = 35 + 60 * simulation.CDScale
|
if (false && 0.5 < Math.random()) {
|
||||||
me.pulseRadius = 2 * Math.min(550, 220 + simulation.difficulty * 4)
|
me.grenadeDelay = 260
|
||||||
|
} else {
|
||||||
|
me.grenadeDelay = 100
|
||||||
|
}
|
||||||
|
me.pulseRadius = 1.4 * Math.min(550, 220 + simulation.difficulty * 4)
|
||||||
|
me.delay = 30 + 35 * simulation.CDScale;
|
||||||
|
me.nextBlinkCycle = me.delay;
|
||||||
spawn.shield(me, x, y, 1);
|
spawn.shield(me, x, y, 1);
|
||||||
me.onDamage = function() {
|
me.onDamage = function() {
|
||||||
// this.cd = simulation.cycle + this.delay;
|
// this.cd = simulation.cycle + this.delay;
|
||||||
|
|||||||
173
js/tech.js
173
js/tech.js
@@ -53,8 +53,8 @@
|
|||||||
}
|
}
|
||||||
const totalRemoved = tech.tech[index].count
|
const totalRemoved = tech.tech[index].count
|
||||||
simulation.makeTextLog(`<span class='color-var'>tech</span>.removeTech("<span class='color-text'>${tech.tech[index].name}</span>")`)
|
simulation.makeTextLog(`<span class='color-var'>tech</span>.removeTech("<span class='color-text'>${tech.tech[index].name}</span>")`)
|
||||||
tech.tech[index].count = 0;
|
|
||||||
tech.tech[index].remove();
|
tech.tech[index].remove();
|
||||||
|
tech.tech[index].count = 0;
|
||||||
simulation.updateTechHUD();
|
simulation.updateTechHUD();
|
||||||
tech.tech[index].isLost = true
|
tech.tech[index].isLost = true
|
||||||
simulation.updateTechHUD();
|
simulation.updateTechHUD();
|
||||||
@@ -73,15 +73,40 @@
|
|||||||
// if (tech.tech[i].isLore && tech.tech[i].count === 0) tech.tech.splice(i, 1)
|
// if (tech.tech[i].isLore && tech.tech[i].count === 0) tech.tech.splice(i, 1)
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
addJunkTechToPool(num = 1) {
|
addJunkTechToPool(chance) { //chance is number between 0-1
|
||||||
|
// { //count JUNK
|
||||||
|
// let count = 0
|
||||||
|
// for (let i = 0, len = tech.tech.length; i < len; i++) {
|
||||||
|
// if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && tech.tech[i].isJunk && tech.tech[i].frequency > 0) count += tech.tech[i].frequency
|
||||||
|
// }
|
||||||
|
// console.log(count)
|
||||||
|
// }
|
||||||
|
// { //count not JUNK
|
||||||
|
// let count = 0
|
||||||
|
// for (let i = 0, len = tech.tech.length; i < len; i++) {
|
||||||
|
// if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk && tech.tech[i].frequency > 0) count++
|
||||||
|
// }
|
||||||
|
// console.log(count)
|
||||||
|
// }
|
||||||
|
// count total non junk tech
|
||||||
|
let count = 0
|
||||||
|
for (let i = 0, len = tech.tech.length; i < len; i++) {
|
||||||
|
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk) count += tech.tech[i].frequency
|
||||||
|
}
|
||||||
|
//make an array for possible junk tech to add
|
||||||
let options = [];
|
let options = [];
|
||||||
for (let i = 0; i < tech.tech.length; i++) {
|
for (let i = 0; i < tech.tech.length; i++) {
|
||||||
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].isJunk) options.push(i);
|
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].isJunk) options.push(i);
|
||||||
}
|
}
|
||||||
|
//add random array options to tech pool
|
||||||
if (options.length) {
|
if (options.length) {
|
||||||
|
const num = chance * count //scale number added
|
||||||
for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++
|
for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++
|
||||||
}
|
|
||||||
simulation.makeTextLog(`<span class='color-var'>tech</span>.tech.push(${num} <span class='color-text'>JUNK</span>)`)
|
simulation.makeTextLog(`<span class='color-var'>tech</span>.tech.push(${num} <span class='color-text'>JUNK</span>)`)
|
||||||
|
return num
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
},
|
},
|
||||||
removeJunkTechFromPool(num = 1) {
|
removeJunkTechFromPool(num = 1) {
|
||||||
for (let j = 0; j < num; j++) {
|
for (let j = 0; j < num; j++) {
|
||||||
@@ -506,7 +531,7 @@
|
|||||||
{
|
{
|
||||||
name: "desublimated ammunition",
|
name: "desublimated ammunition",
|
||||||
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Deposition_(phase_transition)' class="link">desublimated ammunition</a>`,
|
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Deposition_(phase_transition)' class="link">desublimated ammunition</a>`,
|
||||||
description: "every other <strong>crouched</strong> shot uses no <strong class='color-ammo'>ammo</strong><br><strong>+6</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
description: "every other <strong>crouched</strong> shot uses no <strong class='color-ammo'>ammo</strong><br><strong>+6%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -517,32 +542,18 @@
|
|||||||
requires: "",
|
requires: "",
|
||||||
effect() {
|
effect() {
|
||||||
tech.isCrouchAmmo = true
|
tech.isCrouchAmmo = true
|
||||||
tech.addJunkTechToPool(6)
|
this.refundAmount += tech.addJunkTechToPool(0.06)
|
||||||
},
|
},
|
||||||
|
refundAmount: 0,
|
||||||
remove() {
|
remove() {
|
||||||
tech.isCrouchAmmo = false;
|
tech.isExtraChoice = false;
|
||||||
if (this.count > 0) tech.removeJunkTechFromPool(6)
|
if (this.count > 0 && this.refundAmount > 0) {
|
||||||
|
tech.removeJunkTechFromPool(this.refundAmount)
|
||||||
|
this.refundAmount = 0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
// <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
|
||||||
// maxCount: 9,
|
|
||||||
// count: 0,
|
|
||||||
// frequency: 1,
|
|
||||||
// frequencyDefault: 1,
|
|
||||||
// allowed() {
|
|
||||||
// return true
|
|
||||||
// },
|
|
||||||
// requires: "",
|
|
||||||
// effect() {
|
|
||||||
// tech.bonusEnergy += 0.6
|
|
||||||
// m.setMaxEnergy()
|
|
||||||
// tech.addJunkTechToPool(10)
|
|
||||||
// },
|
|
||||||
// remove() {
|
|
||||||
// tech.bonusEnergy = 0;
|
|
||||||
// m.setMaxEnergy()
|
|
||||||
// if (this.count > 0) tech.removeJunkTechFromPool(10)
|
|
||||||
// }
|
|
||||||
{
|
{
|
||||||
name: "gun turret",
|
name: "gun turret",
|
||||||
description: "reduce <strong class='color-harm'>harm</strong> by <strong>55%</strong> when <strong>crouching</strong>",
|
description: "reduce <strong class='color-harm'>harm</strong> by <strong>55%</strong> when <strong>crouching</strong>",
|
||||||
@@ -2470,7 +2481,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "overcharge",
|
name: "overcharge",
|
||||||
description: "increase your <strong>maximum</strong> <strong class='color-f'>energy</strong> by <strong>60</strong><br><strong>+10</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
description: "increase your <strong>maximum</strong> <strong class='color-f'>energy</strong> by <strong>60</strong><br><strong>+10%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
||||||
maxCount: 9,
|
maxCount: 9,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -2482,17 +2493,21 @@
|
|||||||
effect() {
|
effect() {
|
||||||
tech.bonusEnergy += 0.6
|
tech.bonusEnergy += 0.6
|
||||||
m.setMaxEnergy()
|
m.setMaxEnergy()
|
||||||
tech.addJunkTechToPool(10)
|
this.refundAmount += tech.addJunkTechToPool(0.1)
|
||||||
},
|
},
|
||||||
|
refundAmount: 0,
|
||||||
remove() {
|
remove() {
|
||||||
tech.bonusEnergy = 0;
|
tech.bonusEnergy = 0;
|
||||||
m.setMaxEnergy()
|
m.setMaxEnergy()
|
||||||
if (this.count > 0) tech.removeJunkTechFromPool(10)
|
if (this.count > 0 && this.refundAmount > 0) {
|
||||||
|
tech.removeJunkTechFromPool(this.refundAmount)
|
||||||
|
this.refundAmount = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Maxwell's demon",
|
name: "Maxwell's demon",
|
||||||
description: "<strong class='color-f'>energy</strong> above your max decays <strong>92%</strong> slower<br><strong>+18</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
description: "<strong class='color-f'>energy</strong> above your max decays <strong>92%</strong> slower<br><strong>+18%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 2,
|
frequency: 2,
|
||||||
@@ -2503,11 +2518,15 @@
|
|||||||
requires: "energy above your max",
|
requires: "energy above your max",
|
||||||
effect() {
|
effect() {
|
||||||
tech.overfillDrain = 0.85 //70% = 1-(1-0.75)/(1-0.15) //92% = 1-(1-0.75)/(1-0.87)
|
tech.overfillDrain = 0.85 //70% = 1-(1-0.75)/(1-0.15) //92% = 1-(1-0.75)/(1-0.87)
|
||||||
tech.addJunkTechToPool(18)
|
this.refundAmount += tech.addJunkTechToPool(0.18)
|
||||||
},
|
},
|
||||||
|
refundAmount: 0,
|
||||||
remove() {
|
remove() {
|
||||||
tech.overfillDrain = 0.7
|
tech.overfillDrain = 0.7
|
||||||
if (this.count > 0) tech.removeJunkTechFromPool(18)
|
if (this.count > 0 && this.refundAmount > 0) {
|
||||||
|
tech.removeJunkTechFromPool(this.refundAmount)
|
||||||
|
this.refundAmount = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3021,7 +3040,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "pseudoscience",
|
name: "pseudoscience",
|
||||||
description: "<span style = 'font-size:94%;'>when <strong>selecting</strong> a power up, <strong class='color-r'>research</strong> <strong>3</strong> times</span><br>for <strong>free</strong>, but add <strong>0-3</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool",
|
description: "<span style = 'font-size:94%;'>when <strong>selecting</strong> a power up, <strong class='color-r'>research</strong> <strong>3</strong> times</span><br>for <strong>free</strong>, but add <strong>0-3%</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -3072,7 +3091,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "abiogenesis",
|
name: "abiogenesis",
|
||||||
description: `at the start of a level spawn a 2nd <strong>boss</strong><br>use ${powerUps.orb.research(4)}or add <strong>49</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool`,
|
description: `at the start of a level spawn a 2nd <strong>boss</strong><br>use ${powerUps.orb.research(4)}or add <strong>49%</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool`,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 2,
|
frequency: 2,
|
||||||
@@ -3114,9 +3133,9 @@
|
|||||||
frequency: 1,
|
frequency: 1,
|
||||||
frequencyDefault: 1,
|
frequencyDefault: 1,
|
||||||
allowed() {
|
allowed() {
|
||||||
return tech.duplicateChance
|
return true
|
||||||
},
|
},
|
||||||
requires: "replication",
|
requires: "",
|
||||||
effect() {
|
effect() {
|
||||||
tech.isMetaAnalysis = true
|
tech.isMetaAnalysis = true
|
||||||
},
|
},
|
||||||
@@ -3126,7 +3145,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "replication",
|
name: "replication",
|
||||||
description: "<strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+30</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
description: "<strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+30%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
||||||
maxCount: 9,
|
maxCount: 9,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -3139,12 +3158,16 @@
|
|||||||
tech.duplicateChance += 0.1
|
tech.duplicateChance += 0.1
|
||||||
powerUps.setDupChance(); //needed after adjusting duplication chance
|
powerUps.setDupChance(); //needed after adjusting duplication chance
|
||||||
if (!build.isExperimentSelection) simulation.circleFlare(0.1);
|
if (!build.isExperimentSelection) simulation.circleFlare(0.1);
|
||||||
tech.addJunkTechToPool(30)
|
this.refundAmount += tech.addJunkTechToPool(0.3)
|
||||||
},
|
},
|
||||||
|
refundAmount: 0,
|
||||||
remove() {
|
remove() {
|
||||||
tech.duplicateChance = 0
|
tech.duplicateChance = 0
|
||||||
powerUps.setDupChance(); //needed after adjusting duplication chance
|
powerUps.setDupChance(); //needed after adjusting duplication chance
|
||||||
if (this.count > 1) tech.removeJunkTechFromPool(30)
|
if (this.count > 0 && this.refundAmount > 0) {
|
||||||
|
tech.removeJunkTechFromPool(this.refundAmount)
|
||||||
|
this.refundAmount = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3515,11 +3538,15 @@
|
|||||||
requires: "not determinism",
|
requires: "not determinism",
|
||||||
effect: () => {
|
effect: () => {
|
||||||
tech.isExtraChoice = true;
|
tech.isExtraChoice = true;
|
||||||
tech.addJunkTechToPool(5)
|
this.refundAmount += tech.addJunkTechToPool(0.05)
|
||||||
},
|
},
|
||||||
|
refundAmount: 0,
|
||||||
remove() {
|
remove() {
|
||||||
tech.isExtraChoice = false;
|
tech.isExtraChoice = false;
|
||||||
if (this.count > 0) tech.removeJunkTechFromPool(5)
|
if (this.count > 0 && this.refundAmount > 0) {
|
||||||
|
tech.removeJunkTechFromPool(this.refundAmount)
|
||||||
|
this.refundAmount = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3584,7 +3611,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "dark patterns",
|
name: "dark patterns",
|
||||||
description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br><strong>+31</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br><strong>+31%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -3597,12 +3624,13 @@
|
|||||||
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(31)
|
this.refundAmount += tech.addJunkTechToPool(0.31)
|
||||||
// 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])
|
||||||
},
|
},
|
||||||
|
refundAmount: 0,
|
||||||
remove() {
|
remove() {
|
||||||
if (this.count > 0) {
|
if (this.count > 0) {
|
||||||
tech.removeJunkTechFromPool(31)
|
if (this.refundAmount > 0) tech.removeJunkTechFromPool(this.refundAmount)
|
||||||
level.difficultyIncrease(simulation.difficultyMode)
|
level.difficultyIncrease(simulation.difficultyMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3734,9 +3762,9 @@
|
|||||||
frequency: 2,
|
frequency: 2,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 2,
|
||||||
allowed() {
|
allowed() {
|
||||||
return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIceCrystals && !tech.isRivets && !tech.nailRecoil
|
return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIceCrystals && !tech.isRivets && !tech.nailRecoil && !tech.nailRecoil
|
||||||
},
|
},
|
||||||
requires: "nail gun, not ice crystal, rivets, or pneumatic actuator",
|
requires: "nail gun, not ice crystal, rivets, rotary cannon, or pneumatic actuator",
|
||||||
effect() {
|
effect() {
|
||||||
tech.isNeedles = true
|
tech.isNeedles = true
|
||||||
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
|
||||||
@@ -4582,7 +4610,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "booby trap",
|
name: "booby trap",
|
||||||
description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong><br><strong>+53</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong><br><strong>+53%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -4595,11 +4623,15 @@
|
|||||||
effect() {
|
effect() {
|
||||||
tech.isMineDrop = true;
|
tech.isMineDrop = true;
|
||||||
if (tech.isMineDrop) b.mine(m.pos, { x: 0, y: 0 }, 0)
|
if (tech.isMineDrop) b.mine(m.pos, { x: 0, y: 0 }, 0)
|
||||||
tech.addJunkTechToPool(53)
|
this.refundAmount += tech.addJunkTechToPool(0.53)
|
||||||
},
|
},
|
||||||
|
refundAmount: 0,
|
||||||
remove() {
|
remove() {
|
||||||
tech.isMineDrop = false;
|
tech.isMineDrop = false;
|
||||||
if (this.count > 0) tech.removeJunkTechFromPool(53)
|
if (this.count > 0 && this.refundAmount > 0) {
|
||||||
|
tech.removeJunkTechFromPool(this.refundAmount)
|
||||||
|
this.refundAmount = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -6316,7 +6348,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "symbiosis",
|
name: "symbiosis",
|
||||||
description: "after a <strong>mob</strong> <strong>dies</strong>, lose <strong>1</strong> max <strong class='color-h'>health</strong><br><strong>bosses</strong> spawn <strong>1-2</strong> extra <strong class='color-m'>tech</strong> after they <strong>die</strong>",
|
description: "after a <strong>mob</strong> <strong>dies</strong>, lose <strong>1</strong> max <strong class='color-h'>health</strong><br><strong>bosses</strong> spawn <strong>1</strong> extra <strong class='color-m'>tech</strong> after they <strong>die</strong>",
|
||||||
isFieldTech: true,
|
isFieldTech: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -6890,6 +6922,43 @@
|
|||||||
// },
|
// },
|
||||||
// remove() {}
|
// remove() {}
|
||||||
// },
|
// },
|
||||||
|
{
|
||||||
|
name: "planetesimals",
|
||||||
|
description: `spawn a <strong class='color-m'>tech</strong> and play <strong>planetesimals</strong>,<br>an annoying asteroids game with Newtonian physics`,
|
||||||
|
maxCount: 1,
|
||||||
|
count: 0,
|
||||||
|
frequency: 0,
|
||||||
|
isNonRefundable: true,
|
||||||
|
isExperimentHide: true,
|
||||||
|
isJunk: true,
|
||||||
|
allowed() {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
requires: "",
|
||||||
|
effect() {
|
||||||
|
window.open('../../planetesimals/index.html', '_blank')
|
||||||
|
powerUps.spawn(m.pos.x, m.pos.y, "tech");
|
||||||
|
},
|
||||||
|
remove() {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "facsimile",
|
||||||
|
description: `inserts a copy of your current level into the level list`,
|
||||||
|
maxCount: 1,
|
||||||
|
count: 0,
|
||||||
|
frequency: 0,
|
||||||
|
isNonRefundable: true,
|
||||||
|
isExperimentHide: true,
|
||||||
|
isJunk: true,
|
||||||
|
allowed() {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
requires: "",
|
||||||
|
effect() {
|
||||||
|
level.levels.splice(level.onLevel, 0, level.levels[level.onLevel]);
|
||||||
|
},
|
||||||
|
remove() {}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "negative friction",
|
name: "negative friction",
|
||||||
description: "when you touch walls you speed up instead of slowing down. It's kinda fun.",
|
description: "when you touch walls you speed up instead of slowing down. It's kinda fun.",
|
||||||
@@ -7872,7 +7941,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expert system",
|
name: "expert system",
|
||||||
description: "spawn a <strong class='color-m'>tech</strong> power up<br><strong>+64</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
description: "spawn a <strong class='color-m'>tech</strong> power up<br><strong>+64%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
|
||||||
maxCount: 9,
|
maxCount: 9,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 0,
|
frequency: 0,
|
||||||
@@ -7885,7 +7954,7 @@
|
|||||||
requires: "",
|
requires: "",
|
||||||
effect() {
|
effect() {
|
||||||
powerUps.spawn(m.pos.x, m.pos.y, "tech");
|
powerUps.spawn(m.pos.x, m.pos.y, "tech");
|
||||||
tech.addJunkTechToPool(64)
|
tech.addJunkTechToPool(0.64)
|
||||||
},
|
},
|
||||||
remove() {}
|
remove() {}
|
||||||
},
|
},
|
||||||
|
|||||||
30
todo.txt
30
todo.txt
@@ -1,14 +1,34 @@
|
|||||||
******************************************************** NEXT PATCH **************************************************
|
******************************************************** NEXT PATCH **************************************************
|
||||||
tech: neutronium - 90% harm reduce while field is active, 33% slower move speed
|
|
||||||
(requires negative mass field)
|
|
||||||
tech: charmed baryon - 0 cost wormhole, 33% slower move speed
|
|
||||||
harpoon tech: reticulum now always fires extra harpoons even if there are no targets
|
|
||||||
|
|
||||||
tech.removeTech() method has been improved
|
JUNK tech: facsimile - copy current level and insert into level queue
|
||||||
|
JUNK tech: planetesimals - spawn a tech, and play planetesimals, an annoying asteroids like game with realistic physics
|
||||||
|
|
||||||
|
tech that previously added 1 junk tech now adds 1% (of current non-JUNK tech options)
|
||||||
|
the percent values may seem like more but I actually lowered the JUNK chance about 10%
|
||||||
|
|
||||||
|
meta-analysis no longer requires replication - (if you choose a JUNK tech get a random tech and 3 research)
|
||||||
|
symbiosis: only gives 1 bonus tech (was 1 or 2)
|
||||||
|
blink boss rebalanced (it's easier, and has two modes)
|
||||||
|
|
||||||
bug fixes
|
bug fixes
|
||||||
|
|
||||||
******************************************************** TODO ********************************************************
|
******************************************************** TODO ********************************************************
|
||||||
|
|
||||||
|
fields weak in late game?
|
||||||
|
Pilot wave?
|
||||||
|
buff with cool tech options from other fields
|
||||||
|
buff with another damage scaling tech
|
||||||
|
stand wave and diamagnetism
|
||||||
|
buff end stage tech for these
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tech perfect diamagnetism - holding the field makes the field slowly travel forward
|
||||||
|
could be base effect
|
||||||
|
|
||||||
|
make a field that just fires your first gun
|
||||||
|
if they have to share a cooldown give 50% shorter fire CD
|
||||||
|
|
||||||
bug - death while paused crashes game?
|
bug - death while paused crashes game?
|
||||||
|
|
||||||
tech: aerodynamic heating - railgun rods super heat the air around it doing AoE damage
|
tech: aerodynamic heating - railgun rods super heat the air around it doing AoE damage
|
||||||
|
|||||||
Reference in New Issue
Block a user