feat: Enhance terrain generation with new types and drawing mechanics
This commit is contained in:
96
terrain.js
96
terrain.js
@@ -90,6 +90,9 @@ class Perlin {
|
||||
// Terrain types
|
||||
const TERRAIN_WATER = 0;
|
||||
const TERRAIN_GRASS = 1;
|
||||
const TERRAIN_SAND = 2;
|
||||
const TERRAIN_DIRT = 3;
|
||||
const TERRAIN_STONE = 4;
|
||||
|
||||
// Generate terrain map
|
||||
function generateTerrain(width, height, scale) {
|
||||
@@ -108,30 +111,113 @@ function generateTerrain(width, height, scale) {
|
||||
value += 0.25 * perlin.noise(nx * 4, ny * 4);
|
||||
value /= 1.75; // Normalize
|
||||
|
||||
// Generate a second noise value for stone distribution
|
||||
let stoneNoise = perlin.noise(nx * 3, ny * 3);
|
||||
|
||||
// Determine terrain type based on noise value
|
||||
// Lower water threshold to create more land areas
|
||||
if (value < -0.3) { // Changed from 0.0 to -0.3 to reduce water
|
||||
// Adjusted to get more water
|
||||
if (value < -0.2) { // More water
|
||||
terrain[x][y] = TERRAIN_WATER;
|
||||
} else {
|
||||
|
||||
// Check for sand near water (beach)
|
||||
let sandCheck = perlin.noise((nx + 0.1) * 8, (ny + 0.1) * 8);
|
||||
if (value > -0.25 && sandCheck > 0) {
|
||||
terrain[x][y] = TERRAIN_SAND;
|
||||
}
|
||||
} else if (value < 0.0) {
|
||||
// Sand appears near water
|
||||
terrain[x][y] = TERRAIN_SAND;
|
||||
} else if (value < 0.3) {
|
||||
// Grass in middle elevations
|
||||
terrain[x][y] = TERRAIN_GRASS;
|
||||
} else if (stoneNoise > 0.3) {
|
||||
// Stone in higher elevations with specific noise pattern
|
||||
terrain[x][y] = TERRAIN_STONE;
|
||||
} else {
|
||||
// Dirt in higher elevations
|
||||
terrain[x][y] = TERRAIN_DIRT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass to smooth terrain and create better beaches
|
||||
smoothTerrain(terrain, width, height);
|
||||
|
||||
return terrain;
|
||||
}
|
||||
|
||||
function smoothTerrain(terrain, width, height) {
|
||||
// Create sand around water
|
||||
for (let x = 1; x < width - 1; x++) {
|
||||
for (let y = 1; y < height - 1; y++) {
|
||||
if (terrain[x][y] !== TERRAIN_WATER) {
|
||||
// Check if adjacent to water
|
||||
let adjacentToWater = false;
|
||||
for (let dx = -1; dx <= 1; dx++) {
|
||||
for (let dy = -1; dy <= 1; dy++) {
|
||||
if (x + dx >= 0 && x + dx < width && y + dy >= 0 && y + dy < height) {
|
||||
if (terrain[x + dx][y + dy] === TERRAIN_WATER) {
|
||||
adjacentToWater = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (adjacentToWater) break;
|
||||
}
|
||||
|
||||
// If adjacent to water and not already sand, make it sand
|
||||
if (adjacentToWater && terrain[x][y] !== TERRAIN_SAND && Math.random() > 0.3) {
|
||||
terrain[x][y] = TERRAIN_SAND;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a position is in water
|
||||
function isWater(x, y) {
|
||||
return getTerrainType(x, y) === TERRAIN_WATER;
|
||||
}
|
||||
|
||||
// Get terrain type at a position
|
||||
function getTerrainType(x, y) {
|
||||
// Convert world coordinates to terrain grid coordinates
|
||||
const gridX = Math.floor((x + 2000) / 10);
|
||||
const gridY = Math.floor((y + 2000) / 10);
|
||||
|
||||
// Check bounds
|
||||
if (gridX < 0 || gridX >= terrainWidth || gridY < 0 || gridY >= terrainHeight) {
|
||||
return false; // Default to land if out of bounds
|
||||
return TERRAIN_GRASS; // Default to grass if out of bounds
|
||||
}
|
||||
|
||||
return terrainMap[gridX][gridY] === TERRAIN_WATER;
|
||||
return terrainMap[gridX][gridY];
|
||||
}
|
||||
|
||||
// Set terrain type at a position
|
||||
function setTerrainType(x, y, type) {
|
||||
// Convert world coordinates to terrain grid coordinates
|
||||
const gridX = Math.floor((x + 2000) / 10);
|
||||
const gridY = Math.floor((y + 2000) / 10);
|
||||
|
||||
// Check bounds
|
||||
if (gridX < 0 || gridX >= terrainWidth || gridY < 0 || gridY >= terrainHeight) {
|
||||
return false; // Can't set if out of bounds
|
||||
}
|
||||
|
||||
terrainMap[gridX][gridY] = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get terrain name from type
|
||||
function getTerrainName(type) {
|
||||
switch(type) {
|
||||
case TERRAIN_WATER: return "Water";
|
||||
case TERRAIN_GRASS: return "Grass";
|
||||
case TERRAIN_SAND: return "Sand";
|
||||
case TERRAIN_DIRT: return "Dirt";
|
||||
case TERRAIN_STONE: return "Stone";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
// Terrain dimensions
|
||||
|
||||
Reference in New Issue
Block a user