aboutsummaryrefslogtreecommitdiff
path: root/src/games/breakout
diff options
context:
space:
mode:
authorfschildt <florian.schildt@protonmail.com>2026-01-20 01:22:45 +0100
committerfschildt <florian.schildt@protonmail.com>2026-01-20 01:59:19 +0100
commit6da9be5810bf82e9d0b3b2a8bce7606ef2e2bf93 (patch)
tree28bb67ad879f8bbb36476a537fe8b69195500146 /src/games/breakout
parentf463853872210415e06fb3f863325fdba303ab65 (diff)
breakout: delete pong, add breakout
Diffstat (limited to 'src/games/breakout')
-rw-r--r--src/games/breakout/Breakout.cpp171
-rw-r--r--src/games/breakout/Breakout.hpp45
2 files changed, 216 insertions, 0 deletions
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;
+};
+