diff --git a/mods/clouds.js b/mods/clouds.js index ab31d62a..7a0df66a 100644 --- a/mods/clouds.js +++ b/mods/clouds.js @@ -1,70 +1,91 @@ // Clouds.js +if (!enabledMods.includes("mods/betterSettings.js")) { enabledMods.unshift("mods/betterSettings.js"); localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); window.location.reload() }; + +var clouds_settingsTab = new SettingsTab("Clouds"); + +var cloud_count_setting = new Setting("Cloud count", "cloud_count", settingType.NUMBER, false, defaultValue=40); + +clouds_settingsTab.registerSettings("Real time", cloud_count_setting); + +settingsManager.registerTab(clouds_settingsTab); + // Biased random function randomGaussian(A, B, biasFactor=2) { - let u = Math.random(); - let v = Math.random(); - let num = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v); + let u = Math.random(); + let v = Math.random(); + let num = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v); - let mean = (A + B) / 2; - let stdDev = (B - A) / biasFactor; + let mean = (A + B) / 2; + let stdDev = (B - A) / biasFactor; + let result = mean + num * stdDev; - let result = mean + num * stdDev; - - return Math.min(Math.max(result, A), B); + return Math.min(Math.max(result, A), B); } -// Spawn clouds -var clouds = []; -setTimeout(() => { - for (var i = 0;i < 50;i++) { - var w = (Math.random() * 11) + 6; - var h = (Math.random() * 7) + 3; +function randomBetween(A, B) { + return Math.random() * (B - A) + A; +} - // Higher clouds = faster - var y = randomGaussian(0, height * 0.75, 5); - var speedFactor = (1 - (y / (height * 0.75))); +function initClouds(amount) { + for (let i = 0; i < amount; i++) { + var w = randomBetween(6, 17); + var h = randomBetween(4, 10); + var x = randomBetween(0, width - w); + var y = randomGaussian(0, height * 0.75, 4); - clouds.push({ - x: Math.random() * (width - w), - y: y, - w: w, - h: h, - dx: ((Math.random() - 0.5) * 0.05) * (0.5 + speedFactor * 2), // Velocity - color: Math.random() > 0.5 ? "255,255,255" : "210,210,190", - blur: Math.random() * 3 + 1 - }); + // Higher clouds move faster + var speedBoost = 1 - (y / (height * 0.75)); + var speed = ((Math.random() - 0.5) * 0.05) * (0.5 + speedBoost * 2); + + var color = Math.random() > 0.5 ? "255,255,255" : "210,210,190"; + var blur = Math.max(Math.min(1 / (Math.abs(speed) * 48), 4), 0); // For parallax + + // Pre-render the cloud + var offCanvas = document.createElement("canvas"); + var margin = blur; + offCanvas.width = w * pixelSize + 2 * margin; + offCanvas.height = h * pixelSize + 2 * margin; + var offCtx = offCanvas.getContext("2d"); + + var gradient = offCtx.createLinearGradient(0, margin, 0, h * pixelSize + margin); + gradient.addColorStop(0, `RGBA(${color},0.12)`); + gradient.addColorStop(1, `RGBA(${color},0.24)`); + + offCtx.filter = `blur(${blur}px)`; + offCtx.fillStyle = gradient; + offCtx.fillRect(margin, margin, w * pixelSize, h * pixelSize); + + clouds.push({ x, y, w, h, speed, color, blur, image: offCanvas, margin }); } -}, 600); +} function renderClouds(ctx) { - ctx.strokeStyle = "transparent"; - ctx.globalAlpha = Math.min(pixelTicks * 0.02,1); + // Fade in + ctx.globalAlpha = Math.min(pixelTicks * 0.02, 1); - for (var i = 0;i < clouds.length;i++) { + for (var i = 0; i < clouds.length; i++) { var cloud = clouds[i]; - - var gradient = ctx.createLinearGradient( - cloud.x * pixelSize, cloud.y * pixelSize, - cloud.x * pixelSize, (cloud.y + cloud.h) * pixelSize + ctx.drawImage( + cloud.image, + cloud.x * pixelSize - cloud.margin, + cloud.y * pixelSize - cloud.margin ); - gradient.addColorStop(0, `RGBA(${cloud.color},0.1)`); - gradient.addColorStop(1, `RGBA(${cloud.color},0.2)`); - - ctx.filter = `blur(${cloud.blur}px)`; - ctx.fillStyle = gradient; - ctx.fillRect(cloud.x * pixelSize, cloud.y * pixelSize, cloud.w * pixelSize, cloud.h * pixelSize); - ctx.filter = "none"; } } function updateClouds() { - if (paused) {return;} + if (paused) { return; } - for (var i = 0;i < clouds.length;i++) { + if (cloud_count_setting.value != clouds.length) { + clouds = []; + initClouds(cloud_count_setting.value); + return; + } + + for (var i = 0; i < clouds.length; i++) { var cloud = clouds[i]; - - cloud.x += cloud.dx; + cloud.x += cloud.speed; // Wrap around if (cloud.x > width) { @@ -75,5 +96,11 @@ function updateClouds() { } } +// Hooks renderPrePixel(renderClouds); runEveryTick(updateClouds); + +var clouds = []; +runAfterReset(() => { + initClouds(cloud_count_setting.value); +}); diff --git a/mods/wifi_draw.js b/mods/wifi_draw.js index 41bf5ad1..0d7c5e93 100644 --- a/mods/wifi_draw.js +++ b/mods/wifi_draw.js @@ -7,80 +7,80 @@ let receivers = []; let transmitters = []; function updateLogicLists() { - receivers = []; - transmitters = []; - logicReceivers = []; + receivers = []; + transmitters = []; + logicReceivers = []; logicTransmitters = []; - - for (let i = 0; i < currentPixels.length; i++) { - const pixel = currentPixels[i]; - if (pixel.element === "logic_receiver") { - logicReceivers.push(pixel); - } else if (pixel.element === "logic_transmitter") { - logicTransmitters.push(pixel); - } else if (pixel.element === "receiver") { - receivers.push(pixel); - } else if (pixel.element === "transmitter") { - transmitters.push(pixel); - } - } + + for (let i = 0; i < currentPixels.length; i++) { + const pixel = currentPixels[i]; + if (pixel.element === "logic_receiver") { + logicReceivers.push(pixel); + } else if (pixel.element === "logic_transmitter") { + logicTransmitters.push(pixel); + } else if (pixel.element === "receiver") { + receivers.push(pixel); + } else if (pixel.element === "transmitter") { + transmitters.push(pixel); + } + } } // Function to draw lines between linked transmitters and receivers -function drawLinks() { - // Iterate through transmitters and receivers to draw lines for linked channels - for (const transmitter of logicTransmitters) { - for (const receiver of logicReceivers) { - if (transmitter.channel === receiver.channel) { - ctx.beginPath(); - ctx.moveTo(transmitter.x * pixelSize + pixelSizeHalf, transmitter.y * pixelSize + pixelSizeHalf); - ctx.lineTo(receiver.x * pixelSize + pixelSizeHalf, receiver.y * pixelSize + pixelSizeHalf); - ctx.strokeStyle = "RGBA(255,255,255,0.2)"; +function drawLinks(ctx) { + // Iterate through transmitters and receivers to draw lines for linked channels + for (const transmitter of logicTransmitters) { + for (const receiver of logicReceivers) { + if (transmitter.channel === receiver.channel) { + ctx.beginPath(); + ctx.moveTo(transmitter.x * pixelSize + pixelSizeHalf, transmitter.y * pixelSize + pixelSizeHalf); + ctx.lineTo(receiver.x * pixelSize + pixelSizeHalf, receiver.y * pixelSize + pixelSizeHalf); + ctx.strokeStyle = "RGBA(255,255,255,0.2)"; - const neighbors = [ - { x: transmitter.x, y: transmitter.y - 1 }, // Top - { x: transmitter.x, y: transmitter.y + 1 }, // Bottom - { x: transmitter.x - 1, y: transmitter.y }, // Left - { x: transmitter.x + 1, y: transmitter.y } // Right - ]; + const neighbors = [ + { x: transmitter.x, y: transmitter.y - 1 }, // Top + { x: transmitter.x, y: transmitter.y + 1 }, // Bottom + { x: transmitter.x - 1, y: transmitter.y }, // Left + { x: transmitter.x + 1, y: transmitter.y } // Right + ]; - let highlight = false; - for (const neighbor of neighbors) { - if ( - neighbor.x >= 0 && neighbor.x < width && - neighbor.y >= 0 && neighbor.y < height - ) { - const neighborPixel = pixelMap[neighbor.x][neighbor.y]; - if (neighborPixel && neighborPixel.lstate > 0) { - highlight = true; - break; - } - } - } + let highlight = false; + for (const neighbor of neighbors) { + if ( + neighbor.x >= 0 && neighbor.x < width && + neighbor.y >= 0 && neighbor.y < height + ) { + const neighborPixel = pixelMap[neighbor.x][neighbor.y]; + if (neighborPixel && neighborPixel.lstate > 0) { + highlight = true; + break; + } + } + } - if (highlight) { - ctx.strokeStyle = "RGBA(255,200,0,0.4)"; - } - - ctx.lineWidth = 2; - ctx.stroke(); - } - } - } + if (highlight) { + ctx.strokeStyle = "RGBA(255,200,0,0.4)"; + } + + ctx.lineWidth = 2; + ctx.stroke(); + } + } + } - // Iterate through transmitters and receivers to draw lines for linked channels - for (const transmitter of transmitters) { - for (const receiver of receivers) { - if (transmitter._channel === receiver._channel) { - ctx.beginPath(); - ctx.moveTo(transmitter.x * pixelSize + pixelSizeHalf, transmitter.y * pixelSize + pixelSizeHalf); - ctx.lineTo(receiver.x * pixelSize + pixelSizeHalf, receiver.y * pixelSize + pixelSizeHalf); - ctx.strokeStyle = "RGBA(0,0,255,0.2)"; - ctx.lineWidth = 2; - ctx.stroke(); - } - } - } + // Iterate through transmitters and receivers to draw lines for linked channels + for (const transmitter of transmitters) { + for (const receiver of receivers) { + if (transmitter._channel === receiver._channel) { + ctx.beginPath(); + ctx.moveTo(transmitter.x * pixelSize + pixelSizeHalf, transmitter.y * pixelSize + pixelSizeHalf); + ctx.lineTo(receiver.x * pixelSize + pixelSizeHalf, receiver.y * pixelSize + pixelSizeHalf); + ctx.strokeStyle = "RGBA(0,0,255,0.2)"; + ctx.lineWidth = 2; + ctx.stroke(); + } + } + } } renderPostPixel(updateLogicLists);