diff options
-rw-r--r-- | Base/res/apps/Breakout.af | 4 | ||||
-rw-r--r-- | Base/res/apps/Pong.af | 4 | ||||
-rw-r--r-- | Base/res/icons/16x16/app-breakout.png | bin | 1166 -> 0 bytes | |||
-rw-r--r-- | Base/res/icons/16x16/app-pong.png | bin | 252 -> 0 bytes | |||
-rw-r--r-- | Base/res/icons/32x32/app-breakout.png | bin | 4254 -> 0 bytes | |||
-rw-r--r-- | Base/res/icons/32x32/app-pong.png | bin | 377 -> 0 bytes | |||
-rw-r--r-- | Base/usr/share/man/man6/Breakout.md | 17 | ||||
-rw-r--r-- | Base/usr/share/man/man6/Pong.md | 17 | ||||
-rw-r--r-- | Userland/Games/Breakout/CMakeLists.txt | 14 | ||||
-rw-r--r-- | Userland/Games/Breakout/Game.cpp | 335 | ||||
-rw-r--r-- | Userland/Games/Breakout/Game.h | 105 | ||||
-rw-r--r-- | Userland/Games/Breakout/LevelSelectDialog.cpp | 58 | ||||
-rw-r--r-- | Userland/Games/Breakout/LevelSelectDialog.h | 25 | ||||
-rw-r--r-- | Userland/Games/Breakout/main.cpp | 64 | ||||
-rw-r--r-- | Userland/Games/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Userland/Games/Pong/CMakeLists.txt | 13 | ||||
-rw-r--r-- | Userland/Games/Pong/Game.cpp | 325 | ||||
-rw-r--r-- | Userland/Games/Pong/Game.h | 121 | ||||
-rw-r--r-- | Userland/Games/Pong/main.cpp | 64 |
19 files changed, 0 insertions, 1168 deletions
diff --git a/Base/res/apps/Breakout.af b/Base/res/apps/Breakout.af deleted file mode 100644 index e0533589a1..0000000000 --- a/Base/res/apps/Breakout.af +++ /dev/null @@ -1,4 +0,0 @@ -[App] -Name=Breakout -Executable=/bin/Breakout -Category=Games diff --git a/Base/res/apps/Pong.af b/Base/res/apps/Pong.af deleted file mode 100644 index a6eeef3d23..0000000000 --- a/Base/res/apps/Pong.af +++ /dev/null @@ -1,4 +0,0 @@ -[App] -Name=Pong -Executable=/bin/Pong -Category=Games diff --git a/Base/res/icons/16x16/app-breakout.png b/Base/res/icons/16x16/app-breakout.png Binary files differdeleted file mode 100644 index 9fdf8d17d7..0000000000 --- a/Base/res/icons/16x16/app-breakout.png +++ /dev/null diff --git a/Base/res/icons/16x16/app-pong.png b/Base/res/icons/16x16/app-pong.png Binary files differdeleted file mode 100644 index 668d4fe76a..0000000000 --- a/Base/res/icons/16x16/app-pong.png +++ /dev/null diff --git a/Base/res/icons/32x32/app-breakout.png b/Base/res/icons/32x32/app-breakout.png Binary files differdeleted file mode 100644 index 8f3f6bcbab..0000000000 --- a/Base/res/icons/32x32/app-breakout.png +++ /dev/null diff --git a/Base/res/icons/32x32/app-pong.png b/Base/res/icons/32x32/app-pong.png Binary files differdeleted file mode 100644 index c799825f30..0000000000 --- a/Base/res/icons/32x32/app-pong.png +++ /dev/null diff --git a/Base/usr/share/man/man6/Breakout.md b/Base/usr/share/man/man6/Breakout.md deleted file mode 100644 index d701330081..0000000000 --- a/Base/usr/share/man/man6/Breakout.md +++ /dev/null @@ -1,17 +0,0 @@ -## Name - -![Icon](/res/icons/16x16/app-breakout.png) Breakout - -[Open](file:///bin/Breakout) - -## Synopsis - -```**sh -$ Breakout -``` - -## Description - -Breakout is an arcade game from 1976 where the goal is to remove all blocks by hitting them with a ball bouncing it of a pad. - -The pad can be moved by either using the mouse or the left and right arrow keys. diff --git a/Base/usr/share/man/man6/Pong.md b/Base/usr/share/man/man6/Pong.md deleted file mode 100644 index 22f7e63140..0000000000 --- a/Base/usr/share/man/man6/Pong.md +++ /dev/null @@ -1,17 +0,0 @@ -## Name - -![Icon](/res/icons/16x16/app-pong.png) Pong - -[Open](file:///bin/Pong) - -## Synopsis - -```**sh -$ Pong -``` - -## Description - -Implementation of the 1972 Atari game Pong. - -Make the ball pass behind the opponent by bouncing the ball on the players paddle which can be controlled either by the mouse position or the up and down arrow keys. diff --git a/Userland/Games/Breakout/CMakeLists.txt b/Userland/Games/Breakout/CMakeLists.txt deleted file mode 100644 index 8fb1a5ed6e..0000000000 --- a/Userland/Games/Breakout/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -serenity_component( - Breakout - RECOMMENDED - TARGETS Breakout -) - -set(SOURCES - main.cpp - Game.cpp - LevelSelectDialog.cpp -) - -serenity_app(Breakout ICON app-breakout) -target_link_libraries(Breakout LibGUI LibMain LibDesktop) diff --git a/Userland/Games/Breakout/Game.cpp b/Userland/Games/Breakout/Game.cpp deleted file mode 100644 index 4d0e63f231..0000000000 --- a/Userland/Games/Breakout/Game.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * Copyright (c) 2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "Game.h" -#include "LevelSelectDialog.h" -#include <AK/Random.h> -#include <LibGUI/Application.h> -#include <LibGUI/MessageBox.h> -#include <LibGUI/Painter.h> -#include <LibGfx/AntiAliasingPainter.h> -#include <LibGfx/StandardCursor.h> -#include <unistd.h> - -namespace Breakout { - -Game::Game() -{ - set_override_cursor(Gfx::StandardCursor::Hidden); - auto level_dialog = LevelSelectDialog::show(m_board, window()); - if (level_dialog != GUI::Dialog::ExecResult::OK) - m_board = -1; - set_paused(false); - start_timer(16); - reset(); -} - -void Game::reset_paddle() -{ - update(enclosing_int_rect(m_paddle.rect)); - m_paddle.moving_left = false; - m_paddle.moving_right = false; - m_paddle.rect = { game_width / 2 - 40, game_height - 20, 80, 16 }; - update(enclosing_int_rect(m_paddle.rect)); -} - -void Game::reset() -{ - update(lives_left_rect()); - m_lives = 3; - update(lives_left_rect()); - - m_pause_count = 0; - m_cheater = false; - reset_ball(); - reset_paddle(); - generate_bricks(); -} - -void Game::generate_bricks() -{ - m_bricks = {}; - - Gfx::Color colors[] = { - Gfx::Color::Red, - Gfx::Color::Green, - Gfx::Color::Blue, - Gfx::Color::Yellow, - Gfx::Color::Magenta, - Gfx::Color::Cyan, - Gfx::Color::LightGray, - }; - - Vector<Brick> boards[] = { - // :^) - Vector({ - Brick(0, 0, colors[3], 40, 12, 100), - Brick(0, 4, colors[3], 40, 12, 100), - Brick(1, 2, colors[3], 40, 12, 100), - Brick(1, 5, colors[3], 40, 12, 100), - Brick(2, 1, colors[3], 40, 12, 100), - Brick(2, 3, colors[3], 40, 12, 100), - Brick(2, 6, colors[3], 40, 12, 100), - Brick(3, 6, colors[3], 40, 12, 100), - Brick(4, 0, colors[3], 40, 12, 100), - Brick(4, 6, colors[3], 40, 12, 100), - Brick(5, 6, colors[3], 40, 12, 100), - Brick(6, 5, colors[3], 40, 12, 100), - Brick(7, 4, colors[3], 40, 12, 100), - }) - }; - - if (m_board != -1) { - m_bricks = boards[m_board]; - - for (auto& brick : m_bricks) - update(enclosing_int_rect(brick.rect)); - } else { - // Rainbow - for (int row = 0; row < 7; ++row) { - for (int column = 0; column < 10; ++column) { - Brick brick(row, column, colors[row]); - m_bricks.append(brick); - update(enclosing_int_rect(brick.rect)); - } - } - } -} - -void Game::set_paused(bool paused) -{ - m_paused = paused; - - if (m_paused) { - set_override_cursor(Gfx::StandardCursor::None); - m_pause_count++; - } else { - set_override_cursor(Gfx::StandardCursor::Hidden); - } - - update(pause_rect()); -} - -void Game::timer_event(Core::TimerEvent&) -{ - if (m_paused) - return; - tick(); -} - -void Game::paint_event(GUI::PaintEvent& event) -{ - GUI::Painter painter(*this); - painter.add_clip_rect(event.rect()); - Gfx::AntiAliasingPainter aa_painter { painter }; - - painter.fill_rect(rect(), Color::Black); - - aa_painter.fill_ellipse(enclosing_int_rect(m_ball.rect()), Color::Red); - - painter.fill_rect(enclosing_int_rect(m_paddle.rect), Color::White); - - for (auto& brick : m_bricks) { - if (!brick.dead) - painter.fill_rect(enclosing_int_rect(brick.rect), brick.color); - } - - painter.draw_text(lives_left_rect(), String::formatted("Lives: {}", m_lives), Gfx::TextAlignment::Center, Color::White); - - if (m_paused) { - char const* msg = m_cheater ? "C H E A T E R" : "P A U S E D"; - painter.draw_text(pause_rect(), msg, Gfx::TextAlignment::Center, Color::White); - } -} - -void Game::keyup_event(GUI::KeyEvent& event) -{ - if (m_paused) - return; - switch (event.key()) { - case Key_A: - [[fallthrough]]; - case Key_Left: - m_paddle.moving_left = false; - break; - case Key_D: - [[fallthrough]]; - case Key_Right: - m_paddle.moving_right = false; - break; - default: - break; - } -} - -void Game::keydown_event(GUI::KeyEvent& event) -{ - if (m_paused) - return; - switch (event.key()) { - case Key_Escape: - GUI::Application::the()->quit(); - break; - case Key_A: - [[fallthrough]]; - case Key_Left: - m_paddle.moving_left = true; - break; - case Key_D: - [[fallthrough]]; - case Key_Right: - m_paddle.moving_right = true; - break; - default: - break; - } -} - -void Game::mousemove_event(GUI::MouseEvent& event) -{ - if (m_paused) - return; - update(enclosing_int_rect(m_paddle.rect)); - float new_paddle_x = event.x() - m_paddle.rect.width() / 2; - new_paddle_x = max(0.0f, new_paddle_x); - new_paddle_x = min(game_width - m_paddle.rect.width(), new_paddle_x); - m_paddle.rect.set_x(new_paddle_x); - update(enclosing_int_rect(m_paddle.rect)); -} - -void Game::reset_ball() -{ - int position_x_min = (game_width / 2) - 50; - int position_x_max = (game_width / 2) + 50; - int position_x = get_random<u32>() % (position_x_max - position_x_min + 1) + position_x_min; - int position_y = 200; - int velocity_x = get_random<u32>() % 3 + 1; - int velocity_y = 3 + (3 - velocity_x); - if (get_random<u32>() % 2) - velocity_x = velocity_x * -1; - - update(enclosing_int_rect(m_ball.rect())); - m_ball = {}; - m_ball.position = { position_x, position_y }; - m_ball.velocity = { velocity_x, velocity_y }; - update(enclosing_int_rect(m_ball.rect())); -} - -void Game::hurt() -{ - stop_timer(); - update(lives_left_rect()); - m_lives--; - update(lives_left_rect()); - if (m_lives <= 0) { - GUI::MessageBox::show(window(), "You lose!", "Breakout", GUI::MessageBox::Type::Information, GUI::MessageBox::InputType::OK); - reset(); - } - sleep(1); - reset_ball(); - reset_paddle(); - start_timer(16); -} - -void Game::win() -{ - stop_timer(); - update(); - if (m_cheater) { - GUI::MessageBox::show(window(), "You cheated not only the game, but yourself.", "Breakout", GUI::MessageBox::Type::Information, GUI::MessageBox::InputType::OK); - } else { - GUI::MessageBox::show(window(), "You win!", "Breakout", GUI::MessageBox::Type::Information, GUI::MessageBox::InputType::OK); - } - reset(); - start_timer(16); -} - -void Game::tick() -{ - auto new_ball = m_ball; - new_ball.position += new_ball.velocity; - - update(enclosing_int_rect(m_ball.rect())); - - if (new_ball.x() < new_ball.radius || new_ball.x() > game_width - new_ball.radius) { - new_ball.position.set_x(m_ball.x()); - new_ball.velocity.set_x(new_ball.velocity.x() * -1); - } - - if (new_ball.y() < new_ball.radius) { - new_ball.position.set_y(m_ball.y()); - new_ball.velocity.set_y(new_ball.velocity.y() * -1); - } - - if (new_ball.y() > game_height - new_ball.radius) { - hurt(); - return; - } - - update(enclosing_int_rect(new_ball.rect())); - - if (new_ball.rect().intersects(m_paddle.rect)) { - if (m_ball.y() < new_ball.y()) { - new_ball.position.set_y(m_ball.y()); - } - new_ball.velocity.set_y(fabs(new_ball.velocity.y()) * -1); - - float distance_to_middle_of_paddle = new_ball.x() - m_paddle.rect.center().x(); - float relative_impact_point = distance_to_middle_of_paddle / m_paddle.rect.width(); - new_ball.velocity.set_x(relative_impact_point * 7); - } - - for (auto& brick : m_bricks) { - if (brick.dead) - continue; - if (new_ball.rect().intersects(brick.rect)) { - brick.dead = true; - - auto overlap = new_ball.rect().intersected(brick.rect); - if (overlap.width() < overlap.height()) { - new_ball.position.set_x(m_ball.x()); - new_ball.velocity.set_x(new_ball.velocity.x() * -1); - } else { - new_ball.position.set_y(m_ball.y()); - new_ball.velocity.set_y(new_ball.velocity.y() * -1); - } - update(enclosing_int_rect(brick.rect)); - break; - } - } - - bool has_live_bricks = false; - for (auto& brick : m_bricks) { - if (!brick.dead) { - has_live_bricks = true; - break; - } - } - - if (!has_live_bricks) { - win(); - return; - } - - if (m_paddle.moving_left) { - update(enclosing_int_rect(m_paddle.rect)); - m_paddle.rect.set_x(max(0.0f, m_paddle.rect.x() - m_paddle.speed)); - update(enclosing_int_rect(m_paddle.rect)); - } - if (m_paddle.moving_right) { - update(enclosing_int_rect(m_paddle.rect)); - m_paddle.rect.set_x(min(game_width - m_paddle.rect.width(), m_paddle.rect.x() + m_paddle.speed)); - update(enclosing_int_rect(m_paddle.rect)); - } - - m_ball = new_ball; - - if (m_pause_count > 50) - m_cheater = true; -} - -} diff --git a/Userland/Games/Breakout/Game.h b/Userland/Games/Breakout/Game.h deleted file mode 100644 index 7ac05076be..0000000000 --- a/Userland/Games/Breakout/Game.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * Copyright (c) 2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <LibGUI/Widget.h> -#include <LibGfx/Font/Font.h> - -namespace Breakout { - -class Game final : public GUI::Widget { - C_OBJECT(Game); - -public: - static constexpr int game_width = 480; - static constexpr int game_height = 500; - - virtual ~Game() override = default; - - void set_paused(bool paused); - -private: - Game(); - - virtual void paint_event(GUI::PaintEvent&) override; - virtual void keyup_event(GUI::KeyEvent&) override; - virtual void keydown_event(GUI::KeyEvent&) override; - virtual void mousemove_event(GUI::MouseEvent&) override; - virtual void timer_event(Core::TimerEvent&) override; - - void reset(); - void reset_ball(); - void reset_paddle(); - void generate_bricks(); - void tick(); - void hurt(); - void win(); - - struct Ball { - Gfx::FloatPoint position; - Gfx::FloatPoint velocity; - float radius { 8 }; - - float x() const { return position.x(); } - float y() const { return position.y(); } - - Gfx::FloatRect rect() const - { - return { x() - radius, y() - radius, radius * 2, radius * 2 }; - } - }; - - struct Paddle { - Gfx::FloatRect rect; - float speed { 5 }; - bool moving_left { false }; - bool moving_right { false }; - }; - - struct Brick { - Gfx::FloatRect rect; - Gfx::Color color; - bool dead { false }; - - Brick(int row, int column, Gfx::Color c, int brick_width = 40, int brick_height = 12, int field_left_offset = 30, int field_top_offset = 30, int brick_spacing = 3) - { - rect = { - field_left_offset + (column * brick_width) + (column * brick_spacing), - field_top_offset + (row * brick_height) + (row * brick_spacing), - brick_width, - brick_height - }; - color = c; - } - }; - - Gfx::IntRect lives_left_rect() const - { - int msg_width = font().width(String::formatted("Lives: {}", m_lives)); - return { (game_width - msg_width - 2), 2, msg_width, font().glyph_height() }; - } - - Gfx::IntRect pause_rect() const - { - char const* msg = m_cheater ? "C H E A T E R" : "P A U S E D"; - int msg_width = font().width(msg); - int msg_height = font().glyph_height(); - return { (game_width / 2) - (msg_width / 2), (game_height / 2) - (msg_height / 2), msg_width, msg_height }; - } - - bool m_paused; - int m_lives; - int m_board; - long m_pause_count; - bool m_cheater; - Ball m_ball; - Paddle m_paddle; - Vector<Brick> m_bricks; -}; - -} diff --git a/Userland/Games/Breakout/LevelSelectDialog.cpp b/Userland/Games/Breakout/LevelSelectDialog.cpp deleted file mode 100644 index fb45e21adc..0000000000 --- a/Userland/Games/Breakout/LevelSelectDialog.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2020-2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "LevelSelectDialog.h" -#include <LibGUI/BoxLayout.h> -#include <LibGUI/Button.h> -#include <LibGUI/Label.h> -#include <LibGUI/ListView.h> - -namespace Breakout { - -LevelSelectDialog::LevelSelectDialog(Window* parent_window) - : Dialog(parent_window) -{ - set_rect(0, 0, 300, 250); - set_title("Level Select"); - build(); -} - -GUI::Dialog::ExecResult LevelSelectDialog::show(int& board_number, Window* parent_window) -{ - auto box = LevelSelectDialog::construct(parent_window); - box->set_resizable(false); - if (parent_window) - box->set_icon(parent_window->icon()); - auto result = box->exec(); - board_number = box->level(); - return result; -} - -void LevelSelectDialog::build() -{ - auto& main_widget = set_main_widget<GUI::Widget>(); - main_widget.set_fill_with_background_color(true); - - auto& layout = main_widget.set_layout<GUI::VerticalBoxLayout>(); - layout.set_margins(4); - - main_widget.add<GUI::Label>("Choose a level").set_text_alignment(Gfx::TextAlignment::Center); - - auto& level_list = main_widget.add<GUI::Widget>(); - auto& scroll_layout = level_list.set_layout<GUI::VerticalBoxLayout>(); - scroll_layout.set_spacing(4); - - level_list.add<GUI::Button>("Rainbow").on_click = [this](auto) { - m_level = -1; - done(ExecResult::OK); - }; - - level_list.add<GUI::Button>(":^)").on_click = [this](auto) { - m_level = 0; - done(ExecResult::OK); - }; -} -} diff --git a/Userland/Games/Breakout/LevelSelectDialog.h b/Userland/Games/Breakout/LevelSelectDialog.h deleted file mode 100644 index 89ccb40048..0000000000 --- a/Userland/Games/Breakout/LevelSelectDialog.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2020-2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <LibGUI/Dialog.h> - -namespace Breakout { -class LevelSelectDialog : public GUI::Dialog { - C_OBJECT(LevelSelectDialog) -public: - virtual ~LevelSelectDialog() override = default; - static ExecResult show(int& board_number, Window* parent_window); - int level() const { return m_level; } - -private: - explicit LevelSelectDialog(Window* parent_window); - void build(); - - int m_level; -}; -} diff --git a/Userland/Games/Breakout/main.cpp b/Userland/Games/Breakout/main.cpp deleted file mode 100644 index 53a30852d9..0000000000 --- a/Userland/Games/Breakout/main.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "Game.h" -#include <AK/URL.h> -#include <LibCore/System.h> -#include <LibDesktop/Launcher.h> -#include <LibGUI/Application.h> -#include <LibGUI/Icon.h> -#include <LibGUI/Menu.h> -#include <LibGUI/Menubar.h> -#include <LibGUI/Window.h> -#include <LibGfx/Bitmap.h> -#include <LibMain/Main.h> - -ErrorOr<int> serenity_main(Main::Arguments arguments) -{ - TRY(Core::System::pledge("stdio recvfd sendfd rpath unix")); - - auto app = TRY(GUI::Application::try_create(arguments)); - - TRY(Desktop::Launcher::add_allowed_handler_with_only_specific_urls("/bin/Help", { URL::create_with_file_protocol("/usr/share/man/man6/Breakout.md") })); - TRY(Desktop::Launcher::seal_allowlist()); - - TRY(Core::System::pledge("stdio recvfd sendfd rpath")); - - TRY(Core::System::unveil("/res", "r")); - TRY(Core::System::unveil("/tmp/portal/launch", "rw")); - TRY(Core::System::unveil(nullptr, nullptr)); - - auto window = TRY(GUI::Window::try_create()); - window->resize(Breakout::Game::game_width, Breakout::Game::game_height); - window->set_resizable(false); - window->set_double_buffering_enabled(false); - window->set_title("Breakout"); - - auto app_icon = TRY(GUI::Icon::try_create_default_icon("app-breakout")); - window->set_icon(app_icon.bitmap_for_size(16)); - - auto game = TRY(window->try_set_main_widget<Breakout::Game>()); - - auto game_menu = TRY(window->try_add_menu("&Game")); - TRY(game_menu->try_add_action(GUI::Action::create_checkable("&Pause", { {}, Key_P }, [&](auto& action) { - game->set_paused(action.is_checked()); - }))); - - TRY(game_menu->try_add_separator()); - TRY(game_menu->try_add_action(GUI::CommonActions::make_quit_action([](auto&) { - GUI::Application::the()->quit(); - }))); - - auto help_menu = TRY(window->try_add_menu("&Help")); - TRY(help_menu->try_add_action(GUI::CommonActions::make_help_action([](auto&) { - Desktop::Launcher::open(URL::create_with_file_protocol("/usr/share/man/man6/Breakout.md"), "/bin/Help"); - }))); - TRY(help_menu->try_add_action(GUI::CommonActions::make_about_action("Breakout", app_icon, window))); - - window->show(); - - return app->exec(); -} diff --git a/Userland/Games/CMakeLists.txt b/Userland/Games/CMakeLists.txt index a75ac6c7ff..7732fd5f80 100644 --- a/Userland/Games/CMakeLists.txt +++ b/Userland/Games/CMakeLists.txt @@ -1,12 +1,10 @@ add_subdirectory(2048) -add_subdirectory(Breakout) add_subdirectory(Chess) add_subdirectory(FlappyBug) add_subdirectory(GameOfLife) add_subdirectory(Hearts) add_subdirectory(MasterWord) add_subdirectory(Minesweeper) -add_subdirectory(Pong) add_subdirectory(Snake) add_subdirectory(Solitaire) add_subdirectory(Spider) diff --git a/Userland/Games/Pong/CMakeLists.txt b/Userland/Games/Pong/CMakeLists.txt deleted file mode 100644 index 1787e60133..0000000000 --- a/Userland/Games/Pong/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -serenity_component( - Pong - RECOMMENDED - TARGETS Pong -) - -set(SOURCES - main.cpp - Game.cpp -) - -serenity_app(Pong ICON app-pong) -target_link_libraries(Pong LibGUI LibMain LibDesktop) diff --git a/Userland/Games/Pong/Game.cpp b/Userland/Games/Pong/Game.cpp deleted file mode 100644 index eee3697b99..0000000000 --- a/Userland/Games/Pong/Game.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 2020-2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "Game.h" -#include <AK/Random.h> -#include <LibGfx/AntiAliasingPainter.h> - -namespace Pong { - -Game::Game() -{ - start_timer(16); - reset(); -} - -void Game::reset_keys() -{ - m_up_key_held = false; - m_down_key_held = false; -} - -void Game::reset_paddles() -{ - if (m_cursor_paddle_target_y.has_value()) - update(cursor_paddle_target_rect()); - m_cursor_paddle_target_y.clear(); - - update(enclosing_int_rect(m_player1_paddle.rect)); - m_player1_paddle.moving_up = m_up_key_held; - m_player1_paddle.moving_down = m_down_key_held; - m_player1_paddle.rect = { game_width - 12, game_height / 2 - 40, m_player1_paddle.width, m_player1_paddle.height }; - update(enclosing_int_rect(m_player1_paddle.rect)); - - update(enclosing_int_rect(m_player2_paddle.rect)); - m_player2_paddle.moving_up = false; - m_player2_paddle.moving_down = false; - m_player2_paddle.rect = { 4, game_height / 2 - 40, m_player2_paddle.width, m_player2_paddle.height }; - update(enclosing_int_rect(m_player2_paddle.rect)); -} - -void Game::reset() -{ - if (m_game_over) { - m_game_over = false; - start_timer(16); - } - - // Make sure the current ball disappears. - update(enclosing_int_rect(m_ball.rect())); - - reset_scores(); - reset_ball(1); - reset_keys(); - reset_paddles(); -} - -void Game::timer_event(Core::TimerEvent&) -{ - tick(); -} - -void Game::paint_event(GUI::PaintEvent& event) -{ - GUI::Painter painter(*this); - painter.add_clip_rect(event.rect()); - - Gfx::AntiAliasingPainter aa_painter { painter }; - - painter.fill_rect(rect(), Color::Black); - painter.fill_rect(enclosing_int_rect(m_net.rect()), m_net.color); - - aa_painter.fill_ellipse(enclosing_int_rect(m_ball.rect()), Color::Red); - - painter.fill_rect(enclosing_int_rect(m_player1_paddle.rect), m_player1_paddle.color); - painter.fill_rect(enclosing_int_rect(m_player2_paddle.rect), m_player2_paddle.color); - - if (m_cursor_paddle_target_y.has_value()) - aa_painter.fill_ellipse(cursor_paddle_target_rect(), Color::Blue); - - painter.draw_text(player_1_score_rect(), String::formatted("{}", m_player_1_score), Gfx::TextAlignment::TopLeft, Color::White); - painter.draw_text(player_2_score_rect(), String::formatted("{}", m_player_2_score), Gfx::TextAlignment::TopLeft, Color::White); -} - -void Game::keyup_event(GUI::KeyEvent& event) -{ - switch (event.key()) { - case Key_W: - case Key_Up: - m_up_key_held = false; - m_player1_paddle.moving_up = false; - break; - case Key_S: - case Key_Down: - m_down_key_held = false; - m_player1_paddle.moving_down = false; - break; - default: - break; - } -} - -void Game::keydown_event(GUI::KeyEvent& event) -{ - switch (event.key()) { - case Key_Escape: - GUI::Application::the()->quit(); - break; - case Key_W: - case Key_Up: - m_up_key_held = true; - m_player1_paddle.moving_up = true; - m_player1_paddle.moving_down = false; - m_cursor_paddle_target_y.clear(); - break; - case Key_S: - case Key_Down: - m_down_key_held = true; - m_player1_paddle.moving_up = false; - m_player1_paddle.moving_down = true; - m_cursor_paddle_target_y.clear(); - break; - default: - break; - } -} - -void Game::track_mouse_move(Gfx::IntPoint const& point) -{ - if (m_up_key_held || m_down_key_held) { - // We're using the keyboard to move the paddle, the cursor is doing something else - return; - } - - if (m_cursor_paddle_target_y.has_value()) - update(cursor_paddle_target_rect()); - - auto relative_point = point - window()->position(); - m_cursor_paddle_target_y = clamp(relative_point.y() - m_player1_paddle.rect.height() / 2, 0.f, game_height - m_player1_paddle.rect.height()); - if (m_player1_paddle.rect.y() > *m_cursor_paddle_target_y) { - m_player1_paddle.moving_up = true; - m_player1_paddle.moving_down = false; - } else if (m_player1_paddle.rect.y() < *m_cursor_paddle_target_y) { - m_player1_paddle.moving_up = false; - m_player1_paddle.moving_down = true; - } - update(cursor_paddle_target_rect()); -} - -void Game::reset_scores() -{ - // Clearing the scores first would lead to overly narrow rects for multi-digit scores. - update(player_1_score_rect()); - update(player_2_score_rect()); - - m_player_1_score = 0; - m_player_2_score = 0; -} - -void Game::reset_ball(int serve_to_player) -{ - int position_y_min = (game_width / 2) - 50; - int position_y_max = (game_width / 2) + 50; - int position_y = get_random<u32>() % (position_y_max - position_y_min + 1) + position_y_min; - int position_x = (game_height / 2); - int velocity_y = get_random<u32>() % 3 + 1; - int velocity_x = 4 + (5 - velocity_y); - if (get_random<u32>() % 2) - velocity_y = velocity_y * -1; - if (serve_to_player == 2) - velocity_x = velocity_x * -1; - - m_ball = {}; - m_ball.position = { position_x, position_y }; - m_ball.velocity = { velocity_x, velocity_y }; -} - -void Game::show_game_over_message(int winner) -{ - GUI::MessageBox::show(window(), String::formatted("Player {} wins!", winner), "Pong", GUI::MessageBox::Type::Warning, GUI::MessageBox::InputType::OK); -} - -void Game::round_over(int winner) -{ - stop_timer(); - if (winner == 1) { - update(player_1_score_rect()); - m_player_1_score++; - update(player_1_score_rect()); - } - - if (winner == 2) { - update(player_2_score_rect()); - m_player_2_score++; - update(player_2_score_rect()); - } - - if (m_player_1_score == m_score_to_win || m_player_2_score == m_score_to_win) { - m_game_over = true; - show_game_over_message(winner); - return; - } - - reset_ball(winner); - reset_paddles(); - start_timer(16); -} - -void Game::calculate_move() -{ - int player_2_paddle_top = m_player2_paddle.rect.top(); - int player_2_paddle_bottom = m_player2_paddle.rect.bottom(); - - if (m_ball.velocity.x() > 0 || m_ball.x() > game_width / 2) { - // The ball is in the opponent's court, relax. - m_player2_paddle.moving_up = false; - m_player2_paddle.moving_down = false; - return; - } - - int ball_position = m_ball.y() + m_ball.radius; - - // AI paddle begins moving when the ball crosses the begin_trigger, - // but stops only if it crosses the end_trigger. end_trigger forces - // overcorrection, so that the paddle moves more smoothly. - int begin_trigger = m_player2_paddle.rect.height() / 4; - int end_trigger = m_player2_paddle.rect.height() / 2; - - if (m_player2_paddle.moving_up) { - if (player_2_paddle_top + end_trigger < ball_position) - m_player2_paddle.moving_up = false; - } else { - if (player_2_paddle_top + begin_trigger > ball_position) - m_player2_paddle.moving_up = true; - } - - if (m_player2_paddle.moving_down) { - if (player_2_paddle_bottom - end_trigger > ball_position) - m_player2_paddle.moving_down = false; - } else { - if (player_2_paddle_bottom - begin_trigger < ball_position) - m_player2_paddle.moving_down = true; - } -} - -void Game::tick() -{ - auto new_ball = m_ball; - new_ball.position += new_ball.velocity; - - update(enclosing_int_rect(m_ball.rect())); - - if (new_ball.y() < new_ball.radius || new_ball.y() > game_height - new_ball.radius) { - new_ball.position.set_y(m_ball.y()); - new_ball.velocity.set_y(new_ball.velocity.y() * -1); - } - - if (new_ball.x() < new_ball.radius) { - round_over(1); - return; - } - - if (new_ball.x() > (game_width - new_ball.radius)) { - round_over(2); - return; - } - - update(enclosing_int_rect(new_ball.rect())); - - if (new_ball.rect().intersects(m_player1_paddle.rect)) { - new_ball.position.set_x(m_ball.x()); - new_ball.velocity.set_x(new_ball.velocity.x() * -1); - - float distance_to_middle_of_paddle = new_ball.y() - m_player1_paddle.rect.center().y(); - float relative_impact_point = distance_to_middle_of_paddle / m_player1_paddle.rect.height(); - new_ball.velocity.set_y(relative_impact_point * 7); - } - - if (new_ball.rect().intersects(m_player2_paddle.rect)) { - new_ball.position.set_x(m_ball.x()); - new_ball.velocity.set_x(new_ball.velocity.x() * -1); - - float distance_to_middle_of_paddle = new_ball.y() - m_player2_paddle.rect.center().y(); - float relative_impact_point = distance_to_middle_of_paddle / m_player2_paddle.rect.height(); - new_ball.velocity.set_y(relative_impact_point * 7); - } - - if (m_player1_paddle.moving_up) { - update(enclosing_int_rect(m_player1_paddle.rect)); - m_player1_paddle.rect.set_y(max(0.0f, m_player1_paddle.rect.y() - m_player1_paddle.speed)); - if (m_cursor_paddle_target_y.has_value() && m_player1_paddle.rect.y() <= *m_cursor_paddle_target_y) { - m_cursor_paddle_target_y.clear(); - m_player1_paddle.moving_up = false; - } - update(enclosing_int_rect(m_player1_paddle.rect)); - } - if (m_player1_paddle.moving_down) { - update(enclosing_int_rect(m_player1_paddle.rect)); - m_player1_paddle.rect.set_y(min(game_height - m_player1_paddle.rect.height(), m_player1_paddle.rect.y() + m_player1_paddle.speed)); - if (m_cursor_paddle_target_y.has_value() && m_player1_paddle.rect.y() >= *m_cursor_paddle_target_y) { - m_cursor_paddle_target_y.clear(); - m_player1_paddle.moving_down = false; - } - update(enclosing_int_rect(m_player1_paddle.rect)); - } - - calculate_move(); - - if (m_player2_paddle.moving_up) { - update(enclosing_int_rect(m_player2_paddle.rect)); - m_player2_paddle.rect.set_y(max(0.0f, m_player2_paddle.rect.y() - m_player2_paddle.speed)); - update(enclosing_int_rect(m_player2_paddle.rect)); - } - if (m_player2_paddle.moving_down) { - update(enclosing_int_rect(m_player2_paddle.rect)); - m_player2_paddle.rect.set_y(min(game_height - m_player2_paddle.rect.height(), m_player2_paddle.rect.y() + m_player2_paddle.speed)); - update(enclosing_int_rect(m_player2_paddle.rect)); - } - - m_ball = new_ball; -} - -} diff --git a/Userland/Games/Pong/Game.h b/Userland/Games/Pong/Game.h deleted file mode 100644 index ab7973e63a..0000000000 --- a/Userland/Games/Pong/Game.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2020-2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <AK/Optional.h> -#include <LibGUI/Application.h> -#include <LibGUI/MessageBox.h> -#include <LibGUI/MouseTracker.h> -#include <LibGUI/Painter.h> -#include <LibGUI/Widget.h> -#include <LibGfx/Bitmap.h> -#include <LibGfx/Font/Font.h> -#include <LibGfx/StandardCursor.h> - -namespace Pong { - -class Game final : public GUI::Widget - , GUI::MouseTracker { - C_OBJECT(Game); - -public: - static constexpr int game_width = 560; - static constexpr int game_height = 480; - - virtual ~Game() override = default; - - void reset(); - -private: - Game(); - - virtual void paint_event(GUI::PaintEvent&) override; - virtual void keyup_event(GUI::KeyEvent&) override; - virtual void keydown_event(GUI::KeyEvent&) override; - virtual void timer_event(Core::TimerEvent&) override; - virtual void track_mouse_move(Gfx::IntPoint const&) override; - - void reset_scores(); - void reset_ball(int serve_to_player); - void reset_keys(); - void reset_paddles(); - void tick(); - void round_over(int player); - void show_game_over_message(int player); - void calculate_move(); - - struct Ball { - Gfx::FloatPoint position; - Gfx::FloatPoint velocity; - float radius { 4 }; - - float x() const { return position.x(); } - float y() const { return position.y(); } - - Gfx::FloatRect rect() const - { - return { x() - radius, y() - radius, radius * 2, radius * 2 }; - } - }; - - struct Paddle { - Gfx::FloatRect rect; - float speed { 5 }; - float width { 8 }; - float height { 28 }; - bool moving_up { false }; - bool moving_down { false }; - Gfx::Color color { Color::White }; - }; - - struct Net { - Gfx::Color color { Color::White }; - Gfx::FloatRect rect() const - { - return { (game_width / 2) - 1, 0, 2, game_height }; - } - }; - - constexpr static int score_margin = 5; - - Gfx::IntRect player_1_score_rect() const - { - int score_width = font().width(String::formatted("{}", m_player_1_score)); - return { (game_width / 2) + score_margin, score_margin, score_width, font().glyph_height() }; - } - - Gfx::IntRect player_2_score_rect() const - { - int score_width = font().width(String::formatted("{}", m_player_2_score)); - return { (game_width / 2) - score_width - score_margin, score_margin, score_width, font().glyph_height() }; - } - - Gfx::IntRect cursor_paddle_target_rect() const - { - int radius = 3; - int center_x = m_player1_paddle.rect.center().x(); - int center_y = *m_cursor_paddle_target_y + m_player1_paddle.rect.height() / 2; - return { center_x - radius, center_y - radius, 2 * radius, 2 * radius }; - } - - Net m_net; - Ball m_ball; - Paddle m_player1_paddle; - Paddle m_player2_paddle; - - int m_score_to_win = 21; - int m_player_1_score = 0; - int m_player_2_score = 0; - - Optional<int> m_cursor_paddle_target_y; - bool m_up_key_held = false; - bool m_down_key_held = false; - - bool m_game_over = false; -}; - -} diff --git a/Userland/Games/Pong/main.cpp b/Userland/Games/Pong/main.cpp deleted file mode 100644 index fc9fd1c8e4..0000000000 --- a/Userland/Games/Pong/main.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2020-2021, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "Game.h" -#include <AK/URL.h> -#include <LibCore/System.h> -#include <LibDesktop/Launcher.h> -#include <LibGUI/Application.h> -#include <LibGUI/Icon.h> -#include <LibGUI/Menu.h> -#include <LibGUI/Menubar.h> -#include <LibGUI/Window.h> -#include <LibGfx/Bitmap.h> -#include <LibMain/Main.h> - -ErrorOr<int> serenity_main(Main::Arguments arguments) -{ - TRY(Core::System::pledge("stdio rpath recvfd sendfd unix")); - - auto app = TRY(GUI::Application::try_create(arguments)); - - TRY(Desktop::Launcher::add_allowed_handler_with_only_specific_urls("/bin/Help", { URL::create_with_file_protocol("/usr/share/man/man6/Pong.md") })); - TRY(Desktop::Launcher::seal_allowlist()); - - TRY(Core::System::pledge("stdio rpath recvfd sendfd")); - - TRY(Core::System::unveil("/res", "r")); - TRY(Core::System::unveil("/tmp/portal/launch", "rw")); - TRY(Core::System::unveil(nullptr, nullptr)); - - auto window = TRY(GUI::Window::try_create()); - window->resize(Pong::Game::game_width, Pong::Game::game_height); - auto app_icon = TRY(GUI::Icon::try_create_default_icon("app-pong")); - window->set_icon(app_icon.bitmap_for_size(16)); - window->set_title("Pong"); - window->set_double_buffering_enabled(false); - auto game = TRY(window->try_set_main_widget<Pong::Game>()); - window->set_resizable(false); - - 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")), [&](auto&) { - game->reset(); - }))); - - TRY(game_menu->try_add_separator()); - - TRY(game_menu->try_add_action(GUI::CommonActions::make_quit_action([](auto&) { - GUI::Application::the()->quit(); - }))); - - auto help_menu = TRY(window->try_add_menu("&Help")); - TRY(help_menu->try_add_action(GUI::CommonActions::make_help_action([](auto&) { - Desktop::Launcher::open(URL::create_with_file_protocol("/usr/share/man/man6/Pong.md"), "/bin/Help"); - }))); - TRY(help_menu->try_add_action(GUI::CommonActions::make_about_action("Pong", app_icon, window))); - - window->show(); - - return app->exec(); -} |