From 6914cf830d63b6ab2794824a3583ccdd4946cc38 Mon Sep 17 00:00:00 2001 From: John Brehm Date: Wed, 2 Dec 2020 14:49:42 -0800 Subject: [PATCH] Games: Added level select and aditional level to Breakout (#4302) Added a level select menu which is shown when the game start where either of the 2 available levels may be selected. --- Games/Breakout/CMakeLists.txt | 1 + Games/Breakout/Game.cpp | 47 ++++++++++------ Games/Breakout/Game.h | 12 ++++ Games/Breakout/LevelSelectDialog.cpp | 82 ++++++++++++++++++++++++++++ Games/Breakout/LevelSelectDialog.h | 45 +++++++++++++++ 5 files changed, 171 insertions(+), 16 deletions(-) create mode 100644 Games/Breakout/LevelSelectDialog.cpp create mode 100644 Games/Breakout/LevelSelectDialog.h diff --git a/Games/Breakout/CMakeLists.txt b/Games/Breakout/CMakeLists.txt index 7c34f1148eb..b13e635f074 100644 --- a/Games/Breakout/CMakeLists.txt +++ b/Games/Breakout/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES main.cpp Game.cpp + LevelSelectDialog.cpp ) serenity_bin(Breakout) diff --git a/Games/Breakout/Game.cpp b/Games/Breakout/Game.cpp index 21b7405972c..e69b2dab6ad 100644 --- a/Games/Breakout/Game.cpp +++ b/Games/Breakout/Game.cpp @@ -25,6 +25,7 @@ */ #include "Game.h" +#include "LevelSelectDialog.h" #include #include #include @@ -35,6 +36,9 @@ namespace Breakout { Game::Game() { set_override_cursor(Gfx::StandardCursor::Hidden); + auto level_dialog = LevelSelectDialog::show(m_board, window()); + if (level_dialog != GUI::Dialog::ExecOK) + m_board = -1; start_timer(16); reset(); } @@ -69,23 +73,34 @@ void Game::generate_bricks() Gfx::Color::LightGray, }; - int brick_width = 40; - int brick_height = 12; - int brick_spacing = 3; - int field_left_offset = 30; - int field_top_offset = 30; + Vector 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), + }) + }; - for (int row = 0; row < 7; ++row) { - for (int column = 0; column < 10; ++column) { - Brick brick; - brick.rect = { - field_left_offset + (column * brick_width) + (column * brick_spacing), - field_top_offset + (row * brick_height) + (row * brick_spacing), - brick_width, - brick_height - }; - brick.color = colors[row]; - m_bricks.append(brick); + if (m_board != -1) { + m_bricks = boards[m_board]; + } 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); + } } } } diff --git a/Games/Breakout/Game.h b/Games/Breakout/Game.h index 95c6422b9a6..1932b8f0306 100644 --- a/Games/Breakout/Game.h +++ b/Games/Breakout/Game.h @@ -81,8 +81,20 @@ private: 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; + } }; + int m_board; Ball m_ball; Paddle m_paddle; Vector m_bricks; diff --git a/Games/Breakout/LevelSelectDialog.cpp b/Games/Breakout/LevelSelectDialog.cpp new file mode 100644 index 00000000000..3836d0de338 --- /dev/null +++ b/Games/Breakout/LevelSelectDialog.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2020, 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 "LevelSelectDialog.h" +#include +#include +#include +#include + +namespace Breakout { + +LevelSelectDialog::LevelSelectDialog(Window* parent_window) + : Dialog(parent_window) +{ + set_rect(0, 0, 300, 250); + set_title("Level Select"); + build(); +} + +LevelSelectDialog::~LevelSelectDialog() +{ +} + +int 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(); + main_widget.set_fill_with_background_color(true); + + auto& layout = main_widget.set_layout(); + layout.set_margins({ 4, 4, 4, 4 }); + + main_widget.add("Choose a level").set_text_alignment(Gfx::TextAlignment::Center); + + auto& level_list = main_widget.add(); + auto& scroll_layout = level_list.set_layout(); + scroll_layout.set_spacing(4); + + level_list.add("Rainbow").on_click = [this](auto) { + m_level = -1; + done(Dialog::ExecOK); + }; + + level_list.add(":^)").on_click = [this](auto) { + m_level = 0; + done(Dialog::ExecOK); + }; +} +} diff --git a/Games/Breakout/LevelSelectDialog.h b/Games/Breakout/LevelSelectDialog.h new file mode 100644 index 00000000000..3cc4d3b6cdd --- /dev/null +++ b/Games/Breakout/LevelSelectDialog.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, 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 + +namespace Breakout { +class LevelSelectDialog : public GUI::Dialog { + C_OBJECT(LevelSelectDialog) +public: + virtual ~LevelSelectDialog() override; + static int show(int& board_number, Window* parent_window); + int level() const { return m_level; } + +private: + explicit LevelSelectDialog(Window* parent_window); + void build(); + + int m_level; +}; +}