From e1f9be1ec21eed37c775a641fa2edd0db752c65f Mon Sep 17 00:00:00 2001 From: redbirdly <155550833+redbirdly@users.noreply.github.com> Date: Sun, 25 Aug 2024 14:01:28 +0800 Subject: [PATCH] Add files via upload --- mods/planet.js | 270 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 mods/planet.js diff --git a/mods/planet.js b/mods/planet.js new file mode 100644 index 00000000..d51913a6 --- /dev/null +++ b/mods/planet.js @@ -0,0 +1,270 @@ +// Define the corrected biomes with heights +var mercuryLayers = [ + { layers: ["basalt", "iron"], height: 0.6 }, + { layers: ["nickel"], height: 0.2 }, + { layers: ["iron"], height: 0.2 } +]; + +var venusLayers = [ + { layers: ["basalt", "limestone"], height: 0.5 }, + { layers: ["sand", "ash", "clay"], height: 0.25 }, + { layers: ["tuff"], height: 0.15 }, + { layers: ["sulfur", ["basalt", "sand"]], height: 0.1 } +]; + +var earthLayers = [ + { layers: ["rock", "basalt", "tuff", "limestone"], height: 0.55 }, + { layers: ["clay", "mudstone", "clay_soil"], height: 0.3 }, + { layers: [["sand", "wet_sand", "clay"], ["grass", "gravel", "dirt"]], height: 0.15 } +]; + +var marsLayers = [ + { layers: ["iron", "nickel"], height: 0.3 }, + { layers: ["iron", "nickel", "rust"], height: 0.15 }, + { layers: ["iron", "nickel", "rust", "rust"], height: 0.15 }, + { layers: ["rust"], height: 0.4 } +]; + +function tryCreateStaticPixel(pixelType, x, y) { + var staticPixelType = "static_" + pixelType; + + // Check if the static version of the pixel type exists + if (!elements[staticPixelType]) { + // Create the static version of the pixel type + elements[staticPixelType] = Object.assign({}, elements[pixelType], { + behavior: behaviors.WALL, + tick: undefined + }); + } + + // Create the static pixel + tryCreatePixel(staticPixelType, x, y); +} + +function getRandomWeightedElement(weightedList) { + // Parse the input string into an array of objects with name and weight properties + const elements = weightedList.split(',').map(item => { + const [name, weight] = item.split('%'); + return { name: name.trim(), weight: parseFloat(weight) }; + }); + + // Calculate the total weight + const totalWeight = elements.reduce((total, element) => total + element.weight, 0); + + // Generate a random number between 0 and totalWeight + const randomWeight = Math.random() * totalWeight; + + // Find the element corresponding to the random weight + let cumulativeWeight = 0; + for (const element of elements) { + cumulativeWeight += element.weight; + if (randomWeight < cumulativeWeight) { + return element.name; + } + } +} + +// Function to load a script dynamically +function loadScript(url) { + var script = document.createElement("script"); + script.type = "text/javascript"; + script.src = url; + document.head.appendChild(script); +} + +function circleSimplexNoise1D(simplex, theta) { + return simplex.noise2D(Math.cos(theta * Math.PI / 180), Math.sin(theta * Math.PI / 180)); +} + +// Load the simplex-noise library +loadScript("https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js"); + +function getRandomElement(layer) { + if (!layer || layer.length === 0) { + return null; // Return null or handle the error case + } + return layer[Math.floor(Math.random() * layer.length)]; +} + +function generatePlanet(config, x, y, radius) { + var simplex = new SimplexNoise(); + + var centerX = x; + var centerY = y; + var planetRadius = radius; + var cloudStartRadius = planetRadius + 7; + var cloudEndRadius = planetRadius + 14; + + // Generate terrain + for (var r = 0; r <= planetRadius; r++) { + var step = 0.5; + if (r <= 50) { step = 1; } + if (r <= 20) { step = 2; } + for (var theta = 0; theta <= 360; theta += step) { + var x = Math.round(centerX + r * Math.cos(theta * Math.PI / 180)); + var y = Math.round(centerY + r * Math.sin(theta * Math.PI / 180)); + + if (x >= 0 && x < width && y >= 0 && y < height) { + var distance = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2)); + var noise = (-Math.abs(circleSimplexNoise1D(simplex, theta * 0.7)) * 0.5) + (-Math.abs(circleSimplexNoise1D(simplex, theta * 2.5)) * 0.3); + var noisyDistance = distance - (noise * planetRadius * 0.3); + + if (noisyDistance <= planetRadius) { + // Determine the layer based on distance from center + var totalHeight = 0; + for (var i = 0; i < config.biomes.length; i++) { + totalHeight += config.biomes[i].height; + } + + var cumulativeHeight = 0; + var chosenLayer = null; + + for (var i = 0; i < config.biomes.length; i++) { + var biome = config.biomes[i]; + var layerHeight = (biome.height / totalHeight) * planetRadius; + + if (noisyDistance >= cumulativeHeight && noisyDistance < cumulativeHeight + layerHeight) { + chosenLayer = biome.layers; + + // If chosenLayer is a list of lists, pick a sublayer based on noise + if (Array.isArray(chosenLayer) && Array.isArray(chosenLayer[0])) { + var sublayerNoise = (circleSimplexNoise1D(simplex, theta) + 1) / 2; + var sublayerIndex = Math.floor(sublayerNoise * chosenLayer.length); + if (sublayerIndex < 0) { + sublayerIndex = 0; + } else if (sublayerIndex >= chosenLayer.length) { + sublayerIndex = chosenLayer.length - 1; + } + chosenLayer = chosenLayer[sublayerIndex]; + } + break; + } + + cumulativeHeight += layerHeight; + } + + var element = getRandomElement(chosenLayer); + if (element) { + tryCreateStaticPixel(element, x, y); + } + } + } + } + } + + if (config.oceanElements) { + for (var i = centerX - planetRadius; i <= centerX + planetRadius; i++) { + for (var j = centerY - planetRadius; j <= centerY + planetRadius; j++) { + if (i >= 0 && i < width && j >= 0 && j < height) { + var distanceFromCenter = Math.sqrt(Math.pow(i - centerX, 2) + Math.pow(j - centerY, 2)); + if (distanceFromCenter > planetRadius - 40 && distanceFromCenter <= planetRadius - 4) { + // Place ocean in the ring around the planet + tryCreateStaticPixel(getRandomWeightedElement(config.oceanElements), i, j); + } + } + } + } + } + + if (config.cloudElements) { + for (var r = cloudStartRadius; r <= cloudEndRadius; r++) { + var step = 1; + for (var theta = 0; theta <= 360; theta += step) { + var x = Math.round(centerX + r * Math.cos(theta * Math.PI / 180)); + var y = Math.round(centerY + r * Math.sin(theta * Math.PI / 180)); + + if (x >= 0 && x < width && y >= 0 && y < height) { + var distance = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2)); + var cloudNoise = simplex.noise2D(x * 0.05, y * 0.05) + simplex.noise2D(x * 0.17, y * 0.17); + + // Adjust cloud density based on distance from planet + var minCloudThreshold = 0.5 + config.cloudDensityBias; // Minimum threshold closer to the planet + var maxCloudThreshold = 0.8 + config.cloudDensityBias; // Maximum threshold further from the planet + + // Interpolate threshold based on distance from planet + var t = (r - cloudStartRadius) / (cloudEndRadius - cloudStartRadius); + var threshold = minCloudThreshold + t * (maxCloudThreshold - minCloudThreshold); + + if (cloudNoise > threshold) { + tryCreateStaticPixel(getRandomWeightedElement(config.cloudElements), x, y); + } + } + } + } + } +} + + +var mercuryConfig = { + biomes: mercuryLayers, + cloudElements: "", + cloudDensityBias: 0.0 +}; + +var venusConfig = { + biomes: venusLayers, + cloudElements: "ammonia%70,acid_cloud%30", + cloudDensityBias: 0.2 +}; + +var earthConfig = { + biomes: earthLayers, + oceanElements: "salt_water%80,water%20", + cloudElements: "cloud%100", + cloudDensityBias: 0.0 +}; + +var marsConfig = { + biomes: marsLayers, + cloudElements: "", + cloudDensityBias: 0.0 +}; + + +elements.planetMercury = { + behavior: behaviors.WALL, + category: "special", + maxSize: 1, + tick: function(pixel) { + if (pixel.start === pixelTicks) { + deletePixel(pixel.x, pixel.y); + generatePlanet(mercuryConfig, pixel.x, pixel.y, 13); + } + } +}; + +elements.planetVenus = { + behavior: behaviors.WALL, + category: "special", + maxSize: 1, + tick: function(pixel) { + if (pixel.start === pixelTicks) { + deletePixel(pixel.x, pixel.y); + generatePlanet(venusConfig, pixel.x, pixel.y, 30); + } + } +}; + +elements.planetEarth = { + behavior: behaviors.WALL, + category: "special", + maxSize: 1, + tick: function(pixel) { + if (pixel.start === pixelTicks) { + deletePixel(pixel.x, pixel.y); + generatePlanet(earthConfig, pixel.x, pixel.y, 33); + } + } +}; + +elements.planetMars = { + behavior: behaviors.WALL, + category: "special", + maxSize: 1, + tick: function(pixel) { + if (pixel.start === pixelTicks) { + deletePixel(pixel.x, pixel.y); + generatePlanet(marsConfig, pixel.x, pixel.y, 20); + } + } +};