diff --git a/.gitignore b/.gitignore index e69de29..c2dc584 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,3 @@ +*.exe +*.rdi +*.bin diff --git a/src/entity.odin b/src/entity.odin index 166b6ee..6bb8101 100644 --- a/src/entity.odin +++ b/src/entity.odin @@ -112,7 +112,7 @@ get_player_entity_and_data :: proc() -> (^Entity, PlayerData) { if player_entity == nil { fmt.panicf("Player handle is invalid, how???") } - player_data, ok := player_entity.data.(PlayerData);if ok { + player_data, ok := player_entity.data.(PlayerData); if ok { return player_entity, player_data } else { fmt.panicf("Player data is invalid, how???") @@ -126,7 +126,7 @@ draw_entities :: proc() { }) for e in entities { if .Allocated not_in e.flags {continue} - #partial switch &data in e.data { + #partial switch data in e.data { case TileData: draw_tile(e) } @@ -137,7 +137,7 @@ draw_entities :: proc() { // Draw debug circle //rl.DrawCircleV(e.pos, 1, rl.RED) - switch &data in e.data { + switch data in e.data { case TileData: draw_tile_plant(e) case PlayerData: @@ -153,13 +153,13 @@ entity_to_handle :: proc(e: Entity) -> EntityHandle { } draw_player :: proc(e: Entity) { - data, ok := e.data.(PlayerData);if ok { + data, ok := e.data.(PlayerData); if ok { draw_animation(data.animation, e.pos + {TILE_SIZE, TILE_SIZE}) } } draw_item :: proc(e: Entity) { - data, ok := e.data.(ItemData);if ok { + data, ok := e.data.(ItemData); if ok { t := f32(math.sin(rl.GetTime() * 5)) pos := e.pos + {0, t * 3} rl.DrawTextureV(data.texture, pos, rl.WHITE) diff --git a/src/globals.odin b/src/globals.odin index 2613a06..677e1dc 100644 --- a/src/globals.odin +++ b/src/globals.odin @@ -35,6 +35,8 @@ tween_ctx_vec2: t.TweenContext([2]f32) player_inventory: [InventoryItem]int hotbar: Hotbar +should_run: bool = true + InventoryItem :: enum { //Tools hoe, diff --git a/src/main.odin b/src/main.odin index 258d35e..b74b555 100644 --- a/src/main.odin +++ b/src/main.odin @@ -1,6 +1,6 @@ package game -import t "../tween" +// import t "../tween" import "core:fmt" import "core:log" import "core:mem" @@ -41,6 +41,17 @@ main :: proc() { } run :: proc() { + init() + defer shutdown() + + for should_run { + free_all(context.temp_allocator) + update() + draw() + } +} + +init :: proc() { rl.SetConfigFlags({.VSYNC_HINT, .WINDOW_RESIZABLE, .MSAA_4X_HINT}) rl.InitWindow(1280, 720, "Raylib Minimal") rl.SetTargetFPS(rl.GetMonitorRefreshRate(rl.GetCurrentMonitor())) @@ -53,55 +64,57 @@ run :: proc() { } load_resources() +} - for !rl.WindowShouldClose() { - free_all(context.temp_allocator) - update() - draw() - } - +shutdown :: proc() { free_resources() rl.CloseAudioDevice() rl.CloseWindow() } update :: proc() { + dt := rl.GetFrameTime() + // :tween update - t.tween_update(&tween_ctx_f32, auto_cast rl.GetFrameTime()) - t.tween_update(&tween_ctx_vec2, auto_cast rl.GetFrameTime()) + tick_tweens(dt) // :scaling update - screen_width := rl.GetScreenWidth() - screen_height := rl.GetScreenHeight() - screen_scale = min( - f32(screen_width) / GAME_SCREEN_WIDTH, - f32(screen_height) / GAME_SCREEN_HEIGHT, - ) - mouse := rl.GetMousePosition() - virtual_mouse := rl.Vector2 { - (mouse.x - (f32(screen_width) - (GAME_SCREEN_WIDTH * screen_scale)) * 0.5) / screen_scale, - (mouse.y - (f32(screen_height) - (GAME_SCREEN_HEIGHT * screen_scale)) * 0.5) / - screen_scale, - } - virtual_mouse = rl.Vector2Clamp( - virtual_mouse, - {}, - rl.Vector2{GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT}, - ) - world_mouse = rl.GetScreenToWorld2D(virtual_mouse, game_camera) - screen_game_area = rl.Rectangle { - (f32(rl.GetScreenWidth()) - (GAME_SCREEN_WIDTH * screen_scale)) * 0.5, - (f32(rl.GetScreenHeight()) - (GAME_SCREEN_HEIGHT * screen_scale)) * 0.5, - GAME_SCREEN_WIDTH * screen_scale, - GAME_SCREEN_HEIGHT * screen_scale, + { + screen_width := rl.GetScreenWidth() + screen_height := rl.GetScreenHeight() + screen_scale = min( + f32(screen_width) / GAME_SCREEN_WIDTH, + f32(screen_height) / GAME_SCREEN_HEIGHT, + ) + mouse := rl.GetMousePosition() + virtual_mouse := rl.Vector2 { + (mouse.x - (f32(screen_width) - (GAME_SCREEN_WIDTH * screen_scale)) * 0.5) / + screen_scale, + (mouse.y - (f32(screen_height) - (GAME_SCREEN_HEIGHT * screen_scale)) * 0.5) / + screen_scale, + } + virtual_mouse = rl.Vector2Clamp( + virtual_mouse, + {}, + rl.Vector2{GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT}, + ) + world_mouse = rl.GetScreenToWorld2D(virtual_mouse, game_camera) + screen_game_area = rl.Rectangle { + (f32(rl.GetScreenWidth()) - (GAME_SCREEN_WIDTH * screen_scale)) * 0.5, + (f32(rl.GetScreenHeight()) - (GAME_SCREEN_HEIGHT * screen_scale)) * 0.5, + GAME_SCREEN_WIDTH * screen_scale, + GAME_SCREEN_HEIGHT * screen_scale, + } + } + // :hotbar update update_hotbar() // :animation update update_entities() - // :sell + // :sell button update hover_sell_button := rl.CheckCollisionPointRec( world_mouse, {SELL_BUTTON_POS.x, SELL_BUTTON_POS.y, TILE_SIZE * 2, TILE_SIZE * 2}, @@ -114,7 +127,7 @@ update :: proc() { // :player update player := handle_to_entity(player_handle) if player != nil { - pd, ok := &player.data.(PlayerData);if ok { + pd, ok := &player.data.(PlayerData); if ok { vel: rl.Vector2 if rl.IsKeyDown(.D) do vel.x += 1 if rl.IsKeyDown(.A) do vel.x -= 1 diff --git a/src/sequencer.odin b/src/sequencer.odin new file mode 100644 index 0000000..5ef195f --- /dev/null +++ b/src/sequencer.odin @@ -0,0 +1,39 @@ +package game + +sequences: [dynamic]Sequence + +Seq_Payload :: union { + SEQ_MOVE_CIRCLE, +} + +SEQ_MOVE_CIRCLE :: struct { + pos: ^[2]f32, + target_pos: [2]f32, + duration: f32, +} + +Sequence :: struct { + delay: f32, + payload: Seq_Payload, +} + +add_seq :: proc(sequences: ^[dynamic]Sequence, delay: f32, payload: Seq_Payload) -> f32 { + append_elem(sequences, Sequence{delay = delay, payload = payload}) + return delay +} + +tick_sequences :: proc(sequences: ^[dynamic]Sequence, dt: f32) { + if len(sequences) == 0 do return + + seq := &sequences[0] + seq.delay -= dt + if seq.delay <= 0.0 { + switch s in seq.payload + { + case SEQ_MOVE_CIRCLE: + add_vector2_tween(s.pos, s.target_pos, s.duration, .IN_OUT_QUAD) + } + + ordered_remove(sequences, 0) + } +} diff --git a/src/tween.odin b/src/tween.odin new file mode 100644 index 0000000..93038be --- /dev/null +++ b/src/tween.odin @@ -0,0 +1,78 @@ +package game + +import "core:math" +import "core:log" + +// :tweening +Tween_Func :: enum { + LINEAR, + IN_OUT_QUAD, +} + +Tween :: struct { + ptr: ^f32, + start: f32, + target: f32, + duration: f32, + time: f32, + eval: proc(x: f32) -> f32, +} + +tweens: [dynamic]Tween + +append_ret :: proc(container: ^$T/[dynamic]$E, element: E) -> ^E { + append(container, element) + return &container[len(container) - 1] +} + +add_f32_tween :: proc(ptr: ^f32, target: f32, duration: f32, func: Tween_Func) { + tween := append_ret(&tweens, Tween{}) + tween.ptr = ptr + tween.start = ptr^ + tween.target = target + tween.duration = duration + + switch func { + case .LINEAR: + tween.eval = proc(x: f32) -> f32 {return x} + + case .IN_OUT_QUAD: + tween.eval = proc(x: f32) -> f32 { + log.infof("x = {}", x) + if x < 0.5 { + return x * x * 2.0 + } else { + return 1.0 - math.pow(-2.0 * x + 2.0, 2.0) / 2.0 + } + } + } + + log.info(tween.eval) +} + +add_vector2_tween :: proc(ptr: ^[2]f32, target: [2]f32, duration: f32, func: Tween_Func) { + add_f32_tween(&ptr.x, target.x, duration, func) + add_f32_tween(&ptr.y, target.y, duration, func) +} + +tick_tweens :: proc(dt: f32) { + for i := 0; i < len(tweens); i += 1 { + log.infof("i = {}", i) + + tween := &tweens[i] + + tween.time = math.min(tween.time + dt, tween.duration) + log.info(1) + log.info(tween.eval) + t := tween.eval(tween.time / tween.duration) + log.info(2) + log.infof("t = {}", t) + tween.ptr^ = math.lerp(tween.start, tween.target, t) + log.info(3) + + if t == 1.0 { + unordered_remove(&tweens, i) + i -= 1 + } + } +} diff --git a/src/utils.odin b/src/utils.odin new file mode 100644 index 0000000..cde26fe --- /dev/null +++ b/src/utils.odin @@ -0,0 +1 @@ +package game