diff --git a/CMakeLists.txt b/CMakeLists.txt index e76f67b..106b308 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(main src/InputManager.cpp src/MainManager.cpp src/Pad.cpp + src/Block.cpp src/TitleScreen.cpp ) target_compile_features(main PRIVATE cxx_std_17) diff --git a/src/Ball.cpp b/src/Ball.cpp index c8c8ce3..aa3d304 100644 --- a/src/Ball.cpp +++ b/src/Ball.cpp @@ -1,5 +1,8 @@ #include "Ball.h" #include +#include + +const float PI = 3.14159265358979323846; Ball::Ball(sf::RenderWindow *_window, unsigned int WIDTH, unsigned int HEIGHT) : window(_window), @@ -10,7 +13,7 @@ Ball::Ball(sf::RenderWindow *_window, unsigned int WIDTH, unsigned int HEIGHT) maxPosX(WIDTH - (ballRadius * 2) - 25), minPosY(25), maxPosY(HEIGHT - (ballRadius * 2) - 25), - moveSpeed(150), + moveSpeed(300), ballColor(10, 10, 200), ballCircle(ballRadius), directionX(1), @@ -32,8 +35,6 @@ void Ball::move(float deltaTime) // Update position posX = std::max(std::min(posX + (moveSpeed * deltaTime * directionX), maxPosX), minPosY); posY = std::max(std::min(posY + (moveSpeed * deltaTime * directionY), maxPosY), minPosY); - std::cout << "time " << deltaTime << " move speed " << moveSpeed << " direction " << directionX << std::endl; - std::cout << "setting pos x to " << posX << std::endl; ballCircle.setPosition({posX, posY}); // If hit the edge, switch directions @@ -66,4 +67,42 @@ void Ball::checkPadCollision(sf::FloatRect padBounds) ballCircle.setPosition({posX, posY}); directionY *= -1; } +} + +// Checks for collisions with all blocks in the given vector +// Returns the index of the block it collides with, if any +int Ball::checkBlockCollision(vector &blocks) +{ + sf::FloatRect ballBound = ballCircle.getGlobalBounds(); + + // Go through all blocks + for (int i = 0; i < blocks.size(); i++) + { + sf::FloatRect blockBounds = blocks[i].getBounds(); + + // If ball collides with the block, bounce and return the index of block + if (blockBounds.findIntersection(ballBound)) + { + // Get the angle between the two shapes + sf::Vector2f blockCenter = blockBounds.getCenter(); + sf::Vector2f ballCenter = ballBound.getCenter(); + float angle = atan2(ballCenter.y - blockCenter.y, + ballCenter.x - blockCenter.x) * + 180 / PI; + + // Use the angle to determine which way the ball should bounce + if ((blockCenter.x < ballCenter.x && abs(angle) < 45) || (blockCenter.x > ballCenter.x && abs(angle) > 135)) + { + directionX *= -1; + } + else + { + directionY *= -1; + } + + return i; + } + } + + return -1; // No collisions } \ No newline at end of file diff --git a/src/Ball.h b/src/Ball.h index a2a6102..f780c0c 100644 --- a/src/Ball.h +++ b/src/Ball.h @@ -2,6 +2,9 @@ #define BALL_H #include +#include "Block.h" +#include +using namespace std; class Ball { @@ -10,6 +13,7 @@ class Ball void drawBall(); void move(float deltaTime); void checkPadCollision(sf::FloatRect padBounds); + int checkBlockCollision(vector &blocks); private: sf::RenderWindow *window; diff --git a/src/Block.cpp b/src/Block.cpp new file mode 100644 index 0000000..f41b515 --- /dev/null +++ b/src/Block.cpp @@ -0,0 +1,29 @@ +#include "Block.h" + +float Block::edgeSize = 10; + +Block::Block(sf::RenderWindow *_window, int posX_, int posY_, unsigned int blockWidth_, unsigned int blockHeight_, sf::Color outerColor_, sf::Color innerColor_) + : window(_window), + blockWidth(blockWidth_), + blockHeight(blockHeight_), + posX(posX_), + posY(posY_), + outerColor(outerColor_), + innerColor(innerColor_), + innerRect(sf::Vector2f(blockWidth - (edgeSize * 2), blockHeight - (edgeSize * 2))), + outerRect(sf::Vector2f(blockWidth, blockHeight)) +{ + outerRect.setPosition({posX, posY}); + outerRect.setFillColor(outerColor); + innerRect.setPosition({posX + edgeSize, posY + edgeSize}); + innerRect.setFillColor(innerColor); +} + +// Draw the block to the window +void Block::drawBlock() +{ + window->draw(outerRect); + window->draw(innerRect); +} + +sf::FloatRect Block::getBounds() const { return outerRect.getGlobalBounds(); } \ No newline at end of file diff --git a/src/Block.h b/src/Block.h new file mode 100644 index 0000000..0e69d7f --- /dev/null +++ b/src/Block.h @@ -0,0 +1,31 @@ +#ifndef BLOCK_H +#define BLOCK_H + +#include +using namespace std; + +class Block +{ +public: + Block(sf::RenderWindow *_window, int posX_, int posY_, unsigned int blockWidth_, + unsigned int blockHeight_, sf::Color innerColor_, sf::Color outerColor_); + void drawBlock(); + sf::FloatRect getBounds() const; + +private: + static float edgeSize; + + sf::RenderWindow *window; + + int blockWidth; + int blockHeight; + float posY; + float posX; + + sf::Color outerColor; + sf::Color innerColor; + sf::RectangleShape outerRect; + sf::RectangleShape innerRect; +}; + +#endif \ No newline at end of file diff --git a/src/GameManager.cpp b/src/GameManager.cpp index cf701ad..d7d7a49 100644 --- a/src/GameManager.cpp +++ b/src/GameManager.cpp @@ -1,10 +1,12 @@ #include "GameManager.h" #include -GameManager::GameManager(sf::RenderWindow *_window, unsigned int WIDTH, unsigned int HEIGHT) +GameManager::GameManager(sf::RenderWindow *_window, unsigned int WIDTH, unsigned int HEIGHT, + vector blocks_) : window(_window), gamePad(_window, WIDTH, HEIGHT), - gameBall(_window, WIDTH, HEIGHT) + gameBall(_window, WIDTH, HEIGHT), + blocks(blocks_) { } @@ -13,6 +15,13 @@ void GameManager::updateGame(float timeSinceLastUpdate) { gameBall.move(timeSinceLastUpdate); gameBall.checkPadCollision(gamePad.getBounds()); + + // Process collisions with blocks, and destroy any box it collides with + int collisionIndex = gameBall.checkBlockCollision(blocks); + if (collisionIndex != -1) + { + blocks.erase(blocks.begin() + collisionIndex); + } } // Draw the game @@ -20,6 +29,10 @@ void GameManager::drawGame() { gamePad.drawPad(); gameBall.drawBall(); + for (Block block : blocks) + { + block.drawBlock(); + } } Pad &GameManager::pad() { return gamePad; } diff --git a/src/GameManager.h b/src/GameManager.h index 7b3b1a6..8420172 100644 --- a/src/GameManager.h +++ b/src/GameManager.h @@ -3,11 +3,15 @@ #include "Pad.h" #include "Ball.h" +#include "Block.h" +#include +using namespace std; class GameManager { public: - GameManager(sf::RenderWindow *window, unsigned int WIDTH, unsigned int HEIGHT); + GameManager(sf::RenderWindow *window, unsigned int WIDTH, unsigned int HEIGHT, + vector blocks); void updateGame(float timeSinceLastUpdate); void drawGame(); Pad &pad(); @@ -17,6 +21,7 @@ class GameManager sf::RenderWindow *window; Pad gamePad; Ball gameBall; + vector blocks; }; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index cfc0320..58cf5bd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include "TitleScreen.h" #include "Pad.h" #include "GameManager.h" +#include "Block.h" #include "InputManager.h" #include "MainManager.h" @@ -17,8 +18,20 @@ int main() sf::Clock clock; + // Create the list of blocks to be in the game + // (in future, this should happen in some sort of level creator) + vector blocks; + blocks.push_back(Block(&window, 1250, 50, 150, 150, sf::Color(200, 0, 0), sf::Color(255, 0, 0))); + blocks.push_back(Block(&window, 1500, 50, 150, 150, sf::Color(0, 200, 0), sf::Color(0, 255, 0))); + blocks.push_back(Block(&window, 250, 50, 150, 150, sf::Color(0, 0, 200), sf::Color(0, 0, 255))); + blocks.push_back(Block(&window, 750, 50, 150, 150, sf::Color(200, 200, 0), sf::Color(255, 255, 0))); + for (int i = 0; i < 6; i++) + { + blocks.push_back(Block(&window, 250 * i - 200, 350, 150, 150, sf::Color(200, 200, 200), sf::Color(255, 255, 255))); + } + TitleScreen titleScreen(&window, WIDTH, HEIGHT); - GameManager gameManager(&window, WIDTH, HEIGHT); + GameManager gameManager(&window, WIDTH, HEIGHT, blocks); MainManager mainManager(&window, &titleScreen, &gameManager); InputManager inputManager(&mainManager, &titleScreen, &gameManager);