Add files via upload

This commit is contained in:
redbirdly 2024-08-25 14:01:28 +08:00 committed by GitHub
parent d238269606
commit e1f9be1ec2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 270 additions and 0 deletions

270
mods/planet.js Normal file
View File

@ -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);
}
}
};