From 7023d10aae4e7ba7db1327610b3bea78266a31cf Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Fri, 11 Apr 2025 18:02:44 +0530 Subject: [PATCH 01/13] Fix: Correct green component extraction in Colour hex constructor --- cpp/colour.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/colour.cpp b/cpp/colour.cpp index 04926a9..2a4319c 100644 --- a/cpp/colour.cpp +++ b/cpp/colour.cpp @@ -25,7 +25,7 @@ Colour::Colour(std::uint8_t r, std::uint8_t g, std::uint8_t b) } Colour::Colour(std::uint32_t colour) - : Colour((colour >> 16) & 0xff, (colour >> 7) & 0xff, colour & 0xff) + : Colour((colour >> 16) & 0xff, (colour >> 8) & 0xff, colour & 0xff) { } From bf7ed55cbe63a8eb984c176ff30183a798ab15a9 Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 16:12:04 +0530 Subject: [PATCH 02/13] Update CMakeLists.txt --- cpp/CMakeLists.txt | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 06f96bf..f6a4006 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -1,14 +1,35 @@ -add_executable(cpp_game - colour.cpp - entity.cpp - main.cpp - rectangle.cpp - vector2.cpp - window.cpp +cmake_minimum_required(VERSION 3.10) +project(cpp_game) + +set(CMAKE_CXX_STANDARD 20) + +# SDL2 +set(SDL2_DIR "C:/libs/SDL2-2.24.2") +set(SDL2_INCLUDE_DIR "${SDL2_DIR}/include") +set(SDL2_LIB_DIR "${SDL2_DIR}/lib/x64") +# C:/libs/SDL2-2.24.2/include +# C:/libs/SDL2-2.24.2/lib/x64 +# SDL2_ttf +set(SDL2_TTF_DIR "C:/libs/SDL2_ttf-2.22.0") +set(SDL2_TTF_INCLUDE_DIR "${SDL2_TTF_DIR}/include") +set(SDL2_TTF_LIB_DIR "${SDL2_TTF_DIR}/lib/x64") + +include_directories(${SDL2_INCLUDE_DIR} ${SDL2_TTF_INCLUDE_DIR}) +link_directories(${SDL2_LIB_DIR} ${SDL2_TTF_LIB_DIR}) + +file(GLOB SOURCES + *.cpp + *.h ) -target_link_directories(cpp_game PRIVATE ${sdl_BINARY_DIR}) -target_include_directories(cpp_game PRIVATE ${sdl_SOURCE_DIR}/include) -target_compile_features(cpp_game PRIVATE cxx_std_20) +add_executable(cpp_game ${SOURCES}) +target_link_libraries(cpp_game SDL2.lib SDL2main.lib SDL2_ttf.lib) + -target_link_libraries(cpp_game SDL2::SDL2-static) +# Copy SDL DLLs after build +add_custom_command(TARGET cpp_game POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${SDL2_LIB_DIR}/SDL2.dll" + "${SDL2_TTF_LIB_DIR}/SDL2_ttf.dll" + $ +) From c971be2671692f9cbcde27094bb5c73dc630e1f2 Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 17:05:53 +0530 Subject: [PATCH 03/13] README.md File added --- cpp/Game.png | Bin 0 -> 12365 bytes cpp/README.md | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 cpp/Game.png create mode 100644 cpp/README.md diff --git a/cpp/Game.png b/cpp/Game.png new file mode 100644 index 0000000000000000000000000000000000000000..70c09c807d0e7c9d74baab248f75e708351e0e9b GIT binary patch literal 12365 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 + +![Game Banner](./Game.png) + +[![C++](https://img.shields.io/badge/C%2B%2B-00599C?style=for-the-badge&logo=c%2B%2B&logoColor=white)](https://en.cppreference.com/) +[![SDL2](https://img.shields.io/badge/SDL2-FFD700?style=for-the-badge&logo=SDL&logoColor=black)](https://www.libsdl.org/) +[![CMake](https://img.shields.io/badge/CMake-064F8C?style=for-the-badge&logo=cmake&logoColor=white)](https://cmake.org/) + + +## 📝 Description + +A classic arcade-style Brick Breaker game built with modern C++ and SDL2. Break all the bricks with your ball while controlling the paddle to prevent the ball from falling! + +## 🎯 Game Features + +- 🏓 Smooth paddle controls +- 🔴 Colorful brick layouts +- ⚡ Dynamic ball physics +- 🎨 Clean visual design + +## 🎮 Controls + +| Key | Action | +|-----|--------| +| ⬅️ Left Arrow | Move paddle left | +| ➡️ Right Arrow | Move paddle right | +| ❌ Escape | Exit game | + +## 🔄 Game Loop Overview + +```mermaid +graph TD + A[Start Game] --> B[Process Input] + B --> C[Update Game State] + C --> D[Handle Collisions] + D --> E[Render Frame] + E --> B +``` + +## 📁 Project Structure + +### 🎯 Core Files +- `main.cpp` - 🎮 Game loop and core logic +- `window.cpp/h` - 🖼️ SDL window management +- `entity.cpp/h` - 🎲 Game objects (paddle, ball, bricks) + +### 🛠️ Support Files +- `vector2.cpp/h` - ➡️ 2D vector mathematics +- `rectangle.cpp/h` - 📦 Collision shapes +- `colour.cpp/h` - 🎨 Color management +- `key_event.h` - ⌨️ Input handling + +## 🚀 Building the Game + +### Prerequisites +- 📌 C++20 compiler +- 📌 SDL2 library +- 📌 CMake 3.10+ + +### Build Steps + +```bash +# 1. Clone the repository +git clone https://github.com/Prince-Patel84/asm_c_cpp + +# 2. Create build directory +mkdir build +cd build + +# 3. Generate build files +cmake .. + +# 4. Build the game +cmake --build . +``` + +## 🎮 How to Play + +1. 🚀 Launch the game +2. 🏓 Use left and right arrows to move the paddle +3. 🎯 Bounce the ball to break all bricks +4. 🏆 Try to clear all bricks without losing the ball + +## 🔧 Technical Implementation + +### Physics System 🎯 +- Accurate ball bouncing mechanics +- Precise collision detection +- Dynamic paddle reflection angles + +### Rendering Engine 🎨 +- Hardware-accelerated graphics +- Smooth animations +- Efficient frame rendering + +## 🛠️ Future Enhancements + +- [ ] 🏆 Score system +- [ ] 🎵 Sound effects +- [ ] ⭐ Power-ups +- [ ] 🎯 Multiple levels +- [ ] 📊 High score board + +## 📜 License + +
+ +[![License](https://img.shields.io/badge/License-Boost_1.0-lightblue.svg?style=for-the-badge)](https://www.boost.org/LICENSE_1_0.txt) + +Built with 💖 and lots of 🎮 +
+ +--- + +
+ +### 🌟 Star this repository if you find it helpful! + +
\ No newline at end of file From 5abde9e045e9abef0039f8a422532e4044458ab1 Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 17:33:57 +0530 Subject: [PATCH 04/13] README.md link correction --- cpp/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/README.md b/cpp/README.md index edd91a2..36dde2b 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -63,7 +63,7 @@ graph TD ```bash # 1. Clone the repository -git clone https://github.com/Prince-Patel84/asm_c_cpp +git clone https://github.com/Prince-Patel84/asm_c_cpp/tree/develop/cpp # 2. Create build directory mkdir build From 8a3bd0f535babdd826ecab6cecb76b4e909709db Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 18:05:41 +0530 Subject: [PATCH 05/13] GameOver Basic Added and restarts when We Hit SPACE bar. --- cpp/key_event.h | 1 + cpp/main.cpp | 88 ++++++++++++++++++++++++++++++++++++++----------- cpp/window.cpp | 1 + 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/cpp/key_event.h b/cpp/key_event.h index ca33eaf..fd9c5c5 100644 --- a/cpp/key_event.h +++ b/cpp/key_event.h @@ -26,6 +26,7 @@ enum class Key ESCAPE, LEFT, RIGHT, + SPACE, }; /** diff --git a/cpp/main.cpp b/cpp/main.cpp index 032feb2..397585e 100644 --- a/cpp/main.cpp +++ b/cpp/main.cpp @@ -143,6 +143,35 @@ void update_paddle(cpp::Entity &paddle, const cpp::Vector2 &velocity) paddle.translate(velocity); } +/** + * Helper function to check if the game is over (ball falls below paddle) + * + * @param ball + * Ball entity to check position + * + * @returns + * True if game is over, false otherwise + */ +bool is_game_over(const cpp::Entity &ball) +{ + return ball.rectangle().position.y > 800.0f; +} + +/** + * Helper function to reset the ball to initial position + * + * @param ball + * Ball entity to reset + * + * @param ball_velocity + * Ball velocity to reset + */ +void reset_ball(cpp::Entity &ball, cpp::Vector2 &ball_velocity) +{ + ball = cpp::Entity{{{420.0f, 400.0f}, 10.0f, 10.0f}, 0xFFFFFF}; + ball_velocity = cpp::Vector2{0.0f, 1.0f}; +} + } int main() @@ -168,6 +197,8 @@ int main() auto left_press = false; auto right_press = false; + bool game_over = false; + while (running) { for (;;) @@ -189,6 +220,16 @@ int main() { right_press = (event->key_state == DOWN) ? true : false; } + // Add space key to restart game + else if ((event->key_state == DOWN) && (event->key == SPACE)) + { + if (game_over) + { + game_over = false; + // Reset ball position and velocity + reset_ball(entities[1], ball_velocity); + } + } } else { @@ -196,30 +237,39 @@ int main() } } - if ((left_press && right_press) || (!left_press && !right_press)) - { - paddle_velocity.x = 0.0f; - } - else if (left_press) - { - paddle_velocity.x = -paddle_speed; - } - else if (right_press) + // Only update game state if not game over + if (!game_over) { - paddle_velocity.x = paddle_speed; - } + if ((left_press && right_press) || (!left_press && !right_press)) + { + paddle_velocity.x = 0.0f; + } + else if (left_press) + { + paddle_velocity.x = -paddle_speed; + } + else if (right_press) + { + paddle_velocity.x = paddle_speed; + } - // scope the references to the paddle and ball, if check_collisions results in an entity being removed then - // that will invalidate our references, so prevent them from being accidentally used later - { - auto &paddle = entities[0]; - auto &ball = entities[1]; + { + auto &paddle = entities[0]; + auto &ball = entities[1]; - update_paddle(paddle, paddle_velocity); - update_ball(ball, ball_velocity); - check_collisions(ball, ball_velocity, paddle, entities); + update_paddle(paddle, paddle_velocity); + update_ball(ball, ball_velocity); + check_collisions(ball, ball_velocity, paddle, entities); + + // Check for game over condition + if (is_game_over(ball)) + { + game_over = true; + } + } } + // Always render the current state window.render(entities); } diff --git a/cpp/window.cpp b/cpp/window.cpp index 3a813ee..daf6fb9 100644 --- a/cpp/window.cpp +++ b/cpp/window.cpp @@ -37,6 +37,7 @@ std::optional map_sdl_key(SDL_Keycode sdl_code) case SDLK_ESCAPE: return ESCAPE; case SDLK_LEFT: return LEFT; case SDLK_RIGHT: return RIGHT; + case SDLK_SPACE: return SPACE; default: return std::nullopt; } } From d4ac5ea0d2c959ebc0cdb9770f0e33de92c5207e Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 18:58:05 +0530 Subject: [PATCH 06/13] The starting screen added and GameOver bugs resolved --- cpp/CMakeLists.txt | 20 ++- cpp/main.cpp | 198 ++++++++++++++++++++++----- cpp/resources/MinecraftTen-VGORe.ttf | Bin 0 -> 7116 bytes cpp/window.cpp | 97 +++++++++++-- cpp/window.h | 80 ++++++++++- 5 files changed, 344 insertions(+), 51 deletions(-) create mode 100644 cpp/resources/MinecraftTen-VGORe.ttf diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index f6a4006..f23e631 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -14,6 +14,7 @@ set(SDL2_TTF_DIR "C:/libs/SDL2_ttf-2.22.0") set(SDL2_TTF_INCLUDE_DIR "${SDL2_TTF_DIR}/include") set(SDL2_TTF_LIB_DIR "${SDL2_TTF_DIR}/lib/x64") +# Include both SDL2 and SDL2_ttf headers include_directories(${SDL2_INCLUDE_DIR} ${SDL2_TTF_INCLUDE_DIR}) link_directories(${SDL2_LIB_DIR} ${SDL2_TTF_LIB_DIR}) @@ -23,13 +24,28 @@ file(GLOB SOURCES ) add_executable(cpp_game ${SOURCES}) -target_link_libraries(cpp_game SDL2.lib SDL2main.lib SDL2_ttf.lib) +# Link against both SDL2 and SDL2_ttf libraries +target_link_libraries(cpp_game SDL2.lib SDL2main.lib SDL2_ttf.lib) -# Copy SDL DLLs after build +# Copy both SDL2 and SDL2_ttf DLLs after build add_custom_command(TARGET cpp_game POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL2_LIB_DIR}/SDL2.dll" "${SDL2_TTF_LIB_DIR}/SDL2_ttf.dll" $ ) + +# Create resources directory and copy font file +add_custom_command(TARGET cpp_game POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory + $/resources + +) + +# Copy font file to resources directory +add_custom_command(TARGET cpp_game POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_SOURCE_DIR}/resources/MinecraftTen-VGORe.ttf" + $/resources/ +) diff --git a/cpp/main.cpp b/cpp/main.cpp index 397585e..efc99df 100644 --- a/cpp/main.cpp +++ b/cpp/main.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "colour.h" #include "entity.h" @@ -17,6 +18,16 @@ namespace { +enum class GameState +{ + TITLE_SCREEN, + PLAYING, + GAME_OVER +}; + +float title_animation_time = 0.0f; +const float ANIMATION_SPEED = 0.05f; + /** * Helper function to create a row of 10 bricks. * @@ -172,6 +183,78 @@ void reset_ball(cpp::Entity &ball, cpp::Vector2 &ball_velocity) ball_velocity = cpp::Vector2{0.0f, 1.0f}; } +/** + * Helper function to reset the paddle to initial position + * + * @param paddle + * Paddle entity to reset + * + * @param paddle_velocity + * Paddle velocity to reset + */ +void reset_paddle(cpp::Entity &paddle, cpp::Vector2 &paddle_velocity) +{ + paddle = cpp::Entity{{{300.0f, 780.0f}, 300.0f, 20.0f}, 0xFFFFFF}; + paddle_velocity = cpp::Vector2{0.0f, 0.0f}; +} + +/** + * Helper function to render the animated title screen + * + * @param window + * Window to render to + * + * @param animation_time + * Current animation time + */ +void render_title_screen(const cpp::Window& window, float& animation_time, const std::vector &entities) +{ + // Update animation time + animation_time += ANIMATION_SPEED; + + // Render game entities in background with dimmed effect + window.render(entities); + + // Semi-transparent overlay to dim the background + window.render_overlay(0x000000, 180); // Black with alpha 180 (partially transparent) + + // Rainbow colors for BREAKOUT letters + const uint32_t colors[] = { + 0xFF0000, // Red + 0xFF7F00, // Orange + 0xFFFF00, // Yellow + 0x00FF00, // Green + 0x0000FF, // Blue + 0x4B0082, // Indigo + 0x9400D3, // Violet + 0xFF1493 // Pink + }; + + // Render each letter of BREAKOUT with different colors and offsets + const char* letters = "BREAKOUT"; + int base_x = 150; + int letter_spacing = 70; + + for (int i = 0; letters[i] != '\0'; i++) + { + char letter[2] = {letters[i], '\0'}; + float letter_offset = std::sin(animation_time + i * 0.5f) * 15.0f; + window.render_text(letter, + base_x + i * letter_spacing, + 200 + static_cast(letter_offset), + 100, + colors[i % 8]); + } + + // Only show the essential text with pulsing effect + float scale = 1.0f + std::sin(animation_time * 2.0f) * 0.1f; + window.render_text("Press SPACE to Start", + 200, + 500 + static_cast(std::sin(animation_time) * 20.0f), + 48, + 0x00FF00); // Green +} + } int main() @@ -181,6 +264,9 @@ int main() const cpp::Window window{}; auto running = true; + // Initialize game state to title screen + GameState game_state = GameState::TITLE_SCREEN; + std::vector entities{ {{{300.0f, 780.0f}, 300.0f, 20.0f}, 0xFFFFFF}, {{{420.0f, 400.0f}, 10.0f, 10.0f}, 0xFFFFFF}}; @@ -197,8 +283,6 @@ int main() auto left_press = false; auto right_press = false; - bool game_over = false; - while (running) { for (;;) @@ -212,22 +296,36 @@ int main() { running = false; } - else if (event->key == LEFT) - { - left_press = (event->key_state == DOWN) ? true : false; - } - else if (event->key == RIGHT) - { - right_press = (event->key_state == DOWN) ? true : false; - } - // Add space key to restart game else if ((event->key_state == DOWN) && (event->key == SPACE)) { - if (game_over) + if (game_state == GameState::TITLE_SCREEN) + { + game_state = GameState::PLAYING; + // Reset everything when starting from title screen + reset_ball(entities[1], ball_velocity); + reset_paddle(entities[0], paddle_velocity); + left_press = false; // Reset movement states + right_press = false; + } + else if (game_state == GameState::GAME_OVER) { - game_over = false; - // Reset ball position and velocity + game_state = GameState::PLAYING; + // Reset everything when restarting after game over reset_ball(entities[1], ball_velocity); + reset_paddle(entities[0], paddle_velocity); + left_press = false; // Reset movement states + right_press = false; + } + } + else if (game_state == GameState::PLAYING) + { + if (event->key == LEFT) + { + left_press = (event->key_state == DOWN) ? true : false; + } + else if (event->key == RIGHT) + { + right_press = (event->key_state == DOWN) ? true : false; } } } @@ -237,43 +335,67 @@ int main() } } - // Only update game state if not game over - if (!game_over) + // Clear screen at start of frame + window.clear(); + + switch (game_state) { - if ((left_press && right_press) || (!left_press && !right_press)) + case GameState::TITLE_SCREEN: { - paddle_velocity.x = 0.0f; - } - else if (left_press) - { - paddle_velocity.x = -paddle_speed; + // Render animated title screen with game entities in background + render_title_screen(window, title_animation_time, entities); + break; } - else if (right_press) + case GameState::PLAYING: { - paddle_velocity.x = paddle_speed; - } + // Update game state + if ((left_press && right_press) || (!left_press && !right_press)) + { + paddle_velocity.x = 0.0f; + } + else if (left_press) + { + paddle_velocity.x = -paddle_speed; + } + else if (right_press) + { + paddle_velocity.x = paddle_speed; + } - { - auto &paddle = entities[0]; - auto &ball = entities[1]; + { + auto &paddle = entities[0]; + auto &ball = entities[1]; - update_paddle(paddle, paddle_velocity); - update_ball(ball, ball_velocity); - check_collisions(ball, ball_velocity, paddle, entities); + update_paddle(paddle, paddle_velocity); + update_ball(ball, ball_velocity); + check_collisions(ball, ball_velocity, paddle, entities); - // Check for game over condition - if (is_game_over(ball)) - { - game_over = true; + if (is_game_over(ball)) + { + game_state = GameState::GAME_OVER; + } } + + // Render game entities + window.render(entities); + break; + } + case GameState::GAME_OVER: + { + // Render game entities in background + window.render(entities); + + // Render game over screen + window.render_text("Game Over!", 200, 300, 72); + window.render_text("Press Space to Restart", 200, 400, 36); + break; } } - // Always render the current state - window.render(entities); + // Present the frame + window.present(); } std::cout << "goodbye\n"; - return 0; } diff --git a/cpp/resources/MinecraftTen-VGORe.ttf b/cpp/resources/MinecraftTen-VGORe.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9a539dd7bc352abe4c237786c8a7962de3098ea9 GIT binary patch literal 7116 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 DQuie~ literal 0 HcmV?d00001 diff --git a/cpp/window.cpp b/cpp/window.cpp index daf6fb9..f8d6ba0 100644 --- a/cpp/window.cpp +++ b/cpp/window.cpp @@ -10,8 +10,10 @@ #include #include #include +#include #include "SDL.h" +#include "SDL_ttf.h" #include "entity.h" #include "key_event.h" @@ -50,12 +52,18 @@ namespace cpp Window::Window() : window_(nullptr, &SDL_DestroyWindow) , renderer_(nullptr, &SDL_DestroyRenderer) + , font_(nullptr, &TTF_CloseFont) { if (::SDL_Init(SDL_INIT_VIDEO) != 0) { throw std::runtime_error("failed to init SDL"); } + if (::TTF_Init() != 0) + { + throw std::runtime_error("failed to init SDL_ttf"); + } + window_.reset( ::SDL_CreateWindow("cpp_game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 800, SDL_WINDOW_SHOWN)); if (!window_) @@ -68,6 +76,13 @@ Window::Window() { throw std::runtime_error("failed to create renderer"); } + + // Load font from resources directory + font_.reset(::TTF_OpenFont("resources/MinecraftTen-VGORe.ttf", 48)); + if (!font_) + { + throw std::runtime_error("failed to load font"); + } } std::optional Window::get_event() const @@ -104,16 +119,6 @@ std::optional Window::get_event() const void Window::render(const std::vector &entities) const { - if (::SDL_SetRenderDrawColor(renderer_.get(), 0x0, 0x0, 0x0, 0xff) != 0) - { - throw std::runtime_error("failed to set render draw colour"); - } - - if (::SDL_RenderClear(renderer_.get()) != 0) - { - throw std::runtime_error("failed to clear renderer"); - } - for (const auto &entity : entities) { const auto entity_rect = entity.rectangle(); @@ -136,8 +141,80 @@ void Window::render(const std::vector &entities) const throw std::runtime_error("failed to draw filled rect"); } } +} + +void Window::render_text(const std::string& text, int x, int y, int size) const +{ + // Default to white color + render_text(text, x, y, size, 0xFFFFFF); +} + +void Window::render_text(const std::string& text, int x, int y, int size, uint32_t color) const +{ + TTF_Font* temp_font = TTF_OpenFont("resources/MinecraftTen-VGORe.ttf", size); + if (!temp_font) + { + return; + } + + SDL_Color sdl_color = { + static_cast((color >> 16) & 0xFF), // R + static_cast((color >> 8) & 0xFF), // G + static_cast(color & 0xFF), // B + 255 // A + }; + + SDL_Surface* surface = TTF_RenderText_Solid(temp_font, text.c_str(), sdl_color); + TTF_CloseFont(temp_font); + if (!surface) + { + return; + } + + SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer_.get(), surface); + SDL_FreeSurface(surface); + + if (!texture) + { + return; + } + + SDL_Rect dest = {x, y, surface->w, surface->h}; + SDL_RenderCopy(renderer_.get(), texture, NULL, &dest); + SDL_DestroyTexture(texture); +} + +void Window::clear() const +{ + if (::SDL_SetRenderDrawColor(renderer_.get(), 0x0, 0x0, 0x0, 0xff) != 0) + { + throw std::runtime_error("failed to set render draw colour"); + } + + if (::SDL_RenderClear(renderer_.get()) != 0) + { + throw std::runtime_error("failed to clear renderer"); + } +} + +void Window::present() const +{ ::SDL_RenderPresent(renderer_.get()); } +void Window::render_overlay(uint32_t color, uint8_t alpha) const +{ + SDL_SetRenderDrawBlendMode(renderer_.get(), SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(renderer_.get(), + static_cast((color >> 16) & 0xFF), // R + static_cast((color >> 8) & 0xFF), // G + static_cast(color & 0xFF), // B + alpha); + + SDL_Rect fullscreen = {0, 0, 800, 800}; + SDL_RenderFillRect(renderer_.get(), &fullscreen); + SDL_SetRenderDrawBlendMode(renderer_.get(), SDL_BLENDMODE_NONE); +} + } diff --git a/cpp/window.h b/cpp/window.h index 3faf927..0f41995 100644 --- a/cpp/window.h +++ b/cpp/window.h @@ -9,12 +9,16 @@ #include #include #include +#include #include "entity.h" #include "key_event.h" struct SDL_Window; struct SDL_Renderer; +struct SDL_Texture; +struct _TTF_Font; +typedef struct _TTF_Font TTF_Font; using SDLWindowDelete = void (*)(SDL_Window *); using SDLRendererDelete = void (*)(SDL_Renderer *); @@ -32,7 +36,7 @@ class Window * Construct a new Window. */ Window(); - + ~Window() = default; Window(const Window &) = delete; Window &operator=(const Window &) = delete; @@ -55,12 +59,86 @@ class Window */ void render(const std::vector &entities) const; + /** + * Render text on screen + * + * @param text + * Text to render + * + * @param x + * X position + * + * @param y + * Y position + */ + void render_text(const std::string& text, int x, int y) const; + + /** + * Render text on screen with specific size + * + * @param text + * Text to render + * + * @param x + * X position + * + * @param y + * Y position + * + * @param size + * Font size + */ + void render_text(const std::string& text, int x, int y, int size) const; + + /** + * Render text on screen with specific size and color + * + * @param text + * Text to render + * + * @param x + * X position + * + * @param y + * Y position + * + * @param size + * Font size + * + * @param color + * Text color + */ + void render_text(const std::string& text, int x, int y, int size, uint32_t color) const; + + /** + * Clear the render surface + */ + void clear() const; + + /** + * Present the current frame + */ + void present() const; + + /** + * Render a semi-transparent overlay + * + * @param color + * Color of overlay + * + * @param alpha + * Transparency level (0-255) + */ + void render_overlay(uint32_t color, uint8_t alpha) const; + private: /** SDL window object. */ std::unique_ptr window_; /** SDL renderer object. */ std::unique_ptr renderer_; + + std::unique_ptr font_; }; } From 31dbe698329c0a3b2ff50e941739374de81b8bb3 Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 19:14:23 +0530 Subject: [PATCH 07/13] Winning condition ADDED --- cpp/main.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 17 deletions(-) diff --git a/cpp/main.cpp b/cpp/main.cpp index efc99df..17b5f4b 100644 --- a/cpp/main.cpp +++ b/cpp/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "colour.h" #include "entity.h" @@ -22,12 +23,17 @@ enum class GameState { TITLE_SCREEN, PLAYING, - GAME_OVER + GAME_OVER, + WIN }; float title_animation_time = 0.0f; const float ANIMATION_SPEED = 0.05f; +// Add these near other global variables +int current_score = 0; +const int BRICK_POINTS = 100; // Points per brick destroyed + /** * Helper function to create a row of 10 bricks. * @@ -80,18 +86,18 @@ void check_collisions( if (ball_pos.x < paddle_pos.x + 100.0f) { - ball_velocity.x = -0.7f; - ball_velocity.y = -0.7f; + ball_velocity.x = -1.4f; + ball_velocity.y = -1.4f; } else if (ball_pos.x < paddle_pos.x + 200.0f) { ball_velocity.x = 0.0f; - ball_velocity.y = -1.0f; + ball_velocity.y = -2.0f; } else { - ball_velocity.x = 0.7f; - ball_velocity.y = -0.7f; + ball_velocity.x = 1.4f; + ball_velocity.y = -1.4f; } } else @@ -106,7 +112,9 @@ void check_collisions( if (hit_brick != std::ranges::end(bricks_view)) { - // we hit a brick so update ball velocity and remove brick entity + // Add score when brick is destroyed + current_score += BRICK_POINTS; + ball_velocity.y *= -1.0f; entities.erase(hit_brick); } @@ -180,7 +188,7 @@ bool is_game_over(const cpp::Entity &ball) void reset_ball(cpp::Entity &ball, cpp::Vector2 &ball_velocity) { ball = cpp::Entity{{{420.0f, 400.0f}, 10.0f, 10.0f}, 0xFFFFFF}; - ball_velocity = cpp::Vector2{0.0f, 1.0f}; + ball_velocity = cpp::Vector2{0.0f, 2.0f}; } /** @@ -255,6 +263,27 @@ void render_title_screen(const cpp::Window& window, float& animation_time, const 0x00FF00); // Green } +// Add this helper function to reset score +void reset_score() +{ + current_score = 0; +} + +/** + * Helper function to check if all bricks are destroyed + * + * @param entities + * Collection of all entities + * + * @returns + * True if no bricks remain, false otherwise + */ +bool check_win_condition(const std::vector &entities) +{ + // Skip first two entities (paddle and ball) + return entities.size() <= 2; +} + } int main() @@ -279,7 +308,7 @@ int main() cpp::Vector2 ball_velocity{0.0f, 1.0f}; cpp::Vector2 paddle_velocity{0.0f, 0.0f}; - const float paddle_speed = 1.0f; + const float paddle_speed = 2.0f; auto left_press = false; auto right_press = false; @@ -301,19 +330,32 @@ int main() if (game_state == GameState::TITLE_SCREEN) { game_state = GameState::PLAYING; - // Reset everything when starting from title screen reset_ball(entities[1], ball_velocity); reset_paddle(entities[0], paddle_velocity); - left_press = false; // Reset movement states + reset_score(); + left_press = false; right_press = false; } - else if (game_state == GameState::GAME_OVER) + else if (game_state == GameState::GAME_OVER || game_state == GameState::WIN) { game_state = GameState::PLAYING; - // Reset everything when restarting after game over + // Reset everything + entities.clear(); // Clear all entities + entities.push_back({{{300.0f, 780.0f}, 300.0f, 20.0f}, 0xFFFFFF}); // Add paddle + entities.push_back({{{420.0f, 400.0f}, 10.0f, 10.0f}, 0xFFFFFF}); // Add ball + + // Recreate all bricks + create_brick_row(entities, 50.0f, 0xff0000); + create_brick_row(entities, 80.0f, 0xff0000); + create_brick_row(entities, 110.0f, 0xffa500); + create_brick_row(entities, 140.0f, 0xffa500); + create_brick_row(entities, 170.0f, 0x00ff00); + create_brick_row(entities, 200.0f, 0x00ff00); + reset_ball(entities[1], ball_velocity); reset_paddle(entities[0], paddle_velocity); - left_press = false; // Reset movement states + reset_score(); + left_press = false; right_press = false; } } @@ -374,10 +416,18 @@ int main() { game_state = GameState::GAME_OVER; } + else if (check_win_condition(entities)) + { + game_state = GameState::WIN; + } } // Render game entities window.render(entities); + + // Render score at top of screen + std::string score_text = "Score: " + std::to_string(current_score); + window.render_text(score_text, 10, 10, 24, 0xFFFFFF); // White color break; } case GameState::GAME_OVER: @@ -385,9 +435,26 @@ int main() // Render game entities in background window.render(entities); - // Render game over screen - window.render_text("Game Over!", 200, 300, 72); - window.render_text("Press Space to Restart", 200, 400, 36); + // Render game over screen with final score + window.render_text("Game Over!", 200, 250, 72); + std::string final_score = "Final Score: " + std::to_string(current_score); + window.render_text(final_score, 200, 350, 48, 0xFFFF00); // Yellow color + window.render_text("Press Space to Restart", 200, 450, 36); + break; + } + case GameState::WIN: + { + // Render game entities in background + window.render(entities); + + // Semi-transparent overlay + window.render_overlay(0x000000, 180); + + // Render win screen with final score + window.render_text("YOU WIN!", 200, 250, 72, 0x00FF00); // Green color + std::string final_score = "Final Score: " + std::to_string(current_score); + window.render_text(final_score, 200, 350, 48, 0xFFFF00); // Yellow color + window.render_text("Press Space to Play Again", 180, 450, 36, 0xFFFFFF); break; } } From d09213a71779da7835404759e54d3854162ab92c Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 22:24:32 +0530 Subject: [PATCH 08/13] HighScore Added --- cpp/main.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/cpp/main.cpp b/cpp/main.cpp index 17b5f4b..bb1e814 100644 --- a/cpp/main.cpp +++ b/cpp/main.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include "colour.h" #include "entity.h" @@ -33,6 +35,8 @@ const float ANIMATION_SPEED = 0.05f; // Add these near other global variables int current_score = 0; const int BRICK_POINTS = 100; // Points per brick destroyed +int high_score = 0; +const std::string HIGH_SCORE_FILE = "highscore.txt"; /** * Helper function to create a row of 10 bricks. @@ -284,12 +288,41 @@ bool check_win_condition(const std::vector &entities) return entities.size() <= 2; } +// Helper function to load high score +void load_high_score() { + std::ifstream file(HIGH_SCORE_FILE); + if (file.is_open()) { + file >> high_score; + file.close(); + } +} + +// Helper function to save high score +void save_high_score() { + std::ofstream file(HIGH_SCORE_FILE); + if (file.is_open()) { + file << high_score; + file.close(); + } +} + +// Helper function to update high score +void update_high_score() { + if (current_score > high_score) { + high_score = current_score; + save_high_score(); + } +} + } int main() { std::cout << "hello world\n"; + // Load high score at startup + load_high_score(); + const cpp::Window window{}; auto running = true; @@ -384,8 +417,10 @@ int main() { case GameState::TITLE_SCREEN: { - // Render animated title screen with game entities in background render_title_screen(window, title_animation_time, entities); + // Add high score display on title screen + std::string high_score_text = "High Score: " + std::to_string(high_score); + window.render_text(high_score_text, 300, 600, 36, 0xFFD700); // Gold color break; } case GameState::PLAYING: @@ -425,35 +460,47 @@ int main() // Render game entities window.render(entities); - // Render score at top of screen + // Display both current score and high score std::string score_text = "Score: " + std::to_string(current_score); - window.render_text(score_text, 10, 10, 24, 0xFFFFFF); // White color + window.render_text(score_text, 10, 10, 24, 0xFFFFFF); + std::string high_score_text = "High Score: " + std::to_string(high_score); + window.render_text(high_score_text, 600, 10, 24, 0xFFD700); break; } case GameState::GAME_OVER: { - // Render game entities in background window.render(entities); - - // Render game over screen with final score window.render_text("Game Over!", 200, 250, 72); + + // Update high score before displaying + update_high_score(); + std::string final_score = "Final Score: " + std::to_string(current_score); - window.render_text(final_score, 200, 350, 48, 0xFFFF00); // Yellow color + window.render_text(final_score, 200, 350, 48, 0xFFFF00); + + // Display high score + std::string high_score_text = "High Score: " + std::to_string(high_score); + window.render_text(high_score_text, 200, 400, 48, 0xFFD700); + window.render_text("Press Space to Restart", 200, 450, 36); break; } case GameState::WIN: { - // Render game entities in background window.render(entities); - - // Semi-transparent overlay window.render_overlay(0x000000, 180); - - // Render win screen with final score - window.render_text("YOU WIN!", 200, 250, 72, 0x00FF00); // Green color + window.render_text("YOU WIN!", 200, 250, 72, 0x00FF00); + + // Update high score before displaying + update_high_score(); + std::string final_score = "Final Score: " + std::to_string(current_score); - window.render_text(final_score, 200, 350, 48, 0xFFFF00); // Yellow color + window.render_text(final_score, 200, 350, 48, 0xFFFF00); + + // Display high score + std::string high_score_text = "High Score: " + std::to_string(high_score); + window.render_text(high_score_text, 200, 400, 48, 0xFFD700); + window.render_text("Press Space to Play Again", 180, 450, 36, 0xFFFFFF); break; } From 2de268ca28920fb310637610b464058efd841c48 Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 23:04:53 +0530 Subject: [PATCH 09/13] Ball speed increases as we break bricks --- cpp/README.md | 84 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/cpp/README.md b/cpp/README.md index 36dde2b..c124694 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -1,4 +1,4 @@ -# 🎮 Brick Breaker Game +# 🎮 BreakOut Game
@@ -11,14 +11,35 @@ ## 📝 Description -A classic arcade-style Brick Breaker game built with modern C++ and SDL2. Break all the bricks with your ball while controlling the paddle to prevent the ball from falling! +A classic arcade-style BreakOut game built with modern C++ and SDL2. Break all the bricks with your ball while controlling the paddle to prevent the ball from falling! Features multiple brick types, progressive difficulty, and high score tracking. + +## 🖼️ Game Screens + +
+ +### 🎮 Start Screen +![Start Screen](./screenshots/start_screen.png) + +### 🎲 Playing Screen +![Playing Screen](./screenshots/playing_screen.png) + +### 🏆 Win Screen +![Win Screen](./screenshots/win_screen.png) + +### ❌ Game Over Screen +![Game Over Screen](./screenshots/game_over_screen.png) + +
## 🎯 Game Features - 🏓 Smooth paddle controls -- 🔴 Colorful brick layouts -- ⚡ Dynamic ball physics -- 🎨 Clean visual design +- 🔴 Multiple brick types with different hit points +- ⚡ Dynamic ball physics with speed progression +- 🎨 Clean visual design with animations +- 🏆 Score system and high score tracking +- 🎮 Multiple game states (Title, Playing, Win, Game Over) +- 💾 Persistent high score storage ## 🎮 Controls @@ -26,17 +47,34 @@ A classic arcade-style Brick Breaker game built with modern C++ and SDL2. Break |-----|--------| | ⬅️ Left Arrow | Move paddle left | | ➡️ Right Arrow | Move paddle right | +| ⏎ Space | Start/Restart game | | ❌ Escape | Exit game | -## 🔄 Game Loop Overview +## 🧱 Brick Types + +| Color | Hits Required | Points | +|-------|---------------|--------| +| 🟢 Green | 1 | 10 | +| 🟠 Orange | 2 | 20 | +| 🔴 Red | 3 | 30 | + +## 🎯 Game Mechanics + +- Ball speed increases as bricks are destroyed +- Different brick types require multiple hits +- Score based on brick type and destruction +- High score persistence between sessions +- Dynamic paddle collision angles + +## 🔄 Game States ```mermaid graph TD - A[Start Game] --> B[Process Input] - B --> C[Update Game State] - C --> D[Handle Collisions] - D --> E[Render Frame] - E --> B + A[Title Screen] -->|Space| B[Playing] + B -->|All Bricks Destroyed| C[Win Screen] + B -->|Ball Lost| D[Game Over] + C -->|Space| A + D -->|Space| A ``` ## 📁 Project Structure @@ -82,6 +120,8 @@ cmake --build . 2. 🏓 Use left and right arrows to move the paddle 3. 🎯 Bounce the ball to break all bricks 4. 🏆 Try to clear all bricks without losing the ball +5. 📊 Score points based on brick type +6. 💾 Beat your high score! ## 🔧 Technical Implementation @@ -89,19 +129,33 @@ cmake --build . - Accurate ball bouncing mechanics - Precise collision detection - Dynamic paddle reflection angles +- Progressive ball speed system ### Rendering Engine 🎨 - Hardware-accelerated graphics - Smooth animations - Efficient frame rendering +- Dynamic color transitions + +### Game State Management 🎮 +- Title screen with animations +- Playing state with score display +- Win condition with final score +- Game over state with restart option + +### Score System 📊 +- Points based on brick type +- High score tracking +- Persistent storage +- Visual score display ## 🛠️ Future Enhancements -- [ ] 🏆 Score system -- [ ] 🎵 Sound effects -- [ ] ⭐ Power-ups +- [ ] 🔊 Sound effects - [ ] 🎯 Multiple levels -- [ ] 📊 High score board +- [ ] ⚡ Power-ups +- [ ] 💖 Lives system +- [ ] 🎨 Custom themes ## 📜 License From e38482bd9c2fa6bd898172390f763adb39c6fc66 Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 23:05:41 +0530 Subject: [PATCH 10/13] ReadMe.md Edited. --- cpp/main.cpp | 229 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 154 insertions(+), 75 deletions(-) diff --git a/cpp/main.cpp b/cpp/main.cpp index bb1e814..ce26087 100644 --- a/cpp/main.cpp +++ b/cpp/main.cpp @@ -38,25 +38,52 @@ const int BRICK_POINTS = 100; // Points per brick destroyed int high_score = 0; const std::string HIGH_SCORE_FILE = "highscore.txt"; +// Add near other global variables +struct Brick { + cpp::Entity entity; + int hits_required; +}; + +// Different brick colors based on hits required +const uint32_t BRICK_COLORS[] = { + 0x00FF00, // Green (1 hit) + 0xFFA500, // Orange (2 hits) + 0xFF0000 // Red (3 hits) +}; + +// Points awarded based on brick strength +const int BRICK_POINTS_BY_STRENGTH[] = { + 100, // 1-hit brick + 200, // 2-hit brick + 300 // 3-hit brick +}; + +// Add near other global variables +const float INITIAL_BALL_SPEED = 2.0f; +const float MAX_BALL_SPEED = 4.0f; +const float SPEED_INCREMENT = 0.1f; +float current_ball_speed = INITIAL_BALL_SPEED; + /** * Helper function to create a row of 10 bricks. * - * @param entities + * @param bricks * Collection to add new entities to. * * @param y * Y coordinate of row. * - * @param colour - * Colour of bricks. + * @param hits_required + * Number of hits required to destroy the brick */ -void create_brick_row(std::vector &entities, float y, const cpp::Colour &colour) +void create_brick_row(std::vector &bricks, float y, int hits_required) { auto x = 20.0f; - + for (auto i = 0u; i < 10u; ++i) { - entities.push_back({{{x, y}, 58.0f, 20.0f}, colour}); + cpp::Entity entity{{{x, y}, 58.0f, 20.0f}, BRICK_COLORS[hits_required - 1]}; + bricks.push_back({entity, hits_required}); x += 78.0f; } } @@ -73,16 +100,16 @@ void create_brick_row(std::vector &entities, float y, const cpp::Co * @param paddle * Paddle to check for collisions with. * - * @param entities + * @param bricks * Collection of all entities, brick entities will be removed if a collision is detected. */ void check_collisions( const cpp::Entity &ball, cpp::Vector2 &ball_velocity, const cpp::Entity &paddle, - std::vector &entities) + std::vector &bricks) { - // check and handle ball and paddle collision + // Paddle collision if (paddle.intersects(ball)) { const auto ball_pos = ball.rectangle().position; @@ -90,37 +117,57 @@ void check_collisions( if (ball_pos.x < paddle_pos.x + 100.0f) { - ball_velocity.x = -1.4f; - ball_velocity.y = -1.4f; + ball_velocity.x = -current_ball_speed * 0.7f; + ball_velocity.y = -current_ball_speed * 0.7f; } else if (ball_pos.x < paddle_pos.x + 200.0f) { ball_velocity.x = 0.0f; - ball_velocity.y = -2.0f; + ball_velocity.y = -current_ball_speed; } else { - ball_velocity.x = 1.4f; - ball_velocity.y = -1.4f; + ball_velocity.x = current_ball_speed * 0.7f; + ball_velocity.y = -current_ball_speed * 0.7f; } } else { - // only check brick intersections if we didn't intersect the paddle, unlikely these will both happen in the same - // frame due to the layout of the game - - // iterate over all entities, skipping the first two as these are the paddle and ball - auto bricks_view = entities | std::views::drop(2u); - auto hit_brick = - std::ranges::find_if(bricks_view, [&ball](const auto &brick) { return ball.intersects(brick); }); - - if (hit_brick != std::ranges::end(bricks_view)) + // Check brick collisions + for (auto it = bricks.begin(); it != bricks.end(); ++it) { - // Add score when brick is destroyed - current_score += BRICK_POINTS; - - ball_velocity.y *= -1.0f; - entities.erase(hit_brick); + if (it->entity.intersects(ball)) + { + // Reduce hits required and update color + it->hits_required--; + + if (it->hits_required <= 0) + { + // Add score based on original brick strength + current_score += BRICK_POINTS_BY_STRENGTH[it->hits_required]; + bricks.erase(it); + + // Increase ball speed + current_ball_speed = std::min(current_ball_speed + SPEED_INCREMENT, MAX_BALL_SPEED); + + // Adjust current velocity to match new speed while maintaining direction + float current_speed = std::sqrt(ball_velocity.x * ball_velocity.x + + ball_velocity.y * ball_velocity.y); + ball_velocity.x = (ball_velocity.x / current_speed) * current_ball_speed; + ball_velocity.y = (ball_velocity.y / current_speed) * current_ball_speed; + } + else + { + // Update brick color based on remaining hits + it->entity = cpp::Entity{ + it->entity.rectangle(), + BRICK_COLORS[it->hits_required - 1] + }; + } + + ball_velocity.y *= -1.0f; + break; + } } } } @@ -192,7 +239,7 @@ bool is_game_over(const cpp::Entity &ball) void reset_ball(cpp::Entity &ball, cpp::Vector2 &ball_velocity) { ball = cpp::Entity{{{420.0f, 400.0f}, 10.0f, 10.0f}, 0xFFFFFF}; - ball_velocity = cpp::Vector2{0.0f, 2.0f}; + ball_velocity = cpp::Vector2{0.0f, current_ball_speed}; } /** @@ -276,16 +323,15 @@ void reset_score() /** * Helper function to check if all bricks are destroyed * - * @param entities + * @param bricks * Collection of all entities * * @returns * True if no bricks remain, false otherwise */ -bool check_win_condition(const std::vector &entities) +bool check_win_condition(const std::vector &bricks) { - // Skip first two entities (paddle and ball) - return entities.size() <= 2; + return bricks.empty(); } // Helper function to load high score @@ -314,6 +360,17 @@ void update_high_score() { } } +// Add this helper function in the anonymous namespace +void render_entity(const cpp::Window& window, const cpp::Entity& entity) { + std::vector temp{entity}; + window.render(temp); +} + +// Helper function to reset ball speed +void reset_ball_speed() { + current_ball_speed = INITIAL_BALL_SPEED; +} + } int main() @@ -329,15 +386,18 @@ int main() // Initialize game state to title screen GameState game_state = GameState::TITLE_SCREEN; - std::vector entities{ - {{{300.0f, 780.0f}, 300.0f, 20.0f}, 0xFFFFFF}, {{{420.0f, 400.0f}, 10.0f, 10.0f}, 0xFFFFFF}}; + // Change entities vector to separate paddle, ball, and bricks + cpp::Entity paddle{{{300.0f, 780.0f}, 300.0f, 20.0f}, 0xFFFFFF}; + cpp::Entity ball{{{420.0f, 400.0f}, 10.0f, 10.0f}, 0xFFFFFF}; + std::vector bricks; - create_brick_row(entities, 50.0f, 0xff0000); - create_brick_row(entities, 80.0f, 0xff0000); - create_brick_row(entities, 110.0f, 0xffa500); - create_brick_row(entities, 140.0f, 0xffa500); - create_brick_row(entities, 170.0f, 0x00ff00); - create_brick_row(entities, 200.0f, 0x00ff00); + // Create rows with different hit requirements + create_brick_row(bricks, 50.0f, 3); // Red bricks (3 hits) + create_brick_row(bricks, 80.0f, 3); + create_brick_row(bricks, 110.0f, 2); // Orange bricks (2 hits) + create_brick_row(bricks, 140.0f, 2); + create_brick_row(bricks, 170.0f, 1); // Green bricks (1 hit) + create_brick_row(bricks, 200.0f, 1); cpp::Vector2 ball_velocity{0.0f, 1.0f}; cpp::Vector2 paddle_velocity{0.0f, 0.0f}; @@ -363,8 +423,9 @@ int main() if (game_state == GameState::TITLE_SCREEN) { game_state = GameState::PLAYING; - reset_ball(entities[1], ball_velocity); - reset_paddle(entities[0], paddle_velocity); + reset_ball_speed(); + reset_ball(ball, ball_velocity); + reset_paddle(paddle, paddle_velocity); reset_score(); left_press = false; right_press = false; @@ -373,20 +434,19 @@ int main() { game_state = GameState::PLAYING; // Reset everything - entities.clear(); // Clear all entities - entities.push_back({{{300.0f, 780.0f}, 300.0f, 20.0f}, 0xFFFFFF}); // Add paddle - entities.push_back({{{420.0f, 400.0f}, 10.0f, 10.0f}, 0xFFFFFF}); // Add ball + bricks.clear(); // Recreate all bricks - create_brick_row(entities, 50.0f, 0xff0000); - create_brick_row(entities, 80.0f, 0xff0000); - create_brick_row(entities, 110.0f, 0xffa500); - create_brick_row(entities, 140.0f, 0xffa500); - create_brick_row(entities, 170.0f, 0x00ff00); - create_brick_row(entities, 200.0f, 0x00ff00); + create_brick_row(bricks, 50.0f, 3); + create_brick_row(bricks, 80.0f, 3); + create_brick_row(bricks, 110.0f, 2); + create_brick_row(bricks, 140.0f, 2); + create_brick_row(bricks, 170.0f, 1); + create_brick_row(bricks, 200.0f, 1); - reset_ball(entities[1], ball_velocity); - reset_paddle(entities[0], paddle_velocity); + reset_ball_speed(); + reset_ball(ball, ball_velocity); + reset_paddle(paddle, paddle_velocity); reset_score(); left_press = false; right_press = false; @@ -417,7 +477,15 @@ int main() { case GameState::TITLE_SCREEN: { - render_title_screen(window, title_animation_time, entities); + // Create a vector with all entities for the background + std::vector all_entities; + all_entities.push_back(paddle); + all_entities.push_back(ball); + for (const auto& brick : bricks) { + all_entities.push_back(brick.entity); + } + + render_title_screen(window, title_animation_time, all_entities); // Add high score display on title screen std::string high_score_text = "High Score: " + std::to_string(high_score); window.render_text(high_score_text, 300, 600, 36, 0xFFD700); // Gold color @@ -439,28 +507,29 @@ int main() paddle_velocity.x = paddle_speed; } - { - auto &paddle = entities[0]; - auto &ball = entities[1]; - - update_paddle(paddle, paddle_velocity); - update_ball(ball, ball_velocity); - check_collisions(ball, ball_velocity, paddle, entities); + // Update entities + update_paddle(paddle, paddle_velocity); + update_ball(ball, ball_velocity); + check_collisions(ball, ball_velocity, paddle, bricks); - if (is_game_over(ball)) - { - game_state = GameState::GAME_OVER; - } - else if (check_win_condition(entities)) - { - game_state = GameState::WIN; - } + if (is_game_over(ball)) + { + game_state = GameState::GAME_OVER; + } + else if (check_win_condition(bricks)) + { + game_state = GameState::WIN; } - // Render game entities - window.render(entities); + // Render entities + render_entity(window, paddle); + render_entity(window, ball); + for (const auto& brick : bricks) + { + render_entity(window, brick.entity); + } - // Display both current score and high score + // Display scores std::string score_text = "Score: " + std::to_string(current_score); window.render_text(score_text, 10, 10, 24, 0xFFFFFF); std::string high_score_text = "High Score: " + std::to_string(high_score); @@ -469,7 +538,12 @@ int main() } case GameState::GAME_OVER: { - window.render(entities); + render_entity(window, paddle); + render_entity(window, ball); + for (const auto& brick : bricks) + { + render_entity(window, brick.entity); + } window.render_text("Game Over!", 200, 250, 72); // Update high score before displaying @@ -487,7 +561,12 @@ int main() } case GameState::WIN: { - window.render(entities); + render_entity(window, paddle); + render_entity(window, ball); + for (const auto& brick : bricks) + { + render_entity(window, brick.entity); + } window.render_overlay(0x000000, 180); window.render_text("YOU WIN!", 200, 250, 72, 0x00FF00); From 5883af4e51b382915ad7fb27f97242ac09cefe36 Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Mon, 14 Apr 2025 23:21:07 +0530 Subject: [PATCH 11/13] ScreenShots Added in Readme.md --- cpp/README.md | 43 ++++++++++++++++++++++----- cpp/screenshots/game_over_screen.png | Bin 0 -> 6297 bytes cpp/screenshots/playing_screen.png | Bin 0 -> 5013 bytes cpp/screenshots/start_screen.png | Bin 0 -> 6034 bytes cpp/screenshots/win_screen.png | Bin 0 -> 6012 bytes 5 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 cpp/screenshots/game_over_screen.png create mode 100644 cpp/screenshots/playing_screen.png create mode 100644 cpp/screenshots/start_screen.png create mode 100644 cpp/screenshots/win_screen.png diff --git a/cpp/README.md b/cpp/README.md index c124694..3d41e9b 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -2,8 +2,6 @@
-![Game Banner](./Game.png) - [![C++](https://img.shields.io/badge/C%2B%2B-00599C?style=for-the-badge&logo=c%2B%2B&logoColor=white)](https://en.cppreference.com/) [![SDL2](https://img.shields.io/badge/SDL2-FFD700?style=for-the-badge&logo=SDL&logoColor=black)](https://www.libsdl.org/) [![CMake](https://img.shields.io/badge/CMake-064F8C?style=for-the-badge&logo=cmake&logoColor=white)](https://cmake.org/) @@ -54,9 +52,9 @@ A classic arcade-style BreakOut game built with modern C++ and SDL2. Break all t | Color | Hits Required | Points | |-------|---------------|--------| -| 🟢 Green | 1 | 10 | -| 🟠 Orange | 2 | 20 | -| 🔴 Red | 3 | 30 | +| 🟢 Green | 1 | 100 | +| 🟠 Orange | 2 | 200 | +| 🔴 Red | 3 | 300 | ## 🎯 Game Mechanics @@ -75,6 +73,31 @@ graph TD B -->|Ball Lost| D[Game Over] C -->|Space| A D -->|Space| A + + subgraph Title Screen + A1[Show High Score] + A2[Animated Title] + A3[Press Space Prompt] + end + + subgraph Playing + B1[Move Paddle] + B2[Ball Physics] + B3[Break Bricks] + B4[Update Score] + B5[Increase Ball Speed] + end + + subgraph Win Screen + C1[Show Final Score] + C2[Update High Score] + C3[Victory Message] + end + + subgraph Game Over + D1[Show Final Score] + D2[Game Over Message] + end ``` ## 📁 Project Structure @@ -157,11 +180,17 @@ cmake --build . - [ ] 💖 Lives system - [ ] 🎨 Custom themes -## 📜 License +## 👥 Team Motion Minds
-[![License](https://img.shields.io/badge/License-Boost_1.0-lightblue.svg?style=for-the-badge)](https://www.boost.org/LICENSE_1_0.txt) +### 🎮 Game Development Team + +| Name | Student ID | +|------|------------| +| Prince Patel | 202401151 | +| Vishwa Prajapati | 202401163 | +| Dhruv Patel | 202401142 | Built with 💖 and lots of 🎮
diff --git a/cpp/screenshots/game_over_screen.png b/cpp/screenshots/game_over_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..5e1397383fc4961669335e7f2302e94c17728918 GIT binary patch literal 6297 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 literal 0 HcmV?d00001 diff --git a/cpp/screenshots/start_screen.png b/cpp/screenshots/start_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..1a15685ba99441aa7cf28bff843b3363d1b550e7 GIT binary patch literal 6034 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 R9LOke*y_Bc;M)Un{{hJpALRf5 literal 0 HcmV?d00001 diff --git a/cpp/screenshots/win_screen.png b/cpp/screenshots/win_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..4faf42e8f5f6553acb476ce081e47cd49620630c GIT binary patch literal 6012 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 Date: Mon, 14 Apr 2025 23:29:10 +0530 Subject: [PATCH 12/13] Trying diffrent Block Diagram --- cpp/README.md | 41 +++++++++++------------------------------ 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/cpp/README.md b/cpp/README.md index 3d41e9b..d657fed 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -68,36 +68,17 @@ A classic arcade-style BreakOut game built with modern C++ and SDL2. Break all t ```mermaid graph TD - A[Title Screen] -->|Space| B[Playing] - B -->|All Bricks Destroyed| C[Win Screen] - B -->|Ball Lost| D[Game Over] - C -->|Space| A - D -->|Space| A - - subgraph Title Screen - A1[Show High Score] - A2[Animated Title] - A3[Press Space Prompt] - end - - subgraph Playing - B1[Move Paddle] - B2[Ball Physics] - B3[Break Bricks] - B4[Update Score] - B5[Increase Ball Speed] - end - - subgraph Win Screen - C1[Show Final Score] - C2[Update High Score] - C3[Victory Message] - end - - subgraph Game Over - D1[Show Final Score] - D2[Game Over Message] - end + Start[Start Game] -->|Initialize| Init[Initialize Game State] + Init -->|Enter Main Loop| Loop[Game Loop] + Loop -->|Process Input| Input[Handle Player Input] + Input -->|Update| Update[Update Game State] + Update -->|Render| Render[Render Graphics] + Render -->|Check| Check[Check Game State] + Check -->|Win Condition Met| Win[Display Win Screen] + Check -->|Game Over Condition Met| GameOver[Display Game Over Screen] + Check -->|Continue| Loop + Win -->|Restart| Start + GameOver -->|Restart| Start ``` ## 📁 Project Structure From 0614589fa0efc5c72e296a594c064abf76ab160b Mon Sep 17 00:00:00 2001 From: Prince Patel Date: Wed, 16 Apr 2025 13:55:09 +0530 Subject: [PATCH 13/13] Fixing the bouncing of ball --- cpp/Game.png | Bin 12365 -> 0 bytes cpp/main.cpp | 13 +++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) delete mode 100644 cpp/Game.png diff --git a/cpp/Game.png b/cpp/Game.png deleted file mode 100644 index 70c09c807d0e7c9d74baab248f75e708351e0e9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12365 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 800.0f) || (ball_pos.y < 0.0f)) + if (ball_pos.y < 0.0f) { velocity.y *= -1.0f; } - if ((ball_pos.x > 800.0f) || (ball_pos.x < 0.0f)) + if ((ball_pos.x + 10.0f > 800.0f) || (ball_pos.x < 0.0f)) { velocity.x *= -1.0f; } @@ -210,7 +213,9 @@ void update_ball(cpp::Entity &ball, cpp::Vector2 &velocity) */ void update_paddle(cpp::Entity &paddle, const cpp::Vector2 &velocity) { - paddle.translate(velocity); + // Calculate paddle speed based on current ball speed + float paddle_speed = current_ball_speed * PADDLE_SPEED_MULTIPLIER; + paddle.translate(cpp::Vector2{velocity.x * paddle_speed, 0.0f}); } /**