Browse Source

Games: Add Conway

Brendan Coles 4 năm trước cách đây
mục cha
commit
d1d729370e

+ 4 - 0
Base/res/apps/Conway.af

@@ -0,0 +1,4 @@
+[App]
+Name=Conway
+Executable=/bin/Conway
+Category=Games

BIN
Base/res/icons/16x16/app-conway.png


BIN
Base/res/icons/32x32/app-conway.png


+ 1 - 0
Games/CMakeLists.txt

@@ -1,6 +1,7 @@
 add_subdirectory(2048)
 add_subdirectory(Breakout)
 add_subdirectory(Chess)
+add_subdirectory(Conway)
 add_subdirectory(Minesweeper)
 add_subdirectory(Pong)
 add_subdirectory(Snake)

+ 7 - 0
Games/Conway/CMakeLists.txt

@@ -0,0 +1,7 @@
+set(SOURCES
+    main.cpp
+    Game.cpp
+)
+
+serenity_app(Conway ICON app-conway)
+target_link_libraries(Conway LibGUI)

+ 118 - 0
Games/Conway/Game.cpp

@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2021, the SerenityOS developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Game.h"
+#include <LibGUI/Painter.h>
+#include <stdlib.h>
+#include <time.h>
+
+Game::Game()
+{
+    srand(time(nullptr));
+    reset();
+}
+
+Game::~Game()
+{
+}
+
+void Game::reset()
+{
+    stop_timer();
+    seed_universe();
+    start_timer(m_sleep);
+    update();
+}
+
+void Game::seed_universe()
+{
+    for (int y = 0; y < m_rows; y++) {
+        for (int x = 0; x < m_columns; x++) {
+            m_universe[y][x] = (arc4random() % 2) ? 1 : 0;
+        }
+    }
+}
+
+void Game::update_universe()
+{
+    bool new_universe[m_rows][m_columns];
+
+    for (int y = 0; y < m_rows; y++) {
+        for (int x = 0; x < m_columns; x++) {
+            int n = 0;
+            auto cell = m_universe[y][x];
+
+            for (int y1 = y - 1; y1 <= y + 1; y1++) {
+                for (int x1 = x - 1; x1 <= x + 1; x1++) {
+                    if (m_universe[(y1 + m_rows) % m_rows][(x1 + m_columns) % m_columns]) {
+                        n++;
+                    }
+                }
+            }
+
+            if (cell)
+                n--;
+
+            if (n == 3 || (n == 2 && cell))
+                new_universe[y][x] = true;
+            else
+                new_universe[y][x] = false;
+        }
+    }
+
+    for (int y = 0; y < m_rows; y++) {
+        for (int x = 0; x < m_columns; x++) {
+            m_universe[y][x] = new_universe[y][x];
+        }
+    }
+}
+
+void Game::timer_event(Core::TimerEvent&)
+{
+    update_universe();
+    update();
+}
+
+void Game::paint_event(GUI::PaintEvent& event)
+{
+    GUI::Painter painter(*this);
+    painter.add_clip_rect(event.rect());
+    painter.fill_rect(event.rect(), m_dead_color);
+    auto game_rect = rect();
+    auto cell_size = Gfx::IntSize(game_rect.width() / m_columns, game_rect.height() / m_rows);
+
+    for (int y = 0; y < m_rows; y++) {
+        for (int x = 0; x < m_columns; x++) {
+            Gfx::IntRect rect {
+                x * cell_size.width(),
+                y * cell_size.height(),
+                cell_size.width(),
+                cell_size.height()
+            };
+            painter.fill_rect(rect, m_universe[y][x] ? m_alive_color : m_dead_color);
+        }
+    }
+}

+ 52 - 0
Games/Conway/Game.h

@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2021, the SerenityOS developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibGUI/Widget.h>
+
+class Game : public GUI::Widget {
+    C_OBJECT(Game)
+public:
+    virtual ~Game() override;
+    void reset();
+
+private:
+    Game();
+    virtual void paint_event(GUI::PaintEvent&) override;
+    virtual void timer_event(Core::TimerEvent&) override;
+
+    void seed_universe();
+    void update_universe();
+
+    Gfx::Color m_alive_color { Color::Green };
+    Gfx::Color m_dead_color { Color::Black };
+    int m_rows { 200 };
+    int m_columns { 200 };
+    int m_sleep { 100 };
+
+    bool m_universe[200][200];
+};

+ 93 - 0
Games/Conway/main.cpp

@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2021, the SerenityOS developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Game.h"
+#include <LibGUI/AboutDialog.h>
+#include <LibGUI/Application.h>
+#include <LibGUI/Icon.h>
+#include <LibGUI/Menu.h>
+#include <LibGUI/MenuBar.h>
+#include <LibGUI/Window.h>
+#include <stdio.h>
+
+int main(int argc, char** argv)
+{
+    if (pledge("stdio rpath wpath cpath shared_buffer accept cpath unix fattr", nullptr) < 0) {
+        perror("pledge");
+        return 1;
+    }
+
+    auto app = GUI::Application::construct(argc, argv);
+
+    if (pledge("stdio rpath shared_buffer accept", nullptr) < 0) {
+        perror("pledge");
+        return 1;
+    }
+
+    if (unveil("/res", "r") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    if (unveil(nullptr, nullptr) < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    auto app_icon = GUI::Icon::default_icon("app-conway");
+
+    auto window = GUI::Window::construct();
+
+    window->set_title("Conway");
+    window->resize(400, 400);
+    window->set_double_buffering_enabled(true);
+    window->set_icon(app_icon.bitmap_for_size(16));
+
+    auto& game = window->set_main_widget<Game>();
+
+    auto menubar = GUI::MenuBar::construct();
+
+    auto& app_menu = menubar->add_menu("Conway");
+
+    app_menu.add_action(GUI::Action::create("Reset", { Mod_None, Key_F2 }, [&](auto&) {
+        game.reset();
+    }));
+    app_menu.add_separator();
+    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::Action::create("About", [&](auto&) {
+        GUI::AboutDialog::show("Conway", app_icon.bitmap_for_size(32), window);
+    }));
+
+    app->set_menubar(move(menubar));
+
+    window->show();
+
+    return app->exec();
+}