228 lines
6.3 KiB
Odin
228 lines
6.3 KiB
Odin
package game
|
|
|
|
import rl "vendor:raylib"
|
|
import "core:fmt"
|
|
import "core:math"
|
|
|
|
CHUNK_UNLOAD_DISTANCE :: 3
|
|
|
|
Player :: struct {
|
|
position : rl.Vector2,
|
|
move_timer: f32,
|
|
mode: InteractMode,
|
|
camera: rl.Camera2D,
|
|
speed:f32
|
|
}
|
|
|
|
InteractMode :: enum {
|
|
INTERACT,
|
|
ATTACK,
|
|
STEAL,
|
|
}
|
|
|
|
@(private="file")
|
|
handle_player_camera :: proc(p:^Player) {
|
|
p.camera.target = {p.position.x + (CELL_SIZE / 2), p.position.y + (CELL_SIZE / 2)}
|
|
|
|
if rl.IsWindowResized() {
|
|
p.camera.offset = {f32(rl.GetScreenWidth()) / 2, f32(rl.GetScreenHeight()) / 2}
|
|
}
|
|
}
|
|
|
|
player_update :: proc(p : ^Player, w: ^World) {
|
|
handle_player_input(p,w)
|
|
handle_player_camera(p)
|
|
|
|
// if rl.IsKeyPressed(.SPACE) {
|
|
// // set_tile(w, bricks_tile, vec2_to_vec2i(get_player_grid_position(p)))
|
|
// find_desert(w.seed)
|
|
// generate_biome_map(w.seed, 100, 100)
|
|
// }
|
|
}
|
|
|
|
@(private="file")
|
|
player_update_chunks :: proc(p: ^Player, w: ^World) {
|
|
// Configurable view distance (in chunks)
|
|
VIEW_DISTANCE :: 2
|
|
|
|
player_grid_pos := get_player_grid_position(p)
|
|
current_player_chunk := get_chunk_from_world_pos(w, player_grid_pos)
|
|
|
|
// Track which chunks should be loaded
|
|
chunks_to_keep := make(map[Vec2i]bool)
|
|
defer delete(chunks_to_keep)
|
|
|
|
// Load chunks in a square around the player's current chunk
|
|
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
|
|
for chunk_pos in w.chunks {
|
|
if !chunks_to_keep[chunk_pos] {
|
|
unload_chunk(chunk_pos, w)
|
|
}
|
|
}
|
|
}
|
|
|
|
@(private="file")
|
|
handle_player_input :: proc(p:^Player, w:^World) {
|
|
|
|
|
|
current_tile := get_world_tile(w, vec2_to_vec2i(get_player_grid_position(p)))
|
|
// Movement
|
|
|
|
dt := rl.GetFrameTime()
|
|
move_delay : f32 = 0.2 / p.speed
|
|
if p.move_timer > 0 {
|
|
p.move_timer -= dt
|
|
}
|
|
|
|
|
|
if current_tile.type == .WATER {
|
|
p.speed = 0.3
|
|
}
|
|
else {
|
|
p.speed = 1
|
|
}
|
|
|
|
if p.move_timer <= 0 {
|
|
current_pos := get_player_grid_position(p)
|
|
if rl.IsKeyDown(.D) {
|
|
target_pos := rl.Vector2{current_pos.x + 1, current_pos.y}
|
|
if !will_collide(.RIGHT, p, w) {
|
|
player.position.x += CELL_SIZE
|
|
p.move_timer = move_delay
|
|
player_update_chunks(p,w)
|
|
}
|
|
}
|
|
|
|
if rl.IsKeyDown(.A) {
|
|
target_pos := rl.Vector2{current_pos.x - 1, current_pos.y}
|
|
if !will_collide(.LEFT, p, w) {
|
|
player.position.x -= CELL_SIZE
|
|
p.move_timer = move_delay
|
|
player_update_chunks(p,w)
|
|
}
|
|
}
|
|
|
|
if rl.IsKeyDown(.W) {
|
|
target_pos := rl.Vector2{current_pos.x, current_pos.y - 1}
|
|
if !will_collide(.UP, p, w) {
|
|
player.position.y -= CELL_SIZE
|
|
p.move_timer = move_delay
|
|
player_update_chunks(p,w)
|
|
}
|
|
}
|
|
|
|
if rl.IsKeyDown(.S) {
|
|
target_pos := rl.Vector2{current_pos.x, current_pos.y + 1}
|
|
if !will_collide(.DOWN, p, w) {
|
|
p.move_timer = move_delay
|
|
player.position.y += CELL_SIZE
|
|
player_update_chunks(p,w)
|
|
}
|
|
}
|
|
|
|
// Interactions
|
|
if rl.IsKeyPressed(.UP) {
|
|
if p.mode == .INTERACT { handle_interact(.UP, p, w) }
|
|
if p.mode == .ATTACK { handle_attack(.UP, p, w) }
|
|
}
|
|
|
|
if rl.IsKeyPressed(.DOWN) {
|
|
if p.mode == .INTERACT { handle_interact(.DOWN, p, w) }
|
|
if p.mode == .ATTACK { handle_attack(.DOWN, p, w) }
|
|
}
|
|
|
|
if rl.IsKeyPressed(.LEFT) {
|
|
if p.mode == .INTERACT { handle_interact(.LEFT, p, w) }
|
|
if p.mode == .ATTACK { handle_attack(.LEFT, p, w) }
|
|
}
|
|
|
|
if rl.IsKeyPressed(.RIGHT) {
|
|
if p.mode == .INTERACT { handle_interact(.RIGHT, p, w) }
|
|
if p.mode == .ATTACK { handle_attack(.RIGHT, p, w) }
|
|
}
|
|
|
|
if rl.IsKeyPressed(.ONE) { p.mode = .INTERACT }
|
|
if rl.IsKeyPressed(.TWO) { p.mode = .ATTACK }
|
|
if rl.IsKeyPressed(.THREE) { p.mode = .STEAL }
|
|
}
|
|
}
|
|
|
|
@(private="file")
|
|
InteractDirection :: enum {
|
|
UP, DOWN, LEFT, RIGHT
|
|
}
|
|
|
|
@(private="file")
|
|
handle_interact :: proc(direction:InteractDirection, p:^Player, w:^World) {
|
|
tile, pos := get_tile_in_direction(direction, p, w)
|
|
|
|
if tile.interaction == .RESOURCE && tile.resource != .NOTHING {
|
|
if tile.resource == .TREE { handle_tree_interaction(w, p, pos) }
|
|
}
|
|
}
|
|
|
|
@(private="file")
|
|
handle_attack :: proc(direction:InteractDirection, p:^Player, w:^World) {
|
|
tile, pos := get_tile_in_direction(direction, p, w)
|
|
}
|
|
|
|
@(private="file")
|
|
get_tile_in_direction :: proc(direction:InteractDirection, p:^Player, w:^World) -> (^Tile, Vec2i) {
|
|
grid_pos := get_player_grid_position(p)
|
|
|
|
if direction == .UP { grid_pos.y -= 1 }
|
|
if direction == .DOWN { grid_pos.y += 1 }
|
|
if direction == .LEFT { grid_pos.x -= 1 }
|
|
if direction == .RIGHT { grid_pos.x += 1 }
|
|
|
|
return get_world_tile(w, vec2_to_vec2i(grid_pos)), vec2_to_vec2i(grid_pos)
|
|
}
|
|
|
|
get_player_grid_position :: proc(player:^Player) -> rl.Vector2 {
|
|
grid_pos_x := math.floor(player.position.x / CELL_SIZE)
|
|
grid_pos_y := math.floor(player.position.y / CELL_SIZE)
|
|
|
|
return {grid_pos_x, grid_pos_y}
|
|
}
|
|
|
|
draw_player :: proc(player:^Player) {
|
|
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)
|
|
|
|
if tile.type == .SOLID { return true }
|
|
|
|
return false
|
|
}
|
|
|
|
|