diff --git a/CMakeLists.txt b/CMakeLists.txt index 8dbfe23..522c937 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,10 @@ add_executable(LotoStatek main.cpp sources/Bomber.cpp headers/Kamikadze.h sources/Kamikadze.cpp + headers/wiazkowiec.h + sources/Wiazkowiec.cpp + headers/Beam.h + sources/Beam.cpp ) if(WIN32) diff --git a/headers/Beam.h b/headers/Beam.h new file mode 100644 index 0000000..70bd6aa --- /dev/null +++ b/headers/Beam.h @@ -0,0 +1,25 @@ +#ifndef LOTOSTATEK_BEAM_H +#define LOTOSTATEK_BEAM_H + +#include +#include "Position.h" + +class Beam { +public: + Beam(float x, float y, float width, float height, const sf::Color& color); + + void update(); + void render(sf::RenderWindow& window); + + sf::FloatRect getBounds() const; + + bool isVisible() const; + void setVisible(bool visible); + + +private: + sf::RectangleShape beamShape; + bool visible; +}; + +#endif // LOTOSTATEK_BEAM_H \ No newline at end of file diff --git a/headers/Plansza.h b/headers/Plansza.h index 551c0d0..cfbea3f 100644 --- a/headers/Plansza.h +++ b/headers/Plansza.h @@ -6,6 +6,8 @@ #include "AdvancedEnemy.h" #include "Bomber.h" #include "Kamikadze.h" +#include "Wiazkowiec.h" +#include "Beam.h" #include "RandomNumberGenerator.h" #include "SFML/System/Clock.hpp" #include "SFML/Graphics/RenderWindow.hpp" @@ -44,6 +46,7 @@ private: sf::Texture meteorTexture1; sf::Texture meteorTexture2; sf::Texture enemyBulletTexture; + sf::Texture WiazkaTexture; sf::Texture BombaTexture; sf::Texture playerTexture; sf::Texture playerBulletTexture; @@ -52,16 +55,19 @@ private: sf::Texture advancedEnemyTexture; sf::Texture BomberEnemyTexture; sf::Texture KamikadzeTexture; + sf::Texture WiazkowiecTexture; sf::Clock spawnClock; sf::Clock shooterSpawnClock; std::vector enemies; std::vector AEnemies; std::vector BEnemies; std::vector KEnemies; + std::vector WEnemies; sf::Clock enemySpawnClock; sf::Clock AenemySpawnClock; sf::Clock BomberSpawnClock; sf::Clock KamikadzeSpawnClock; + sf::Clock WiazkowiecSpawnClock; std::vector meteors; sf::RenderWindow *window; }; diff --git a/headers/Wiazkowiec.h b/headers/Wiazkowiec.h new file mode 100644 index 0000000..8a44ae5 --- /dev/null +++ b/headers/Wiazkowiec.h @@ -0,0 +1,51 @@ +#ifndef WIAZKOWIEC_H +#define WIAZKOWIEC_H + +#include "Enemy.h" +#include "Actor.h" +#include "Beam.h" +enum class DirectionW { + Up, + Down, + Left, + Right +}; + +class Wiazkowiec : public Actor { +public: + Wiazkowiec(int x, int y, const sf::Texture& texture); + + void shoot() override; + void move(float deltaX, float deltaY) override; + void moveLeft() override; + void moveRight() override; + void moveUp() override; + void moveDown() override; + void setRandomDirection(); + + void update(); + + void render(sf::RenderWindow &window); + + bool isAlive() const; + void takeDamage(); + void updateDirection(); + bool isShooting() const; + const Beam& getBeam() const; + + +private: + sf::Clock shootClock; + sf::Texture WiazkaTexture; + float movementSpeed = 2.0f; + bool alive = true; + DirectionW direction = DirectionW::Down; + Beam beam; // Wiązka + bool shooting = false; // Czy obecnie strzela + sf::Clock shootingClock; // Zegar kontrolujący czas strzału + float beamDuration = 1.0f; // Czas trwania widoczności wiązki (w sekundach) + + void spawnBeam(); // Tworzy wiązkę +}; + +#endif //WIAZKOWIEC_H diff --git a/sources/Beam.cpp b/sources/Beam.cpp new file mode 100644 index 0000000..afd3ac4 --- /dev/null +++ b/sources/Beam.cpp @@ -0,0 +1,31 @@ +#include "../headers/Beam.h" + +Beam::Beam(float x, float y, float width, float height, const sf::Color& color) + : visible(false) { + beamShape.setPosition(x, y); + beamShape.setSize({width, height}); + beamShape.setFillColor(color); +} + +void Beam::update() { + // Wiązka może mieć logikę do czasu, jeśli potrzebne +} + +void Beam::render(sf::RenderWindow& window) { + if (visible) { + window.draw(beamShape); + } +} + +sf::FloatRect Beam::getBounds() const { + return beamShape.getGlobalBounds(); +} + +bool Beam::isVisible() const { + return visible; +} + +void Beam::setVisible(bool visible) { + this->visible = visible; +} + diff --git a/sources/Bomber.cpp b/sources/Bomber.cpp index 4114d3a..76b090c 100644 --- a/sources/Bomber.cpp +++ b/sources/Bomber.cpp @@ -25,13 +25,13 @@ void Bomber::setRandomDirection() { if (position.y > 0) direction = DirectionB::Up; break; case 1: - if (position.y < 800) direction = DirectionB::Down; + if (position.y < 600) direction = DirectionB::Down; break; case 2: if (position.x > 0) direction = DirectionB::Left; break; case 3: - if (position.x < 600) direction = DirectionB::Right; + if (position.x < 800) direction = DirectionB::Right; break; } } diff --git a/sources/Plansza.cpp b/sources/Plansza.cpp index 4c68109..8b2217c 100644 --- a/sources/Plansza.cpp +++ b/sources/Plansza.cpp @@ -34,11 +34,15 @@ Plansza::Plansza(unsigned int windowHeight, unsigned int windowWidth, sf::Render std::cerr << "Failed to load enemy texture!" << std::endl; exit(-1); } + if (!WiazkaTexture.loadFromFile("../assets/img/bullets/wiazka.png")) { + std::cerr << "Failed to load wiazka texture!" << std::endl; + exit(-1); + } if (!advancedEnemyTexture.loadFromFile("../assets/img/enemy/advanced_enemy.png")) { std::cerr << "Failed to load advanced enemy texture!" << std::endl; exit(-1); } - if (!BomberEnemyTexture.loadFromFile("../assets/img/enemy/wiazkowiec.png")) { + if (!BomberEnemyTexture.loadFromFile("../assets/img/enemy/bomber.png")) { std::cerr << "Failed to load advanced enemy texture!" << std::endl; exit(-1); } @@ -50,6 +54,10 @@ Plansza::Plansza(unsigned int windowHeight, unsigned int windowWidth, sf::Render std::cerr << "Failed to load BombaTexture!" << std::endl; exit(-1); } + if (!WiazkowiecTexture.loadFromFile("../assets/img/enemy/wiazkowiec.png")) { + std::cerr << "Failed to load BombaTexture!" << std::endl; + exit(-1); + } spawnClock.restart(); } @@ -95,7 +103,7 @@ void Plansza::update() { //spawn_meteor(); spawn_enemy(); spawn_advanced_enemy(); - //spawn_wiazkowiec(); + spawn_wiazkowiec(); spawn_bomber(); spawn_kamikadze(); @@ -361,6 +369,51 @@ void Plansza::update() { } } + for (auto& bomberEnemy : BEnemies) { + for (auto it = bomberEnemy.getBullets().begin(); it != bomberEnemy.getBullets().end();) { + bool bulletDestroyed = false; + + // Kolizja pocisku gracza z pociskiem Bombera + for (auto playerBulletIt = ship.getBullets().begin(); playerBulletIt != ship.getBullets().end();) { + if (playerBulletIt->getSprite().getGlobalBounds().intersects(it->getSprite().getGlobalBounds())) { + // Usuń pocisk Bombera i pocisk gracza + it = bomberEnemy.getBullets().erase(it); + playerBulletIt = ship.getBullets().erase(playerBulletIt); + bulletDestroyed = true; + break; + } else { + ++playerBulletIt; + } + } + + // Kolizja rakiety gracza z pociskiem Bombera + if (!bulletDestroyed) { + for (auto rocketIt = ship.getRockets().begin(); rocketIt != ship.getRockets().end();) { + if (rocketIt->getSprite().getGlobalBounds().intersects(it->getSprite().getGlobalBounds())) { + // Usuń pocisk Bombera i rakietę gracza + it = bomberEnemy.getBullets().erase(it); + rocketIt = ship.getRockets().erase(rocketIt); + bulletDestroyed = true; + break; + } else { + ++rocketIt; + } + } + } + + // Jeśli pocisk Bombera przetrwał dotychczasowe sprawdzenia, wykonaj inne działania + if (!bulletDestroyed) { + if (ship.getSprite().getGlobalBounds().intersects(it->getSprite().getGlobalBounds())) { + // Kolizja pocisku Bombera z graczem + ship.takeDamage(); + it = bomberEnemy.getBullets().erase(it); + } else { + ++it; + } + } + } + } + // 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();) { @@ -451,7 +504,18 @@ void Plansza::update() { } } + for (auto& wiazkowiec : WEnemies) { + wiazkowiec.update(); + if (wiazkowiec.isShooting() && wiazkowiec.getBeam().isVisible()) { + if (ship.getSprite().getGlobalBounds().intersects(wiazkowiec.getBeam().getBounds())) { + ship.takeDamage(); // Gracz otrzymuje obrażenia + } + } + + window->draw(wiazkowiec.getSprite()); + wiazkowiec.render(*window); + } //oblsuga dla rakiety for (auto enemyIt = enemies.begin(); enemyIt != enemies.end();) { @@ -577,7 +641,7 @@ void Plansza::spawn_advanced_enemy() { } void Plansza::spawn_bomber() { - if (BomberSpawnClock.getElapsedTime().asSeconds() >= 10) { // Spawn co 10 sekund + if (BomberSpawnClock.getElapsedTime().asSeconds() >= 120) { // 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; @@ -586,7 +650,7 @@ void Plansza::spawn_bomber() { } void Plansza::spawn_kamikadze() { - if (KamikadzeSpawnClock.getElapsedTime().asSeconds() >= 50) { // Spawn co 10 sekund + if (KamikadzeSpawnClock.getElapsedTime().asSeconds() >= 220) { // Spawn co 10 sekund int spawnX = RandomNumberGenerator::getRandomNumber(50, size.width - 50); KEnemies.emplace_back(spawnX, -50, KamikadzeTexture); std::cout << "Spawned Kamikadze Enemy at X: " << spawnX << std::endl; @@ -594,6 +658,14 @@ void Plansza::spawn_kamikadze() { } } +void Plansza::spawn_wiazkowiec() { + if (WiazkowiecSpawnClock.getElapsedTime().asSeconds() >= 10) { // Spawn co 10 sekund + int spawnX = RandomNumberGenerator::getRandomNumber(50, size.width - 50); + WEnemies.emplace_back(spawnX, -50, WiazkowiecTexture); + std::cout << "Spawned Wiazkowiec Enemy at X: " << spawnX << std::endl; + WiazkowiecSpawnClock.restart(); + } +} diff --git a/sources/Wiazkowiec.cpp b/sources/Wiazkowiec.cpp new file mode 100644 index 0000000..a9443f9 --- /dev/null +++ b/sources/Wiazkowiec.cpp @@ -0,0 +1,157 @@ +#include "../headers/Wiazkowiec.h" + +#include + +#include "../headers/Bullet.h" +#include + +Wiazkowiec::Wiazkowiec(int x, int y, const sf::Texture& texture) : Actor(x, y, texture), beam(0, 0, 50.f, 50.f, sf::Color::Red) { + actorSprite.setTexture(texture); + hp = 2; // 2 punkty życia + firerate = 5000; // Strzela co 10 + moving_speed = 1.0f; // Prędkość + // BombaTexture.loadFromFile("../assets/img/bullets/bomba.png"); +} + +void Wiazkowiec::spawnBeam() { + float beamX = position.x; + float beamY = position.y; + float beamWidth = 50.f; + float beamHeight = 0.f; + + switch (direction) { + case DirectionW::Up: + beamHeight = position.y; + beamY -= beamHeight; + break; + case DirectionW::Down: + beamHeight = 600 - position.y; + break; + case DirectionW::Left: + beamWidth = position.x; + beamX -= beamWidth; + break; + case DirectionW::Right: + beamWidth = 800 - position.x; + break; + } + + beam = Beam(beamX, beamY, beamWidth, beamHeight, sf::Color::Red); + beam.setVisible(true); + + shooting = true; + shootingClock.restart(); // Reset zegara +} + +// Strzał wiązki +void Wiazkowiec::shoot() { + if (!shooting) { + spawnBeam(); + std::cout << "Wiazkowiec shot a beam!" << std::endl; + } +} + +void Wiazkowiec::setRandomDirection() { + // Losowanie kierunku: 0 = Up, 1 = Down, 2 = Left, 3 = Right + int directionIndex = std::rand() % 4; + + switch (directionIndex) { + case 0: + direction = DirectionW::Up; + break; + case 1: + direction = DirectionW::Down; + break; + case 2: + direction = DirectionW::Left; + break; + case 3: + direction = DirectionW::Right; + break; + } +} + +void Wiazkowiec::updateDirection() { + // Zmieniamy kierunek przeciwnika, gdy dotrze do krawędzi + if (position.y <= 0) { + direction = DirectionW::Down; + } else if (position.y >= 800) { + direction = DirectionW::Up; + } + + // logika dla kierunku lewo/prawo + if (position.x <= 0) { + direction = DirectionW::Right; + } else if (position.x >= 1200) { + direction = DirectionW::Left; + } +} + +void Wiazkowiec::move(float deltaX, float deltaY) { + actorSprite.move(deltaX, deltaY); + position.x += static_cast(deltaX); + position.y += static_cast(deltaY); +} + +void Wiazkowiec::moveLeft() { move(-moving_speed, 0.0f); } +void Wiazkowiec::moveRight() { move(moving_speed, 0.0f); } +void Wiazkowiec::moveUp() { move(0.0f, -moving_speed); } +void Wiazkowiec::moveDown() { move(0.0f, moving_speed); } + +void Wiazkowiec::update() { + if (shooting) { + // Kontrola zakończenia strzału + if (shootingClock.getElapsedTime().asSeconds() >= beamDuration) { + beam.setVisible(false); + shooting = false; + setRandomDirection(); // Zmień kierunek po strzale + } + } else { + updateDirection(); + + switch (direction) { + case DirectionW::Up: + moveUp(); + break; + case DirectionW::Down: + moveDown(); + break; + case DirectionW::Left: + moveLeft(); + break; + case DirectionW::Right: + moveRight(); + break; + } + + if (shootClock.getElapsedTime().asSeconds() >= 3.0f) { // Co 3 sekundy + shoot(); + shootClock.restart(); + } + } +} + +// Ustawianie widoczności wiązki podczas renderowania +void Wiazkowiec::render(sf::RenderWindow& window) { + if (beam.isVisible()) { + beam.render(window); + } +} + +bool Wiazkowiec::isAlive() const { + return alive; +} + +void Wiazkowiec::takeDamage() { + if (--hp <= 0) { + alive = false; + } +} + +bool Wiazkowiec::isShooting() const { + return shooting; +} + +const Beam& Wiazkowiec::getBeam() const { + return beam; +} \ No newline at end of file