Saving and loading chunks actually works now
This commit is contained in:
parent
c6c8864d67
commit
cddba06c25
1
game/%!(MISSING ARGUMENT).log
Normal file
1
game/%!(MISSING ARGUMENT).log
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,8 +1,8 @@
|
||||
package game
|
||||
|
||||
Vec2i :: struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
x: int,
|
||||
y: int,
|
||||
}
|
||||
|
||||
vec2i_to_vec2 :: proc(v2i:Vec2i) -> [2]f32 {
|
||||
@ -10,7 +10,7 @@ vec2i_to_vec2 :: proc(v2i:Vec2i) -> [2]f32 {
|
||||
}
|
||||
|
||||
vec2_to_vec2i :: proc(v2:[2]f32) -> Vec2i {
|
||||
return {i32(v2.x), i32(v2.y)}
|
||||
return {int(v2.x), int(v2.y)}
|
||||
}
|
||||
|
||||
to_bytes :: proc(v: $T) -> [size_of(T)]u8 {
|
||||
|
@ -28,32 +28,35 @@ handle_player_camera :: proc(p:^Player) {
|
||||
player_update :: proc(p : ^Player, w: ^World) {
|
||||
handle_player_input(p,w)
|
||||
handle_player_camera(p)
|
||||
|
||||
|
||||
if rl.IsKeyPressed(.SPACE) {
|
||||
set_tile(w, tree_tile, vec2_to_vec2i(get_player_grid_position(p)))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
load_nearby_chunks :: proc(w:^World, player_pos:rl.Vector2) {
|
||||
player_chunk_pos := world_pos_to_chunk_pos(player_pos)
|
||||
// player_chunk_pos := world_pos_to_chunk_pos(player_pos)
|
||||
|
||||
chunk_radius := 2 // Adjust based on the camera size
|
||||
// chunk_radius := 2 // Adjust based on the camera size
|
||||
|
||||
for x := -chunk_radius; x <= chunk_radius; x += 1 {
|
||||
for y := -chunk_radius; y <= chunk_radius; y += 1 {
|
||||
chunk_pos := Vec2i{player_chunk_pos.x + x, player_chunk_pos.y + y}
|
||||
get_chunk(w, chunk_pos) // Ensures chunk is loaded or generated
|
||||
}
|
||||
}
|
||||
// for x := -chunk_radius; x <= chunk_radius; x += 1 {
|
||||
// for y := -chunk_radius; y <= chunk_radius; y += 1 {
|
||||
// chunk_pos := Vec2i{player_chunk_pos.x + x, player_chunk_pos.y + y}
|
||||
// get_chunk(w, chunk_pos) // Ensures chunk is loaded or generated
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
unload_far_chunks :: proc(w: ^World, player_pos: Vec2i) {
|
||||
for chunk_pos in w.chunks {
|
||||
dist_x := abs(chunk_pos.x - player_pos.x)
|
||||
dist_y := abs(chunk_pos.y - player_pos.y)
|
||||
// for chunk_pos in w.chunks {
|
||||
// dist_x := abs(chunk_pos.x - player_pos.x)
|
||||
// dist_y := abs(chunk_pos.y - player_pos.y)
|
||||
|
||||
if dist_x > CHUNK_UNLOAD_DISTANCE || dist_y > CHUNK_UNLOAD_DISTANCE {
|
||||
unload_chunk(chunk_pos, w)
|
||||
}
|
||||
}
|
||||
// if dist_x > CHUNK_UNLOAD_DISTANCE || dist_y > CHUNK_UNLOAD_DISTANCE {
|
||||
// unload_chunk(chunk_pos, w)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
handle_player_input :: proc(p:^Player, w:^World) {
|
||||
|
107
game/tiles.odin
107
game/tiles.odin
@ -5,130 +5,33 @@ import "core:math/rand"
|
||||
|
||||
Tile :: struct #packed {
|
||||
tilemap_pos: Vec2i,
|
||||
color: rl.Color,
|
||||
color: [4]u8,
|
||||
type: TileType,
|
||||
interaction: InteractionType,
|
||||
resource: ResourceType,
|
||||
}
|
||||
|
||||
TileType :: enum {
|
||||
TileType :: enum u8 {
|
||||
NOTHING,
|
||||
WALL,
|
||||
FOLIAGE,
|
||||
}
|
||||
|
||||
ResourceType :: enum {
|
||||
ResourceType :: enum u8 {
|
||||
NOTHING,
|
||||
TREE,
|
||||
}
|
||||
|
||||
InteractionType :: enum {
|
||||
InteractionType :: enum u8 {
|
||||
NOTHING,
|
||||
RESOURCE,
|
||||
ENEMY,
|
||||
}
|
||||
serialize_tile :: proc(t: Tile) -> []byte {
|
||||
data: [dynamic]byte
|
||||
|
||||
// Tilemap Pos (16 bytes)
|
||||
tilemap_pos_bytes := serialize_vec2i(t.tilemap_pos)
|
||||
append(&data, ..tilemap_pos_bytes[:])
|
||||
|
||||
// Color (4 bytes)
|
||||
append(&data, byte(t.color.r), byte(t.color.g), byte(t.color.b), byte(t.color.a))
|
||||
|
||||
// TileType (8 bytes)
|
||||
tile_type_bytes := serialize_int(int(t.type))
|
||||
append(&data, ..tile_type_bytes[:])
|
||||
|
||||
// Interaction Type (8 bytes)
|
||||
interaction_bytes := serialize_int(int(t.interaction))
|
||||
append(&data, ..interaction_bytes[:])
|
||||
|
||||
// Resource Type (8 bytes)
|
||||
resource_bytes := serialize_int(int(t.resource))
|
||||
append(&data, ..resource_bytes[:])
|
||||
|
||||
return data[:]
|
||||
}
|
||||
|
||||
deserialize_tile :: proc(data: []byte) -> Tile {
|
||||
t: Tile
|
||||
|
||||
// Tilemap Pos (16 bytes)
|
||||
t.tilemap_pos = deserialize_vec2i(data[0:16])
|
||||
|
||||
// Color (4 bytes)
|
||||
t.color.r = u8(data[16])
|
||||
t.color.g = u8(data[17])
|
||||
t.color.b = u8(data[18])
|
||||
t.color.a = u8(data[19])
|
||||
|
||||
// TileType (8 bytes)
|
||||
t.type = TileType(deserialize_int(data[20:28]))
|
||||
|
||||
// Interaction Type (8 bytes)
|
||||
t.interaction = InteractionType(deserialize_int(data[28:36]))
|
||||
|
||||
// Resource Type (8 bytes)
|
||||
t.resource = ResourceType(deserialize_int(data[36:44]))
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// serialize_tile :: proc(t: Tile) -> []byte {
|
||||
// data: [dynamic]byte
|
||||
|
||||
// // TileType
|
||||
// tile_type_bytes := serialize_int(int(t.type))
|
||||
// append(&data, ..tile_type_bytes[:])
|
||||
|
||||
// // Tilemap Pos
|
||||
// tilemap_pos_bytes := serialize_vec2i(t.tilemap_pos)
|
||||
// append(&data, ..tilemap_pos_bytes[:])
|
||||
|
||||
// // Color
|
||||
// append(&data, byte(t.color.r), byte(t.color.g), byte(t.color.b), byte(t.color.a))
|
||||
|
||||
// // Interaction Type
|
||||
// interaction_bytes := serialize_int(int(t.interaction))
|
||||
// append(&data, ..interaction_bytes[:])
|
||||
|
||||
// // Resource Type
|
||||
// resource_bytes := serialize_int(int(t.resource))
|
||||
// append(&data, ..resource_bytes[:])
|
||||
|
||||
// return data[:]
|
||||
// }
|
||||
|
||||
// deserialize_tile :: proc(data:[]byte) -> Tile {
|
||||
// t: Tile
|
||||
|
||||
// // TileType
|
||||
// t.type = TileType(deserialize_int(data[0:4]))
|
||||
|
||||
// // TilemapPos
|
||||
// t.tilemap_pos = deserialize_vec2i(data[4:12])
|
||||
|
||||
// // Color
|
||||
// t.color.r = u8(data[12])
|
||||
// t.color.g = u8(data[13])
|
||||
// t.color.b = u8(data[14])
|
||||
// t.color.a = u8(data[15])
|
||||
|
||||
// // ResourceType
|
||||
// t.resource = ResourceType(deserialize_int(data[16:20]))
|
||||
|
||||
// // InteractionType
|
||||
// t.interaction = InteractionType(deserialize_int(data[20:24]))
|
||||
|
||||
// return t
|
||||
// }
|
||||
|
||||
tree_tile := Tile {
|
||||
type = .WALL,
|
||||
tilemap_pos = {0,1},
|
||||
color = rl.DARKGREEN,
|
||||
color = {17,87,30,255},
|
||||
resource = .TREE,
|
||||
interaction = .RESOURCE,
|
||||
}
|
||||
|
174
game/world.odin
174
game/world.odin
@ -4,9 +4,10 @@ import rl "vendor:raylib"
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
import "core:path/filepath"
|
||||
import "core:mem"
|
||||
|
||||
CELL_SIZE :: 16
|
||||
CHUNK_SIZE :: 32
|
||||
CHUNK_SIZE :: 5
|
||||
WORLD_DATA_PATH :: "data/worlds"
|
||||
|
||||
World :: struct {
|
||||
@ -61,105 +62,97 @@ save_world :: proc(w:^World) {
|
||||
}
|
||||
}
|
||||
|
||||
serialize_chunk :: proc(c:^Chunk) -> []byte {
|
||||
data : [dynamic]byte
|
||||
|
||||
// Position
|
||||
pos_bytes := serialize_vec2i(c.position)
|
||||
append(&data, ..pos_bytes[:])
|
||||
|
||||
// Tiles
|
||||
for y in 0..<CHUNK_SIZE {
|
||||
for x in 0..<CHUNK_SIZE {
|
||||
tile_bytes := serialize_tile(c.tiles[x][y])
|
||||
fmt.printfln("Serialized tile size: %v", len(tile_bytes))
|
||||
append(&data, ..tile_bytes[:])
|
||||
}
|
||||
}
|
||||
|
||||
fmt.printfln("Serialized chunk size: %v", len(data)) // Print final serialized size
|
||||
fmt.printfln("Before serialization, Chunk position: %v", c.position)
|
||||
return data[:]
|
||||
}
|
||||
|
||||
|
||||
deserialize_chunk :: proc(data: []byte) -> Chunk {
|
||||
chunk: Chunk
|
||||
|
||||
// Position
|
||||
chunk.position = deserialize_vec2i(data[0:8])
|
||||
|
||||
// Tiles
|
||||
offset := 8
|
||||
tile_size := size_of(Tile)
|
||||
|
||||
// Check total expected size of data
|
||||
expected_size := offset + (CHUNK_SIZE * CHUNK_SIZE * tile_size)
|
||||
if len(data) != expected_size {
|
||||
fmt.printfln("Error: Data size mismatch. Expected size: %v, Actual size: %v", expected_size, len(data))
|
||||
fmt.printfln("Chunk position: %v", chunk.position)
|
||||
|
||||
return chunk // Return empty or invalid chunk to handle the error.
|
||||
}
|
||||
|
||||
for y in 0..<CHUNK_SIZE {
|
||||
for x in 0..<CHUNK_SIZE {
|
||||
start := offset + (y * CHUNK_SIZE + x) * tile_size
|
||||
end := start + tile_size
|
||||
|
||||
fmt.printfln("Start:%v, End:%v", start, end)
|
||||
|
||||
if end > len(data) {
|
||||
fmt.printfln("Out of bounds access. Start:%v, End:%v | Data Length: %v", start, end, len(data))
|
||||
break
|
||||
}
|
||||
|
||||
chunk.tiles[x][y] = deserialize_tile(data[start:end])
|
||||
}
|
||||
}
|
||||
|
||||
fmt.printfln("Expected chunk size: %v | Serialized chunk data size: %v", size_of(Chunk), len(data))
|
||||
|
||||
return chunk
|
||||
}
|
||||
|
||||
|
||||
save_chunk :: proc(c:^Chunk, w:^World) {
|
||||
chunk_dir := fmt.tprintf("%v/%v", w.data_dir, "chunks")
|
||||
if !os.is_dir(chunk_dir) {
|
||||
os.make_directory(chunk_dir)
|
||||
}
|
||||
|
||||
filename := fmt.tprintf("%v/%v_%v.chunk", chunk_dir, c.position.x, c.position.y)
|
||||
|
||||
data := serialize_chunk(c)
|
||||
fmt.printfln("Saving chunk: %v", filename)
|
||||
|
||||
fmt.printfln("Writing chunk data: %v bytes", len(data))
|
||||
data := make([dynamic]u8)
|
||||
|
||||
|
||||
err := os.write_entire_file_or_err(filename, data)
|
||||
// Append Position
|
||||
for byte in transmute([size_of(int)]u8)c.position.x {append(&data, byte)}
|
||||
for byte in transmute([size_of(int)]u8)c.position.y {append(&data, byte)}
|
||||
|
||||
if err != nil {
|
||||
fmt.printfln("Failed to save chunk: %v", err)
|
||||
// Append Tiles
|
||||
for row in &c.tiles {
|
||||
for tile in row {
|
||||
for byte in transmute([size_of(int)]u8)tile.tilemap_pos.x {append(&data, byte)}
|
||||
for byte in transmute([size_of(int)]u8)tile.tilemap_pos.y {append(&data, byte)}
|
||||
for byte in transmute([4]u8)tile.color {append(&data, byte)}
|
||||
for byte in transmute([size_of(TileType)]u8)tile.type {append(&data, byte)}
|
||||
for byte in transmute([size_of(InteractionType)]u8)tile.interaction {append(&data, byte)}
|
||||
for byte in transmute([size_of(ResourceType)]u8)tile.resource {append(&data, byte)}
|
||||
}
|
||||
}
|
||||
|
||||
err := os.write_entire_file_or_err(filename, data[:])
|
||||
|
||||
}
|
||||
|
||||
load_chunk :: proc(pos:Vec2i, w:^World) -> Chunk {
|
||||
chunk_dir := fmt.tprintf("%v/%v", w.data_dir, "chunks")
|
||||
if !os.is_dir(chunk_dir) {
|
||||
|
||||
filename := fmt.tprintf("%v/%v_%v.chunk", chunk_dir, pos.x, pos.y)
|
||||
|
||||
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)
|
||||
save_chunk(&chunk, w)
|
||||
return chunk
|
||||
}
|
||||
|
||||
filename := fmt.tprintf("%v/%v_%v.chunk", chunk_dir, pos.x, pos.y)
|
||||
|
||||
data, err := os.read_entire_file_from_filename_or_err(filename)
|
||||
chunk: Chunk
|
||||
offset := 0
|
||||
|
||||
if err != nil {
|
||||
fmt.printfln("Chunk %v file does not exist, creating new chunk", pos)
|
||||
return generate_chunk(pos)
|
||||
}
|
||||
// Load Position
|
||||
mem.copy(transmute([^]u8)&chunk.position.x, &data[offset], size_of(int))
|
||||
offset += size_of(int)
|
||||
mem.copy(transmute([^]u8)&chunk.position.y, &data[offset], size_of(int))
|
||||
offset += size_of(int)
|
||||
|
||||
|
||||
// // Load Tiles
|
||||
// for row in &chunk.tiles {
|
||||
// for &tile in row {
|
||||
// mem.copy(transmute([^]u8)tile.tilemap_pos.x, &data[offset], size_of(int))
|
||||
// offset += size_of(int)
|
||||
// mem.copy(transmute([^]u8)tile.tilemap_pos.y, &data[offset], size_of(int))
|
||||
// offset += size_of(int)
|
||||
|
||||
// //Color
|
||||
// tile.color = {}
|
||||
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
// Load tiles
|
||||
for row_index := 0; row_index < len(chunk.tiles); row_index += 1 {
|
||||
for tile_index := 0; tile_index < len(chunk.tiles[row_index]); tile_index += 1 {
|
||||
tile := &chunk.tiles[row_index][tile_index] // Get address of tile
|
||||
mem.copy(&tile.tilemap_pos.x, &data[offset], size_of(int))
|
||||
offset += size_of(int)
|
||||
mem.copy(&tile.tilemap_pos.y, &data[offset], size_of(int))
|
||||
offset += size_of(int)
|
||||
|
||||
// Load color
|
||||
color_temp: [4]u8
|
||||
mem.copy(&color_temp, &data[offset], 4)
|
||||
tile.color = color_temp
|
||||
offset += 4
|
||||
|
||||
mem.copy(&tile.type, &data[offset], size_of(TileType))
|
||||
offset += size_of(TileType)
|
||||
mem.copy(&tile.interaction, &data[offset], size_of(InteractionType))
|
||||
offset += size_of(InteractionType)
|
||||
mem.copy(&tile.resource, &data[offset], size_of(ResourceType))
|
||||
offset += size_of(ResourceType)
|
||||
}
|
||||
}
|
||||
|
||||
return chunk
|
||||
|
||||
return deserialize_chunk(data)
|
||||
}
|
||||
|
||||
unload_chunk :: proc(pos:Vec2i, w:^World) {
|
||||
@ -170,7 +163,6 @@ unload_chunk :: proc(pos:Vec2i, w:^World) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
generate_chunk :: proc(pos:Vec2i) -> Chunk {
|
||||
chunk := Chunk {position = pos}
|
||||
|
||||
@ -181,7 +173,7 @@ generate_chunk :: proc(pos:Vec2i) -> Chunk {
|
||||
tilemap_pos = {0,2},
|
||||
interaction = .NOTHING,
|
||||
resource = .NOTHING,
|
||||
color = rl.GREEN
|
||||
color = {0,255,0,255}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -234,6 +226,14 @@ set_chunk_tile :: proc(c:^Chunk, t:Tile, pos:Vec2i) {
|
||||
c.tiles[pos.x][pos.y] = t
|
||||
}
|
||||
|
||||
set_tile :: proc(w:^World, t:Tile, p:Vec2i) {
|
||||
chunk := get_chunk_from_world_pos(w, vec2i_to_vec2(p))
|
||||
|
||||
set_chunk_tile(chunk, t, get_local_chunk_pos(p))
|
||||
|
||||
save_chunk(chunk, w)
|
||||
}
|
||||
|
||||
draw_world :: proc(w:^World) {
|
||||
for chunk_pos, chunk in w.chunks {
|
||||
for x in 0..<CHUNK_SIZE {
|
||||
@ -244,7 +244,7 @@ draw_world :: proc(w:^World) {
|
||||
pos := rl.Vector2{f32(world_x * CELL_SIZE), f32(world_y * CELL_SIZE)}
|
||||
|
||||
if tile.type != .NOTHING {
|
||||
draw_tile(vec2i_to_vec2(tile.tilemap_pos), pos, tile.color)
|
||||
draw_tile(vec2i_to_vec2(tile.tilemap_pos), pos, rl.Color(tile.color))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user