Closed Whyisthisnotavalable closed 3 months ago
soft() { simulation.makeTextLog(`<img src="https://raw.githubusercontent.com/Whyisthisnotavalable/image-yy/main/Hotpot-removed.png" width="100" height="100" style="background-image: radial-gradient(circle, gray, black, transparent)">`); simulation.makeTextLog(`<strong>soft</strong> by <span class='color-var'>Richard0820</span>`); simulation.makeTextLog("<em>The lasers deal less damage the higher level you are</em>") const portals = []; portals.push(level.portal({ x: -1525, y: -250 }, Math.PI / 2, { x: 1100, y: -1025 }, Math.PI / 2)) const soft = { createCloth(x, y, radius, width, height, attachToPlayer = false, stayStill = false, options, touchPlayer = true, constrictionStrength = 0.001) { const bodies = []; const constraints = []; const otherCons = []; const bodyWidth = radius; const bodyHeight = radius; const numRows = Math.ceil(height / bodyHeight); const numCols = Math.ceil(width / bodyWidth); for (let i = 0; i < numRows; i++) { for (let j = 0; j < numCols; j++) { const posX = x + j * bodyWidth + bodyWidth / 2; const posY = y + i * bodyHeight + bodyHeight / 2; const rect = Matter.Bodies.circle(posX, posY, (bodyWidth + bodyHeight) / 4, options); rect.collisionFilter.category = cat.body; rect.collisionFilter.mask = (touchPlayer ? cat.player | cat.body | cat.bullet | cat.mob | cat.mobBullet : cat.body | cat.bullet | cat.mob | cat.mobBullet); rect.classType = "body"; Composite.add(engine.world, rect); bodies.push(rect); } } for (let i = 0; i < numRows; i++) { for (let j = 0; j < numCols; j++) { const bodyIndexA = i * numCols + j; if (j < numCols - 1) { const bodyIndexB = i * numCols + (j + 1); const constraint = Constraint.create({ bodyA: bodies[bodyIndexA], bodyB: bodies[bodyIndexB], stiffness: 0.06, damping: 0.001 }); Composite.add(engine.world, constraint); constraints.push(constraint); } if (i < numRows - 1) { const bodyIndexB = (i + 1) * numCols + j; const constraint = Constraint.create({ bodyA: bodies[bodyIndexA], bodyB: bodies[bodyIndexB], stiffness: 0.06, damping: 0.001 }); Composite.add(engine.world, constraint); constraints.push(constraint); } } } for (let i = 0; i < numRows - 1; i++) { for (let j = 0; j < numCols - 1; j++) { const bodyA = bodies[i * numCols + j]; const bodyB = bodies[(i + 1) * numCols + j + 1]; const constraint = Constraint.create({ bodyA: bodyA, bodyB: bodyB, stiffness: 0.02 }); constraints.push(constraint); } } for (let i = 0; i < numRows - 1; i++) { for (let j = 1; j < numCols; j++) { const bodyA = bodies[i * numCols + j]; const bodyB = bodies[(i + 1) * numCols + j - 1]; const constraint = Constraint.create({ bodyA: bodyA, bodyB: bodyB, stiffness: 0.02 }); constraints.push(constraint); } } if (stayStill) { for (let i = 0; i < bodies.length; i++) { const by = bodies[i]; const spawnX = by.position.x + bodyWidth / 2; const spawnY = by.position.y + bodyHeight / 2; const isLastColumn = (i + 1) % numCols === 0; const isFirstColumn = i % numCols === 0; const stiffness = constrictionStrength * (isLastColumn || isFirstColumn ? 100 : 1); // Apply extra stiffness to first and last columns const cost = Constraint.create({ bodyA: by, pointB: { x: spawnX, y: spawnY }, stiffness: stiffness, length: 0 }); Composite.add(engine.world, cost); otherCons.push(cost); } } if(attachToPlayer) { for(let i = 0; i < bodies.length; i++) { const cost = Constraint.create({ bodyA: bodies[i], pointB: player.position, stiffness: 0.0005, length: 0 }); Composite.add(engine.world, cost); } } return { bodies, constraints, otherCons}; }, clothOptions: { frictionAir: 0.005, }, isOuterBoundary(body, bodies) { //unused const neighbors = [ { x: body.position.x + 1, y: body.position.y }, { x: body.position.x - 1, y: body.position.y }, { x: body.position.x, y: body.position.y + 1 }, { x: body.position.x, y: body.position.y - 1 } ]; for (let i = 0; i < neighbors.length; i++) { const neighbor = neighbors[i]; const isNeighbor = bodies.some(b => b.position.x === neighbor.x && b.position.y === neighbor.y); if (!isNeighbor) { return true; } } return false; }, draw(cloth) { ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = "rgba(0,0,0,0.3)"; ctx.fillStyle = "black"; for (let i = 0, len = cloth.constraints.length; i < len; ++i) { const constraint = cloth.constraints[i]; ctx.moveTo(constraint.bodyA.position.x, constraint.bodyA.position.y); ctx.lineTo(constraint.bodyB.position.x, constraint.bodyB.position.y); } ctx.closePath(); ctx.fill(); ctx.stroke(); }, addGravity(bodies, magnitude) { for (var i = 0; i < bodies.length; i++) { bodies[i].force.y += bodies[i].mass * magnitude; } }, gravity(cloth) { this.addGravity(cloth.bodies, simulation.g); }, breaker(cloth, percentage = 0.5) { const totalConstraints = cloth.constraints.length; const constraintsToRemove = Math.ceil(totalConstraints * percentage); for (let i = 0; i < constraintsToRemove; i++) { const randomIndex = Math.floor(Math.random() * cloth.constraints.length); let removedConstraint = cloth.constraints.splice(randomIndex, 1)[0]; Composite.remove(engine.world, removedConstraint); } }, destroyer(cloth, percentage = 0.99999) { const otherCons = cloth.otherCons.length; const otherCons2Remove = Math.ceil(otherCons * percentage); for (let i = 0; i < otherCons2Remove; i++) { const randomIndex = Math.floor(Math.random() * cloth.otherCons.length); let removedConstraint = cloth.otherCons.splice(randomIndex, 1)[0]; Composite.remove(engine.world, removedConstraint); } }, annihilate(cloth) { const totalBodies = cloth.bodies.length; for (let i = 0; i < totalBodies; i++) { const removeBody = cloth.bodies[i]; Composite.remove(engine.world, removeBody); } cloth.bodies.length = 0; // Clear the bodies array after removal } } const clothArray = []; clothArray.push(soft.createCloth(-100, 0, 50, 1000, 300, false, true, soft.clothOptions, true)) clothArray.push(soft.createCloth(-2000, 2375, 50, 1525, 200, false, true, soft.clothOptions, true)) clothArray.push(soft.createCloth(-3950, 125, 50, 1800, 125, false, true, soft.clothOptions, true)) const annoyingStuff = { lasers(where, angle) { const vertexCollision = function (v1, v1End, domain) { for (let i = 0; i < domain.length; ++i) { let vertices = domain[i].vertices; const len = vertices.length - 1; for (let j = 0; j < len; j++) { results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]); if (results.onLine1 && results.onLine2) { const dx = v1.x - results.x; const dy = v1.y - results.y; const dist2 = dx * dx + dy * dy; if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: vertices[j], v2: vertices[j + 1] }; } } results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]); if (results.onLine1 && results.onLine2) { const dx = v1.x - results.x; const dy = v1.y - results.y; const dist2 = dx * dx + dy * dy; if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: vertices[0], v2: vertices[len] }; } } }; const seeRange = 7000; best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; const look = { x: where.x + seeRange * Math.cos(angle), y: where.y + seeRange * Math.sin(angle) }; // vertexCollision(where, look, mob); vertexCollision(where, look, map); vertexCollision(where, look, body); if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]); if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second const dmg = 0.5 / simulation.dmgScale; m.damage(dmg); simulation.drawList.push({ //add dmg to draw queue x: best.x, y: best.y, radius: dmg * 1500, color: "rgba(80,0,255,0.5)", time: 20 }); } //draw beam if (best.dist2 === Infinity) best = look; ctx.moveTo(where.x, where.y); ctx.lineTo(best.x, best.y); }, laserBoss(x, y, radius = 30) { mobs.spawn(x, y, 6, radius, "#f00"); let me = mob[mob.length - 1]; setTimeout(() => { //fix mob in place, but allow rotation me.constraint = Constraint.create({ pointA: { x: me.position.x, y: me.position.y }, bodyB: me, stiffness: 1, damping: 1 }); Composite.add(engine.world, me.constraint); }, 2000); //add in a delay in case the level gets flipped left right me.count = 0; me.frictionAir = 0.03; // me.torque -= me.inertia * 0.002 spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.isBoss = true; // spawn.shield(me, x, y, 1); //not working, not sure why me.onDeath = function () { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; me.rotateVelocity = -Math.min(0.0045, 0.0015 * simulation.accelScale * simulation.accelScale) * (level.levelsCleared > 8 ? 1 : -1) me.do = function () { this.fill = '#' + Math.random().toString(16).substr(-6); //flash colors this.checkStatus(); if (!this.isStunned) { //check if slowed let slowed = false for (let i = 0; i < this.status.length; i++) { if (this.status[i].type === "slow") { slowed = true break } } if (!slowed) { this.count++ Matter.Body.setAngle(this, this.count * this.rotateVelocity) Matter.Body.setAngularVelocity(this, 0) } ctx.beginPath(); for(let i = 0; i < this.vertices.length; i++) { if(Math.sin((2 * Math.PI * simulation.cycle) / (50 + i)) > 0) { this.lasers(this.vertices[i], Math.atan2(this.vertices[i].y - this.position.y, this.vertices[i].x - this.position.x)); } } ctx.strokeStyle = "#50f"; ctx.lineWidth = 1.5; ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]); ctx.stroke(); // Draw it ctx.setLineDash([]); ctx.lineWidth = 20; ctx.strokeStyle = "rgba(80,0,255,0.07)"; ctx.stroke(); // Draw it } }; me.lasers = function (where, angle) { const vertexCollision = function (v1, v1End, domain) { for (let i = 0; i < domain.length; ++i) { let vertices = domain[i].vertices; const len = vertices.length - 1; for (let j = 0; j < len; j++) { results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]); if (results.onLine1 && results.onLine2) { const dx = v1.x - results.x; const dy = v1.y - results.y; const dist2 = dx * dx + dy * dy; if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: vertices[j], v2: vertices[j + 1] }; } } results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]); if (results.onLine1 && results.onLine2) { const dx = v1.x - results.x; const dy = v1.y - results.y; const dist2 = dx * dx + dy * dy; if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: vertices[0], v2: vertices[len] }; } } }; const seeRange = 7000; best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; const look = { x: where.x + seeRange * Math.cos(angle), y: where.y + seeRange * Math.sin(angle) }; // vertexCollision(where, look, mob); vertexCollision(where, look, map); vertexCollision(where, look, body); if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]); if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second const dmg = 0.5 / simulation.dmgScale; m.damage(dmg); simulation.drawList.push({ //add dmg to draw queue x: best.x, y: best.y, radius: dmg * 1500, color: "rgba(80,0,255,0.5)", time: 20 }); } //draw beam if (best.dist2 === Infinity) best = look; ctx.moveTo(where.x, where.y); ctx.lineTo(best.x, best.y); } } } level.setPosToSpawn(-350, 0); level.exit.x = 1075; level.exit.y = 20; spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit level.defaultZoom = 1800 simulation.zoomTransition(level.defaultZoom) document.body.style.backgroundColor = "#aaFFFF55"; spawn.mapRect(900, 50, 425, 250); // spawn.mapRect(900, -1050, 0.1, 1350); spawn.mapRect(-475, 2375, 1800, 250); spawn.mapRect(-4400, 2375, 2475, 250); spawn.mapRect(-4400, -450, 250, 3075); spawn.mapRect(-4400, -450, 2225, 250); spawn.mapRect(-2425, -1300, 250, 1100); spawn.mapRect(-2425, -1300, 3825, 250); spawn.mapRect(1325, -1300, 250, 3925); spawn.mapRect(-875, -1300, 250, 1375); spawn.mapRect(-725, 50, 675, 250); spawn.mapRect(-875, 175, 175, 125); for(let i = 0; i < 6; i++) { spawn.mapRect(-4175, 2000 - i*375, 50, 125); } spawn.mapRect(-3925, 162.5, 50, 125); spawn.mapRect(-2175, 162.5, 50, 125); spawn.mapRect(300, 2025, 250, 600); spawn.mapRect(-2150, 175, 50, 25); spawn.mapRect(-2150, 250, 50, 25); spawn.mapRect(-900, 175, 50, 25); spawn.mapRect(-900, 250, 50, 25); spawn.mapRect(-1600, 175, 50, 25); spawn.mapRect(-1500, 175, 50, 25); spawn.mapRect(-1600, 250, 50, 25); spawn.mapRect(-1500, 250, 50, 25); spawn.mapRect(-1925, 175, 50, 25); spawn.mapRect(-1925, 250, 50, 25); spawn.mapRect(-1200, 175, 50, 25); spawn.mapRect(-1200, 250, 50, 25); spawn.bodyRect(-2125, 200, 1250, 50); spawn.debris(425, 200, 50); spawn.debris(-650, 2100, 50); spawn.debris(-3000, 1925, 50); spawn.debris(-3825, 1550, 50); spawn.debris(-2475, -50, 50); const bouncyBody = body[body.length - 1]; bouncyBody.restitution = 0.9; spawn.mapVertex(-2175 + 1300 / 2, -1050 + 1225 / 2, "0 -400 -100 -300 -100 0 100 0 100 -300"); spawn.mapVertex(-4150 + 1975 / 2, -200 + 2575 / 2, "0 -800 -200 -600 -200 0 0 200 200 0 200 -600 0 200"); const mapWithVertex = map[map.length - 1]; let index1 = 0; level.custom = () => { level.exit.drawAndCheck(); level.enter.draw(); if(player.position.x > 425 && index1 === 0) { soft.breaker(clothArray[0], 0.7); soft.destroyer(clothArray[0]); index1++; } if (player.position.y > 1300 && index1 === 1) { setTimeout(() => { soft.breaker(clothArray[0], 1); soft.annihilate(clothArray[0]); clothArray.splice(0, 1); }, 1000); //prevents bugs simulation.makeTextLog("Couldn't be so simple, could it?", 2000 * Math.random()); index1++; } }; level.customTopLayer = () => { for(let i = 0; i < portals.length; i++) { portals[i][2].query(); portals[i][3].query(); portals[i][0].draw(); portals[i][1].draw(); portals[i][2].draw(); portals[i][3].draw(); } ctx.beginPath(); if(Math.sin((2 * Math.PI * simulation.cycle) / (50)) > 0) { annoyingStuff.lasers(mapWithVertex.vertices[0], Math.atan2(mapWithVertex.vertices[0].y - mapWithVertex.position.y, mapWithVertex.vertices[0].x - mapWithVertex.position.x)); annoyingStuff.lasers(mapWithVertex.vertices[3], Math.atan2(mapWithVertex.vertices[3].y - mapWithVertex.position.y, mapWithVertex.vertices[3].x - mapWithVertex.position.x)); } if(Math.sin((2 * Math.PI * simulation.cycle) / (51)) > 0) { annoyingStuff.lasers(mapWithVertex.vertices[1], Math.atan2(mapWithVertex.vertices[1].y - mapWithVertex.position.y, mapWithVertex.vertices[1].x - mapWithVertex.position.x)); annoyingStuff.lasers(mapWithVertex.vertices[4], Math.atan2(mapWithVertex.vertices[4].y - mapWithVertex.position.y, mapWithVertex.vertices[4].x - mapWithVertex.position.x)); } if(Math.sin((2 * Math.PI * simulation.cycle) / (52)) > 0) { annoyingStuff.lasers(mapWithVertex.vertices[2], Math.atan2(mapWithVertex.vertices[2].y - mapWithVertex.position.y, mapWithVertex.vertices[2].x - mapWithVertex.position.x)); annoyingStuff.lasers(mapWithVertex.vertices[5], Math.atan2(mapWithVertex.vertices[5].y - mapWithVertex.position.y, mapWithVertex.vertices[5].x - mapWithVertex.position.x)); } ctx.strokeStyle = "#000"; ctx.lineWidth = 1.5; ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]); ctx.stroke(); // Draw it ctx.setLineDash([]); ctx.lineWidth = 20; ctx.strokeStyle = "rgba(0,0,0,0.07)"; ctx.stroke(); // Draw it for(let i = 0; i < clothArray.length; i++) { soft.draw(clothArray[i]); soft.gravity(clothArray[i]); } ctx.beginPath(); ctx.fillStyle = "rgba(69, 69, 69, 0.1)"; ctx.rect(-475, 175, 425, 2300); ctx.rect(900, 175, 425, 2300); ctx.rect(-875, 175, 400, 10000); ctx.rect(-4200, -250, 2025, 2775); ctx.fill(); ctx.beginPath(); ctx.fillStyle = (m.pos.x < -725 && m.pos.y < 175) ? `rgba(68, 68, 68, ${Math.max(0.3, Math.min((-775 - m.pos.x) / 100, 0.99))})` : color.map; ctx.rect(-875, 50, 175, 150); ctx.fill(); }; annoyingStuff.laserBoss(-1525, 1025); spawn.pulsar(-1525, -850); spawn.pulsar(1125, 1600); spawn.pulsar(-250, 1600); spawn.pulsar(-1450, 1600); spawn.pulsar(-2950, 1750); spawn.pulsar(-3375, 1750); spawn.pulsar(-3825, 1300); spawn.pulsar(-3825, 850); spawn.pulsar(-3450, 50); spawn.pulsar(-2925, 50); spawn.pulsar(-1900, -400); spawn.pulsar(-1200, -400); powerUps.addResearchToLevel() powerUps.directSpawn(-775, 125, "tech"); powerUp[powerUp.length - 1].collisionFilter.mask = cat.map | cat.body | cat.powerUp spawn.bodyRect(-875, 75, 25, 100); let hardBody = body[body.length - 1]; hardBody.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.powerUp },
added to patch. another great map. keep em coming!