procgen #3
@ -25,7 +25,7 @@ main :: proc() {
|
|||||||
rl.SetTargetFPS(60)
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
player = {
|
player = {
|
||||||
position = {CELL_SIZE * 10000, CELL_SIZE * 10000},
|
position = {CELL_SIZE * 10, CELL_SIZE * 10},
|
||||||
camera = {
|
camera = {
|
||||||
zoom = 4,
|
zoom = 4,
|
||||||
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)},
|
||||||
@ -37,7 +37,7 @@ main :: proc() {
|
|||||||
load_tilemap()
|
load_tilemap()
|
||||||
defer unload_tilemap()
|
defer unload_tilemap()
|
||||||
|
|
||||||
world = create_world("test_world", 23456725245)
|
world = create_world("test_world", 10172020)
|
||||||
save_world(&world)
|
save_world(&world)
|
||||||
|
|
||||||
game_loop()
|
game_loop()
|
||||||
@ -45,8 +45,6 @@ main :: proc() {
|
|||||||
|
|
||||||
game_loop :: proc() {
|
game_loop :: proc() {
|
||||||
|
|
||||||
pos_string : string
|
|
||||||
pos_cstring : cstring
|
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
for !rl.WindowShouldClose() {
|
||||||
|
|
||||||
@ -66,13 +64,21 @@ game_loop :: proc() {
|
|||||||
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)
|
current_chunk := get_chunk_from_world_pos(&world, player_grid_pos)
|
||||||
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)
|
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() {
|
||||||
|
@ -12,7 +12,7 @@ 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(v2.x), int(v2.y)}
|
return {int(math.floor(v2.x)), int(math.floor(v2.y))}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_noise :: proc(x, y: int, seed: i64) -> f32 {
|
hash_noise :: proc(x, y: int, seed: i64) -> f32 {
|
||||||
|
130
game/player.odin
130
game/player.odin
@ -2,6 +2,7 @@ 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
|
||||||
|
|
||||||
@ -31,57 +32,42 @@ 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, bricks_tile, vec2_to_vec2i(get_player_grid_position(p)))
|
||||||
find_desert(w.seed)
|
// find_desert(w.seed)
|
||||||
generate_biome_map(w.seed, 100, 100)
|
// 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)
|
||||||
|
|
||||||
directions := [8]Vec2i{
|
// Track which chunks should be loaded
|
||||||
Vec2i{ 1, 0 }, Vec2i{ -1, 0 }, // Right, Left
|
chunks_to_keep := make(map[Vec2i]bool)
|
||||||
Vec2i{ 0, 1 }, Vec2i{ 0, -1 }, // Down, Up
|
defer delete(chunks_to_keep)
|
||||||
Vec2i{ 1, 1 }, Vec2i{ -1, -1 }, // Bottom-right, Top-left
|
|
||||||
Vec2i{ 1, -1 }, Vec2i{ -1, 1 }, // Top-right, Bottom-left
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always ensure the current chunk is loaded
|
// Load chunks in a square around the player's current chunk
|
||||||
get_chunk(w, current_player_chunk.position)
|
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 adjacent chunks
|
// Load the chunk and mark it to keep
|
||||||
for dir in directions {
|
get_chunk(w, chunk_pos)
|
||||||
adjacent_pos := Vec2i{
|
chunks_to_keep[chunk_pos] = true
|
||||||
current_player_chunk.position.x + dir.x,
|
|
||||||
current_player_chunk.position.y + dir.y
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get_chunk(w, adjacent_pos)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload non-adjacent chunks
|
// Unload chunks outside the view distance
|
||||||
for chunk_pos in w.chunks {
|
for chunk_pos in w.chunks {
|
||||||
if chunk_pos == current_player_chunk.position {
|
if !chunks_to_keep[chunk_pos] {
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +77,7 @@ player_update_chunks :: proc(p: ^Player, w: ^World) {
|
|||||||
handle_player_input :: proc(p:^Player, w:^World) {
|
handle_player_input :: proc(p:^Player, w:^World) {
|
||||||
|
|
||||||
// Movement
|
// Movement
|
||||||
target_pos := get_player_grid_position(p)
|
|
||||||
dt := rl.GetFrameTime()
|
dt := rl.GetFrameTime()
|
||||||
move_delay : f32 = 0.2
|
move_delay : f32 = 0.2
|
||||||
if p.move_timer > 0 {
|
if p.move_timer > 0 {
|
||||||
@ -99,9 +85,10 @@ handle_player_input :: proc(p:^Player, w:^World) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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.x += 1
|
target_pos := rl.Vector2{current_pos.x + 1, current_pos.y}
|
||||||
if !will_collide(w, target_pos) {
|
if !will_collide(.RIGHT, p, w) {
|
||||||
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)
|
||||||
@ -109,8 +96,8 @@ handle_player_input :: proc(p:^Player, w:^World) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rl.IsKeyDown(.A) {
|
if rl.IsKeyDown(.A) {
|
||||||
target_pos.x -= 1
|
target_pos := rl.Vector2{current_pos.x - 1, current_pos.y}
|
||||||
if !will_collide(w, target_pos) {
|
if !will_collide(.LEFT, p, w) {
|
||||||
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)
|
||||||
@ -118,8 +105,8 @@ handle_player_input :: proc(p:^Player, w:^World) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rl.IsKeyDown(.W) {
|
if rl.IsKeyDown(.W) {
|
||||||
target_pos.y -= 1
|
target_pos := rl.Vector2{current_pos.x, current_pos.y - 1}
|
||||||
if !will_collide(w, target_pos) {
|
if !will_collide(.UP, p, w) {
|
||||||
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)
|
||||||
@ -127,8 +114,8 @@ handle_player_input :: proc(p:^Player, w:^World) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rl.IsKeyDown(.S) {
|
if rl.IsKeyDown(.S) {
|
||||||
target_pos.y += 1
|
target_pos := rl.Vector2{current_pos.x, current_pos.y + 1}
|
||||||
if !will_collide(w, target_pos) {
|
if !will_collide(.DOWN, p, w) {
|
||||||
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)
|
||||||
@ -194,29 +181,50 @@ 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 := player.position.x / CELL_SIZE
|
grid_pos_x := math.floor(player.position.x / CELL_SIZE)
|
||||||
grid_pos_y := player.position.y / CELL_SIZE
|
grid_pos_y := math.floor(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({25,0}, player.position, {30,100,120,255})
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
will_collide :: proc(w:^World, pos:rl.Vector2) -> bool {
|
if tile.type == .SOLID { return true }
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// }
|
||||||
|
@ -5,6 +5,7 @@ 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
|
||||||
@ -173,24 +174,37 @@ 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})
|
|
||||||
return chunk_pos
|
x := int(math.floor(pos.x / CHUNK_SIZE))
|
||||||
|
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 {
|
||||||
return Vec2i {
|
x := (pos.x % CHUNK_SIZE + CHUNK_SIZE) % CHUNK_SIZE
|
||||||
(pos.x % CHUNK_SIZE + CHUNK_SIZE) % CHUNK_SIZE,
|
y := (pos.y % 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_pos := world_pos_to_chunk_pos(vec2i_to_vec2(pos))
|
chunk_x := int(math.floor(f32(pos.x) / f32(CHUNK_SIZE)))
|
||||||
local_pos := get_local_chunk_pos(pos)
|
chunk_y := int(math.floor(f32(pos.y) / f32(CHUNK_SIZE)))
|
||||||
|
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