Compare commits
No commits in common. "4871a4ed3e59bc7407fcf33fc0f5ad05820b3852" and "bdf4f7a7b61a7bbada171393c2a92cc3cf944d3b" have entirely different histories.
4871a4ed3e
...
bdf4f7a7b6
@ -1,206 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import "core:fmt"
|
|
||||||
import "core:math/noise"
|
|
||||||
|
|
||||||
// Fixed desert finding procedure
|
|
||||||
find_desert :: proc(seed: i64) -> (found: bool, pos: Vec2i) {
|
|
||||||
search_radius := 1000
|
|
||||||
step_size := 20 // Check every 20 blocks to speed up the search
|
|
||||||
|
|
||||||
// Track how many desert tiles we find for debugging
|
|
||||||
desert_count := 0
|
|
||||||
total_checked := 0
|
|
||||||
last_desert_pos := Vec2i{0, 0}
|
|
||||||
|
|
||||||
fmt.println("Searching for deserts with seed:", seed)
|
|
||||||
|
|
||||||
for x := -search_radius; x < search_radius; x += step_size {
|
|
||||||
for y := -search_radius; y < search_radius; y += step_size {
|
|
||||||
pos := Vec2i{x, y}
|
|
||||||
biome := get_biome_type(pos, seed)
|
|
||||||
total_checked += 1
|
|
||||||
|
|
||||||
if biome.type == .DESERT {
|
|
||||||
desert_count += 1
|
|
||||||
last_desert_pos = pos
|
|
||||||
fmt.println("Found desert at:", pos)
|
|
||||||
|
|
||||||
if desert_count <= 5 { // Only report the first few to avoid spam
|
|
||||||
// Verify by checking adjacent tiles to confirm it's not just a single glitched tile
|
|
||||||
desert_size := 0
|
|
||||||
check_radius := 3
|
|
||||||
|
|
||||||
for cx := -check_radius; cx <= check_radius; cx += 1 {
|
|
||||||
for cy := -check_radius; cy <= check_radius; cy += 1 {
|
|
||||||
check_pos := Vec2i{x + cx, y + cy}
|
|
||||||
check_biome := get_biome_type(check_pos, seed)
|
|
||||||
|
|
||||||
if check_biome.type == .DESERT {
|
|
||||||
desert_size += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.println(" Desert size (in 7x7 area):", desert_size, "out of", (check_radius*2+1)*(check_radius*2+1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report desert statistics
|
|
||||||
desert_percentage := f32(desert_count) / f32(total_checked) * 100.0
|
|
||||||
fmt.println("Desert statistics:")
|
|
||||||
fmt.println(" Total positions checked:", total_checked)
|
|
||||||
fmt.println(" Desert tiles found:", desert_count)
|
|
||||||
fmt.println(" Desert percentage:", desert_percentage, "%")
|
|
||||||
|
|
||||||
if desert_count > 0 {
|
|
||||||
return true, last_desert_pos // Return the last desert found
|
|
||||||
} else {
|
|
||||||
fmt.println("No desert found within search radius")
|
|
||||||
return false, Vec2i{0, 0}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a biome distribution map to visualize the actual distribution
|
|
||||||
generate_biome_map :: proc(seed: i64, width: int, height: int) {
|
|
||||||
biome_counts := [BiomeType]int{}
|
|
||||||
total_tiles := width * height
|
|
||||||
|
|
||||||
fmt.println("Generating biome distribution map", width, "x", height)
|
|
||||||
|
|
||||||
// First pass - count biomes
|
|
||||||
for y := 0; y < height; y += 1 {
|
|
||||||
for x := 0; x < width; x += 1 {
|
|
||||||
// Use a different area of the world for better sampling
|
|
||||||
world_x := (x - width/2) * 20
|
|
||||||
world_y := (y - height/2) * 20
|
|
||||||
|
|
||||||
biome := get_biome_type(Vec2i{world_x, world_y}, seed)
|
|
||||||
biome_counts[biome.type] += 1
|
|
||||||
|
|
||||||
// Print a character representing each biome for a ASCII map
|
|
||||||
if y % 5 == 0 && x % 5 == 0 { // Print sparse map to fit in console
|
|
||||||
c := '?'
|
|
||||||
switch biome.type {
|
|
||||||
case .DESERT: c = 'D'
|
|
||||||
case .GRASSLAND: c = 'G'
|
|
||||||
case .FOREST: c = 'F'
|
|
||||||
case .LAKE: c = 'L'
|
|
||||||
}
|
|
||||||
fmt.print(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if y % 5 == 0 {
|
|
||||||
fmt.println()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print biome statistics
|
|
||||||
fmt.println("\nBiome Distribution:")
|
|
||||||
fmt.println(" Total area:", total_tiles, "tiles")
|
|
||||||
|
|
||||||
for biome_type, count in biome_counts {
|
|
||||||
percentage := f32(count) / f32(total_tiles) * 100.0
|
|
||||||
fmt.println(" ", biome_type, ":", count, "tiles (", percentage, "%)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug the noise distribution directly
|
|
||||||
debug_noise_values :: proc(seed: i64) {
|
|
||||||
// Import math package at the top of your file
|
|
||||||
// import "core:math"
|
|
||||||
|
|
||||||
// Collect some sample values to see the actual distribution
|
|
||||||
samples := 1000
|
|
||||||
temp_values := make([dynamic]f64, 0, samples)
|
|
||||||
moisture_values := make([dynamic]f64, 0, samples)
|
|
||||||
|
|
||||||
for i := 0; i < samples; i += 1 {
|
|
||||||
// Sample across a wide area
|
|
||||||
x := (i % 50) * 100 - 2500
|
|
||||||
y := (i / 50) * 100 - 2500
|
|
||||||
|
|
||||||
// Generate values the same way as in get_biome_type
|
|
||||||
continent_scale := 0.001
|
|
||||||
region_scale := 0.005
|
|
||||||
|
|
||||||
moisture_seed := seed + 20000
|
|
||||||
temperature_seed := seed + 30000
|
|
||||||
|
|
||||||
// Get raw noise values
|
|
||||||
moisture := noise.noise_2d(moisture_seed, {f64(x) * region_scale, f64(y) * region_scale})
|
|
||||||
temperature := noise.noise_2d(temperature_seed, {f64(x) * region_scale, f64(y) * region_scale})
|
|
||||||
|
|
||||||
// Apply the same transformations as in your get_biome_type function
|
|
||||||
// Remove this line if you don't have math imported, or replace with your own pow implementation
|
|
||||||
// temperature = math.pow(temperature * 0.5 + 0.5, 0.8) * 2.0 - 1.0
|
|
||||||
|
|
||||||
// Normalize to 0-1 range
|
|
||||||
normalized_moisture := f64(moisture * 0.5 + 0.5)
|
|
||||||
normalized_temperature := f64(temperature * 0.5 + 0.5)
|
|
||||||
|
|
||||||
append_elem(&temp_values, normalized_temperature)
|
|
||||||
append_elem(&moisture_values, normalized_moisture)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate statistics
|
|
||||||
temp_min, temp_max, temp_avg := 1.0, 0.0, 0.0
|
|
||||||
moisture_min, moisture_max, moisture_avg := 1.0, 0.0, 0.0
|
|
||||||
|
|
||||||
for i := 0; i < samples; i += 1 {
|
|
||||||
temp := temp_values[i]
|
|
||||||
moisture := moisture_values[i]
|
|
||||||
|
|
||||||
temp_avg += temp
|
|
||||||
moisture_avg += moisture
|
|
||||||
|
|
||||||
temp_min = min(temp_min, temp)
|
|
||||||
temp_max = max(temp_max, temp)
|
|
||||||
moisture_min = min(moisture_min, moisture)
|
|
||||||
moisture_max = max(moisture_max, moisture)
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_avg /= f64(samples)
|
|
||||||
moisture_avg /= f64(samples)
|
|
||||||
|
|
||||||
// Print statistics
|
|
||||||
fmt.println("Temperature values (normalized to 0-1):")
|
|
||||||
fmt.println(" Min:", temp_min, "Max:", temp_max, "Avg:", temp_avg)
|
|
||||||
fmt.println("Moisture values (normalized to 0-1):")
|
|
||||||
fmt.println(" Min:", moisture_min, "Max:", moisture_max, "Avg:", moisture_avg)
|
|
||||||
|
|
||||||
// Count how many points would qualify as deserts with different thresholds
|
|
||||||
desert_count_strict := 0
|
|
||||||
desert_count_medium := 0
|
|
||||||
desert_count_loose := 0
|
|
||||||
|
|
||||||
for i := 0; i < samples; i += 1 {
|
|
||||||
temp := temp_values[i]
|
|
||||||
moisture := moisture_values[i]
|
|
||||||
|
|
||||||
// Strict: temp > 0.55 && moisture < 0.4
|
|
||||||
if temp > 0.55 && moisture < 0.4 {
|
|
||||||
desert_count_strict += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Medium: temp > 0.4 && moisture < 0.6
|
|
||||||
if temp > 0.4 && moisture < 0.6 {
|
|
||||||
desert_count_medium += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loose: temp > 0.3 || moisture < 0.4
|
|
||||||
if temp > 0.3 || moisture < 0.4 {
|
|
||||||
desert_count_loose += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.println("\nDesert qualification rates with different thresholds:")
|
|
||||||
fmt.println(" Strict (temp > 0.55 && moisture < 0.4):",
|
|
||||||
f32(desert_count_strict)/f32(samples)*100.0, "%")
|
|
||||||
fmt.println(" Medium (temp > 0.4 && moisture < 0.6):",
|
|
||||||
f32(desert_count_medium)/f32(samples)*100.0, "%")
|
|
||||||
fmt.println(" Loose (temp > 0.3 || moisture < 0.4):",
|
|
||||||
f32(desert_count_loose)/f32(samples)*100.0, "%")
|
|
||||||
}
|
|
||||||
@ -24,28 +24,34 @@ main :: proc() {
|
|||||||
|
|
||||||
rl.SetTargetFPS(60)
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
|
|
||||||
player = {
|
player = {
|
||||||
position = {CELL_SIZE * 0, CELL_SIZE * 0},
|
position = {CELL_SIZE * 10, CELL_SIZE * 10},
|
||||||
camera = {
|
camera = {
|
||||||
zoom = 4,
|
zoom = 3,
|
||||||
target = {player.position.x + (CELL_SIZE / 2), player.position.y + (CELL_SIZE / 2)},
|
target = {player.position.x + (CELL_SIZE / 2), player.position.y + (CELL_SIZE / 2)},
|
||||||
offset = {f32(rl.GetScreenWidth()) / 2, f32(rl.GetScreenHeight()) / 2},
|
offset = {f32(rl.GetScreenWidth()) / 2, f32(rl.GetScreenHeight()) / 2},
|
||||||
},
|
},
|
||||||
mode = .INTERACT,
|
mode = .INTERACT,
|
||||||
speed = 1,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_tilemap()
|
load_tilemap()
|
||||||
defer unload_tilemap()
|
defer unload_tilemap()
|
||||||
|
|
||||||
world = create_world("test_world", 10172020)
|
world = create_world("test_world")
|
||||||
|
|
||||||
|
set_tile(&world, tree_tile, {400,400})
|
||||||
|
|
||||||
save_world(&world)
|
save_world(&world)
|
||||||
|
|
||||||
|
|
||||||
game_loop()
|
game_loop()
|
||||||
}
|
}
|
||||||
|
|
||||||
game_loop :: proc() {
|
game_loop :: proc() {
|
||||||
|
|
||||||
|
pos_string : string
|
||||||
|
pos_cstring : cstring
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
for !rl.WindowShouldClose() {
|
||||||
|
|
||||||
@ -63,23 +69,16 @@ game_loop :: proc() {
|
|||||||
|
|
||||||
player_grid_pos := get_player_grid_position(&player)
|
player_grid_pos := get_player_grid_position(&player)
|
||||||
player_grid_pos_tile := get_world_tile(&world, vec2_to_vec2i(player_grid_pos))
|
player_grid_pos_tile := get_world_tile(&world, vec2_to_vec2i(player_grid_pos))
|
||||||
current_chunk := get_chunk_from_world_pos(&world, player_grid_pos)
|
status_string := rl.TextFormat("POS: [%i,%i] : %v | MODE: %v", int(player_grid_pos.x), int(player_grid_pos.y), player_grid_pos_tile.type, player.mode)
|
||||||
status_string := rl.TextFormat("POS: [%i,%i] : %v | Chunk: [%i,%i] : %v | MODE: %v", int(player_grid_pos.x), int(player_grid_pos.y), player_grid_pos_tile.type, current_chunk.position.x, current_chunk.position.y, get_biome_from_id(current_chunk.biome_id).name, player.mode)
|
|
||||||
pos_string := rl.TextFormat("Actual pos: %v", player.position)
|
|
||||||
rl.DrawText(status_string, 5, 25, 20, rl.RED)
|
rl.DrawText(status_string, 5, 25, 20, rl.RED)
|
||||||
|
|
||||||
// Debug: Draw collision check position
|
|
||||||
target_pos := player_grid_pos
|
|
||||||
chunk_pos := world_pos_to_chunk_pos(player_grid_pos)
|
|
||||||
local_pos := get_local_chunk_pos(vec2_to_vec2i(player_grid_pos))
|
|
||||||
format_string := rl.TextFormat("Grid: (%.0f,%.0f) Chunk: (%d,%d) Local: (%d,%d)",
|
|
||||||
player_grid_pos.x, player_grid_pos.y,
|
|
||||||
chunk_pos.x, chunk_pos.y,
|
|
||||||
local_pos.x, local_pos.y)
|
|
||||||
rl.DrawText(format_string, 10, 45, 20, rl.YELLOW)
|
|
||||||
|
|
||||||
rl.EndDrawing()
|
rl.EndDrawing()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete(pos_string)
|
||||||
|
delete(pos_cstring)
|
||||||
}
|
}
|
||||||
|
|
||||||
update :: proc() {
|
update :: proc() {
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
import "core:math"
|
|
||||||
|
|
||||||
Vec2i :: struct {
|
Vec2i :: struct {
|
||||||
x: int,
|
x: int,
|
||||||
y: int,
|
y: int,
|
||||||
@ -12,15 +10,17 @@ vec2i_to_vec2 :: proc(v2i:Vec2i) -> [2]f32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vec2_to_vec2i :: proc(v2:[2]f32) -> Vec2i {
|
vec2_to_vec2i :: proc(v2:[2]f32) -> Vec2i {
|
||||||
return {int(math.floor(v2.x)), int(math.floor(v2.y))}
|
return {int(v2.x), int(v2.y)}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_noise :: proc(x, y: int, seed: i64) -> f32 {
|
to_bytes :: proc(v: $T) -> [size_of(T)]u8 {
|
||||||
h: i64 = i64(x) * 374761393
|
val := v
|
||||||
h *= i64(y) * 668265263
|
encoded_bytes := (^[size_of(T)]u8)(&val)
|
||||||
h *= seed
|
return encoded_bytes^
|
||||||
h *= 3266489917
|
|
||||||
h >>= 16
|
|
||||||
return f32(h & 0xFFFF) / 65535.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
from_bytes :: proc($T:typeid, data: [size_of(T)]u8) -> T {
|
||||||
|
bytes := data
|
||||||
|
decoded_value := (^T)(&bytes)^
|
||||||
|
return decoded_value
|
||||||
|
}
|
||||||
|
|||||||
135
game/player.odin
135
game/player.odin
@ -2,7 +2,6 @@ package game
|
|||||||
|
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:math"
|
|
||||||
|
|
||||||
CHUNK_UNLOAD_DISTANCE :: 3
|
CHUNK_UNLOAD_DISTANCE :: 3
|
||||||
|
|
||||||
@ -11,7 +10,6 @@ Player :: struct {
|
|||||||
move_timer: f32,
|
move_timer: f32,
|
||||||
mode: InteractMode,
|
mode: InteractMode,
|
||||||
camera: rl.Camera2D,
|
camera: rl.Camera2D,
|
||||||
speed:f32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InteractMode :: enum {
|
InteractMode :: enum {
|
||||||
@ -33,42 +31,55 @@ player_update :: proc(p : ^Player, w: ^World) {
|
|||||||
handle_player_input(p,w)
|
handle_player_input(p,w)
|
||||||
handle_player_camera(p)
|
handle_player_camera(p)
|
||||||
|
|
||||||
// if rl.IsKeyPressed(.SPACE) {
|
if rl.IsKeyPressed(.SPACE) {
|
||||||
// // set_tile(w, bricks_tile, vec2_to_vec2i(get_player_grid_position(p)))
|
set_tile(w, tree_tile, vec2_to_vec2i(get_player_grid_position(p)))
|
||||||
// find_desert(w.seed)
|
}
|
||||||
// generate_biome_map(w.seed, 100, 100)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private="file")
|
@(private="file")
|
||||||
player_update_chunks :: proc(p: ^Player, w: ^World) {
|
player_update_chunks :: proc(p: ^Player, w: ^World) {
|
||||||
// Configurable view distance (in chunks)
|
|
||||||
VIEW_DISTANCE :: 2
|
|
||||||
|
|
||||||
player_grid_pos := get_player_grid_position(p)
|
player_grid_pos := get_player_grid_position(p)
|
||||||
current_player_chunk := get_chunk_from_world_pos(w, player_grid_pos)
|
current_player_chunk := get_chunk_from_world_pos(w, player_grid_pos)
|
||||||
|
|
||||||
// Track which chunks should be loaded
|
directions := [8]Vec2i{
|
||||||
chunks_to_keep := make(map[Vec2i]bool)
|
Vec2i{ 1, 0 }, Vec2i{ -1, 0 }, // Right, Left
|
||||||
defer delete(chunks_to_keep)
|
Vec2i{ 0, 1 }, Vec2i{ 0, -1 }, // Down, Up
|
||||||
|
Vec2i{ 1, 1 }, Vec2i{ -1, -1 }, // Bottom-right, Top-left
|
||||||
// Load chunks in a square around the player's current chunk
|
Vec2i{ 1, -1 }, Vec2i{ -1, 1 }, // Top-right, Bottom-left
|
||||||
for y := -VIEW_DISTANCE; y <= VIEW_DISTANCE; y += 1 {
|
|
||||||
for x := -VIEW_DISTANCE; x <= VIEW_DISTANCE; x += 1 {
|
|
||||||
chunk_pos := Vec2i{
|
|
||||||
current_player_chunk.position.x + x,
|
|
||||||
current_player_chunk.position.y + y,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the chunk and mark it to keep
|
|
||||||
get_chunk(w, chunk_pos)
|
|
||||||
chunks_to_keep[chunk_pos] = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload chunks outside the view distance
|
// Always ensure the current chunk is loaded
|
||||||
|
get_chunk(w, current_player_chunk.position)
|
||||||
|
|
||||||
|
// Load adjacent chunks
|
||||||
|
for dir in directions {
|
||||||
|
adjacent_pos := Vec2i{
|
||||||
|
current_player_chunk.position.x + dir.x,
|
||||||
|
current_player_chunk.position.y + dir.y
|
||||||
|
}
|
||||||
|
|
||||||
|
get_chunk(w, adjacent_pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload non-adjacent chunks
|
||||||
for chunk_pos in w.chunks {
|
for chunk_pos in w.chunks {
|
||||||
if !chunks_to_keep[chunk_pos] {
|
if chunk_pos == current_player_chunk.position {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
is_adjacent := false
|
||||||
|
for dir in directions {
|
||||||
|
check_pos := Vec2i{
|
||||||
|
current_player_chunk.position.x + dir.x,
|
||||||
|
current_player_chunk.position.y + dir.y
|
||||||
|
}
|
||||||
|
if chunk_pos == check_pos {
|
||||||
|
is_adjacent = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !is_adjacent {
|
||||||
unload_chunk(chunk_pos, w)
|
unload_chunk(chunk_pos, w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,29 +88,18 @@ player_update_chunks :: proc(p: ^Player, w: ^World) {
|
|||||||
@(private="file")
|
@(private="file")
|
||||||
handle_player_input :: proc(p:^Player, w:^World) {
|
handle_player_input :: proc(p:^Player, w:^World) {
|
||||||
|
|
||||||
|
|
||||||
current_tile := get_world_tile(w, vec2_to_vec2i(get_player_grid_position(p)))
|
|
||||||
// Movement
|
// Movement
|
||||||
|
target_pos := get_player_grid_position(p)
|
||||||
dt := rl.GetFrameTime()
|
dt := rl.GetFrameTime()
|
||||||
move_delay : f32 = 0.2 / p.speed
|
move_delay : f32 = 0.2
|
||||||
if p.move_timer > 0 {
|
if p.move_timer > 0 {
|
||||||
p.move_timer -= dt
|
p.move_timer -= dt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if current_tile.type == .WATER {
|
|
||||||
p.speed = 0.3
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p.speed = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.move_timer <= 0 {
|
if p.move_timer <= 0 {
|
||||||
current_pos := get_player_grid_position(p)
|
|
||||||
if rl.IsKeyDown(.D) {
|
if rl.IsKeyDown(.D) {
|
||||||
target_pos := rl.Vector2{current_pos.x + 1, current_pos.y}
|
target_pos.x += 1
|
||||||
if !will_collide(.RIGHT, p, w) {
|
if !will_collide(w, target_pos) {
|
||||||
player.position.x += CELL_SIZE
|
player.position.x += CELL_SIZE
|
||||||
p.move_timer = move_delay
|
p.move_timer = move_delay
|
||||||
player_update_chunks(p,w)
|
player_update_chunks(p,w)
|
||||||
@ -107,8 +107,8 @@ handle_player_input :: proc(p:^Player, w:^World) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rl.IsKeyDown(.A) {
|
if rl.IsKeyDown(.A) {
|
||||||
target_pos := rl.Vector2{current_pos.x - 1, current_pos.y}
|
target_pos.x -= 1
|
||||||
if !will_collide(.LEFT, p, w) {
|
if !will_collide(w, target_pos) {
|
||||||
player.position.x -= CELL_SIZE
|
player.position.x -= CELL_SIZE
|
||||||
p.move_timer = move_delay
|
p.move_timer = move_delay
|
||||||
player_update_chunks(p,w)
|
player_update_chunks(p,w)
|
||||||
@ -116,8 +116,8 @@ handle_player_input :: proc(p:^Player, w:^World) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rl.IsKeyDown(.W) {
|
if rl.IsKeyDown(.W) {
|
||||||
target_pos := rl.Vector2{current_pos.x, current_pos.y - 1}
|
target_pos.y -= 1
|
||||||
if !will_collide(.UP, p, w) {
|
if !will_collide(w, target_pos) {
|
||||||
player.position.y -= CELL_SIZE
|
player.position.y -= CELL_SIZE
|
||||||
p.move_timer = move_delay
|
p.move_timer = move_delay
|
||||||
player_update_chunks(p,w)
|
player_update_chunks(p,w)
|
||||||
@ -125,8 +125,8 @@ handle_player_input :: proc(p:^Player, w:^World) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rl.IsKeyDown(.S) {
|
if rl.IsKeyDown(.S) {
|
||||||
target_pos := rl.Vector2{current_pos.x, current_pos.y + 1}
|
target_pos.y += 1
|
||||||
if !will_collide(.DOWN, p, w) {
|
if !will_collide(w, target_pos) {
|
||||||
p.move_timer = move_delay
|
p.move_timer = move_delay
|
||||||
player.position.y += CELL_SIZE
|
player.position.y += CELL_SIZE
|
||||||
player_update_chunks(p,w)
|
player_update_chunks(p,w)
|
||||||
@ -192,36 +192,29 @@ get_tile_in_direction :: proc(direction:InteractDirection, p:^Player, w:^World)
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_player_grid_position :: proc(player:^Player) -> rl.Vector2 {
|
get_player_grid_position :: proc(player:^Player) -> rl.Vector2 {
|
||||||
grid_pos_x := math.floor(player.position.x / CELL_SIZE)
|
grid_pos_x := player.position.x / CELL_SIZE
|
||||||
grid_pos_y := math.floor(player.position.y / CELL_SIZE)
|
grid_pos_y := player.position.y / CELL_SIZE
|
||||||
|
|
||||||
return {grid_pos_x, grid_pos_y}
|
return {grid_pos_x, grid_pos_y}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_player :: proc(player:^Player) {
|
draw_player :: proc(player:^Player) {
|
||||||
draw_tile({25,0}, player.position, {30,100,120,255})
|
draw_tile({27,0}, player.position, rl.DARKBLUE)
|
||||||
|
|
||||||
// Debug: Draw player's grid cell
|
|
||||||
// player_grid_pos := get_player_grid_position(player)
|
|
||||||
// world_pos_x := player_grid_pos.x * CELL_SIZE
|
|
||||||
// world_pos_y := player_grid_pos.y * CELL_SIZE
|
|
||||||
// rl.DrawRectangleLines(
|
|
||||||
// i32(world_pos_x),
|
|
||||||
// i32(world_pos_y),
|
|
||||||
// i32(CELL_SIZE),
|
|
||||||
// i32(CELL_SIZE),
|
|
||||||
// rl.RED
|
|
||||||
// )
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
will_collide :: proc(direction:InteractDirection, p:^Player, w:^World) -> bool {
|
|
||||||
tile, pos := get_tile_in_direction(direction, p, w)
|
|
||||||
|
|
||||||
if tile.type == .SOLID { return true }
|
will_collide :: proc(w:^World, pos:rl.Vector2) -> bool {
|
||||||
|
world_grid_pos := vec2_to_vec2i(pos)
|
||||||
|
chunk_pos := world_pos_to_chunk_pos(pos)
|
||||||
|
local_pos := get_local_chunk_pos(world_grid_pos)
|
||||||
|
|
||||||
|
chunk := get_chunk(w, chunk_pos)
|
||||||
|
tile := get_chunk_tile(chunk, local_pos)
|
||||||
|
|
||||||
|
#partial switch tile.type {
|
||||||
|
case .SOLID:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
Structure :: struct {
|
|
||||||
name:string,
|
|
||||||
tile_map:[dynamic][dynamic]Tile,
|
|
||||||
// Other data here later like NPCs and enemies?
|
|
||||||
}
|
|
||||||
|
|
||||||
test_structure := Structure {
|
|
||||||
name = "Test",
|
|
||||||
tile_map = {
|
|
||||||
// Make a structure here?????
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,227 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
import "core:math/noise"
|
|
||||||
import "core:math"
|
|
||||||
import "core:fmt"
|
|
||||||
|
|
||||||
BIOME_SCALE : f64 : 1
|
|
||||||
|
|
||||||
biome_list := map[u32]Biome {
|
|
||||||
0 = grasslands_biome,
|
|
||||||
1 = forest_biome,
|
|
||||||
2 = desert_biome,
|
|
||||||
3 = lake_biome,
|
|
||||||
}
|
|
||||||
|
|
||||||
BiomeType :: enum {
|
|
||||||
GRASSLAND,
|
|
||||||
FOREST,
|
|
||||||
LAKE,
|
|
||||||
DESERT,
|
|
||||||
}
|
|
||||||
|
|
||||||
Biome :: struct {
|
|
||||||
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 = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
forest_biome := Biome {
|
|
||||||
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 = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
lake_biome := Biome {
|
|
||||||
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_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 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 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})
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
if normalized_elevation < 0.3 {
|
|
||||||
return lake_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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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}
|
|
||||||
|
|
||||||
// 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}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk.tiles[x][y] = generate_tile(world_pos, seed, biome_to_use)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
// 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})
|
|
||||||
|
|
||||||
// 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:
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -15,13 +15,11 @@ TileType :: enum u8 {
|
|||||||
NOTHING,
|
NOTHING,
|
||||||
SOLID,
|
SOLID,
|
||||||
FOLIAGE,
|
FOLIAGE,
|
||||||
WATER,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceType :: enum u8 {
|
ResourceType :: enum u8 {
|
||||||
NOTHING,
|
NOTHING,
|
||||||
TREE,
|
TREE,
|
||||||
BONE,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InteractionType :: enum u8 {
|
InteractionType :: enum u8 {
|
||||||
@ -30,92 +28,18 @@ InteractionType :: enum u8 {
|
|||||||
ENEMY,
|
ENEMY,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nothing_tile := Tile {
|
||||||
// Premade Tiles
|
|
||||||
nothing_tile := Tile { // The most common tile, makes up the majority of the world.
|
|
||||||
type = .NOTHING,
|
|
||||||
tilemap_pos = {0,0},
|
|
||||||
color = {0,0,0,255},
|
|
||||||
interaction = .NOTHING,
|
|
||||||
resource = .NOTHING
|
|
||||||
}
|
|
||||||
|
|
||||||
grass_tile := Tile { // Common fauna, more dense in grasslands
|
|
||||||
type = .FOLIAGE,
|
type = .FOLIAGE,
|
||||||
tilemap_pos = {5,0},
|
tilemap_pos = {1,2},
|
||||||
color = {50,120,25,255},
|
color = {30,30,0,255},
|
||||||
interaction = .NOTHING,
|
interaction = .NOTHING,
|
||||||
resource = .NOTHING
|
resource = .NOTHING
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_tile := Tile { // Common grassland fauna, dense population in forests
|
tree_tile := Tile {
|
||||||
type = .SOLID,
|
type = .SOLID,
|
||||||
tilemap_pos = {0,1},
|
tilemap_pos = {0,1},
|
||||||
color = {10,60,15,255},
|
color = {17,87,30,255},
|
||||||
resource = .TREE,
|
resource = .TREE,
|
||||||
interaction = .RESOURCE,
|
interaction = .RESOURCE,
|
||||||
}
|
}
|
||||||
|
|
||||||
double_tree_tile := Tile { // Only found in forests, densly packed
|
|
||||||
type = .SOLID,
|
|
||||||
tilemap_pos = {3,2},
|
|
||||||
color = {10,60,15,255},
|
|
||||||
resource = .TREE,
|
|
||||||
interaction = .RESOURCE,
|
|
||||||
}
|
|
||||||
|
|
||||||
bricks_tile := Tile { // Unused, for now
|
|
||||||
type = .SOLID,
|
|
||||||
tilemap_pos = {10,17},
|
|
||||||
color = {140,30,10,255},
|
|
||||||
resource = .NOTHING,
|
|
||||||
interaction = .NOTHING,
|
|
||||||
}
|
|
||||||
|
|
||||||
water_tile := Tile { // Only seen in bodies of water
|
|
||||||
type = .WATER,
|
|
||||||
tilemap_pos = {19,1},
|
|
||||||
color = {5,10,70,255},
|
|
||||||
resource = .NOTHING,
|
|
||||||
interaction = .NOTHING,
|
|
||||||
}
|
|
||||||
|
|
||||||
shallow_water_tile := Tile { // Only seen in bodies of water
|
|
||||||
type = .WATER,
|
|
||||||
tilemap_pos = {19,1},
|
|
||||||
color = {5,40,80,255},
|
|
||||||
resource = .NOTHING,
|
|
||||||
interaction = .NOTHING,
|
|
||||||
}
|
|
||||||
|
|
||||||
cactus_tile := Tile { // Common desert fauna
|
|
||||||
type = .SOLID,
|
|
||||||
tilemap_pos = {6,1},
|
|
||||||
color = {5,40,0,255},
|
|
||||||
resource = .NOTHING,
|
|
||||||
interaction = .NOTHING,
|
|
||||||
}
|
|
||||||
|
|
||||||
double_cactus_tile := Tile { // Sparse desert fauna
|
|
||||||
type = .SOLID,
|
|
||||||
tilemap_pos = {7,1},
|
|
||||||
color = {5,40,0,255},
|
|
||||||
resource = .NOTHING,
|
|
||||||
interaction = .NOTHING,
|
|
||||||
}
|
|
||||||
|
|
||||||
cow_skull_tile := Tile { // Rare chance of spawning in a desert
|
|
||||||
type = .SOLID,
|
|
||||||
tilemap_pos = {1,15},
|
|
||||||
color = {200,200,200,255},
|
|
||||||
resource = .BONE,
|
|
||||||
interaction = .RESOURCE,
|
|
||||||
}
|
|
||||||
|
|
||||||
dead_bush_tile := Tile { // Common desert fauna
|
|
||||||
type = .FOLIAGE,
|
|
||||||
tilemap_pos = {6,2},
|
|
||||||
color = {145,100,30,255},
|
|
||||||
interaction = .NOTHING,
|
|
||||||
resource = .NOTHING
|
|
||||||
}
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import "core:fmt"
|
|||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:path/filepath"
|
import "core:path/filepath"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:math"
|
|
||||||
|
|
||||||
CELL_SIZE :: 16
|
CELL_SIZE :: 16
|
||||||
CHUNK_SIZE :: 32
|
CHUNK_SIZE :: 32
|
||||||
@ -13,17 +12,15 @@ WORLD_DATA_PATH :: "data/worlds"
|
|||||||
|
|
||||||
World :: struct {
|
World :: struct {
|
||||||
data_dir: string,
|
data_dir: string,
|
||||||
chunks: map[Vec2i]Chunk,
|
chunks: map[Vec2i]Chunk
|
||||||
seed: i64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk :: struct #packed {
|
Chunk :: struct #packed {
|
||||||
position: Vec2i,
|
position: Vec2i,
|
||||||
tiles: [CHUNK_SIZE][CHUNK_SIZE]Tile,
|
tiles: [CHUNK_SIZE][CHUNK_SIZE]Tile,
|
||||||
biome_id:u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
create_world :: proc(name:string, seed:i64) -> World {
|
create_world :: proc(name:string) -> World {
|
||||||
data_dir := fmt.tprintf("%v/%v", WORLD_DATA_PATH, name)
|
data_dir := fmt.tprintf("%v/%v", WORLD_DATA_PATH, name)
|
||||||
if !os.is_dir(data_dir) {
|
if !os.is_dir(data_dir) {
|
||||||
fmt.printfln("Data dir: %v does not exist", data_dir)
|
fmt.printfln("Data dir: %v does not exist", data_dir)
|
||||||
@ -38,11 +35,10 @@ create_world :: proc(name:string, seed:i64) -> World {
|
|||||||
return World {
|
return World {
|
||||||
data_dir = data_dir,
|
data_dir = data_dir,
|
||||||
chunks = make(map[Vec2i]Chunk),
|
chunks = make(map[Vec2i]Chunk),
|
||||||
seed = seed
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
load_world :: proc(name:string, seed:i64) -> World {
|
load_world :: proc(name:string) -> World {
|
||||||
dir := fmt.tprintf("%v/%v", WORLD_DATA_PATH, name)
|
dir := fmt.tprintf("%v/%v", WORLD_DATA_PATH, name)
|
||||||
if !os.is_dir(dir) {
|
if !os.is_dir(dir) {
|
||||||
panic("Couldnt load world")
|
panic("Couldnt load world")
|
||||||
@ -51,7 +47,6 @@ load_world :: proc(name:string, seed:i64) -> World {
|
|||||||
return World {
|
return World {
|
||||||
data_dir = dir,
|
data_dir = dir,
|
||||||
chunks = make(map[Vec2i]Chunk),
|
chunks = make(map[Vec2i]Chunk),
|
||||||
seed = seed
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,9 +86,6 @@ save_chunk :: proc(c:^Chunk, w:^World) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Biome ID
|
|
||||||
for byte in transmute([size_of(u32)]u8)c.biome_id {append(&data, byte)}
|
|
||||||
|
|
||||||
err := os.write_entire_file_or_err(filename, data[:])
|
err := os.write_entire_file_or_err(filename, data[:])
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -105,7 +97,7 @@ load_chunk :: proc(pos:Vec2i, w:^World) -> Chunk {
|
|||||||
data, err := os.read_entire_file_from_filename_or_err(filename)
|
data, err := os.read_entire_file_from_filename_or_err(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// fmt.printfln("No chunk %v found, generating new chunk", pos)
|
// fmt.printfln("No chunk %v found, generating new chunk", pos)
|
||||||
chunk := generate_chunk(pos, w.seed)
|
chunk := generate_chunk(pos)
|
||||||
save_chunk(&chunk, w)
|
save_chunk(&chunk, w)
|
||||||
return chunk
|
return chunk
|
||||||
}
|
}
|
||||||
@ -143,10 +135,6 @@ load_chunk :: proc(pos:Vec2i, w:^World) -> Chunk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load Biome ID
|
|
||||||
mem.copy(transmute([^]u8)&chunk.biome_id, &data[offset], size_of(u32))
|
|
||||||
offset += size_of(u32)
|
|
||||||
|
|
||||||
return chunk
|
return chunk
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -159,6 +147,20 @@ unload_chunk :: proc(pos:Vec2i, w:^World) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generate_chunk :: proc(pos:Vec2i) -> Chunk {
|
||||||
|
chunk := Chunk {position = pos}
|
||||||
|
|
||||||
|
for x in 0..<CHUNK_SIZE {
|
||||||
|
for y in 0..<CHUNK_SIZE {
|
||||||
|
chunk.tiles[x][y] = nothing_tile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
center_pos := Vec2i{CHUNK_SIZE/2, CHUNK_SIZE/2}
|
||||||
|
set_chunk_tile(&chunk, tree_tile, center_pos)
|
||||||
|
|
||||||
|
return chunk
|
||||||
|
}
|
||||||
|
|
||||||
get_chunk :: proc(w:^World, chunk_pos:Vec2i) -> ^Chunk {
|
get_chunk :: proc(w:^World, chunk_pos:Vec2i) -> ^Chunk {
|
||||||
chunk, exists := w.chunks[chunk_pos]
|
chunk, exists := w.chunks[chunk_pos]
|
||||||
@ -174,37 +176,24 @@ get_chunk_from_world_pos :: proc(w:^World, pos:rl.Vector2) -> ^Chunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
world_pos_to_chunk_pos :: proc(pos:rl.Vector2) -> Vec2i {
|
world_pos_to_chunk_pos :: proc(pos:rl.Vector2) -> Vec2i {
|
||||||
|
chunk_pos := vec2_to_vec2i({pos.x / CHUNK_SIZE, pos.y / CHUNK_SIZE})
|
||||||
x := int(math.floor(pos.x / CHUNK_SIZE))
|
return chunk_pos
|
||||||
y := int(math.floor(pos.y / CHUNK_SIZE))
|
|
||||||
return Vec2i{x,y}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get_local_chunk_pos :: proc(pos:Vec2i) -> Vec2i {
|
get_local_chunk_pos :: proc(pos:Vec2i) -> Vec2i {
|
||||||
x := (pos.x % CHUNK_SIZE + CHUNK_SIZE) % CHUNK_SIZE
|
return Vec2i {
|
||||||
y := (pos.y % CHUNK_SIZE + CHUNK_SIZE) % CHUNK_SIZE
|
(pos.x % CHUNK_SIZE + CHUNK_SIZE) % CHUNK_SIZE,
|
||||||
|
(pos.y % CHUNK_SIZE + CHUNK_SIZE) % CHUNK_SIZE,
|
||||||
return Vec2i{x,y}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get_world_tile :: proc(w:^World, pos:Vec2i) -> ^Tile {
|
get_world_tile :: proc(w:^World, pos:Vec2i) -> ^Tile {
|
||||||
chunk_x := int(math.floor(f32(pos.x) / f32(CHUNK_SIZE)))
|
chunk_pos := world_pos_to_chunk_pos(vec2i_to_vec2(pos))
|
||||||
chunk_y := int(math.floor(f32(pos.y) / f32(CHUNK_SIZE)))
|
local_pos := get_local_chunk_pos(pos)
|
||||||
chunk_pos := Vec2i{chunk_x, chunk_y}
|
|
||||||
|
|
||||||
local_x := (pos.x % CHUNK_SIZE + CHUNK_SIZE) % CHUNK_SIZE
|
|
||||||
local_y := (pos.y % CHUNK_SIZE + CHUNK_SIZE) % CHUNK_SIZE
|
|
||||||
local_pos := Vec2i{local_x, local_y}
|
|
||||||
|
|
||||||
chunk := get_chunk(w, chunk_pos)
|
chunk := get_chunk(w, chunk_pos)
|
||||||
|
|
||||||
return get_chunk_tile(chunk, local_pos)
|
return get_chunk_tile(chunk, local_pos)
|
||||||
|
|
||||||
// chunk_pos := world_pos_to_chunk_pos(vec2i_to_vec2(pos))
|
|
||||||
// local_pos := get_local_chunk_pos(pos)
|
|
||||||
//
|
|
||||||
// chunk := get_chunk(w, chunk_pos)
|
|
||||||
|
|
||||||
// return get_chunk_tile(chunk, local_pos)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get_chunk_tile :: proc(c:^Chunk, pos:Vec2i) -> ^Tile {
|
get_chunk_tile :: proc(c:^Chunk, pos:Vec2i) -> ^Tile {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user