diff --git a/index.html b/index.html index f4e9c1c..58e7192 100644 --- a/index.html +++ b/index.html @@ -54,8 +54,8 @@
@@ -228,19 +228,7 @@
about
- - - - - - - - Chat about n-gon in the discord.
Let me know about ideas, or bugs. -


+ n-gon is a solo project written in JavaScript, CSS, and HTML using the matter.js 2-D physics library. It's free and open source on Github. @@ -249,7 +237,6 @@ - Github hosts n-gon's source code.
It's written in JavaScript, CSS, and HTML and uses the matter.js 2-D physics library. Images are generated mostly through midJourney.
diff --git a/js/level.js b/js/level.js index 791add1..8a9c4be 100644 --- a/js/level.js +++ b/js/level.js @@ -34,7 +34,7 @@ const level = { // b.giveGuns("nail gun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.guns[3].ammo = 100000000 - // tech.giveTech("nitinol") + // tech.giveTech("accretion") // tech.giveTech("surface plasmons") // for (let i = 0; i < 6; ++i) tech.giveTech("Lorentz transformation") // for (let i = 0; i < 1; ++i) tech.giveTech("waste heat recovery") @@ -1521,10 +1521,10 @@ const level = { for (let i = 0, len = powerUpCollide.length; i < len; i++) { const diameter = 2 * powerUpCollide[i].size const buoyancy = 1 - 0.2 * Math.max(0, Math.min(diameter, this.min.y - powerUpCollide[i].position.y + powerUpCollide[i].size)) / diameter - powerUpCollide[i].force.y -= buoyancy * 1.14 * powerUpCollide[i].mass * simulation.g; + powerUpCollide[i].force.y -= buoyancy * 1.24 * powerUpCollide[i].mass * simulation.g; Matter.Body.setVelocity(powerUpCollide[i], { x: powerUpCollide[i].velocity.x, - y: 0.96 * powerUpCollide[i].velocity.y + y: 0.97 * powerUpCollide[i].velocity.y }); } } @@ -2629,8 +2629,8 @@ const level = { subway() { // simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode // level.difficultyIncrease(10 * 4); - // spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns - m.maxHealth = m.health = 100 + // m.maxHealth = m.health = 100 + const mobSpawnCap = mobs.mobDeaths + 100 level.isProcedural = true //used in generating text for the level builder @@ -2660,7 +2660,7 @@ const level = { train[train.length - 1].stops = { left: -7225, right: -1725 } const stationList = [] //organize the possible stations into a random order, with one station removed - for (let i = 0, totalNumberOfStations = 4; i < totalNumberOfStations; ++i) stationList.push(i) + for (let i = 0, totalNumberOfStations = 5; i < totalNumberOfStations; ++i) stationList.push(i) //!!!! update station number when you add a new station shuffle(stationList); stationList.splice(Math.floor(Math.random() * stationList.length), 1); //remove one random element from array let isExitOpen = false @@ -2689,13 +2689,20 @@ const level = { // bullet = []; // removeAll(composite); // composite = []; - removeAll(powerUp); - powerUp = []; // removeAll(cons); // don't allow constraints that don't come from a mob (like elevators, rotors?) // cons = []; // removeAll(consBB); // don't allow constraints that don't come from a mob (like elevators, rotors?) // consBB = []; + // removeAll(powerUp); + // powerUp = []; + //remove any powerUp that is too far from player + for (let i = 0; i < powerUp.length; ++i) { + if (Vector.magnitudeSquared(Vector.sub(player.position, powerUp[i].position)) > 9000000) { //remove any powerUp farther then 3000 pixels from player + Matter.Composite.remove(engine.world, powerUp[i]); + powerUp.splice(i--, 1) + } + } //remove any mob that is too far from player for (let i = 0; i < mob.length; ++i) { if (Vector.magnitudeSquared(Vector.sub(player.position, mob[i].position)) > 4000000) { //remove any mob farther then 2000 pixels from player @@ -2710,7 +2717,91 @@ const level = { } else { for (let i = 0; i < 8; ++i) powerUps.chooseRandomPowerUp(100 * (Math.random() - 0.5), -200 - 100 * Math.random())//only spawn heal or ammo once at the first station } - const stations = [ //update totalNumberOfStations as you add move stations + const stations = [ //update totalNumberOfStations as you add more stations + () => { //slime + if (isExitOpen) { + level.exit.x = x - 665; + level.exit.y = -920; + } + spawn.mapRect(x + -1575, -2000, 3025, 100); //roof + // spawn.mapRect(x + -1575, -2200, 3025, 300); //roof + // spawn.mapRect(x + -1500, -210, 3000, 400);//station floor + spawn.mapRect(x + -1500, -210, 500, 350); //station floor left + spawn.mapRect(x + 1000, -210, 500, 350); //station floor right + spawn.mapRect(x + 900, -1250, 125, 1250); + spawn.mapRect(x - 1025, -1550, 125, 1625); + spawn.mapRect(x - 50, -1900, 100, 1500); + spawn.mapRect(x + -975, -1250, 200, 25); + spawn.mapRect(x + -950, -625, 150, 25); + spawn.mapRect(x - 925, -400, 250, 175); + spawn.mapRect(x - 725, -900, 225, 300); + spawn.mapRect(x + 325, -225, 325, 75); + spawn.mapRect(x + 400, -950, 275, 25); + spawn.mapRect(x + 775, -575, 200, 25); + spawn.mapRect(x + 0, -1225, 125, 25); + spawn.mapRect(x + 0, -575, 225, 175); + spawn.mapRect(x - 925, -75, 875, 150); + spawn.mapRect(x + 475, -1400, 75, 1250); + + if (mobs.mobDeaths < mobSpawnCap) { + if (Math.random() < 0.5) { + spawn.randomMob(x + -850, -450, 0); + spawn.randomMob(x + -850, -125, 0); + spawn.randomMob(x + -725, -100, 0); + spawn.randomMob(x + 0, -100, 0); + spawn.randomMob(x + 800, -50, 0); + spawn.randomMob(x + 50, -275, 0); + spawn.randomMob(x + -300, -425, 0); + spawn.randomMob(x + -750, -475, 0); + spawn.randomMob(x + -850, -775, 0); + spawn.randomMob(x + -650, -1000, 0); + spawn.randomMob(x + -150, -1325, 0); + spawn.randomMob(x + -825, -1350, 0); + spawn.randomMob(x + -375, -150, 0); + } else { + spawn.randomMob(x + 350, -350, 0); + spawn.randomMob(x + 175, -700, 0); + spawn.randomMob(x + 350, -1175, 0); + spawn.randomMob(x + 200, -1600, 0); + spawn.randomMob(x + 500, -1675, 0); + spawn.randomMob(x + 425, -50, 0); + spawn.randomMob(x + 725, -75, 0); + spawn.randomMob(x + 650, -700, 0); + spawn.randomMob(x + 775, -1150, 0); + spawn.randomMob(x + 500, -1675, 0); + spawn.randomMob(x + -150, -175, 0); + spawn.randomMob(x + -800, -150, 0); + } + } + + const boost1 = level.boost(x - 1185, -225, 1400) + const boost2 = level.boost(x + 1100, -225, 1100) + const hazard1 = level.hazard(x - 900, -1225, 1800, 1225) + let isSlimeRiseUp = false + const drip = [] + drip.push(level.drip(x - 900 + 1800 * Math.random(), -1900, 0, 100)) // drip(x, yMin, yMax, period = 100, color = "hsla(160, 100%, 35%, 0.5)") { + drip.push(level.drip(x - 900 + 1800 * Math.random(), -1900, 0, 150)) + drip.push(level.drip(x - 900 + 1800 * Math.random(), -1900, 0, 70)) + // drip.push(level.drip(x - 900 + 1800 * Math.random(), -1900, 0, 210)) + // drip.push(level.drip(x - 900 + 1800 * Math.random(), -1900, 0, 67)) + stationCustom = () => { + for (let i = 0; i < drip.length; i++) drip[i].draw() + // drip1.draw(); + // drip2.draw(); + // drip3.draw(); + } + stationCustomTopLayer = () => { + hazard1.query(); + hazard1.level(isSlimeRiseUp, 1.5) + if (!(hazard1.height < hazard1.maxHeight)) { + isSlimeRiseUp = false + } else if (!(hazard1.height > 0)) { + isSlimeRiseUp = true + } + boost1.query(); + boost2.query(); + } + }, () => { //portals if (isExitOpen) { level.exit.x = x + 950; @@ -2748,9 +2839,6 @@ const level = { spawn.randomMob(x + 17150, -3150, 0); spawn.randomMob(x + 17700, -3300, 0); } - - if (!isInProgress) spawn.secondaryBossChance(420, -2200) // spawn.randomLevelBoss(5750, -600); - const portal1 = level.portal({ x: x + 0, y: -200 @@ -2879,7 +2967,6 @@ const level = { }, ] if (mobs.mobDeaths < mobSpawnCap) mobPlacement[Math.floor(Math.random() * mobPlacement.length)]()//different random mob placements, with mobs clustered to surprise player - if (!isInProgress) spawn.secondaryBossChance(900, -2700) // spawn.randomLevelBoss(5750, -600); stationCustom = () => { } stationCustomTopLayer = () => { } }, @@ -2963,7 +3050,6 @@ const level = { }, ] if (mobs.mobDeaths < mobSpawnCap) mobPlacement[Math.floor(Math.random() * mobPlacement.length)]()//different random mob placements, with mobs clustered to surprise player - if (!isInProgress) spawn.secondaryBossChance(600, -2500) // spawn.randomLevelBoss(5750, -600); const boost1 = level.boost(x - 50, -225, 790) const boost2 = level.boost(x + 550, -985, 900) const boost3 = level.boost(x + -850, -835, 1900) @@ -3015,7 +3101,6 @@ const level = { spawn.randomMob(x + 75, -1750, 0); spawn.randomMob(x + 1000, -375, 0); } - if (!isInProgress) spawn.secondaryBossChance(100, -850) // spawn.randomLevelBoss(5750, -600); stationCustom = () => { } stationCustomTopLayer = () => { ctx.fillStyle = "rgba(0,0,0,0.08)" @@ -3025,7 +3110,7 @@ const level = { } }, ] - // stations[3]() //for testing a specific station + // stations[0]() //for testing a specific station stations[stationList[Math.abs((stationNumber + Math.floor(stationList.length / 2)) % stationList.length)]]() //*************** run this one when uploading //add in standard station map infrastructure spawn.mapRect(x + -8000, 0, 16000, 800);//tunnel floor diff --git a/js/player.js b/js/player.js index 012736f..dcbfbd5 100644 --- a/js/player.js +++ b/js/player.js @@ -1959,7 +1959,7 @@ const m = { if (tech.isTimeCrystals) { m.fieldRegen *= 2.5 } else if (tech.isGroundState) { - m.fieldRegen *= 0.6 + m.fieldRegen *= 0.66 } }, regenEnergy: function () { //used in drawRegenEnergy // rewritten by some tech diff --git a/js/simulation.js b/js/simulation.js index c563300..c694597 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -1262,6 +1262,8 @@ const simulation = { m.holdingTarget.collisionFilter.category = 0; m.holdingTarget.collisionFilter.mask = 0; m.definePlayerMass(m.defaultMass + m.holdingTarget.mass * m.holdingMassScale) + Composite.add(engine.world, m.holdingTarget); //add to world + m.holdingTarget.classType = "body" } //set fps back to default simulation.fpsCap = simulation.fpsCapDefault diff --git a/js/tech.js b/js/tech.js index 8d3939c..f6d9657 100644 --- a/js/tech.js +++ b/js/tech.js @@ -2533,7 +2533,7 @@ const tech = { }, { name: "ground state", - description: "+200 maximum energy
–40% passive energy generation", + description: "+200 maximum energy
–33% passive energy generation", // description: "reduce defense by 66%
you no longer passively regenerate energy", maxCount: 1, count: 0, diff --git a/todo.txt b/todo.txt index 03929e0..c5536ff 100644 --- a/todo.txt +++ b/todo.txt @@ -1,27 +1,25 @@ ******************************************************** NEXT PATCH ************************************************** -level: subway - replaces gauntlet just before the final boss - gauntlet moved to community map pool - subway todo: - add a few more stations - balance difficulty - find bugs - -surface plasmons does 50% more damage -elasticity renamed nitinol because I bought some nitinol wire and it's neat -entanglement power up no longer shows guns or fields you already have -disabled minimal HUD for training levels -reaction inhibitor 12->11% mob max health reduction - -spawn.bodyRect() now can add blocks mid level without any extra code - I think I found all the bugs this causes, but let me know if any blocks added mid game aren't colliding - -community map - clock update: - visual overhaul,live lighting, remove pendulum overlap, move with pendulum if you stand in it, debris, trap exit only opens after completing the fight, moving elements now freeze while using time dilation +added a random station in subway +a few bug fixes *********************************************************** TODO ***************************************************** +mob non-combat behaviors, like Rain World + gathering + blocks + eating blocks to heal? + power ups + eating power ups and ejecting them on death + flocking + grouping near mobs + keeping distance from mobs + sharing velocity with other mobs: boids + wander + random walk with a bias towards the player + play + fight other mobs + consider increasing the base player horizontal movement maybe only increase ground movement, air control seems fine @@ -30,7 +28,6 @@ level: subway - a map that uses the train level element and line of sight graphi station theme ideas: portals teleport to far away rooms - slime map elements that alternate between positions buttons and doors boss @@ -1152,14 +1149,6 @@ level Boss: fractal Sierpiński triangle they spawn once at the start of the level if a version dies, one can be replaced every ten seconds by the largest version -give mobs more animal-like behaviors like rain world - mobs play, look for food, explore - mobs some times aren't aggressive - when low on life or after taking a large hit - mobs can fight each other - this might be hard to code - isolated mobs try to group up - mob: wall mounted guns / lasers not part of randomized mob pool, customized to each level