Serenity Operating System
at master 119 lines 4.5 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "Game.h" 8#include <AK/URL.h> 9#include <Games/Snake/SnakeGML.h> 10#include <LibConfig/Client.h> 11#include <LibCore/System.h> 12#include <LibDesktop/Launcher.h> 13#include <LibGUI/Action.h> 14#include <LibGUI/Application.h> 15#include <LibGUI/BoxLayout.h> 16#include <LibGUI/Button.h> 17#include <LibGUI/ColorPicker.h> 18#include <LibGUI/Icon.h> 19#include <LibGUI/Menu.h> 20#include <LibGUI/Menubar.h> 21#include <LibGUI/Statusbar.h> 22#include <LibGUI/Window.h> 23#include <LibMain/Main.h> 24#include <stdio.h> 25 26ErrorOr<int> serenity_main(Main::Arguments arguments) 27{ 28 TRY(Core::System::pledge("stdio rpath recvfd sendfd unix")); 29 30 auto app = TRY(GUI::Application::try_create(arguments)); 31 32 Config::pledge_domain("Snake"); 33 34 TRY(Desktop::Launcher::add_allowed_handler_with_only_specific_urls("/bin/Help", { URL::create_with_file_scheme("/usr/share/man/man6/Snake.md") })); 35 TRY(Desktop::Launcher::seal_allowlist()); 36 37 TRY(Core::System::pledge("stdio rpath recvfd sendfd")); 38 39 TRY(Core::System::unveil("/tmp/session/%sid/portal/launch", "rw")); 40 TRY(Core::System::unveil("/res", "r")); 41 TRY(Core::System::unveil(nullptr, nullptr)); 42 43 auto app_icon = TRY(GUI::Icon::try_create_default_icon("app-snake"sv)); 44 45 auto window = TRY(GUI::Window::try_create()); 46 47 window->set_double_buffering_enabled(false); 48 window->set_title("Snake"); 49 window->resize(324, 345); 50 51 auto widget = TRY(window->set_main_widget<GUI::Widget>()); 52 TRY(widget->load_from_gml(snake_gml)); 53 54 auto& game = *widget->find_descendant_of_type_named<Snake::Game>("game"); 55 game.set_focus(true); 56 57 auto high_score = Config::read_u32("Snake"sv, "Snake"sv, "HighScore"sv, 0); 58 59 auto& statusbar = *widget->find_descendant_of_type_named<GUI::Statusbar>("statusbar"sv); 60 statusbar.set_text(0, "Score: 0"sv); 61 statusbar.set_text(1, DeprecatedString::formatted("High Score: {}", high_score)); 62 63 game.on_score_update = [&](auto score) { 64 statusbar.set_text(0, DeprecatedString::formatted("Score: {}", score)); 65 if (score <= high_score) 66 return false; 67 68 statusbar.set_text(1, DeprecatedString::formatted("High Score: {}", score)); 69 Config::write_u32("Snake"sv, "Snake"sv, "HighScore"sv, score); 70 71 high_score = score; 72 return true; 73 }; 74 75 auto game_menu = TRY(window->try_add_menu("&Game")); 76 77 TRY(game_menu->try_add_action(GUI::Action::create("&New Game", { Mod_None, Key_F2 }, TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/reload.png"sv)), [&](auto&) { 78 game.reset(); 79 }))); 80 static DeprecatedString const pause_text = "&Pause Game"sv; 81 auto const pause_icon = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/pause.png"sv)); 82 static DeprecatedString const continue_text = "&Continue Game"sv; 83 auto const continue_icon = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/play.png"sv)); 84 TRY(game_menu->try_add_action(GUI::Action::create(pause_text, { Mod_None, Key_Space }, pause_icon, [&](auto& action) { 85 if (game.has_timer()) { 86 game.pause(); 87 action.set_text(continue_text); 88 action.set_icon(continue_icon); 89 } else { 90 game.start(); 91 action.set_text(pause_text); 92 action.set_icon(pause_icon); 93 } 94 }))); 95 TRY(game_menu->try_add_action(GUI::Action::create("&Change snake color", TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/color-chooser.png"sv)), [&](auto&) { 96 game.pause(); 97 auto dialog = GUI::ColorPicker::construct(Gfx::Color::White, window); 98 if (dialog->exec() == GUI::Dialog::ExecResult::OK) 99 game.set_snake_base_color(dialog->color()); 100 game.start(); 101 }))); 102 TRY(game_menu->try_add_separator()); 103 TRY(game_menu->try_add_action(GUI::CommonActions::make_quit_action([](auto&) { 104 GUI::Application::the()->quit(); 105 }))); 106 107 auto help_menu = TRY(window->try_add_menu("&Help")); 108 TRY(help_menu->try_add_action(GUI::CommonActions::make_command_palette_action(window))); 109 TRY(help_menu->try_add_action(GUI::CommonActions::make_help_action([](auto&) { 110 Desktop::Launcher::open(URL::create_with_file_scheme("/usr/share/man/man6/Snake.md"), "/bin/Help"); 111 }))); 112 TRY(help_menu->try_add_action(GUI::CommonActions::make_about_action("Snake", app_icon, window))); 113 114 window->show(); 115 116 window->set_icon(app_icon.bitmap_for_size(16)); 117 118 return app->exec(); 119}