diff options
author | Andres Crucitti <dasc495@gmail.com> | 2021-04-11 18:46:58 -0700 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-05-15 17:44:21 +0100 |
commit | d99991e39c30e44a4a1200107782a1e4b0ea8cb6 (patch) | |
tree | 9e7c14311c1879c21aa03a2d1aad6fbcf6765871 /Userland/Games/GameOfLife/main.cpp | |
parent | e4f61c6f284d78e442d2e63b6fa83aa3f741072e (diff) | |
download | serenity-d99991e39c30e44a4a1200107782a1e4b0ea8cb6.zip |
Games: Add GameOfLife
This patch introduces a new game based on Conway's Game of Life.
Diffstat (limited to 'Userland/Games/GameOfLife/main.cpp')
-rw-r--r-- | Userland/Games/GameOfLife/main.cpp | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/Userland/Games/GameOfLife/main.cpp b/Userland/Games/GameOfLife/main.cpp new file mode 100644 index 0000000000..0fc71f0bbe --- /dev/null +++ b/Userland/Games/GameOfLife/main.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021, Andres Crucitti <dasc495@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "BoardWidget.h" +#include <Games/GameOfLife/GameOfLifeGML.h> +#include <LibGUI/Application.h> +#include <LibGUI/BoxLayout.h> +#include <LibGUI/Button.h> +#include <LibGUI/Icon.h> +#include <LibGUI/Label.h> +#include <LibGUI/Menu.h> +#include <LibGUI/Menubar.h> +#include <LibGUI/MessageBox.h> +#include <LibGUI/Slider.h> +#include <LibGUI/SpinBox.h> +#include <LibGUI/Statusbar.h> +#include <LibGUI/Toolbar.h> +#include <LibGUI/ToolbarContainer.h> +#include <LibGUI/Window.h> + +const char* click_tip = "Tip: click the board to toggle individual cells, or click+drag to toggle multiple cells"; + +int main(int argc, char** argv) +{ + auto app = GUI::Application::construct(argc, argv); + auto app_icon = GUI::Icon::default_icon("app-gameoflife"); + + auto window = GUI::Window::construct(); + window->set_icon(app_icon.bitmap_for_size(16)); + + size_t board_columns = 35; + size_t board_rows = 35; + + window->set_double_buffering_enabled(false); + window->set_title("Game Of Life"); + + auto& main_widget = window->set_main_widget<GUI::Widget>(); + main_widget.load_from_gml(game_of_life_gml); + main_widget.set_fill_with_background_color(true); + + auto& main_toolbar = *main_widget.find_descendant_of_type_named<GUI::Toolbar>("toolbar"); + + auto& board_widget_container = *main_widget.find_descendant_of_type_named<GUI::Widget>("board_widget_container"); + auto& board_layout = board_widget_container.set_layout<GUI::VerticalBoxLayout>(); + board_layout.set_spacing(0); + auto& board_widget = board_widget_container.add<BoardWidget>(board_rows, board_columns); + board_widget.randomize_cells(); + + auto& statusbar = *main_widget.find_descendant_of_type_named<GUI::Statusbar>("statusbar"); + statusbar.set_text(click_tip); + + auto& columns_spinbox = *main_widget.find_descendant_of_type_named<GUI::SpinBox>("columns_spinbox"); + auto& rows_spinbox = *main_widget.find_descendant_of_type_named<GUI::SpinBox>("rows_spinbox"); + + columns_spinbox.set_value(board_columns); + rows_spinbox.set_value(board_rows); + + auto size_changed_function = [&] { + statusbar.set_text(click_tip); + board_widget.update_board(rows_spinbox.value(), columns_spinbox.value()); + board_widget.randomize_cells(); + board_widget.update(); + }; + + rows_spinbox.on_change = [&](auto) { size_changed_function(); }; + columns_spinbox.on_change = [&](auto) { size_changed_function(); }; + + auto& interval_spinbox = *main_widget.find_descendant_of_type_named<GUI::SpinBox>("interval_spinbox"); + + interval_spinbox.on_change = [&](auto value) { + board_widget.set_running_timer_interval(value); + }; + + interval_spinbox.set_value(150); + + auto interval_label = GUI::Label::construct(); + interval_label->set_fixed_width(15); + interval_label->set_text("ms"); + + main_toolbar.add_child(interval_label); + + auto paused_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/pause.png"); + auto play_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/play.png"); + + auto toggle_running_action = GUI::Action::create("Toggle Running", { Mod_None, Key_Return }, *play_icon, [&](GUI::Action&) { + board_widget.set_running(!board_widget.is_running()); + }); + + toggle_running_action->set_checkable(true); + main_toolbar.add_action(toggle_running_action); + + auto run_one_generation_action = GUI::Action::create("Run Next Generation", { Mod_Ctrl, Key_Equal }, Gfx::Bitmap::load_from_file("/res/icons/16x16/go-forward.png"), [&](const GUI::Action&) { + statusbar.set_text(click_tip); + board_widget.run_generation(); + }); + main_toolbar.add_action(run_one_generation_action); + + auto clear_board_action = GUI::Action::create("Clear board", { Mod_Ctrl, Key_N }, Gfx::Bitmap::load_from_file("/res/icons/16x16/delete.png"), [&](auto&) { + statusbar.set_text(click_tip); + board_widget.clear_cells(); + board_widget.update(); + }); + main_toolbar.add_action(clear_board_action); + + auto randomize_cells_action = GUI::Action::create("Randomize board", { Mod_Ctrl, Key_R }, Gfx::Bitmap::load_from_file("/res/icons/16x16/reload.png"), [&](auto&) { + statusbar.set_text(click_tip); + board_widget.randomize_cells(); + board_widget.update(); + }); + main_toolbar.add_action(randomize_cells_action); + + auto menubar = GUI::Menubar::construct(); + auto& app_menu = menubar->add_menu("Game Of Life"); + + app_menu.add_action(clear_board_action); + app_menu.add_action(randomize_cells_action); + app_menu.add_separator(); + app_menu.add_action(toggle_running_action); + app_menu.add_action(run_one_generation_action); + + app_menu.add_action(GUI::CommonActions::make_quit_action([](auto&) { + GUI::Application::the()->quit(); + })); + + auto& help_menu = menubar->add_menu("Help"); + help_menu.add_action(GUI::CommonActions::make_about_action("GameOfLife", app_icon, window)); + + window->set_menubar(move(menubar)); + + board_widget.on_running_state_change = [&]() { + if (board_widget.is_running()) { + statusbar.set_text("Running..."); + toggle_running_action->set_icon(paused_icon); + main_widget.set_override_cursor(Gfx::StandardCursor::None); + } else { + statusbar.set_text(click_tip); + toggle_running_action->set_icon(play_icon); + main_widget.set_override_cursor(Gfx::StandardCursor::Drag); + } + + interval_spinbox.set_value(board_widget.running_timer_interval()); + + rows_spinbox.set_enabled(!board_widget.is_running()); + columns_spinbox.set_enabled(!board_widget.is_running()); + interval_spinbox.set_enabled(!board_widget.is_running()); + + run_one_generation_action->set_enabled(!board_widget.is_running()); + clear_board_action->set_enabled(!board_widget.is_running()); + randomize_cells_action->set_enabled(!board_widget.is_running()); + + board_widget.update(); + }; + + board_widget.on_stall = [&] { + toggle_running_action->activate(); + statusbar.set_text("Stalled..."); + }; + + board_widget.on_cell_toggled = [&](auto, auto) { + statusbar.set_text(click_tip); + }; + + window->resize(500, 420); + window->show(); + + return app->exec(); +} |