From 85af303aa0aa720e7ec177c924710254982818c6 Mon Sep 17 00:00:00 2001 From: Nefrace Date: Thu, 5 Sep 2024 22:39:52 +0300 Subject: [PATCH] working basic game state, state stack --- .gitignore | 2 ++ game.odin | 45 +++++++++++++++++++++++++++++++++------------ main.odin | 43 +++++++++++++++++++++++++++++++++++++++++-- state.odin | 36 +++++++++++++++++++++++++++++++++--- 4 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5542bb8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +arkanoid +core.* diff --git a/game.odin b/game.odin index f811c51..3633c43 100644 --- a/game.odin +++ b/game.odin @@ -1,11 +1,12 @@ package main import rl "vendor:raylib" +import "core:fmt" Pad :: struct { position: Vec2, - width: Vec2, + size: Vec2, } Ball :: struct { @@ -31,20 +32,40 @@ Game :: struct { } -game_init :: proc() -> Game { - return Game{ - update = game_update, - draw = game_draw, - lives = 3, - pad = Pad{ - position = {f32(WINDOW_WIDTH / 2), f32(WINDOW_HEIGHT - 40)} - } +game_init :: proc() -> ^GameState { + state := new(Game) + state.variant = state + state.draw = game_draw + state.update = game_update + state.lives = 3 + state.pad = Pad{ + position = {f32(WINDOW_WIDTH / 2), f32(WINDOW_HEIGHT - 40)}, + size = {80, 10}, } + return state } -game_update :: proc(delta: f32) { - +game_update :: proc(state: ^GameState, delta: f32) { + game := transmute(^Game)state + + using game + + if rl.IsKeyDown(rl.KeyboardKey.LEFT) { + pad.position.x -= 100 * delta + fmt.println(pad.position) + } + if rl.IsKeyDown(rl.KeyboardKey.RIGHT) { + pad.position.x += 100 * delta + } + } -game_draw :: proc() { +game_draw :: proc(state: ^GameState) { + game := transmute(^Game)state + + using game + + rl.ClearBackground(rl.RAYWHITE) + + rl.DrawRectangleV(pad.position, pad.size, rl.GREEN) } diff --git a/main.odin b/main.odin index 9456e79..0051dbf 100644 --- a/main.odin +++ b/main.odin @@ -1,13 +1,52 @@ package main import rl "vendor:raylib" +import "core:slice" Vec2 :: [2]f32 Vec2i :: [2]i32 -WINDOW_WIDTH : i32 -WINDOW_HEIGHT : i32 +WINDOW_WIDTH : i32 = 800 +WINDOW_HEIGHT : i32 = 480 + main :: proc() { + rl.SetConfigFlags(rl.ConfigFlags{.BORDERLESS_WINDOWED_MODE, .VSYNC_HINT, .WINDOW_RESIZABLE}) + monitor := rl.GetCurrentMonitor() + WINDOW_WIDTH = rl.GetMonitorWidth(monitor) + WINDOW_HEIGHT = rl.GetMonitorHeight(monitor) + rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "SinePong") + rl.SetTargetFPS(9999) + + stack_init() + + defer { + for s, i in state_stack { + free(s) + } + } + + game := game_init() + append(&state_stack, game) + + for (!rl.WindowShouldClose()) { + if rl.IsWindowResized() { + WINDOW_WIDTH = rl.GetScreenWidth() + WINDOW_HEIGHT = rl.GetScreenHeight() + } + + current_state := state_stack[len(state_stack)-1] + + delta := rl.GetFrameTime() + + current_state->update(delta) + + { + rl.BeginDrawing() + defer rl.EndDrawing() + current_state->draw() + } + + } } diff --git a/state.odin b/state.odin index e5cccc5..58b9279 100644 --- a/state.odin +++ b/state.odin @@ -1,11 +1,14 @@ package main +import "core:slice" + +StateVariant :: union{^Game, ^Menu} GameState :: struct { - update: proc(f32), - draw: proc(), + update: proc(state: ^GameState, delta: f32), + draw: proc(state: ^GameState), - variant: union{^Game, ^Menu} + variant: StateVariant } new_state :: proc($T: typeid) -> ^T { @@ -13,3 +16,30 @@ new_state :: proc($T: typeid) -> ^T { state.variant = state return state } + + + +STACK_SIZE :: 16 +state_buf : [STACK_SIZE]^GameState +state_stack : [dynamic]^GameState + +stack_init :: proc() { + state_stack = slice.into_dynamic(state_buf[:]) +} + +stack_push :: proc(state: ^GameState) -> (bool) { + if len(state_stack) == STACK_SIZE { + return false + } + append(&state_stack, state) + return true +} + +stack_pop :: proc() -> (bool) { + if len(state_stack) == 0 { + return false + } + state := pop(&state_stack) + free(state) + return true +}