From 1d140622c014d40bfc03703d7e5eb333c826ff48 Mon Sep 17 00:00:00 2001 From: Bogdan Velicu Date: Tue, 7 Nov 2023 23:59:42 +0200 Subject: [PATCH] base class GameObject added --- README.md | 10 ++--- doodle_jump/game/Game.cpp | 25 +++++++---- doodle_jump/game/Game.h | 42 ++--------------- doodle_jump/game_object/GameObject.cpp | 62 ++++++++++++++++++++++++-- doodle_jump/game_object/GameObject.h | 25 ++++++----- doodle_jump/platform/Platform.cpp | 32 +++---------- doodle_jump/platform/Platform.h | 12 +++-- doodle_jump/player/Player.cpp | 45 +++++++------------ doodle_jump/player/Player.h | 9 +--- doodle_jump/powerups/Powerups.cpp | 46 +++++++------------ doodle_jump/powerups/Powerups.h | 9 ++-- doodle_jump/screen/GameOver.cpp | 18 +++++--- doodle_jump/screen/GameOver.h | 2 +- 13 files changed, 158 insertions(+), 179 deletions(-) diff --git a/README.md b/README.md index 82da01a..df4c861 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,13 @@ - minim o clasă de bază și **3 clase derivate** - ierarhia trebuie să fie cu bază proprie, nu derivată dintr-o clasă predefinită - [x] clasă cu atribut de tip pointer la o clasă de bază cu derivate - - [ ] funcții virtuale (pure) apelate prin pointeri de bază din clasa care conține atributul de tip pointer de bază + - [x] funcții virtuale (pure) apelate prin pointeri de bază din clasa care conține atributul de tip pointer de bază - minim o funcție virtuală va fi **specifică temei** (e.g. nu simple citiri/afișări) - constructori virtuali (clone): sunt necesari, dar nu se consideră funcții specifice temei - - [ ] apelarea constructorului din clasa de bază din constructori din derivate - - [ ] smart pointers (recomandat, opțional) - - [ ] `dynamic_cast`/`std::dynamic_pointer_cast` pentru downcast cu sens -- [ ] suprascris cc/op= pentru copieri/atribuiri corecte, copy and swap + - [x] apelarea constructorului din clasa de bază din constructori din derivate + - [x] smart pointers (recomandat, opțional) + - [x] `dynamic_cast`/`std::dynamic_pointer_cast` pentru downcast cu sens +- [x] suprascris cc/op= pentru copieri/atribuiri corecte, copy and swap - [ ] excepții - [ ] ierarhie proprie cu baza `std::exception` sau derivată din `std::exception`; minim 2 clase pentru erori specifice - [ ] utilizare cu sens: de exemplu, `throw` în constructor, `try`/`catch` în `main` diff --git a/doodle_jump/game/Game.cpp b/doodle_jump/game/Game.cpp index 68e8252..58c5574 100644 --- a/doodle_jump/game/Game.cpp +++ b/doodle_jump/game/Game.cpp @@ -3,6 +3,7 @@ #include "./../screen/PlayScreen.h" #include "./../screen/GameOver.h" #include +#include #include const int SCREEN_WIDTH = 800; @@ -21,13 +22,20 @@ Game::Game() { currentScreen = ScreenType::MAIN_MENU; score = 0; maxScore = 0; + + gameObject = &player; + + auto player = dynamic_cast(gameObject); + if (player) { + player->setHealth(4); + } else { + std::cout << "gameObject is not a Player\n"; + } initTextures(); platforms = std::vector(); powerups = std::vector(); - powerDrawer = PowerDrawer(); - // powerup = nullptr; lastPlatform = new Platform(); @@ -77,7 +85,6 @@ void Game::reset() { lastPlatform = new Platform(); powerups.clear(); - // powerup = nullptr; for (int i = 0; i < 20; i++) { auto platform = Platform(); @@ -136,7 +143,7 @@ void Game::run() { Game::play(); break; case ScreenType::GAME_OVER: - GameOver::render(window); + GameOver::render(window, maxScore); break; case ScreenType::CLOSE: window.close(); @@ -253,7 +260,9 @@ void Game::play() { } } else { - player.moveSprite({0.0f, velocity.y}); + // funcție virtuala apelata prin pointer + gameObject->moveSprite({0.0f, velocity.y}); + // player.moveSprite({0.0f, velocity.y}); } player.moveSprite({velocity.x, 0.0f}); @@ -262,12 +271,12 @@ void Game::play() { window.draw(backgroundSprite[0]); window.draw(backgroundSprite[1]); - player.draw(window, player.getSprite()); + player.draw(window); for (auto& platform : platforms) { - platform.draw(window, platform.getSprite()); + platform.draw(window); } for (auto& powerup : powerups) { - powerup.draw(window, powerup.getSprite()); + powerup.draw(window); } displayScore(); // displayDebugInfo(); diff --git a/doodle_jump/game/Game.h b/doodle_jump/game/Game.h index d0197be..f3e9229 100644 --- a/doodle_jump/game/Game.h +++ b/doodle_jump/game/Game.h @@ -6,43 +6,7 @@ #include #include #include - -class PowerDrawer { -private: - GameObject* gameObject; -public: - PowerDrawer() { - gameObject = nullptr; - } - - void setGameObject(GameObject* gameObject_) { - gameObject = gameObject_; - } - - void assignTexture(sf::Texture& texture) { - if (gameObject != nullptr) - gameObject->assignTexture(texture); - } - - sf::Texture& getTexture() { - if (gameObject != nullptr) - return gameObject->getTexture(); - } - - sf::Sprite getSprite() { - if (gameObject != nullptr) - return gameObject->getSprite(); - } - - void draw(sf::RenderWindow& window, const sf::Sprite& sprite) { - std::cout << "PowerDrawer draw called\n"; - - if (gameObject != nullptr) - gameObject->draw(window, sprite); - else - window.draw(sprite); - } -}; +#include class Game { ScreenType currentScreen; @@ -61,8 +25,8 @@ class Game { std::vector platforms; std::vector powerups; - PowerDrawer powerDrawer; - // GameObject *powerup; + GameObject *gameObject; + Platform *lastPlatform; public: Game(); diff --git a/doodle_jump/game_object/GameObject.cpp b/doodle_jump/game_object/GameObject.cpp index 4bc70fb..2d25878 100644 --- a/doodle_jump/game_object/GameObject.cpp +++ b/doodle_jump/game_object/GameObject.cpp @@ -10,11 +10,65 @@ GameObject::~GameObject() { std::cout << "GameObject destructor called\n"; } +GameObject::GameObject(const GameObject& gameObject) { + std::cout << "GameObject copy constructor called\n"; + // texture = new sf::Texture(); + texture = gameObject.texture; + sprite = sf::Sprite(); + sprite.setPosition(gameObject.sprite.getPosition()); + sprite.setTexture(*texture); +} + +GameObject& GameObject::operator=(const GameObject& gameObject) { + std::cout << "GameObject copy assignment operator called\n"; + if (this != &gameObject) { + // texture = new sf::Texture(); + texture = gameObject.texture; + sprite = sf::Sprite(); + sprite.setPosition(gameObject.sprite.getPosition()); + sprite.setTexture(*texture); + } + return *this; +} + void GameObject::assignTexture(sf::Texture& texture_) { - texture = texture_; - sprite.setTexture(texture); + texture = &texture_; + sprite.setTexture(*texture); +} + +void GameObject::draw(sf::RenderWindow& window) { + window.draw(sprite); +} + +sf::Texture& GameObject::getTexture() { + return *texture; +} + +void GameObject::loadTexture(const std::string& path) { + texture->loadFromFile(path); + sprite.setTexture(*texture); +} + +sf::Sprite GameObject::getSprite() const { + return sprite; +} + +void GameObject::setSpritePos(const sf::Vector2f& coordinates) { + sprite.setPosition(coordinates); +} + +void GameObject::setSpriteScale(const sf::Vector2f& scale) { + sprite.setScale(scale); +} + +void GameObject::setSpriteOrigin(const sf::Vector2f& origin) { + sprite.setOrigin(origin); +} + +void GameObject::moveSprite(const sf::Vector2f& coordinates_) { + sprite.move(coordinates_); } -void GameObject::draw(sf::RenderWindow &window, const sf::Sprite& sprite_) { - window.draw(sprite_); +void GameObject::setSpritePosition(const sf::Vector2f& coordinates) { + sprite.setPosition(coordinates); } diff --git a/doodle_jump/game_object/GameObject.h b/doodle_jump/game_object/GameObject.h index 7f9f764..b1949cf 100644 --- a/doodle_jump/game_object/GameObject.h +++ b/doodle_jump/game_object/GameObject.h @@ -4,20 +4,21 @@ class GameObject { private: - sf::Texture texture; - sf::Sprite sprite; + sf::Texture *texture = new sf::Texture(); + sf::Sprite sprite = sf::Sprite(); public: GameObject(); virtual ~GameObject(); + GameObject(const GameObject& gameObject); + GameObject& operator=(const GameObject& gameObject); + virtual void draw(sf::RenderWindow& window); virtual void assignTexture(sf::Texture& texture_); - - virtual sf::Texture& getTexture() { - return texture; - } - - virtual sf::Sprite getSprite() { - return sprite; - } - - virtual void draw(sf::RenderWindow& window, const sf::Sprite& sprite_); + virtual sf::Texture& getTexture(); + virtual void loadTexture(const std::string& path); + virtual sf::Sprite getSprite() const; + virtual void setSpritePos(const sf::Vector2f& coordinates); + virtual void setSpriteScale(const sf::Vector2f& scale); + virtual void setSpriteOrigin(const sf::Vector2f& origin); + virtual void moveSprite(const sf::Vector2f& coordinates_); + virtual void setSpritePosition(const sf::Vector2f& coordinates); }; \ No newline at end of file diff --git a/doodle_jump/platform/Platform.cpp b/doodle_jump/platform/Platform.cpp index f12e8a0..2a36fe5 100644 --- a/doodle_jump/platform/Platform.cpp +++ b/doodle_jump/platform/Platform.cpp @@ -12,17 +12,15 @@ Platform::Platform() { int x = 0; int y = 800; - sprite.setPosition((float)x, (float)y); + setSpritePosition({(float)x, (float)y}); } Platform::~Platform() { std::cout << "Platform destructor called\n"; } -Platform::Platform(const Platform& platform) { +Platform::Platform(const Platform& platform) : GameObject(platform) { std::cout << "Platform copy constructor called\n"; - texture = new sf::Texture(); - sprite = platform.sprite; type = platform.type; updateCount = platform.updateCount; } @@ -30,9 +28,8 @@ Platform::Platform(const Platform& platform) { Platform& Platform::operator=(const Platform& platform) { std::cout << "Platform copy assignment operator called\n"; if (this != &platform) { + GameObject::operator=(platform); type = platform.type; - texture = platform.texture; - sprite = platform.sprite; updateCount = platform.updateCount; } return *this; @@ -67,12 +64,7 @@ void Platform::useGenerator(const sf::Vector2f& lastPlatformCoordinates) { type = platformType; - sprite.setPosition((float)x, (float)y); -} - -void Platform::assignTexture(sf::Texture& texture_) { - texture = &texture_; - sprite.setTexture(*texture); + setSpritePosition({(float)x, (float)y}); } std::ostream& operator<<(std::ostream& os, const PlatformType& platformType) { @@ -102,16 +94,12 @@ std::ostream& operator<<(std::ostream& os, const Platform& platform) { return os; } -void Platform::moveSprite(const sf::Vector2f& coordinates_) { - sprite.move(coordinates_); -} - void Platform::animateMovement() { if (updateCount < 100) { - sprite.move({ -1.0f, 0.0f }); + moveSprite({ -1.0f, 0.0f }); } else if (updateCount < 200) { - sprite.move({ 1.0f, 0.0f }); + moveSprite({ 1.0f, 0.0f }); } else { updateCount = 0; @@ -121,12 +109,4 @@ void Platform::animateMovement() { PlatformType Platform::getType() const { return type; -} - -sf::Sprite Platform::getSprite() const { - return sprite; -} - -void Platform::draw(sf::RenderWindow& window, const sf::Sprite& _sprite) { - window.draw(_sprite); } \ No newline at end of file diff --git a/doodle_jump/platform/Platform.h b/doodle_jump/platform/Platform.h index 742acd6..5318677 100644 --- a/doodle_jump/platform/Platform.h +++ b/doodle_jump/platform/Platform.h @@ -15,20 +15,18 @@ std::ostream& operator<<(std::ostream& os, const PlatformType& platformType); class Platform : public GameObject { private: PlatformType type; - sf::Texture *texture = new sf::Texture(); - sf::Sprite sprite = sf::Sprite(); + // sf::Texture *texture = new sf::Texture(); + // sf::Sprite sprite = sf::Sprite(); int updateCount; public: Platform(); - ~Platform(); + ~Platform() override; Platform(const Platform& platform); Platform& operator=(const Platform& platform); void useGenerator(const sf::Vector2f& lastPlatformCoordinates); friend std::ostream& operator<<(std::ostream& os, const Platform& platform); PlatformType getType() const; - sf::Sprite getSprite() const; - void moveSprite(const sf::Vector2f& coordinates_); + // sf::Sprite getSprite() const; + // void moveSprite(const sf::Vector2f& coordinates_); void animateMovement(); - void assignTexture(sf::Texture& texture_); - void draw(sf::RenderWindow& window, const sf::Sprite& sprite) override; }; \ No newline at end of file diff --git a/doodle_jump/player/Player.cpp b/doodle_jump/player/Player.cpp index f263a14..0c63af2 100644 --- a/doodle_jump/player/Player.cpp +++ b/doodle_jump/player/Player.cpp @@ -1,32 +1,19 @@ #include "Player.h" #include -Player::Player() { +Player::Player() : GameObject() { std::cout << "Player constructor called\n"; currentHeight = 0; + health = 3; xVelocity = 0; yVelocity = 0; - texture.loadFromFile("assets/Doodle-Ninja.png"); + loadTexture("assets/Doodle-Ninja.png"); + setSpritePos({400, 550}); - sprite.setTexture(texture); - sprite.setPosition(400, 550); - - sprite.setOrigin(sprite.getLocalBounds().width / 2, sprite.getLocalBounds().height / 2); - sprite.scale(-1.0f, 1.0f); -} - -sf::Sprite Player::getSprite() const { - return sprite; -} - -void Player::setSpritePosition(const sf::Vector2f& coordinates_) { - sprite.setPosition(coordinates_); -} - -void Player::moveSprite(const sf::Vector2f& coordinates_) { - sprite.move(coordinates_); + setSpriteOrigin({getSprite().getLocalBounds().width / 2, getSprite().getLocalBounds().height / 2}); + setSpriteScale({-1.0f, 1.0f}); } void Player::setYVelocity(float yVelocity_) { @@ -41,6 +28,10 @@ sf::Vector2f Player::getVelocity() const { return {xVelocity, yVelocity}; } +void Player::setHealth(int health_) { + health = health_; +} + void Player::jump() { yVelocity = -12.0f; // state = PlayerState::JUMPING; @@ -50,7 +41,7 @@ void Player::moveLeft() { if (xVelocity > -5.0f) { xVelocity -= 1.0f; if (state == PlayerState::MOVING_RIGHT) - sprite.scale(-1.0f, 1.0f); + setSpriteScale({-1.0f, 1.0f}); state = PlayerState::MOVING_LEFT; } } @@ -59,7 +50,7 @@ void Player::moveRight() { if (xVelocity < 5.0f) { xVelocity += 1.0f; if (state == PlayerState::MOVING_LEFT) - sprite.scale(-1.0f, 1.0f); + setSpriteScale({-1.0f, 1.0f}); state = PlayerState::MOVING_RIGHT; } } @@ -87,11 +78,11 @@ void Player::handleMovement() { } // Handle moving off screen - if (sprite.getPosition().x < 0.0f) { - sprite.setPosition(800.0f, sprite.getPosition().y); + if (getSprite().getPosition().x < 0.0f) { + setSpritePosition({800.0f, getSprite().getPosition().y}); } - else if (sprite.getPosition().x > 800.0f) { - sprite.setPosition(0.0f, sprite.getPosition().y); + else if (getSprite().getPosition().x > 800.0f) { + setSpritePosition({0.0f, getSprite().getPosition().y}); } // Handle gravity @@ -108,8 +99,4 @@ std::ostream& operator<<(std::ostream& out, const Player& player) { out << "Player: coordinates = (" << coordinates.x << ", " << coordinates.y << ")" << ", xVelocity = " << player.xVelocity << ", yVelocity = " << player.yVelocity; return out; -} - -void Player::draw(sf::RenderWindow& window, const sf::Sprite& _sprite) { - window.draw(_sprite); } \ No newline at end of file diff --git a/doodle_jump/player/Player.h b/doodle_jump/player/Player.h index 8f1301a..c741979 100644 --- a/doodle_jump/player/Player.h +++ b/doodle_jump/player/Player.h @@ -12,26 +12,21 @@ enum class PlayerState { class Player : public GameObject { private: - sf::Texture texture = sf::Texture(); PlayerState state = PlayerState::MOVING_LEFT; - sf::Sprite sprite = sf::Sprite(); float currentHeight; float xVelocity; float yVelocity; + int health; public: Player(); friend std::ostream& operator<<(std::ostream& out, const Player& player); void setYVelocity(float yVelocity_); float getYVelocity() const; sf::Vector2f getVelocity() const; - sf::Sprite getSprite() const; - void setSpritePosition(const sf::Vector2f& coordinates_); - void moveSprite(const sf::Vector2f& coordinates_); + void setHealth(int health_); void handleMovement(); void update(); void jump(); void moveLeft(); void moveRight(); - - void draw(sf::RenderWindow& window, const sf::Sprite& sprite) override; }; \ No newline at end of file diff --git a/doodle_jump/powerups/Powerups.cpp b/doodle_jump/powerups/Powerups.cpp index b6abc94..82b6287 100644 --- a/doodle_jump/powerups/Powerups.cpp +++ b/doodle_jump/powerups/Powerups.cpp @@ -7,7 +7,6 @@ Powerups::Powerups() { std::cout << "Powerups constructor called\n"; updateCount = 0; type = PowerupsType::JETPACK; - gameObject = nullptr; } Powerups::~Powerups() { @@ -29,9 +28,21 @@ std::ostream& operator<<(std::ostream& out, const PowerupsType& powerupsType) { return out; } -// void Powerups::setGameObject(GameObject *gameObject_) { -// gameObject = gameObject_; -// } +Powerups& Powerups::operator=(const Powerups& powerups) { + std::cout << "Powerups copy assignment operator called\n"; + if (this != &powerups) { + GameObject::operator=(powerups); + type = powerups.type; + updateCount = powerups.updateCount; + } + return *this; +} + +Powerups::Powerups(const Powerups& powerups) : GameObject(powerups) { + std::cout << "Powerups copy constructor called\n"; + type = powerups.type; + updateCount = powerups.updateCount; +} void Powerups::useGenerator(const sf::Vector2f& lastPlatformCoordinates) { std::cout << "Powerups constructor called\n"; @@ -52,7 +63,7 @@ void Powerups::useGenerator(const sf::Vector2f& lastPlatformCoordinates) { float y = lastPlatformCoordinates.y - 100; - sprite.setPosition(x, y); + setSpritePos({x, y}); type = powerupsType; } @@ -67,33 +78,10 @@ PowerupsType Powerups::getType() const { return type; } -// sf::Sprite Powerups::getSprite() const { -// return sprite; -// } - -// void Powerups::assignTexture(sf::Texture& texture_) { -// texture = &texture_; -// sprite.setTexture(*texture); -// } - -void Powerups::moveSprite(const sf::Vector2f& coordinates_) { - sprite.move(coordinates_); -} - // void Powerups::animateMovement() { // updateCount++; // if (updateCount == 100) { // updateCount = 0; // } // sprite.move(0.0f, 1.0f); -// } - -void Powerups::draw(sf::RenderWindow& window, const sf::Sprite& sprite_) { - window.draw(sprite_); - // if (gameObject != nullptr) { - // gameObject->draw(window, sprite_); - // } - // else { - // std::cout << "Powerups::draw() gameObject is nullptr\n"; - // } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/doodle_jump/powerups/Powerups.h b/doodle_jump/powerups/Powerups.h index 8634dd0..0b3c922 100644 --- a/doodle_jump/powerups/Powerups.h +++ b/doodle_jump/powerups/Powerups.h @@ -12,21 +12,18 @@ std::ostream& operator<<(std::ostream& out, const PowerupsType& powerupsType); class Powerups : public GameObject { private: - sf::Texture *texture = new sf::Texture(); - sf::Sprite sprite = sf::Sprite(); PowerupsType type; - GameObject* gameObject; int updateCount; public: Powerups(); - ~Powerups(); + ~Powerups() override; void useGenerator(const sf::Vector2f& lastPlatformCoordinates); friend std::ostream& operator<<(std::ostream& os, const Powerups& powerups); + Powerups& operator=(const Powerups& powerups); + Powerups(const Powerups& powerups); PowerupsType getType() const; // sf::Sprite getSprite() const; // void assignTexture(sf::Texture& texture_); // void setGameObject(GameObject* gameObject_); - void moveSprite(const sf::Vector2f& coordinates_); // void animateMovement(); - void draw(sf::RenderWindow& window, const sf::Sprite& sprite) override; }; \ No newline at end of file diff --git a/doodle_jump/screen/GameOver.cpp b/doodle_jump/screen/GameOver.cpp index 20f8146..38f1870 100644 --- a/doodle_jump/screen/GameOver.cpp +++ b/doodle_jump/screen/GameOver.cpp @@ -8,21 +8,27 @@ GameOver::~GameOver() { std::cout << "GameOver destructor called\n"; } -void GameOver::render(sf::RenderWindow& window) { +void GameOver::render(sf::RenderWindow& window, float score) { std::cout << "GameOver render called\n"; sf::Font font; font.loadFromFile("fonts/Valoon.ttf"); - sf::Text text; - text.setFont(font); - text.setString("Game Over \nPress Enter to play again\nPress Esc to exit"); - text.setCharacterSize(40); + sf::Text text = sf::Text{"Game Over \nPress Enter to play again\nPress Esc to exit", font, 40}, + scoreText = sf::Text{"Score: " + std::to_string((int)score), font, 50}; + + scoreText.setFillColor(sf::Color::Red); + scoreText.setStyle(sf::Text::Bold); + scoreText.setOrigin(text.getGlobalBounds().getSize() / 2.f + text.getLocalBounds().getPosition()); + scoreText.setPosition((float)window.getSize().x / 2.f, (float)window.getSize().y / 2.f - 200.f); + text.setFillColor(sf::Color::Red); text.setStyle(sf::Text::Bold); - text.setPosition(100, 200); + text.setOrigin(text.getGlobalBounds().getSize() / 2.f + text.getLocalBounds().getPosition()); + text.setPosition((float)window.getSize().x / 2.f, (float)window.getSize().y / 2.f); window.clear(sf::Color::Black); window.draw(text); + window.draw(scoreText); window.display(); } diff --git a/doodle_jump/screen/GameOver.h b/doodle_jump/screen/GameOver.h index 3342417..03b0f5d 100644 --- a/doodle_jump/screen/GameOver.h +++ b/doodle_jump/screen/GameOver.h @@ -5,6 +5,6 @@ class GameOver : private GameScreen { public: GameOver(); ~GameOver(); - static void render(sf::RenderWindow& window); + static void render(sf::RenderWindow& window, float score); static void handleInput(const sf::Event& event, ScreenType& currentScreen); }; \ No newline at end of file