just making sure the repo is up to date
This commit is contained in:
@@ -1,227 +1,247 @@
|
||||
#+feature dynamic-literals
|
||||
package game
|
||||
|
||||
import "core:math/noise"
|
||||
import "core:math"
|
||||
import "core:fmt"
|
||||
import "core:math"
|
||||
import "core:math/noise"
|
||||
|
||||
BIOME_SCALE : f64 : 1
|
||||
BIOME_SCALE: f64 : 1
|
||||
|
||||
biome_list := map[u32]Biome {
|
||||
0 = grasslands_biome,
|
||||
1 = forest_biome,
|
||||
2 = desert_biome,
|
||||
3 = lake_biome,
|
||||
0 = grasslands_biome,
|
||||
1 = forest_biome,
|
||||
2 = desert_biome,
|
||||
3 = lake_biome,
|
||||
}
|
||||
|
||||
BiomeType :: enum {
|
||||
GRASSLAND,
|
||||
FOREST,
|
||||
LAKE,
|
||||
DESERT,
|
||||
GRASSLAND,
|
||||
FOREST,
|
||||
LAKE,
|
||||
DESERT,
|
||||
}
|
||||
|
||||
Biome :: struct {
|
||||
id:u32,
|
||||
name: string,
|
||||
type: BiomeType,
|
||||
fauna_color: [4]u8,
|
||||
valid_structures: [dynamic]u32
|
||||
id: u32,
|
||||
name: string,
|
||||
type: BiomeType,
|
||||
fauna_color: [4]u8,
|
||||
valid_structures: [dynamic]u32,
|
||||
}
|
||||
|
||||
// Define biome constants
|
||||
grasslands_biome := Biome {
|
||||
id = 0,
|
||||
name = "Grasslands",
|
||||
type = .GRASSLAND,
|
||||
fauna_color = {50, 120, 25, 255},
|
||||
valid_structures = {}
|
||||
id = 0,
|
||||
name = "Grasslands",
|
||||
type = .GRASSLAND,
|
||||
fauna_color = {50, 120, 25, 255},
|
||||
valid_structures = {},
|
||||
}
|
||||
|
||||
forest_biome := Biome {
|
||||
id = 1,
|
||||
name = "Forest",
|
||||
type = .FOREST,
|
||||
fauna_color = {30, 80, 20, 255},
|
||||
valid_structures = {}
|
||||
id = 1,
|
||||
name = "Forest",
|
||||
type = .FOREST,
|
||||
fauna_color = {30, 80, 20, 255},
|
||||
valid_structures = {},
|
||||
}
|
||||
|
||||
desert_biome := Biome {
|
||||
id = 2,
|
||||
name = "Desert",
|
||||
type = .DESERT,
|
||||
fauna_color = {200, 180, 100, 255},
|
||||
valid_structures = {}
|
||||
id = 2,
|
||||
name = "Desert",
|
||||
type = .DESERT,
|
||||
fauna_color = {200, 180, 100, 255},
|
||||
valid_structures = {},
|
||||
}
|
||||
|
||||
lake_biome := Biome {
|
||||
id = 3,
|
||||
name = "Lake",
|
||||
type = .LAKE,
|
||||
fauna_color = {0, 50, 150, 255},
|
||||
valid_structures = {}
|
||||
id = 3,
|
||||
name = "Lake",
|
||||
type = .LAKE,
|
||||
fauna_color = {0, 50, 150, 255},
|
||||
valid_structures = {},
|
||||
}
|
||||
|
||||
get_biome_from_id :: proc(id:u32) -> Biome {
|
||||
return biome_list[id]
|
||||
get_biome_from_id :: proc(id: u32) -> Biome {
|
||||
return biome_list[id]
|
||||
}
|
||||
|
||||
get_biome_type :: proc(world_pos: Vec2i, seed: i64) -> Biome {
|
||||
// Use multiple noise scales for different features
|
||||
continent_scale := 0.0008 // Very large scale features (continents)
|
||||
region_scale := 0.007 // Medium scale features (regions)
|
||||
local_scale := 0.025 // Local variations
|
||||
// Use multiple noise scales for different features
|
||||
continent_scale := 0.0008 // Very large scale features (continents)
|
||||
region_scale := 0.007 // Medium scale features (regions)
|
||||
local_scale := 0.025 // Local variations
|
||||
|
||||
// Use different seed offsets for each noise layer
|
||||
continent_seed := seed
|
||||
region_seed := seed + 10000
|
||||
moisture_seed := seed + 20000
|
||||
temperature_seed := seed + 30000
|
||||
// Use different seed offsets for each noise layer
|
||||
continent_seed := seed
|
||||
region_seed := seed + 10000
|
||||
moisture_seed := seed + 20000
|
||||
temperature_seed := seed + 30000
|
||||
|
||||
// Generate base continent shapes
|
||||
continent := noise.noise_2d(continent_seed, {f64(world_pos.x) * continent_scale, f64(world_pos.y) * continent_scale})
|
||||
// Amplify to get more defined continents
|
||||
continent = math.pow(continent * 0.5 + 0.5, 1.5) * 2.0 - 1.0
|
||||
// Generate base continent shapes
|
||||
continent := noise.noise_2d(
|
||||
continent_seed,
|
||||
{f64(world_pos.x) * continent_scale, f64(world_pos.y) * continent_scale},
|
||||
)
|
||||
// Amplify to get more defined continents
|
||||
continent = math.pow(continent * 0.5 + 0.5, 1.5) * 2.0 - 1.0
|
||||
|
||||
// Generate regional variations
|
||||
region := noise.noise_2d(region_seed, {f64(world_pos.x) * region_scale, f64(world_pos.y) * region_scale})
|
||||
// Generate regional variations
|
||||
region := noise.noise_2d(
|
||||
region_seed,
|
||||
{f64(world_pos.x) * region_scale, f64(world_pos.y) * region_scale},
|
||||
)
|
||||
|
||||
// Generate moisture and temperature maps for biome determination
|
||||
moisture := noise.noise_2d(moisture_seed, {f64(world_pos.x) * region_scale, f64(world_pos.y) * region_scale})
|
||||
temperature := noise.noise_2d(temperature_seed, {f64(world_pos.x) * region_scale, f64(world_pos.y) * region_scale})
|
||||
// Generate moisture and temperature maps for biome determination
|
||||
moisture := noise.noise_2d(
|
||||
moisture_seed,
|
||||
{f64(world_pos.x) * region_scale, f64(world_pos.y) * region_scale},
|
||||
)
|
||||
temperature := noise.noise_2d(
|
||||
temperature_seed,
|
||||
{f64(world_pos.x) * region_scale, f64(world_pos.y) * region_scale},
|
||||
)
|
||||
|
||||
// Adjust temperature to create larger hot regions
|
||||
// This skews the distribution to have more areas with higher temperature
|
||||
// temperature = math.pow(temperature * 0.5 + 0.5, 0.8) * 2.0 - 1.0
|
||||
// Adjust temperature to create larger hot regions
|
||||
// This skews the distribution to have more areas with higher temperature
|
||||
// temperature = math.pow(temperature * 0.5 + 0.5, 0.8) * 2.0 - 1.0
|
||||
|
||||
// Local variations (small details)
|
||||
local_var := noise.noise_2d(seed, {f64(world_pos.x) * local_scale, f64(world_pos.y) * local_scale}) * 0.1
|
||||
// Local variations (small details)
|
||||
local_var :=
|
||||
noise.noise_2d(seed, {f64(world_pos.x) * local_scale, f64(world_pos.y) * local_scale}) *
|
||||
0.1
|
||||
|
||||
// Combine all factors with proper weighting
|
||||
elevation := continent * 0.7 + region * 0.3 + local_var
|
||||
// Combine all factors with proper weighting
|
||||
elevation := continent * 0.7 + region * 0.3 + local_var
|
||||
|
||||
// Convert noise values to 0-1 range for easier thresholding
|
||||
normalized_elevation := elevation * 0.5 + 0.5
|
||||
normalized_moisture := moisture * 0.5 + 0.5
|
||||
normalized_temperature := temperature * 0.5 + 0.5
|
||||
// Convert noise values to 0-1 range for easier thresholding
|
||||
normalized_elevation := elevation * 0.5 + 0.5
|
||||
normalized_moisture := moisture * 0.5 + 0.5
|
||||
normalized_temperature := temperature * 0.5 + 0.5
|
||||
|
||||
if normalized_elevation < 0.3 {
|
||||
return lake_biome
|
||||
}
|
||||
if normalized_elevation < 0.3 {
|
||||
return lake_biome
|
||||
}
|
||||
|
||||
if normalized_temperature > 0.7 && normalized_moisture < 0.2 {
|
||||
return desert_biome
|
||||
}
|
||||
if normalized_temperature > 0.7 && normalized_moisture < 0.2 {
|
||||
return desert_biome
|
||||
}
|
||||
|
||||
// Forests need moderate to high moisture
|
||||
if normalized_moisture > 0.55 {
|
||||
return forest_biome
|
||||
}
|
||||
// Forests need moderate to high moisture
|
||||
if normalized_moisture > 0.55 {
|
||||
return forest_biome
|
||||
}
|
||||
|
||||
// Default to grasslands
|
||||
return grasslands_biome
|
||||
// Default to grasslands
|
||||
return grasslands_biome
|
||||
}
|
||||
|
||||
// Improved chunk generation that considers neighboring chunks
|
||||
generate_chunk :: proc(pos: Vec2i, seed: i64) -> Chunk {
|
||||
chunk := Chunk{position = pos}
|
||||
chunk := Chunk {
|
||||
position = pos,
|
||||
}
|
||||
|
||||
// Store the biome for this chunk for consistency
|
||||
chunk_center := Vec2i{pos.x * CHUNK_SIZE + CHUNK_SIZE/2, pos.y * CHUNK_SIZE + CHUNK_SIZE/2}
|
||||
biome := get_biome_type(chunk_center, seed)
|
||||
chunk.biome_id = biome.id
|
||||
// Store the biome for this chunk for consistency
|
||||
chunk_center := Vec2i{pos.x * CHUNK_SIZE + CHUNK_SIZE / 2, pos.y * CHUNK_SIZE + CHUNK_SIZE / 2}
|
||||
biome := get_biome_type(chunk_center, seed)
|
||||
chunk.biome_id = biome.id
|
||||
|
||||
// Generate each tile, allowing for biome blending at edges
|
||||
for x in 0..<CHUNK_SIZE {
|
||||
for y in 0..<CHUNK_SIZE {
|
||||
world_x := pos.x * CHUNK_SIZE + x
|
||||
world_y := pos.y * CHUNK_SIZE + y
|
||||
world_pos := Vec2i{world_x, world_y}
|
||||
// Generate each tile, allowing for biome blending at edges
|
||||
for x in 0 ..< CHUNK_SIZE {
|
||||
for y in 0 ..< CHUNK_SIZE {
|
||||
world_x := pos.x * CHUNK_SIZE + x
|
||||
world_y := pos.y * CHUNK_SIZE + y
|
||||
world_pos := Vec2i{world_x, world_y}
|
||||
|
||||
// Check the tile's specific biome (for transitions)
|
||||
tile_biome := get_biome_type(world_pos, seed)
|
||||
// Check the tile's specific biome (for transitions)
|
||||
tile_biome := get_biome_type(world_pos, seed)
|
||||
|
||||
// Calculate distances to chunk edges for potential blending
|
||||
edge_dist_x := min(x, CHUNK_SIZE - 1 - x)
|
||||
edge_dist_y := min(y, CHUNK_SIZE - 1 - y)
|
||||
edge_dist := min(edge_dist_x, edge_dist_y)
|
||||
// Calculate distances to chunk edges for potential blending
|
||||
edge_dist_x := min(x, CHUNK_SIZE - 1 - x)
|
||||
edge_dist_y := min(y, CHUNK_SIZE - 1 - y)
|
||||
edge_dist := min(edge_dist_x, edge_dist_y)
|
||||
|
||||
// Blend between chunk biome and tile biome near edges
|
||||
// for smoother transitions between chunks
|
||||
biome_to_use := biome
|
||||
if edge_dist < 4 { // Within 4 tiles of chunk edge
|
||||
blend_factor := f32(edge_dist) / 4.0
|
||||
// Blend between chunk biome and tile biome near edges
|
||||
// for smoother transitions between chunks
|
||||
biome_to_use := biome
|
||||
if edge_dist < 4 { // Within 4 tiles of chunk edge
|
||||
blend_factor := f32(edge_dist) / 4.0
|
||||
|
||||
// Simple way to blend biomes - just pick one based on blend factor
|
||||
// For a more sophisticated approach, you could actually blend features
|
||||
if hash_noise(world_x, world_y, seed) > blend_factor {
|
||||
biome_to_use = tile_biome
|
||||
}
|
||||
}
|
||||
// Simple way to blend biomes - just pick one based on blend factor
|
||||
// For a more sophisticated approach, you could actually blend features
|
||||
if hash_noise(world_x, world_y, seed) > blend_factor {
|
||||
biome_to_use = tile_biome
|
||||
}
|
||||
}
|
||||
|
||||
chunk.tiles[x][y] = generate_tile(world_pos, seed, biome_to_use)
|
||||
}
|
||||
}
|
||||
chunk.tiles[x][y] = generate_tile(world_pos, seed, biome_to_use)
|
||||
}
|
||||
}
|
||||
|
||||
return chunk
|
||||
return chunk
|
||||
}
|
||||
|
||||
// Improved tile generation with biome transition support
|
||||
generate_tile :: proc(pos: Vec2i, seed: i64, biome: Biome) -> Tile {
|
||||
hash_value := hash_noise(pos.x, pos.y, seed)
|
||||
hash_value := hash_noise(pos.x, pos.y, seed)
|
||||
|
||||
// Use multiple noise scales for natural-looking features
|
||||
large_scale := 0.025
|
||||
medium_scale := 0.07
|
||||
small_scale := 0.20
|
||||
// Use multiple noise scales for natural-looking features
|
||||
large_scale := 0.025
|
||||
medium_scale := 0.07
|
||||
small_scale := 0.20
|
||||
|
||||
large_noise := noise.noise_2d(seed, {f64(pos.x) * large_scale, f64(pos.y) * large_scale})
|
||||
medium_noise := noise.noise_2d(seed + 5000, {f64(pos.x) * medium_scale, f64(pos.y) * medium_scale})
|
||||
small_noise := noise.noise_2d(seed + 10000, {f64(pos.x) * small_scale, f64(pos.y) * small_scale})
|
||||
large_noise := noise.noise_2d(seed, {f64(pos.x) * large_scale, f64(pos.y) * large_scale})
|
||||
medium_noise := noise.noise_2d(
|
||||
seed + 5000,
|
||||
{f64(pos.x) * medium_scale, f64(pos.y) * medium_scale},
|
||||
)
|
||||
small_noise := noise.noise_2d(
|
||||
seed + 10000,
|
||||
{f64(pos.x) * small_scale, f64(pos.y) * small_scale},
|
||||
)
|
||||
|
||||
// Combine noise at different scales
|
||||
combined_noise := large_noise * 0.6 + medium_noise * 0.3 + small_noise * 0.1
|
||||
// Combine noise at different scales
|
||||
combined_noise := large_noise * 0.6 + medium_noise * 0.3 + small_noise * 0.1
|
||||
|
||||
// Different biomes use the noise differently
|
||||
switch biome.type {
|
||||
case .GRASSLAND:
|
||||
if combined_noise > 0.8 {
|
||||
return tree_tile
|
||||
} else if combined_noise > 0.2 {
|
||||
return grass_tile
|
||||
} else {
|
||||
return nothing_tile
|
||||
}
|
||||
case .FOREST:
|
||||
if combined_noise > 0.75 {
|
||||
return double_tree_tile
|
||||
} else if combined_noise > 0.4 {
|
||||
return tree_tile
|
||||
} else if combined_noise > 0.0 {
|
||||
return grass_tile
|
||||
} else {
|
||||
return nothing_tile
|
||||
}
|
||||
case .DESERT:
|
||||
// Different biomes use the noise differently
|
||||
switch biome.type {
|
||||
case .GRASSLAND:
|
||||
if combined_noise > 0.8 {
|
||||
return tree_tile
|
||||
} else if combined_noise > 0.2 {
|
||||
return grass_tile
|
||||
} else {
|
||||
return nothing_tile
|
||||
}
|
||||
case .FOREST:
|
||||
if combined_noise > 0.75 {
|
||||
return double_tree_tile
|
||||
} else if combined_noise > 0.4 {
|
||||
return tree_tile
|
||||
} else if combined_noise > 0.0 {
|
||||
return grass_tile
|
||||
} else {
|
||||
return nothing_tile
|
||||
}
|
||||
case .DESERT:
|
||||
cactus_noise := medium_noise * 0.5 + 0.5 // Normalize to 0-1
|
||||
|
||||
cactus_noise := medium_noise * 0.5 + 0.5 // Normalize to 0-1
|
||||
|
||||
if cactus_noise > 0.8 && hash_value > 0.65 {
|
||||
return cactus_tile
|
||||
} else if combined_noise > 0.85 {
|
||||
return dead_bush_tile
|
||||
} else {
|
||||
return nothing_tile
|
||||
}
|
||||
case .LAKE:
|
||||
// Lakes can have different depths
|
||||
if combined_noise > 0.7 {
|
||||
return shallow_water_tile // You'd need to define this
|
||||
} else {
|
||||
return water_tile
|
||||
}
|
||||
case:
|
||||
return nothing_tile
|
||||
}
|
||||
if cactus_noise > 0.8 && hash_value > 0.65 {
|
||||
return cactus_tile
|
||||
} else if combined_noise > 0.85 {
|
||||
return dead_bush_tile
|
||||
} else {
|
||||
return nothing_tile
|
||||
}
|
||||
case .LAKE:
|
||||
// Lakes can have different depths
|
||||
if combined_noise > 0.7 {
|
||||
return shallow_water_tile // You'd need to define this
|
||||
} else {
|
||||
return water_tile
|
||||
}
|
||||
case:
|
||||
return nothing_tile
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user