diff --git a/game.odin b/game.odin index fc0323c..c2dc92a 100644 --- a/game.odin +++ b/game.odin @@ -59,6 +59,10 @@ game_update :: proc(state: ^GameState, delta: f32) { using game + if rl.IsKeyPressed(rl.KeyboardKey.ESCAPE) { + pause := pause_init(game) + stack_push(pause) + } pad_update(&game.pad, delta) if rl.IsKeyPressed(rl.KeyboardKey.SPACE) { for &ball, i in balls { diff --git a/menu.odin b/menu.odin index 234f7d0..c88f65e 100644 --- a/menu.odin +++ b/menu.odin @@ -21,19 +21,21 @@ menu_strings := [Menu_Buttons]cstring { Menu :: struct { using state: GameState, - menu_pos: Vec2, - menu_element_offset: f32, - active_element: Menu_Buttons, - active_marker: Vec2, - marker_tween: ^Tween, + list: MenuList(Menu_Buttons), + } menu_init :: proc(prev: ^GameState = nil) -> ^GameState { state := new(Menu) state.variant = state - state.menu_pos = {300, 300} - state.menu_element_offset = 60 - state.active_marker = state.menu_pos + Vec2{0, f32(state.active_element) * state.menu_element_offset} + state.list = MenuList(Menu_Buttons){ + state = state, + position = {300, 300}, + line_size = 60, + font_size = 42, + elements = &menu_strings, + menu_pressed = menu_button_pressed + } state.update = menu_update state.draw = menu_draw state.free = menu_free @@ -44,41 +46,20 @@ menu_init :: proc(prev: ^GameState = nil) -> ^GameState { menu_update :: proc(state: ^GameState, delta: f32) { menu := transmute(^Menu)state + + menu_list_update(&menu.list) +} - prev_element := cast(i8)menu.active_element - cur_element := prev_element - - if rl.IsKeyPressed(rl.KeyboardKey.DOWN) { - cur_element += 1 - } - if rl.IsKeyPressed(rl.KeyboardKey.UP) { - cur_element -= 1 - } - if prev_element != cur_element { - if cur_element < 0 { cur_element = len(Menu_Buttons) -1 } - if cur_element == len(Menu_Buttons) { cur_element = 0 } - menu.active_element = cast(Menu_Buttons)cur_element - if menu.marker_tween != nil { - tween_cancel(menu.marker_tween) - } - menu.marker_tween = tween_to( - &menu.active_marker.y, - menu.menu_pos.y + f32(menu.active_element) * menu.menu_element_offset, - 0.5, - ease.Ease.Back_Out, - ) - } - if rl.IsKeyPressed(rl.KeyboardKey.ENTER) || rl.IsKeyPressed(rl.KeyboardKey.SPACE) { - switch menu.active_element { - case .START: - game := game_init(state) - stack_push(game) - case .FULLSCREEN: - case .HOW_TO_PLAY: - case .EXIT: - WindowShouldExit = true - return - } +menu_button_pressed :: proc(state: ^GameState, el: Menu_Buttons) { + switch el { + case .START: + game := game_init(state) + stack_push(game) + case .FULLSCREEN: + case .HOW_TO_PLAY: + case .EXIT: + WindowShouldExit = true + return } } @@ -91,11 +72,8 @@ menu_draw :: proc(state: ^GameState) { TitleSize := rl.MeasureTextEx(FontTitle, TitleText, TitleFontSize, TitleSpacing) rl.DrawTextPro(FontTitle, "ARKADODGE", {WINDOWF.x - 50, 50}, {TitleSize.x, 0}, 0, 96, 3, rl.WHITE) - rl.DrawTextEx(FontUI, ">", menu.active_marker + {-30, 0}, 48, 2, rl.WHITE) - for el, i in menu_strings { - pos := menu.menu_pos + {0, f32(i) * menu.menu_element_offset} - rl.DrawTextEx(FontUI, el, pos, 48, 2, rl.WHITE) - } + menu_list_draw(&menu.list) + } menu_free :: proc(state: ^GameState) { diff --git a/menu_list.odin b/menu_list.odin new file mode 100644 index 0000000..73390eb --- /dev/null +++ b/menu_list.odin @@ -0,0 +1,55 @@ +package main + +import rl "vendor:raylib" +import "core:math/ease" + +MenuList :: struct($T: typeid) { + 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), +} + + +menu_list_update :: proc(list: ^MenuList($T)) { + prev_element := cast(i8)list.active_element + cur_element := prev_element + + + if rl.IsKeyPressed(rl.KeyboardKey.DOWN) { + cur_element += 1 + } + if rl.IsKeyPressed(rl.KeyboardKey.UP) { + 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 } + list.active_element = cast(T)cur_element + if list.tween != nil { + tween_cancel(list.tween) + } + list.tween = tween_to( + &list.active_marker.y, + f32(list.active_element) * list.line_size, + 0.5, + ease.Ease.Back_Out, + ) + } + if rl.IsKeyPressed(rl.KeyboardKey.ENTER) || rl.IsKeyPressed(rl.KeyboardKey.SPACE) { + list.menu_pressed(list.state, list.active_element) + } +} + +menu_list_draw :: proc(list: ^MenuList($T)) { + rl.DrawTextEx(FontUI, ">", list.position + list.active_marker + {-30, 0}, 48, 2, rl.WHITE) + for el, i in list.elements { + pos := list.position + {0, f32(i) * list.line_size} + rl.DrawTextEx(FontUI, el, pos, 48, 2, rl.WHITE) + } +} diff --git a/pause.odin b/pause.odin index ad3bef9..eff6af4 100644 --- a/pause.odin +++ b/pause.odin @@ -11,7 +11,7 @@ Pause_Buttons :: enum { } pause_strings := [Pause_Buttons]cstring { - .RESUME = "Старт", + .RESUME = "Продолжить", .FULLSCREEN = "Полный экран", .EXIT = "Выход" } @@ -19,23 +19,24 @@ pause_strings := [Pause_Buttons]cstring { Pause :: struct { using state: GameState, - menu_pos: Vec2, - menu_element_offset: f32, - active_element: Pause_Buttons, - active_marker: Vec2, - marker_tween: ^Tween, + list: MenuList(Pause_Buttons) } pause_init :: proc(prev: ^GameState = nil) -> ^GameState { state := new(Pause) state.variant = state - state.menu_pos = {300, 300} - state.menu_element_offset = 60 - state.active_marker = state.menu_pos + Vec2{0, f32(state.active_element) * state.menu_element_offset} - state.update = menu_update - state.draw = menu_draw - state.free = menu_free + state.list = MenuList(Pause_Buttons){ + position = {-300, 300}, + line_size = 60, + font_size = 42, + elements = &pause_strings, + menu_pressed = pause_button_pressed + } + 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) return state @@ -43,56 +44,35 @@ pause_init :: proc(prev: ^GameState = nil) -> ^GameState { pause_update :: proc(state: ^GameState, delta: f32) { menu := transmute(^Pause)state + + menu_list_update(&menu.list) +} - prev_element := cast(i8)menu.active_element - cur_element := prev_element - - if rl.IsKeyPressed(rl.KeyboardKey.DOWN) { - cur_element += 1 - } - if rl.IsKeyPressed(rl.KeyboardKey.UP) { - cur_element -= 1 - } - if prev_element != cur_element { - if cur_element < 0 { cur_element = len(Pause_Buttons) -1 } - if cur_element == len(Pause_Buttons) { cur_element = 0 } - menu.active_element = cast(Pause_Buttons)cur_element - if menu.marker_tween != nil { - tween_cancel(menu.marker_tween) - } - menu.marker_tween = tween_to( - &menu.active_marker.y, - menu.menu_pos.y + f32(menu.active_element) * menu.menu_element_offset, - 0.5, - ease.Ease.Back_Out, - ) - } - if rl.IsKeyPressed(rl.KeyboardKey.ENTER) || rl.IsKeyPressed(rl.KeyboardKey.SPACE) { - switch menu.active_element { - case .RESUME: - stack_pop() - case .FULLSCREEN: - case .EXIT: - stack_pop() - stack_pop() - } +pause_button_pressed :: proc(state: ^GameState, el: Pause_Buttons) { + switch el { + case .RESUME: + stack_pop() + case .FULLSCREEN: + case .EXIT: + stack_pop() + stack_pop() } } pause_draw :: proc(state: ^GameState) { menu := transmute(^Pause)state + if state.previous != nil { + state.previous->draw() + } + TitleFontSize :: 96 TitleSpacing :: 3 TitleText :: "ПАУЗА" TitleSize := rl.MeasureTextEx(FontTitle, TitleText, TitleFontSize, TitleSpacing) - rl.DrawTextPro(FontTitle, "ARKADODGE", {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) - rl.DrawTextEx(FontUI, ">", menu.active_marker + {-30, 0}, 48, 2, rl.WHITE) - for el, i in menu_strings { - pos := menu.menu_pos + {0, f32(i) * menu.menu_element_offset} - rl.DrawTextEx(FontUI, el, pos, 48, 2, rl.WHITE) - } + menu_list_draw(&menu.list) } pause_free :: proc(state: ^GameState) {