diff --git a/game/game b/game/game index cdf8827..8e14cda 100755 Binary files a/game/game and b/game/game differ diff --git a/game/game.odin b/game/game.odin index 1d5b546..bba01b9 100644 --- a/game/game.odin +++ b/game/game.odin @@ -26,9 +26,9 @@ main :: proc() { player = { - position = {CELL_SIZE * 10, CELL_SIZE * 10}, + position = {CELL_SIZE * 10000, CELL_SIZE * 10000}, camera = { - zoom = 3, + zoom = 4, target = {player.position.x + (CELL_SIZE / 2), player.position.y + (CELL_SIZE / 2)}, offset = {f32(rl.GetScreenWidth()) / 2, f32(rl.GetScreenHeight()) / 2}, }, @@ -38,7 +38,7 @@ main :: proc() { load_tilemap() defer unload_tilemap() - world = create_world("test_world") + world = create_world("test_world", 5761) set_tile(&world, tree_tile, {400,400}) @@ -58,7 +58,7 @@ game_loop :: proc() { update() rl.BeginDrawing() - rl.ClearBackground(rl.BLACK) + rl.ClearBackground({10,80,10,255}) rl.BeginMode2D(player.camera) draw() diff --git a/game/math.odin b/game/math.odin index 2cb0de4..06ce7ba 100644 --- a/game/math.odin +++ b/game/math.odin @@ -1,5 +1,7 @@ package game +import "core:math" + Vec2i :: struct { x: int, y: int, @@ -13,14 +15,12 @@ vec2_to_vec2i :: proc(v2:[2]f32) -> Vec2i { return {int(v2.x), int(v2.y)} } -to_bytes :: proc(v: $T) -> [size_of(T)]u8 { - val := v - encoded_bytes := (^[size_of(T)]u8)(&val) - return encoded_bytes^ +hash_noise :: proc(x, y: int, seed: u32) -> f32 { + h: u32 = u32(x) * 374761393 + h *= u32(y) * 668265263 + h *= seed + 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 -} diff --git a/game/player.odin b/game/player.odin index e3d5c05..1f0137d 100644 --- a/game/player.odin +++ b/game/player.odin @@ -32,7 +32,7 @@ player_update :: proc(p : ^Player, w: ^World) { handle_player_camera(p) if rl.IsKeyPressed(.SPACE) { - set_tile(w, tree_tile, vec2_to_vec2i(get_player_grid_position(p))) + set_tile(w, bricks_tile, vec2_to_vec2i(get_player_grid_position(p))) } } @@ -199,7 +199,7 @@ get_player_grid_position :: proc(player:^Player) -> rl.Vector2 { } draw_player :: proc(player:^Player) { - draw_tile({27,0}, player.position, rl.DARKBLUE) + draw_tile({25,0}, player.position, {50,0,80,255}) } diff --git a/game/tiles.odin b/game/tiles.odin index b18e1a6..67d28f7 100644 --- a/game/tiles.odin +++ b/game/tiles.odin @@ -15,6 +15,7 @@ TileType :: enum u8 { NOTHING, SOLID, FOLIAGE, + WATER, } ResourceType :: enum u8 { @@ -29,9 +30,17 @@ InteractionType :: enum u8 { } nothing_tile := Tile { + type = .NOTHING, + tilemap_pos = {0,0}, + color = {0,0,0,255}, + interaction = .NOTHING, + resource = .NOTHING +} + +grass_tile := Tile { type = .FOLIAGE, - tilemap_pos = {1,2}, - color = {30,30,0,255}, + tilemap_pos = {5,0}, + color = {50,120,25,255}, interaction = .NOTHING, resource = .NOTHING } @@ -39,7 +48,23 @@ nothing_tile := Tile { tree_tile := Tile { type = .SOLID, tilemap_pos = {0,1}, - color = {17,87,30,255}, + color = {10,60,15,255}, resource = .TREE, interaction = .RESOURCE, } + +bricks_tile := Tile { + type = .SOLID, + tilemap_pos = {10,17}, + color = {140,30,10,255}, + resource = .NOTHING, + interaction = .NOTHING, +} + +water_tile := Tile { + type = .WATER, + tilemap_pos = {19,1}, + color = {5,40,80,255}, + resource = .NOTHING, + interaction = .NOTHING, +} diff --git a/game/world.odin b/game/world.odin index 5044b55..d82542e 100644 --- a/game/world.odin +++ b/game/world.odin @@ -12,7 +12,8 @@ WORLD_DATA_PATH :: "data/worlds" World :: struct { data_dir: string, - chunks: map[Vec2i]Chunk + chunks: map[Vec2i]Chunk, + seed: u32 } Chunk :: struct #packed { @@ -20,7 +21,7 @@ Chunk :: struct #packed { tiles: [CHUNK_SIZE][CHUNK_SIZE]Tile, } -create_world :: proc(name:string) -> World { +create_world :: proc(name:string, seed:u32) -> World { data_dir := fmt.tprintf("%v/%v", WORLD_DATA_PATH, name) if !os.is_dir(data_dir) { fmt.printfln("Data dir: %v does not exist", data_dir) @@ -34,11 +35,12 @@ create_world :: proc(name:string) -> World { return World { data_dir = data_dir, - chunks = make(map[Vec2i]Chunk), + chunks = make(map[Vec2i]Chunk), + seed = seed } } -load_world :: proc(name:string) -> World { +load_world :: proc(name:string, seed:u32) -> World { dir := fmt.tprintf("%v/%v", WORLD_DATA_PATH, name) if !os.is_dir(dir) { panic("Couldnt load world") @@ -47,6 +49,7 @@ load_world :: proc(name:string) -> World { return World { data_dir = dir, chunks = make(map[Vec2i]Chunk), + seed = seed } } @@ -97,7 +100,7 @@ load_chunk :: proc(pos:Vec2i, w:^World) -> Chunk { data, err := os.read_entire_file_from_filename_or_err(filename) if err != nil { // fmt.printfln("No chunk %v found, generating new chunk", pos) - chunk := generate_chunk(pos) + chunk := generate_chunk(pos, w.seed) save_chunk(&chunk, w) return chunk } @@ -147,21 +150,43 @@ unload_chunk :: proc(pos:Vec2i, w:^World) { } } -generate_chunk :: proc(pos:Vec2i) -> Chunk { +generate_chunk :: proc(pos:Vec2i, seed:u32) -> Chunk { chunk := Chunk {position = pos} for x in 0.. Tile { + base_noise := hash_noise(x, y, seed) + cluster_noise := hash_noise(x / 3, y / 3, seed + 12345) // Larger scale noise for clusters + + if base_noise < 0.70 { + return nothing_tile + } else if base_noise < 0.85 { + return grass_tile + } else if base_noise < 0.95 { + if cluster_noise > 0.5 { // Favor trees in cluster regions + return tree_tile + } + return grass_tile + } else { + if cluster_noise > 0.4 { // Only allow ponds in certain areas + return water_tile + } + return nothing_tile + } +} + + get_chunk :: proc(w:^World, chunk_pos:Vec2i) -> ^Chunk { chunk, exists := w.chunks[chunk_pos] if !exists {