diff --git a/CMakeLists.txt b/CMakeLists.txt index c301c75..34a32e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,8 @@ add_executable(LotoStatek main.cpp headers/Enemy.h headers/AdvancedEnemy.h sources/AdvancedEnemy.cpp + headers/Bomber.h + sources/Bomber.cpp ) if(WIN32) diff --git a/assets/img/bullets/bomba.png b/assets/img/bullets/bomba.png new file mode 100644 index 0000000..6f09bde Binary files /dev/null and b/assets/img/bullets/bomba.png differ diff --git a/assets/img/enemy/advanced_enemy.png b/assets/img/enemy/advanced_enemy.png new file mode 100644 index 0000000..12fad0b Binary files /dev/null and b/assets/img/enemy/advanced_enemy.png differ diff --git a/assets/img/enemy/wiazkowiec.png b/assets/img/enemy/wiazkowiec.png new file mode 100644 index 0000000..bdfa19e Binary files /dev/null and b/assets/img/enemy/wiazkowiec.png differ diff --git a/headers/AdvancedEnemy.h b/headers/AdvancedEnemy.h index 09fe88f..769fa74 100644 --- a/headers/AdvancedEnemy.h +++ b/headers/AdvancedEnemy.h @@ -2,6 +2,7 @@ #define ADVANCED_ENEMY_H #include "Enemy.h" + #include enum class DirectionA { diff --git a/headers/Bomber.h b/headers/Bomber.h new file mode 100644 index 0000000..7f1a77c --- /dev/null +++ b/headers/Bomber.h @@ -0,0 +1,41 @@ +// +// Created by k on 11.12.2024. +// + +#ifndef BOMBER_H +#define BOMBER_H + +#include "Enemy.h" +#include "Actor.h" +enum class DirectionB { + Up, + Down, + Left, + Right +}; + +class Bomber : public Actor { +public: + Bomber(int x, int y, const sf::Texture& texture, const sf::Texture& bulletTexture); + + void shoot() override; + void move(float deltaX, float deltaY) override; + void moveLeft() override; + void moveRight() override; + void moveUp() override; + void moveDown() override; + + void update(); + + bool isAlive() const; + void takeDamage(); + void updateDirection(); + +private: + sf::Clock shootClock; + sf::Texture BombaTexture; + float movementSpeed = 2.0f; + bool alive = true; + DirectionB direction = DirectionB::Down; +}; +#endif //BOMBER_H diff --git a/headers/Plansza.h b/headers/Plansza.h index 4173def..b29e586 100644 --- a/headers/Plansza.h +++ b/headers/Plansza.h @@ -4,6 +4,7 @@ #include "Meteor.h" #include "Enemy.h" #include "AdvancedEnemy.h" +#include "Bomber.h" #include "RandomNumberGenerator.h" #include "SFML/System/Clock.hpp" #include "SFML/Graphics/RenderWindow.hpp" @@ -29,8 +30,9 @@ public: void update(); void spawn_enemy(); void setOutOfBounds(bool status); - void spawn_advanced_enemy(); + void spawn_wiazkowiec(); + void spawn_bomber(); private: Size size; @@ -40,17 +42,21 @@ private: sf::Texture meteorTexture1; sf::Texture meteorTexture2; sf::Texture enemyBulletTexture; + sf::Texture BombaTexture; sf::Texture playerTexture; sf::Texture playerBulletTexture; sf::Texture playerRocketTexture; sf::Texture enemyTexture; sf::Texture advancedEnemyTexture; + sf::Texture BomberEnemyTexture; sf::Clock spawnClock; sf::Clock shooterSpawnClock; std::vector enemies; std::vector AEnemies; + std::vector BEnemies; sf::Clock enemySpawnClock; sf::Clock AenemySpawnClock; + sf::Clock BomberSpawnClock; std::vector meteors; sf::RenderWindow *window; }; diff --git a/sources/Bomber.cpp b/sources/Bomber.cpp new file mode 100644 index 0000000..b909971 --- /dev/null +++ b/sources/Bomber.cpp @@ -0,0 +1,78 @@ +#include "../headers/Bomber.h" +#include "../headers/Bullet.h" + +Bomber::Bomber(int x, int y, const sf::Texture& texture, const sf::Texture& bulletTexture) : Actor(x, y, texture) { + actorSprite.setTexture(texture); + BombaTexture = bulletTexture; + hp = 2; // 2 punkty życia + firerate = 2000; // Strzela co 2 + moving_speed = 2.0f; // Prędkość + BombaTexture.loadFromFile("../assets/img/bullets/bomba.png"); +} + +void Bomber::shoot() { + if (shootClock.getElapsedTime().asMilliseconds() >= firerate) { + Bullet Bbullet(position.x, position.y + actorSprite.getGlobalBounds().height / 2, BombaTexture); + Bbullet.setSpeed(0.5f); // Prędkość w dół + bullets.emplace_back(std::move(Bbullet)); + shootClock.restart(); + } +} + +void Bomber::updateDirection() { + // Zmieniamy kierunek przeciwnika, gdy dotrze do krawędzi + if (position.y <= 0) { + direction = DirectionB::Down; + } else if (position.y >= 800) { + direction = DirectionB::Up; + } + + // logika dla kierunku lewo/prawo + if (position.x <= 0) { + direction = DirectionB::Right; + } else if (position.x >= 1200) { + direction = DirectionB::Left; + } +} + +void Bomber::move(float deltaX, float deltaY) { + actorSprite.move(deltaX, deltaY); + position.x += static_cast(deltaX); + position.y += static_cast(deltaY); +} + +void Bomber::moveLeft() { move(-moving_speed, 0.0f); } +void Bomber::moveRight() { move(moving_speed, 0.0f); } +void Bomber::moveUp() { move(0.0f, -moving_speed); } +void Bomber::moveDown() { move(0.0f, moving_speed); } + +void Bomber::update() { + // Sprawdzamy, czy przeciwnik dotarł do krawędzi i zmieniamy kierunek + updateDirection(); + + switch (direction) { + case DirectionB::Up: + moveUp(); + break; + case DirectionB::Down: + moveDown(); + break; + case DirectionB::Left: + moveLeft(); + break; + case DirectionB::Right: + moveRight(); + break; + } +} + + +bool Bomber::isAlive() const { + return alive; +} + +void Bomber::takeDamage() { + if (--hp <= 0) { + alive = false; + } +} \ No newline at end of file diff --git a/sources/Plansza.cpp b/sources/Plansza.cpp index 19727cb..9e91303 100644 --- a/sources/Plansza.cpp +++ b/sources/Plansza.cpp @@ -7,16 +7,14 @@ Plansza::Plansza(unsigned int windowHeight, unsigned int windowWidth, sf::Render const sf::Texture& playerTexture, const sf::Texture& playerBulletTexture, const sf::Texture& playerRocketTexture) -: background("../assets/img/background/background.png", 2.0f), -ship(static_cast(mainWindow->getSize().x) / 2, static_cast(mainWindow->getSize().y) - 100, playerTexture, playerBulletTexture, playerRocketTexture) -{ - + : background("../assets/img/background/background.png", 2.0f), + ship(static_cast(mainWindow->getSize().x) / 2, static_cast(mainWindow->getSize().y) - 100, + playerTexture, playerBulletTexture, playerRocketTexture) { window = mainWindow; size.height = static_cast(windowHeight); size.width = static_cast(windowWidth); - ship.setMovingSpeed(8); ship.setFirerate(200); @@ -28,7 +26,6 @@ ship(static_cast(mainWindow->getSize().x) / 2, static_cast(mainWindow- audioManager.loadSoundEffect("fail", "../assets/sounds/fail.mp3"); - meteorTexture1.loadFromFile("../assets/img/meteors/meteor-1.png"); meteorTexture2.loadFromFile("../assets/img/meteors/meteor-2.png"); @@ -41,6 +38,10 @@ ship(static_cast(mainWindow->getSize().x) / 2, static_cast(mainWindow- std::cerr << "Failed to load advanced enemy texture!" << std::endl; exit(-1); } + if (!BomberEnemyTexture.loadFromFile("../assets/img/enemy/wiazkowiec.png")) { + std::cerr << "Failed to load advanced enemy texture!" << std::endl; + exit(-1); + } spawnClock.restart(); } @@ -83,9 +84,11 @@ void Plansza::update() { } // generowanie nowego meteoru - spawn_meteor(); + //spawn_meteor(); spawn_enemy(); spawn_advanced_enemy(); + //spawn_wiazkowiec(); + spawn_bomber(); // utrzymanie meteorów i pocisków w ruchu for (auto& meteor : getMeteors()) { @@ -143,6 +146,7 @@ void Plansza::update() { } + if (!ship.isAlive()) { std::cout << "Game Over! Player is dead." << std::endl; std::cout << "You lost the game!\n"; @@ -216,6 +220,7 @@ void Plansza::update() { // Usunięcie martwych przeciwników if (!it->isAlive()) { + std::cout << "Basic Enemy has been eliminated." << std::endl; it = enemies.erase(it); } else { ++it; @@ -234,7 +239,21 @@ void Plansza::update() { ++it; } } - // std::cout << "Current AEnemies size: " << AEnemies.size() << std::endl; + for (auto it = BEnemies.begin(); it != BEnemies.end();) { + it->update(); // Ruch b + it->shoot(); // Strzał przeciwnika + + window->draw(it->getSprite()); // Rysowanie na ekranie + + if (!it->isAlive()) { + std::cout << "Bomber has been eliminated." << std::endl; + it = BEnemies.erase(it); // Usunięcie martwych przeciwników + } else { + ++it; + } + } + + // Obsługa pocisków zaawansowanych przeciwników for (auto& aEnemy : AEnemies) { for (auto it = aEnemy.getBullets().begin(); it != aEnemy.getBullets().end();) { @@ -247,22 +266,25 @@ void Plansza::update() { } } - for (auto advancedIt = AEnemies.begin(); advancedIt != AEnemies.end();) { - bool hit = false; - for (auto bulletIt = ship.getBullets().begin(); bulletIt != ship.getBullets().end();) { - if (advancedIt->getSprite().getGlobalBounds().intersects(bulletIt->getSprite().getGlobalBounds())) { - bulletIt = ship.getBullets().erase(bulletIt); - advancedIt->takeDamage(); - hit = true; - break; + // Obsługa bomb + for (auto& aEnemy : BEnemies) { + for (auto it = aEnemy.getBullets().begin(); it != aEnemy.getBullets().end();) { + if (ship.getSprite().getGlobalBounds().intersects(it->getSprite().getGlobalBounds())) { + ship.takeDamage(); // Zadanie obrażeń graczowi + it = aEnemy.getBullets().erase(it); // Usuwanie pocisku po trafieniu } else { - ++bulletIt; + ++it; } } - if (hit && !advancedIt->isAlive()) { - advancedIt = AEnemies.erase(advancedIt); // Usunięcie przeciwnika AdvancedEnemy - } else { - ++advancedIt; + } + + + for (auto& enemy : enemies) { + enemy.shoot(); + enemy.updateBullets(); + for (auto& bullet : enemy.getBullets()) { + bullet.update(); + window->draw(bullet.getSprite()); } } @@ -274,6 +296,14 @@ void Plansza::update() { } } + for (auto& bomberEnemy : BEnemies) { + bomberEnemy.updateBullets(); // Obsługuje bomby + for (auto& bullet : bomberEnemy.getBullets()) { + bullet.update(); + window->draw(bullet.getSprite()); + } + } + for (auto& enemy : enemies) { for (auto it = enemy.getBullets().begin(); it != enemy.getBullets().end();) { if (ship.getSprite().getGlobalBounds().intersects(it->getSprite().getGlobalBounds())) { @@ -290,16 +320,7 @@ void Plansza::update() { } } - for (auto& enemy : enemies) { - enemy.shoot(); - enemy.updateBullets(); - for (auto& bullet : enemy.getBullets()) { - bullet.update(); - window->draw(bullet.getSprite()); - } - } - - // Usuwanie pocisków, które są poza ekranem + // Usuwanie pocisków, które są poza ekranem srednio to dziala for (auto enemyIt = enemies.begin(); enemyIt != enemies.end(); ) { for (auto bulletIt = enemyIt->getBullets().begin(); bulletIt != enemyIt->getBullets().end();) { if (bulletIt->isOutOfBounds()) { @@ -331,6 +352,47 @@ void Plansza::update() { ++enemyIt; } } + + for (auto advancedIt = AEnemies.begin(); advancedIt != AEnemies.end();) { + bool hit = false; + for (auto bulletIt = ship.getBullets().begin(); bulletIt != ship.getBullets().end();) { + if (advancedIt->getSprite().getGlobalBounds().intersects(bulletIt->getSprite().getGlobalBounds())) { + bulletIt = ship.getBullets().erase(bulletIt); + advancedIt->takeDamage(); + hit = true; + break; + } else { + ++bulletIt; + } + } + if (hit && !advancedIt->isAlive()) { + advancedIt = AEnemies.erase(advancedIt); // Usunięcie przeciwnika AdvancedEnemy + } else { + ++advancedIt; + } + } + + for (auto bomberIt = BEnemies.begin(); bomberIt != BEnemies.end();) { + bool hit = false; + for (auto bulletIt = ship.getBullets().begin(); bulletIt != ship.getBullets().end();) { + if (bomberIt->getSprite().getGlobalBounds().intersects(bulletIt->getSprite().getGlobalBounds())) { + bulletIt = ship.getBullets().erase(bulletIt); + bomberIt->takeDamage(); + hit = true; + break; + } else { + ++bulletIt; + } + } + if (hit && !bomberIt->isAlive()) { + bomberIt = BEnemies.erase(bomberIt); // Usunięcie przeciwnika AdvancedEnemy + } else { + ++bomberIt; + } + } + + + //oblsuga dla rakiety for (auto enemyIt = enemies.begin(); enemyIt != enemies.end();) { bool hit = false; @@ -370,6 +432,25 @@ void Plansza::update() { } } + for (auto bomberIt = BEnemies.begin(); bomberIt != BEnemies.end();) { + bool hit = false; + for (auto rocketIt = ship.getRockets().begin(); rocketIt != ship.getRockets().end();) { + if (bomberIt->getSprite().getGlobalBounds().intersects(rocketIt->getSprite().getGlobalBounds())) { + rocketIt = ship.getRockets().erase(rocketIt); + bomberIt->takeDamage(); + hit = true; + break; + } else { + ++rocketIt; + } + } + if (hit && !bomberIt->isAlive()) { + bomberIt = BEnemies.erase(bomberIt); + } else { + ++bomberIt; + } + } + } @@ -398,7 +479,7 @@ void Plansza::update_meteors() { } void Plansza::spawn_enemy() { - if (enemySpawnClock.getElapsedTime().asSeconds() >= 6) { // Spawn co 10 sekund + if (enemySpawnClock.getElapsedTime().asSeconds() >= 110) { // Spawn co 10 sekund int spawnX = RandomNumberGenerator::getRandomNumber(50, size.width - 50); enemies.emplace_back(spawnX, -50, enemyTexture); @@ -408,14 +489,25 @@ void Plansza::spawn_enemy() { } void Plansza::spawn_advanced_enemy() { - if (AenemySpawnClock.getElapsedTime().asSeconds() >= 5) { // Spawn co 10 sekund + if (AenemySpawnClock.getElapsedTime().asSeconds() >= 100) { // Spawn co 10 sekund int spawnX = RandomNumberGenerator::getRandomNumber(50, size.width - 50); - AEnemies.emplace_back(spawnX, 50, advancedEnemyTexture, enemyBulletTexture); + AEnemies.emplace_back(spawnX, -50, advancedEnemyTexture, enemyBulletTexture); std::cout << "Spawned Advanced Enemy at X: " << spawnX << std::endl; AenemySpawnClock.restart(); } } +void Plansza::spawn_bomber() { + if (BomberSpawnClock.getElapsedTime().asSeconds() >= 5) { // Spawn co 10 sekund + int spawnX = RandomNumberGenerator::getRandomNumber(50, size.width - 50); + BEnemies.emplace_back(spawnX, -50, BomberEnemyTexture, BombaTexture); + std::cout << "Spawned Bomber Enemy at X: " << spawnX << std::endl; + BomberSpawnClock.restart(); + } +} + + + Size Plansza::getSize() {