diff options
| author | fschildt <florian.schildt@protonmail.com> | 2026-01-20 01:22:45 +0100 |
|---|---|---|
| committer | fschildt <florian.schildt@protonmail.com> | 2026-01-20 01:59:19 +0100 |
| commit | 6da9be5810bf82e9d0b3b2a8bce7606ef2e2bf93 (patch) | |
| tree | 28bb67ad879f8bbb36476a537fe8b69195500146 /src | |
| parent | f463853872210415e06fb3f863325fdba303ab65 (diff) | |
breakout: delete pong, add breakout
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/math.hpp | 24 | ||||
| -rw-r--r-- | src/games/Game.cpp | 8 | ||||
| -rw-r--r-- | src/games/Game.hpp | 4 | ||||
| -rw-r--r-- | src/games/breakout/Breakout.cpp | 171 | ||||
| -rw-r--r-- | src/games/breakout/Breakout.hpp | 45 | ||||
| -rw-r--r-- | src/games/minesweeper/Minesweeper.cpp | 2 | ||||
| -rw-r--r-- | src/games/minesweeper/Minesweeper.hpp | 2 | ||||
| -rw-r--r-- | src/games/pong/Pong.cpp | 140 | ||||
| -rw-r--r-- | src/games/pong/Pong.hpp | 42 | ||||
| -rw-r--r-- | src/games/snake/Snake.cpp | 2 | ||||
| -rw-r--r-- | src/games/snake/Snake.hpp | 2 | ||||
| -rw-r--r-- | src/games/tetris/Tetris.cpp | 2 | ||||
| -rw-r--r-- | src/games/tetris/Tetris.hpp | 2 | ||||
| -rw-r--r-- | src/main.cpp | 4 |
14 files changed, 254 insertions, 196 deletions
diff --git a/src/common/math.hpp b/src/common/math.hpp index afbda1a..48a5869 100644 --- a/src/common/math.hpp +++ b/src/common/math.hpp @@ -2,6 +2,8 @@ #include <cstddef> #include <cstdint> +#include <common/shapes.hpp> +#include <algorithm> struct V2ST { @@ -56,3 +58,25 @@ struct Color { float a; }; + +inline bool +Intersect_Rectangle_Circle(Rectangle rect, Circle circle) +{ + float xmin = std::min(rect.x0, rect.x1); + float xmax = std::max(rect.x0, rect.x1); + float ymin = std::min(rect.y0, rect.y1); + float ymax = std::max(rect.y0, rect.y1); + + float closest_x = std::max(xmin, std::min(circle.x, xmax)); + float closest_y = std::max(ymin, std::min(circle.y, ymax)); + + float dx = closest_x - circle.x; + float dy = closest_y - circle.y; + float d_sq = dx*dx + dy*dy; + + float r_sq = circle.r * circle.r; + + bool is_intersect = d_sq <= r_sq; + return is_intersect; +} + diff --git a/src/games/Game.cpp b/src/games/Game.cpp index 1e94df6..dc3a5a2 100644 --- a/src/games/Game.cpp +++ b/src/games/Game.cpp @@ -2,7 +2,7 @@ #include "games/tetris/Tetris.hpp" #include "games/snake/Snake.hpp" #include "games/minesweeper/Minesweeper.hpp" -#include "games/pong/Pong.hpp" +#include "games/breakout/Breakout.hpp" #include "common/defs.hpp" #include "renderer/Renderer.hpp" @@ -30,8 +30,8 @@ Game::Select(GameType type) return std::make_unique<Tetris>(); } break; - case pong: { - return std::make_unique<Pong>(); + case breakout: { + return std::make_unique<Breakout>(); } break; InvalidDefaultCase; @@ -80,7 +80,7 @@ Game::Update(std::vector<SDL_Event>& events) bool result = true; switch (m_game_status) { case game_start: DrawGameStartMenu(); break; - case game_resume: FinishUpdate(dt); break; + case game_resume: Update(dt); break; case game_over: DrawGameOverMenu(); break; case game_pause: DrawGamePauseMenu(); break; case game_exit: result = false; break; diff --git a/src/games/Game.hpp b/src/games/Game.hpp index c75f586..0cdf4b9 100644 --- a/src/games/Game.hpp +++ b/src/games/Game.hpp @@ -16,7 +16,7 @@ public: minesweeper, snake, tetris, - pong + breakout }; enum GameStatus { @@ -54,7 +54,7 @@ protected: protected: virtual void Start() = 0; virtual void ProcessEvent(SDL_Event& event) = 0; - virtual void FinishUpdate(float dt) = 0; + virtual void Update(float dt) = 0; virtual void Draw() = 0; virtual void DrawGameStartMenu(); diff --git a/src/games/breakout/Breakout.cpp b/src/games/breakout/Breakout.cpp new file mode 100644 index 0000000..62ee17c --- /dev/null +++ b/src/games/breakout/Breakout.cpp @@ -0,0 +1,171 @@ +#include "games/breakout/Breakout.hpp" +#include "common/math.hpp" +#include "games/Game.hpp" +#include "common/shapes.hpp" +#include "renderer/Renderer.hpp" + + +void +Breakout::Start() +{ + float xmid = (3.0f / 2); + m_paddle.x = xmid - (PADDLE_WIDTH / 2); + m_paddle.dx = 0.0f; + + + m_ball.circle.x = xmid; + m_ball.circle.y = 2.0f; + m_ball.circle.r = 0.05f; + m_ball.dx = 0.0f; + m_ball.dy = 1.0f; + + + float brickmap_w = 1.00f * MAP_WIDTH; + float brickmap_h = 0.25f * MAP_HEIGHT; + + float brick_w_sum = 0.80f * brickmap_w; + float brick_h_sum = 0.70f * brickmap_h; + float brick_xgap_sum = brickmap_w - brick_w_sum; + float brick_ygap_sum = brickmap_h - brick_h_sum; + + float brick_w = brick_w_sum / BRICK_COLS; + float brick_h = brick_h_sum / BRICK_ROWS; + float brick_xgap = brick_xgap_sum / (BRICK_COLS+1); + float brick_ygap = brick_ygap_sum / (BRICK_ROWS+1); + + float y = MAP_HEIGHT - brickmap_h; + for (uint32_t row = 0; row < BRICK_ROWS; row++) { + float x = brick_xgap; + for (uint32_t col = 0; col < BRICK_COLS; col++) { + m_bricks[row][col].x0 = x; + m_bricks[row][col].y0 = y; + m_bricks[row][col].x1 = x + brick_w; + m_bricks[row][col].y1 = y + brick_h; + x += brick_w + brick_xgap; + } + y += brick_h + brick_ygap; + } + + + m_game_status = game_resume; +} + +void +Breakout::ProcessEvent(SDL_Event& event) +{ + switch (event.type) { + case SDL_EVENT_KEY_DOWN: { + auto key = event.key.key; + if (key == SDLK_ESCAPE) { + m_game_status = game_pause; + } + else if (key == SDLK_RIGHT || key == SDLK_D) { + m_paddle.dx = 1.0f; + } + else if (key == SDLK_LEFT || key == SDLK_A) { + m_paddle.dx = -1.0f; + } + else { + } + } break; + + case SDL_EVENT_KEY_UP: { + auto key = event.key.key; + if (key == SDLK_RIGHT || key == SDLK_D) { + m_paddle.dx = 0.0f; + } + else if (key == SDLK_LEFT || key == SDLK_A) { + m_paddle.dx = 0.0f; + } + } break; + + default:; + } +} + +void +Breakout::Update(float dt) +{ + MoveBall(dt); + MovePaddle(dt); +} + +void +Breakout::MovePaddle(float dt) +{ + float x = m_paddle.x + m_paddle.dx * dt; + if (x + PADDLE_WIDTH >= MAP_WIDTH) { + x = MAP_WIDTH - PADDLE_WIDTH; + } + if (x <= 0.0f) { + x = 0.0f; + } + m_paddle.x = x; +} + +void +Breakout::MoveBall(float dt) +{ + float x = m_ball.circle.x + m_ball.dx * dt; + float y = m_ball.circle.y + m_ball.dy * dt; + m_ball.circle.x = x; + m_ball.circle.y = y; + + // collision walls + if (m_ball.circle.x <= 0.0f) { + m_ball.dx = std::abs(m_ball.dx); + } + if (m_ball.circle.x + m_ball.circle.r >= MAP_WIDTH) { + m_ball.dx = -std::abs(m_ball.dx); + } + if (m_ball.circle.y <= 0.0f) { + m_game_status = game_over; + } + if (m_ball.circle.y + m_ball.circle.r >= MAP_HEIGHT) { + m_ball.dy = -std::abs(m_ball.dy); + } + + // collision paddle + Rectangle paddle_rect = { + m_paddle.x, + 0.0f, + m_paddle.x + PADDLE_WIDTH, + PADDLE_HEIGHT + }; + if (Intersect_Rectangle_Circle(paddle_rect, m_ball.circle)) { + m_ball.dy = std::abs(m_ball.dy); + } +} + +void +Breakout::Draw() +{ + // Todo: draw a circle + Rectangle ball_rectangle = { + m_ball.circle.x - m_ball.circle.r, + m_ball.circle.y - m_ball.circle.r, + m_ball.circle.x + m_ball.circle.r, + m_ball.circle.y + m_ball.circle.r + }; + Color ball_color = {0.3f, 0.5f, 0.3f, 1.0f}; + g_renderer.PushRectangle(ball_rectangle, ball_color, z_layer2); + + + Color paddle_color = {0.6f, 0.3f, 0.3f, 1.0f}; + Rectangle paddle_rect = { + m_paddle.x, + 0.0f, + m_paddle.x + PADDLE_WIDTH, + PADDLE_HEIGHT + }; + g_renderer.PushRectangle(paddle_rect, paddle_color, z_layer1); + + + Color brick_color = {0.5f, 0.3f, 0.3f, 1.0f}; + for (uint32_t y = 0; y < BRICK_ROWS; y++) { + for (uint32_t x = 0; x < BRICK_COLS; x++) { + g_renderer.PushRectangle(m_bricks[y][x], brick_color, z_layer1); + } + } +} + diff --git a/src/games/breakout/Breakout.hpp b/src/games/breakout/Breakout.hpp new file mode 100644 index 0000000..2b7c9b3 --- /dev/null +++ b/src/games/breakout/Breakout.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "games/Game.hpp" +#include "common/shapes.hpp" + + +class Breakout : public Game { + struct Paddle { + float x; + float dx; + }; + + struct Ball { + Circle circle; + float dx; + float dy; + }; + + static constexpr float MAP_WIDTH = 4.0f; + static constexpr float MAP_HEIGHT = 3.0f; + + static constexpr uint32_t BRICK_ROWS = 8; + static constexpr uint32_t BRICK_COLS = 14; + + static constexpr float PADDLE_HEIGHT = 0.1f; + static constexpr float PADDLE_WIDTH = 0.6f; + static constexpr float PADDLE_SPEED = 1.0f; + + +private: + void Start() override; + void ProcessEvent(SDL_Event& event) override; + void Update(float dt) override; + void Draw() override; + +private: + void MovePaddle(float dt); + void MoveBall(float dt); + +private: + Rectangle m_bricks[BRICK_ROWS][BRICK_COLS]; + Paddle m_paddle; + Ball m_ball; +}; + diff --git a/src/games/minesweeper/Minesweeper.cpp b/src/games/minesweeper/Minesweeper.cpp index f1aa223..a168dcb 100644 --- a/src/games/minesweeper/Minesweeper.cpp +++ b/src/games/minesweeper/Minesweeper.cpp @@ -186,7 +186,7 @@ Minesweeper::ProcessEvent(SDL_Event& event) } void -Minesweeper::FinishUpdate(float dt) +Minesweeper::Update(float dt) { } diff --git a/src/games/minesweeper/Minesweeper.hpp b/src/games/minesweeper/Minesweeper.hpp index 46c6b3d..0bb53aa 100644 --- a/src/games/minesweeper/Minesweeper.hpp +++ b/src/games/minesweeper/Minesweeper.hpp @@ -22,7 +22,7 @@ public: private: void Start() override; void ProcessEvent(SDL_Event& event) override; - void FinishUpdate(float dt) override; + void Update(float dt) override; void Draw() override; void DrawGameStartMenu() override; diff --git a/src/games/pong/Pong.cpp b/src/games/pong/Pong.cpp deleted file mode 100644 index 9a77f38..0000000 --- a/src/games/pong/Pong.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "games/pong/Pong.hpp" -#include "games/Game.hpp" -#include "common/shapes.hpp" -#include "renderer/Renderer.hpp" - - -void -Pong::Start() -{ - m_paddles[0].dir = NONE; - m_paddles[0].y = 1.5f; - - m_paddles[1].dir = NONE; - m_paddles[1].y = 1.5f; - - m_ball.circle.x = 2.0f; - m_ball.circle.y = 1.5f; - m_ball.circle.r = 0.1f; - - m_ball.velocity.x = 1.0f; - m_ball.velocity.y = 0.0f; - - m_game_status = game_resume; -} - -void -Pong::ProcessEvent(SDL_Event& event) -{ - switch (event.type) { - case SDL_EVENT_KEY_DOWN: { - auto key = event.key.key; - if (key == SDLK_ESCAPE) { - m_game_status = game_pause; - } - else if (key == SDLK_W) { - m_paddles[0].dir = UP; - } - else if (key == SDLK_S) { - m_paddles[0].dir = DOWN; - } - else if (key == SDLK_UP) { - m_paddles[1].dir = UP; - } - else if (key == SDLK_DOWN) { - m_paddles[1].dir = DOWN; - } - } break; - - case SDL_EVENT_KEY_UP: { - auto key = event.key.key; - if (key == SDLK_W && m_paddles[0].dir == UP) { - m_paddles[0].dir = NONE; - } - else if (key == SDLK_S && m_paddles[0].dir == DOWN) { - m_paddles[0].dir = NONE; - } - else if (key == SDLK_UP && m_paddles[1].dir == UP) { - m_paddles[1].dir = NONE; - } - else if (key == SDLK_DOWN && m_paddles[1].dir == DOWN) { - m_paddles[1].dir = NONE; - } - } break; - - default:; - } -} - -void -Pong::FinishUpdate(float dt) -{ - MoveBall(dt); - MovePaddle(m_paddles[0], dt); - MovePaddle(m_paddles[1], dt); -} - -void -Pong::MovePaddle(Paddle& paddle, float dt) -{ - if (paddle.dir) { - paddle.y += (float)paddle.dir * (PADDLE_SPEED * dt); - } - - if (paddle.y <= 0.0f) { - paddle.y = 0.0f; - } - if (paddle.y + PADDLE_HEIGHT > 3.0f) { - paddle.y = 3.0f - PADDLE_HEIGHT; - } -} - -void -Pong::MoveBall(float dt) -{ - // Todo: do physics! find trajectories, find intersection, bounce off properly - - m_ball.circle.x += m_ball.velocity.x * dt; - m_ball.circle.y += m_ball.velocity.y * dt; - if (m_ball.circle.x - m_ball.circle.r <= PADDLE_WIDTH) { - m_ball.circle.x = PADDLE_WIDTH + m_ball.circle.r; - m_ball.velocity.x *= -1.0f; - m_ball.velocity.y *= -1.0f; - } - if (m_ball.circle.x + m_ball.circle.r > 4.0f - PADDLE_WIDTH) { - m_ball.circle.x = 4.0f - PADDLE_WIDTH - m_ball.circle.r; - m_ball.velocity.x *= -1.0f; - m_ball.velocity.y *= -1.0f; - } -} - -void -Pong::Draw() -{ - Color paddle_color = {0.6f, 0.3f, 0.3f, 1.0f}; - Rectangle paddle1_rect = { - 0.0f, - m_paddles[0].y, - 0.0f + PADDLE_WIDTH, - m_paddles[0].y + PADDLE_HEIGHT - }; - Rectangle paddle2_rect = { - 4.0f - PADDLE_WIDTH, - m_paddles[1].y, - 4.0f, - m_paddles[1].y + PADDLE_HEIGHT - }; - g_renderer.PushRectangle(paddle1_rect, paddle_color, z_layer1); - g_renderer.PushRectangle(paddle2_rect, paddle_color, z_layer1); - - // Todo: draw a circle - Rectangle ball_rectangle = { - m_ball.circle.x - m_ball.circle.r, - m_ball.circle.y - m_ball.circle.r, - m_ball.circle.x + m_ball.circle.r, - m_ball.circle.y + m_ball.circle.r - }; - Color ball_color = {0.3f, 0.5f, 0.3f, 1.0f}; - g_renderer.PushRectangle(ball_rectangle, ball_color, z_layer1); -} - diff --git a/src/games/pong/Pong.hpp b/src/games/pong/Pong.hpp deleted file mode 100644 index ec6145b..0000000 --- a/src/games/pong/Pong.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "games/Game.hpp" -#include "common/shapes.hpp" - - -class Pong : public Game { - enum PaddleDirection { - NONE = 0, - UP = 1, - DOWN = -1 - }; - - struct Paddle { - float y; - PaddleDirection dir; - }; - - struct Ball { - Circle circle; - V2F32 velocity; - }; - - static constexpr float PADDLE_HEIGHT = 0.5f; - static constexpr float PADDLE_WIDTH = 0.2f; - static constexpr float PADDLE_SPEED = 1.0f; - -private: - void Start() override; - void ProcessEvent(SDL_Event& event) override; - void FinishUpdate(float dt) override; - void Draw() override; - -private: - void MovePaddle(Paddle& paddle, float dt); - void MoveBall(float dt); - -private: - Paddle m_paddles[2]; - Ball m_ball; -}; - diff --git a/src/games/snake/Snake.cpp b/src/games/snake/Snake.cpp index de9dad7..fe329c9 100644 --- a/src/games/snake/Snake.cpp +++ b/src/games/snake/Snake.cpp @@ -60,7 +60,7 @@ Snake::Start() } void -Snake::FinishUpdate(float dt) +Snake::Update(float dt) { MaybeMoveSnake(dt); } diff --git a/src/games/snake/Snake.hpp b/src/games/snake/Snake.hpp index 0303238..3d08baf 100644 --- a/src/games/snake/Snake.hpp +++ b/src/games/snake/Snake.hpp @@ -24,7 +24,7 @@ public: private: void Start() override; void ProcessEvent(SDL_Event& event) override; - void FinishUpdate(float dt) override; + void Update(float dt) override; void Draw() override; void MaybeMoveSnake(float dt_in_seconds); diff --git a/src/games/tetris/Tetris.cpp b/src/games/tetris/Tetris.cpp index 043033f..c9d3e32 100644 --- a/src/games/tetris/Tetris.cpp +++ b/src/games/tetris/Tetris.cpp @@ -44,7 +44,7 @@ Tetris::Start() } void -Tetris::FinishUpdate(float dt) +Tetris::Update(float dt) { if (m_game_status == game_resume) { uint32_t softdrop_count = GetSoftdropCount(dt); diff --git a/src/games/tetris/Tetris.hpp b/src/games/tetris/Tetris.hpp index 22d271e..d53fbbc 100644 --- a/src/games/tetris/Tetris.hpp +++ b/src/games/tetris/Tetris.hpp @@ -14,7 +14,7 @@ public: private: void Start() override; void ProcessEvent(SDL_Event& event) override; - void FinishUpdate(float dt) override; + void Update(float dt) override; void Draw() override; void DrawGameOverMenu() override; diff --git a/src/main.cpp b/src/main.cpp index e3241d4..ebbaa55 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,8 +36,8 @@ DrawGameMenu() if (ImGui::Button("Snake")) { type = Game::snake; } - if (ImGui::Button("Pong")) { - type = Game::pong; + if (ImGui::Button("Breakout")) { + type = Game::breakout; } ImGui::End(); |
