From 45153ae418d719b554c9e3c1eac35c317f9f674d Mon Sep 17 00:00:00 2001 From: Nefrace Date: Mon, 4 Nov 2024 22:26:42 +0300 Subject: [PATCH] Moved tweens to NTween --- .gitmodules | 3 ++ gameover.odin | 60 ++++++++++++++++++++++++++++------- leveldone.odin | 50 +++++++++++++++++++++++------ main.odin | 40 +++++++++++++++--------- menu_list.odin | 48 ++++++++++++++-------------- ntween | 1 + pause.odin | 50 +++++++++++++++++------------ tween.odin | 85 -------------------------------------------------- 8 files changed, 172 insertions(+), 165 deletions(-) create mode 100644 .gitmodules create mode 160000 ntween delete mode 100644 tween.odin diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..22d5caf --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ntween"] + path = ntween + url = https://git.nefrace.ru/nefrace/ntween.git diff --git a/gameover.odin b/gameover.odin index bd9a93b..186a17d 100644 --- a/gameover.odin +++ b/gameover.odin @@ -1,13 +1,14 @@ package main -import rl "vendor:raylib" import "core:math/ease" +import "ntween" +import rl "vendor:raylib" GameOver :: struct { using state: GameState, - position: Vec2, - size: Vec2, + position: Vec2, + size: Vec2, ready_to_go: bool, } @@ -21,8 +22,16 @@ gameover_init :: proc(prev: ^GameState = nil) -> ^GameState { state.free = gameover_free state.previous = prev - tween_to(&state.position.y, WINDOWF.y / 2, 1, ease.Ease.Back_Out, state, gameover_ready) - + ntween.animate( + &v2tween, + &state.position, + WINDOWF.y, + 1, + ease.Ease.Back_Out, + state, + gameover_ready, + ) + return state } @@ -32,7 +41,7 @@ gameover_update :: proc(state: ^GameState, delta: f32) { if rl.IsKeyPressed(rl.KeyboardKey.ESCAPE) { stack_pop() stack_pop() - return + return } if rl.IsKeyPressed(rl.KeyboardKey.ENTER) { stack_pop() @@ -45,7 +54,7 @@ gameover_update :: proc(state: ^GameState, delta: f32) { gameover_draw :: proc(state: ^GameState) { gameover := transmute(^GameOver)state - + if state.previous != nil { state.previous->draw() } @@ -55,7 +64,11 @@ gameover_draw :: proc(state: ^GameState) { TitleText :: "ИГРА ОКОНЧЕНА" TitleSize := rl.MeasureTextEx(FontTitle, TitleText, TitleFontSize, TitleSpacing) - SubtitleText := [3]cstring{"Нажмите Enter", "чтобы начать сначала", "Или Escape для выхода"} + SubtitleText := [3]cstring { + "Нажмите Enter", + "чтобы начать сначала", + "Или Escape для выхода", + } SubtitleFontSize :: 48 SubtitleSpacing :: 2 SubtitleSizes := [3]Vec2{} @@ -63,12 +76,34 @@ gameover_draw :: proc(state: ^GameState) { SubtitleSizes = rl.MeasureTextEx(FontUI, c, SubtitleFontSize, SubtitleSpacing) } - - rl.DrawRectangleV(gameover.position - gameover.size / 2, gameover.size, rl.Color{90, 30, 150, 255}) - rl.DrawTextPro(FontTitle, TitleText, gameover.position - {0, 100}, TitleSize / 2, 0, TitleFontSize, TitleSpacing, rl.WHITE) + rl.DrawRectangleV( + gameover.position - gameover.size / 2, + gameover.size, + rl.Color{90, 30, 150, 255}, + ) + + rl.DrawTextPro( + FontTitle, + TitleText, + gameover.position - {0, 100}, + TitleSize / 2, + 0, + TitleFontSize, + TitleSpacing, + rl.WHITE, + ) for c, i in SubtitleText { - rl.DrawTextPro(FontUI, c, gameover.position - {0, f32(10 - i * 50)}, SubtitleSizes[i] / 2, 0, SubtitleFontSize, SubtitleSpacing, rl.WHITE) + rl.DrawTextPro( + FontUI, + c, + gameover.position - {0, f32(10 - i * 50)}, + SubtitleSizes[i] / 2, + 0, + SubtitleFontSize, + SubtitleSpacing, + rl.WHITE, + ) } @@ -82,3 +117,4 @@ gameover_ready :: proc(state: rawptr) { gameover := transmute(^GameOver)state gameover.ready_to_go = true } + diff --git a/leveldone.odin b/leveldone.odin index 169d0a7..01876d7 100644 --- a/leveldone.odin +++ b/leveldone.odin @@ -1,13 +1,14 @@ package main -import rl "vendor:raylib" import "core:math/ease" +import "ntween" +import rl "vendor:raylib" LevelDone :: struct { using state: GameState, - position: Vec2, - size: Vec2, + position: Vec2, + size: Vec2, ready_to_go: bool, } @@ -21,8 +22,16 @@ leveldone_init :: proc(prev: ^GameState = nil) -> ^GameState { state.free = leveldone_free state.previous = prev - tween_to(&state.position.y, WINDOWF.y / 2, 1, ease.Ease.Back_Out, state, leveldone_ready) - + ntween.animate( + &v2tween, + &state.position, + WINDOWF / 2, + 1, + ease.Ease.Back_Out, + state, + leveldone_ready, + ) + return state } @@ -61,11 +70,33 @@ leveldone_draw :: proc(state: ^GameState) { SubtitleSpacing :: 2 SubtitleSize := rl.MeasureTextEx(FontUI, SubtitleText, SubtitleFontSize, SubtitleSpacing) - - rl.DrawRectangleV(leveldone.position - leveldone.size / 2, leveldone.size, rl.Color{90, 30, 150, 255}) - rl.DrawTextPro(FontTitle, TitleText, leveldone.position - {0, 50}, TitleSize / 2, 0, TitleFontSize, TitleSpacing, rl.WHITE) - rl.DrawTextPro(FontUI, SubtitleText, leveldone.position + {0, 20}, SubtitleSize / 2, 0, SubtitleFontSize, SubtitleSpacing, rl.WHITE) + rl.DrawRectangleV( + leveldone.position - leveldone.size / 2, + leveldone.size, + rl.Color{90, 30, 150, 255}, + ) + + rl.DrawTextPro( + FontTitle, + TitleText, + leveldone.position - {0, 50}, + TitleSize / 2, + 0, + TitleFontSize, + TitleSpacing, + rl.WHITE, + ) + rl.DrawTextPro( + FontUI, + SubtitleText, + leveldone.position + {0, 20}, + SubtitleSize / 2, + 0, + SubtitleFontSize, + SubtitleSpacing, + rl.WHITE, + ) } @@ -77,3 +108,4 @@ leveldone_ready :: proc(state: rawptr) { leveldone := transmute(^LevelDone)state leveldone.ready_to_go = true } + diff --git a/main.odin b/main.odin index 610b43b..91c0a31 100644 --- a/main.odin +++ b/main.odin @@ -1,36 +1,45 @@ package main +import "core:fmt" +import "core:slice" +import "ntween" import rl "vendor:raylib" import rlgl "vendor:raylib/rlgl" -import "core:slice" -import "core:fmt" import "core:math/ease" Vec2 :: [2]f32 Vec2i :: [2]i32 -WINDOW : Vec2i -WINDOWF : Vec2 +WINDOW: Vec2i +WINDOWF: Vec2 -FontTitle : rl.Font +FontTitle: rl.Font FontUI: rl.Font WindowShouldExit := false +f32tween: ntween.Tween_Map(f32) +v2tween: ntween.Tween_Map(Vec2) + + main :: proc() { - rl.SetConfigFlags(rl.ConfigFlags{.FULLSCREEN_MODE, .VSYNC_HINT, }) + rl.SetConfigFlags(rl.ConfigFlags{.FULLSCREEN_MODE, .VSYNC_HINT}) monitor := rl.GetCurrentMonitor() rl.InitWindow(0, 0, "SinePong") rl.SetTargetFPS(9999) - tween_init() - defer tween_clean() + f32tween = ntween.init(f32) + v2tween = ntween.init(Vec2) + defer { + ntween.destroy_tweens(&f32tween) + ntween.destroy_tweens(&v2tween) + } FontUI = rl.LoadFontEx("assets/monogram-extended.ttf", 96, nil, 2048) -// FontUI = rl.LoadFont("assets/monogram-extended.ttf") - FontTitle = rl.LoadFontEx("assets/monogram-extended.ttf", 96*2, nil, 2048) + // FontUI = rl.LoadFont("assets/monogram-extended.ttf") + FontTitle = rl.LoadFontEx("assets/monogram-extended.ttf", 96 * 2, nil, 2048) defer rl.UnloadFont(FontTitle) defer rl.UnloadFont(FontUI) rl.SetTextureFilter(FontUI.texture, rl.TextureFilter.POINT) @@ -47,7 +56,7 @@ main :: proc() { state->free() } } - + game := game_init() menu := menu_init() append(&state_stack, menu) @@ -59,10 +68,11 @@ main :: proc() { WINDOWF = Vec2{f32(WINDOW.x), f32(WINDOW.y)} } - current_state := state_stack[len(state_stack)-1] - + current_state := state_stack[len(state_stack) - 1] + delta := rl.GetFrameTime() - tweens_process(delta) + ntween.process(&f32tween, delta) + ntween.process(&v2tween, delta) current_state->update(delta) { @@ -76,7 +86,6 @@ main :: proc() { } - /* TODO: @@ -92,3 +101,4 @@ main :: proc() { [ ] Звуки */ + diff --git a/menu_list.odin b/menu_list.odin index 29aaba4..aff4505 100644 --- a/menu_list.odin +++ b/menu_list.odin @@ -1,21 +1,22 @@ package main -import rl "vendor:raylib" -import "core:math/ease" import "core:fmt" +import "core:math/ease" +import "ntween" +import rl "vendor:raylib" MenuList :: struct($T: typeid) { - state: ^GameState, - position: Vec2, - line_size: f32, - font_size: f32, + state: ^GameState, + position: Vec2, + line_size: f32, + font_size: f32, active_element: T, - active_marker: Vec2, - tween: ^Tween, - elements: ^[T]cstring, - menu_pressed: proc(state: ^GameState, element: T), - background: rl.Color, - mouse_pos: Vec2, + active_marker: Vec2, + tween: ^ntween.Tween(f32), + elements: ^[T]cstring, + menu_pressed: proc(state: ^GameState, element: T), + background: rl.Color, + mouse_pos: Vec2, } @@ -29,14 +30,12 @@ menu_list_update :: proc(list: ^MenuList($T)) { list.mouse_pos = rl.GetMousePosition() size := menu_list_get_size(list) - if rl.CheckCollisionPointRec(list.mouse_pos, rl.Rectangle{ - x = list.position.x, - y = list.position.y, - width = size.x, - height = size.y, - }) { + if rl.CheckCollisionPointRec( + list.mouse_pos, + rl.Rectangle{x = list.position.x, y = list.position.y, width = size.x, height = size.y}, + ) { if last_mouse_pos != list.mouse_pos { - mouse_relative := list.mouse_pos - list.position + mouse_relative := list.mouse_pos - list.position cur_element = i8(mouse_relative.y / list.line_size) fmt.println(cur_element) } @@ -47,7 +46,6 @@ menu_list_update :: proc(list: ^MenuList($T)) { last_mouse_pos = list.mouse_pos - if rl.IsKeyPressed(rl.KeyboardKey.DOWN) { cur_element += 1 } @@ -55,13 +53,14 @@ menu_list_update :: proc(list: ^MenuList($T)) { cur_element -= 1 } if prev_element != cur_element { - if cur_element < 0 { cur_element = len(T) -1 } - if cur_element == len(T) { cur_element = 0 } + if cur_element < 0 {cur_element = len(T) - 1} + if cur_element == len(T) {cur_element = 0} list.active_element = cast(T)cur_element if list.tween != nil { - tween_cancel(list.tween) + ntween.cancel(list.tween) } - list.tween = tween_to( + list.tween = ntween.animate( + &f32tween, &list.active_marker.y, f32(list.active_element) * list.line_size, 0.25, @@ -97,3 +96,4 @@ menu_list_get_size :: proc(list: ^MenuList($T)) -> Vec2 { } return size } + diff --git a/ntween b/ntween new file mode 160000 index 0000000..7136c68 --- /dev/null +++ b/ntween @@ -0,0 +1 @@ +Subproject commit 7136c68f3e63470b9b1c80109dd0904151e08070 diff --git a/pause.odin b/pause.odin index b8fcc61..08a33b3 100644 --- a/pause.odin +++ b/pause.odin @@ -1,49 +1,49 @@ package main -import rl "vendor:raylib" import "core:math/ease" +import "ntween" +import rl "vendor:raylib" Pause_Buttons :: enum { RESUME, - EXIT + EXIT, } pause_strings := [Pause_Buttons]cstring { .RESUME = "Продолжить", - .EXIT = "Выход" + .EXIT = "Выход", } Pause :: struct { using state: GameState, - - list: MenuList(Pause_Buttons) + list: MenuList(Pause_Buttons), } pause_init :: proc(prev: ^GameState = nil) -> ^GameState { state := new(Pause) state.variant = state - state.list = MenuList(Pause_Buttons){ - position = {-300, 300}, - line_size = 60, - font_size = 42, - elements = &pause_strings, + state.list = MenuList(Pause_Buttons) { + position = {-300, 300}, + line_size = 60, + font_size = 42, + elements = &pause_strings, menu_pressed = pause_button_pressed, - background = rl.Color{50, 10, 110, 180}, + background = rl.Color{50, 10, 110, 180}, } state.update = pause_update state.draw = pause_draw state.free = pause_free state.previous = prev - tween_to(&state.list.position.x, 300, 1, ease.Ease.Back_Out) - + ntween.animate(&f32tween, &state.list.position.x, 300, 1, ease.Ease.Back_Out) + return state } pause_update :: proc(state: ^GameState, delta: f32) { menu := transmute(^Pause)state - + if rl.IsKeyPressed(rl.KeyboardKey.ESCAPE) { stack_pop() return @@ -53,11 +53,11 @@ pause_update :: proc(state: ^GameState, delta: f32) { pause_button_pressed :: proc(state: ^GameState, el: Pause_Buttons) { switch el { - case .RESUME: - stack_pop() - case .EXIT: - stack_pop() - stack_pop() + case .RESUME: + stack_pop() + case .EXIT: + stack_pop() + stack_pop() } } @@ -72,7 +72,16 @@ pause_draw :: proc(state: ^GameState) { TitleSpacing :: 3 TitleText :: "ПАУЗА" TitleSize := rl.MeasureTextEx(FontTitle, TitleText, TitleFontSize, TitleSpacing) - rl.DrawTextPro(FontTitle, "ПАУЗА", {WINDOWF.x - 50, 50}, {TitleSize.x, 0}, 0, 96, 3, rl.WHITE) + rl.DrawTextPro( + FontTitle, + "ПАУЗА", + {WINDOWF.x - 50, 50}, + {TitleSize.x, 0}, + 0, + 96, + 3, + rl.WHITE, + ) menu_list_draw(&menu.list) } @@ -81,3 +90,4 @@ pause_free :: proc(state: ^GameState) { pause := transmute(^Pause)state free(state) } + diff --git a/tween.odin b/tween.odin deleted file mode 100644 index dbc90ff..0000000 --- a/tween.odin +++ /dev/null @@ -1,85 +0,0 @@ -package main - -import "core:math" -import "core:math/ease" -import "core:math/linalg" -import "core:slice" - - -Tween :: struct { - ptr: ^f32, - from: f32, - to: f32, - time: f32, - duration: f32, - ease_type: ease.Ease, - active: bool, - finished: proc(data: rawptr), - data: rawptr -} - - -TWEEN_SIZE :: 128 -tweens_buf: [TWEEN_SIZE]^Tween -tweens : [dynamic]^Tween - -tween_init :: proc() { - tweens = slice.into_dynamic(tweens_buf[:]) -} - -tween_clean :: proc() { - for tween, i in tweens { - free(tween) - } -} - -tween_to :: proc( - value: ^f32, to: f32, duration: f32, - ease: ease.Ease = ease.Ease.Quartic_In_Out, - data: rawptr = nil, - callback: proc(data: rawptr) = nil - ) -> ^Tween { - - tween := new(Tween) - tween.ptr = value - tween.from = value^ - tween.to = to - tween.duration = duration - tween.ease_type = ease - tween.active = true - tween.data = data - tween.finished = callback - - append(&tweens, tween) - return tween -} - -tween_cancel :: proc(t: ^Tween) { - t.active = false -} - -tweens_process :: proc(delta: f32) { - #reverse for tween, i in tweens { - - tween.time += delta - p := clamp(tween.time / tween.duration, 0, 1) - - val := ease.ease(tween.ease_type, p) - if tween.ptr != nil { - tween.ptr^ = math.lerp(tween.from, tween.to, val) - } else { - tween.active = false - } - - if tween.time >= tween.duration { - tween.active = false - if tween.finished != nil { - tween.finished(tween.data) - } - } - if !tween.active { - free(tween) - unordered_remove(&tweens, i) - } - } -}