diff options
author | Timothy Flynn <trflynn89@pm.me> | 2022-12-20 08:55:56 -0500 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-12-23 23:26:21 +0100 |
commit | 661c02b91484fbdeba0efe32d2f03afa9c3cb954 (patch) | |
tree | 8c505a690c92b74825d1181607abb8b5bf468f32 | |
parent | cb66c02bc4638ee53cf0879cccc3d6e6db6b8c17 (diff) | |
download | serenity-661c02b91484fbdeba0efe32d2f03afa9c3cb954.zip |
Snake: Use a statusbar to display the current and high score
The food bitmaps would sometimes be placed underneath the score text,
which was a bit hard to see. Use a statusbar like we do in other games
like Solitaire.
Note the default height change of the Snake window is to make the inner
game widget fit exactly 20x20 cells.
-rw-r--r-- | Userland/Games/Snake/Game.cpp | 36 | ||||
-rw-r--r-- | Userland/Games/Snake/Game.h | 7 | ||||
-rw-r--r-- | Userland/Games/Snake/Snake.gml | 5 | ||||
-rw-r--r-- | Userland/Games/Snake/main.cpp | 21 |
4 files changed, 36 insertions, 33 deletions
diff --git a/Userland/Games/Snake/Game.cpp b/Userland/Games/Snake/Game.cpp index 3afdaa34bb..d3350339e3 100644 --- a/Userland/Games/Snake/Game.cpp +++ b/Userland/Games/Snake/Game.cpp @@ -74,8 +74,7 @@ Game::Game() { set_font(Gfx::FontDatabase::default_fixed_width_font().bold_variant()); reset(); - m_high_score = Config::read_i32("Snake"sv, "Snake"sv, "HighScore"sv, 0); - m_high_score_text = DeprecatedString::formatted("Best: {}", m_high_score); + m_snake_base_color = Color::from_argb(Config::read_u32("Snake"sv, "Snake"sv, "BaseColor"sv, m_snake_base_color.value())); } @@ -96,9 +95,12 @@ void Game::reset() m_tail.clear_with_capacity(); m_length = 2; m_score = 0; - m_score_text = "Score: 0"; m_is_new_high_score = false; m_velocity_queue.clear(); + + if (on_score_update) + on_score_update(m_score); + pause(); start(); spawn_fruit(); @@ -137,18 +139,6 @@ void Game::spawn_fruit() m_fruit_type = get_random_uniform(m_food_bitmaps.size()); } -Gfx::IntRect Game::score_rect() const -{ - int score_width = font().width(m_score_text); - return { frame_inner_rect().width() - score_width - 2, frame_inner_rect().height() - font().glyph_height() - 2, score_width, font().glyph_height() }; -} - -Gfx::IntRect Game::high_score_rect() const -{ - int high_score_width = font().width(m_high_score_text); - return { frame_thickness() + 2, frame_inner_rect().height() - font().glyph_height() - 2, high_score_width, font().glyph_height() }; -} - void Game::timer_event(Core::TimerEvent&) { Vector<Coordinate> dirty_cells; @@ -191,15 +181,10 @@ void Game::timer_event(Core::TimerEvent&) if (m_head == m_fruit) { ++m_length; ++m_score; - m_score_text = DeprecatedString::formatted("Score: {}", m_score); - if (m_score > m_high_score) { - m_is_new_high_score = true; - m_high_score = m_score; - m_high_score_text = DeprecatedString::formatted("Best: {}", m_high_score); - update(high_score_rect()); - Config::write_i32("Snake"sv, "Snake"sv, "HighScore"sv, m_high_score); - } - update(score_rect()); + + if (on_score_update) + m_is_new_high_score = on_score_update(m_score); + dirty_cells.append(m_fruit); spawn_fruit(); dirty_cells.append(m_fruit); @@ -279,9 +264,6 @@ void Game::paint_event(GUI::PaintEvent& event) } painter.draw_scaled_bitmap(cell_rect(m_fruit), m_food_bitmaps[m_fruit_type], m_food_bitmaps[m_fruit_type].rect()); - - painter.draw_text(high_score_rect(), m_high_score_text, Gfx::TextAlignment::TopLeft, Color::from_rgb(0xfafae0)); - painter.draw_text(score_rect(), m_score_text, Gfx::TextAlignment::TopLeft, Color::White); } void Game::game_over() diff --git a/Userland/Games/Snake/Game.h b/Userland/Games/Snake/Game.h index 41b30933fd..0c512813b3 100644 --- a/Userland/Games/Snake/Game.h +++ b/Userland/Games/Snake/Game.h @@ -25,6 +25,8 @@ public: void set_snake_base_color(Color color); + Function<bool(u32)> on_score_update; + private: Game(); @@ -53,8 +55,6 @@ private: void queue_velocity(int v, int h); Velocity const& last_velocity() const; Gfx::IntRect cell_rect(Coordinate const&) const; - Gfx::IntRect score_rect() const; - Gfx::IntRect high_score_rect() const; int m_rows { 20 }; int m_columns { 20 }; @@ -72,9 +72,6 @@ private: size_t m_length { 0 }; unsigned m_score { 0 }; - DeprecatedString m_score_text; - unsigned m_high_score { 0 }; - DeprecatedString m_high_score_text; bool m_is_new_high_score { false }; NonnullRefPtrVector<Gfx::Bitmap> m_food_bitmaps; diff --git a/Userland/Games/Snake/Snake.gml b/Userland/Games/Snake/Snake.gml index 865c6d8b1f..bbf142cae7 100644 --- a/Userland/Games/Snake/Snake.gml +++ b/Userland/Games/Snake/Snake.gml @@ -6,4 +6,9 @@ name: "game" fill_with_background_color: true } + + @GUI::Statusbar { + name: "statusbar" + segment_count: 2 + } } diff --git a/Userland/Games/Snake/main.cpp b/Userland/Games/Snake/main.cpp index 93644bc5df..c363643e02 100644 --- a/Userland/Games/Snake/main.cpp +++ b/Userland/Games/Snake/main.cpp @@ -18,6 +18,7 @@ #include <LibGUI/Icon.h> #include <LibGUI/Menu.h> #include <LibGUI/Menubar.h> +#include <LibGUI/Statusbar.h> #include <LibGUI/Window.h> #include <LibMain/Main.h> #include <stdio.h> @@ -45,7 +46,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) window->set_double_buffering_enabled(false); window->set_title("Snake"); - window->resize(324, 344); + window->resize(324, 345); auto widget = TRY(window->try_set_main_widget<GUI::Widget>()); widget->load_from_gml(snake_gml); @@ -53,6 +54,24 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) auto& game = *widget->find_descendant_of_type_named<Snake::Game>("game"); game.set_focus(true); + auto high_score = Config::read_u32("Snake"sv, "Snake"sv, "HighScore"sv, 0); + + auto& statusbar = *widget->find_descendant_of_type_named<GUI::Statusbar>("statusbar"sv); + statusbar.set_text(0, "Score: 0"sv); + statusbar.set_text(1, DeprecatedString::formatted("High Score: {}", high_score)); + + game.on_score_update = [&](auto score) { + statusbar.set_text(0, DeprecatedString::formatted("Score: {}", score)); + if (score <= high_score) + return false; + + statusbar.set_text(1, DeprecatedString::formatted("High Score: {}", score)); + Config::write_u32("Snake"sv, "Snake"sv, "HighScore"sv, score); + + high_score = score; + return true; + }; + auto game_menu = TRY(window->try_add_menu("&Game")); TRY(game_menu->try_add_action(GUI::Action::create("&New Game", { Mod_None, Key_F2 }, TRY(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/reload.png"sv)), [&](auto&) { |