From c1a24a701b85fd35d4714f9bc905da784d261bf1 Mon Sep 17 00:00:00 2001 From: Kuba Date: Wed, 11 Dec 2024 17:43:43 +0100 Subject: [PATCH] Kamikadze sledzi gracza --- assets/img/enemy/kamikadze.png | Bin 0 -> 6266 bytes headers/Kamikadze.h | 45 +++++++++++- headers/Plansza.h | 5 ++ sources/Kamikadze.cpp | 129 ++++++++++++++++++++++++++++++++- sources/Plansza.cpp | 87 +++++++++++++++++++++- 5 files changed, 256 insertions(+), 10 deletions(-) create mode 100644 assets/img/enemy/kamikadze.png diff --git a/assets/img/enemy/kamikadze.png b/assets/img/enemy/kamikadze.png new file mode 100644 index 0000000000000000000000000000000000000000..e8fe1a6f85e0124dddb01ea6ca2712bcd9bf6864 GIT binary patch literal 6266 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 enemies; std::vector AEnemies; std::vector BEnemies; + std::vector KEnemies; sf::Clock enemySpawnClock; sf::Clock AenemySpawnClock; sf::Clock BomberSpawnClock; + sf::Clock KamikadzeSpawnClock; std::vector meteors; sf::RenderWindow *window; }; diff --git a/sources/Kamikadze.cpp b/sources/Kamikadze.cpp index 2fcec76..bd8f05c 100644 --- a/sources/Kamikadze.cpp +++ b/sources/Kamikadze.cpp @@ -1,3 +1,126 @@ -// -// Created by k on 11.12.2024. -// +#include "../headers/Kamikadze.h" +#include "../headers/Bullet.h" +#include + +Kamikadze::Kamikadze(int x, int y, const sf::Texture& texture) : Actor(x, y, texture) { + actorSprite.setTexture(texture); + hp = 3; // 3 punkty życia + moving_speed = 2.0f; // Prędkość +} + +void Kamikadze::shoot(){} + +// Losuje losowy kierunek dla Bombera +void Kamikadze::setRandomDirection() { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(0, 3); + + int randomDirection = dist(gen); + + // Zapobieganie wyjscia poza ekran + switch (randomDirection) { + case 0: + if (position.y > 0) direction = DirectionK::Up; + break; + case 1: + if (position.y < 800) direction = DirectionK::Down; + break; + case 2: + if (position.x > 0) direction = DirectionK::Left; + break; + case 3: + if (position.x < 1200) direction = DirectionK::Right; + break; + } +} + + +void Kamikadze::updateDirection() { + // Zmieniamy kierunek przeciwnika, gdy dotrze do krawędzi + if (position.y <= 0) { + direction = DirectionK::Down; + } else if (position.y >= 800) { + direction = DirectionK::Up; + } + + // logika dla kierunku lewo/prawo + if (position.x <= 0) { + direction = DirectionK::Right; + } else if (position.x >= 1200) { + direction = DirectionK::Left; + } +} + +void Kamikadze::followPlayer(const sf::Vector2f& playerPosition) { + // Oblicz różnicę w pozycjach + float diffX = playerPosition.x - position.x; + float diffY = playerPosition.y - position.y; + + // Normalizacja wektora (skrócenie kierunku do jednostkowego) + float magnitude = std::sqrt(diffX * diffX + diffY * diffY); + if (magnitude != 0) { + diffX /= magnitude; + diffY /= magnitude; + + // Aktualizacja pozycji Kamikadze w kierunku gracza z uwzględnieniem prędkości + position.x += diffX * movementSpeed; + position.y += diffY * movementSpeed; + } else { + // Jeśli Kamikadze jest dokładnie na pozycji gracza, zatrzymaj jego ruch + movementSpeed = 0.0f; + } +} + +void Kamikadze::explode(const sf::Vector2f& playerPosition, bool& playerHit) { + if (!exploding) { + // Kamikadze rozpoczyna eksplozję + exploding = true; + explosionClock.restart(); + movementSpeed = 0.0f; // Zatrzymaj ruch + + // Sprawdź, czy gracz jest w obszarze eksplozji + const float explosionRange = 50.0f; // Zakładając promień wybuchu + sf::Vector2f diff = playerPosition - sf::Vector2f(static_cast(position.x), static_cast(position.y)); + float distance = std::sqrt(diff.x * diff.x + diff.y * diff.y); + + if (distance <= explosionRange) { + playerHit = true; // Gracz został trafiony + } + } + + // Po zakończeniu eksplozji, Kamikadze umiera + if (exploding && explosionClock.getElapsedTime().asSeconds() >= 0.5f) { // 0.5 sekundy + alive = false; + } +} + +void Kamikadze::move(float deltaX, float deltaY) { + actorSprite.move(deltaX, deltaY); + position.x += static_cast(deltaX); + position.y += static_cast(deltaY); +} + +void Kamikadze::moveLeft() { move(-moving_speed, 0.0f); } +void Kamikadze::moveRight() { move(moving_speed, 0.0f); } +void Kamikadze::moveUp() { move(0.0f, -moving_speed); } +void Kamikadze::moveDown() { move(0.0f, moving_speed); } + +void Kamikadze::update(const sf::Vector2f& playerPosition) { + if (alive && !exploding) { + // Podążaj za graczem, dopóki Kamikadze jest żywy i nie eksploduje + followPlayer(playerPosition); + actorSprite.setPosition(position.x, position.y); // Aktualizuj sprite + } +} + + +bool Kamikadze::isAlive() const { + return alive; +} + +void Kamikadze::takeDamage() { + if (--hp <= 0) { + alive = false; + } +} \ No newline at end of file diff --git a/sources/Plansza.cpp b/sources/Plansza.cpp index 15beee7..9383785 100644 --- a/sources/Plansza.cpp +++ b/sources/Plansza.cpp @@ -42,6 +42,10 @@ Plansza::Plansza(unsigned int windowHeight, unsigned int windowWidth, sf::Render std::cerr << "Failed to load advanced enemy texture!" << std::endl; exit(-1); } + if (!KamikadzeTexture.loadFromFile("../assets/img/enemy/kamikadze.png")) { + std::cerr << "Failed to load advanced enemy texture!" << std::endl; + exit(-1); + } if (!BombaTexture.loadFromFile("../assets/img/bullets/bomba.png")) { std::cerr << "Failed to load BombaTexture!" << std::endl; exit(-1); @@ -93,6 +97,7 @@ void Plansza::update() { spawn_advanced_enemy(); //spawn_wiazkowiec(); spawn_bomber(); + spawn_kamikadze(); // utrzymanie meteorów i pocisków w ruchu for (auto& meteor : getMeteors()) { @@ -258,6 +263,35 @@ void Plansza::update() { } + for (auto it = KEnemies.begin(); it != KEnemies.end();) { + sf::Vector2f playerPosition = ship.getSprite().getPosition(); // Pozycja gracza + bool playerHit = false; + + // Aktualizacja ruchu Kamikadze + + it->update(playerPosition); + + // Sprawdź kolizję z graczem + if (ship.getSprite().getGlobalBounds().intersects(it->getSprite().getGlobalBounds())) { + it->explode(playerPosition, playerHit); + + if (playerHit) { + ship.takeDamage(); // Gracz traci punkt życia + } + } + + // Rysuj Kamikadze na ekranie + if (it->isAlive()) { + window->draw(it->getSprite()); + ++it; + } else { + // Usuń, jeśli Kamikadze już nie żyje + std::cout << "Kamikadze has exploded!" << std::endl; + it = KEnemies.erase(it); + } + } + + // Obsługa pocisków zaawansowanych przeciwników for (auto& aEnemy : AEnemies) { for (auto it = aEnemy.getBullets().begin(); it != aEnemy.getBullets().end();) { @@ -389,12 +423,31 @@ void Plansza::update() { } } if (hit && !bomberIt->isAlive()) { - bomberIt = BEnemies.erase(bomberIt); // Usunięcie przeciwnika AdvancedEnemy + bomberIt = BEnemies.erase(bomberIt); // Usunięcie przeciwnika Bomber } else { ++bomberIt; } } + for (auto kamikadzeIt = KEnemies.begin(); kamikadzeIt != KEnemies.end();) { + bool hit = false; + for (auto bulletIt = ship.getBullets().begin(); bulletIt != ship.getBullets().end();) { + if (kamikadzeIt->getSprite().getGlobalBounds().intersects(bulletIt->getSprite().getGlobalBounds())) { + bulletIt = ship.getBullets().erase(bulletIt); + kamikadzeIt->takeDamage(); + hit = true; + break; + } else { + ++bulletIt; + } + } + if (hit && !kamikadzeIt->isAlive()) { + kamikadzeIt = KEnemies.erase(kamikadzeIt); // Usunięcie przeciwnika Kamikadze + } else { + ++kamikadzeIt; + } + } + //oblsuga dla rakiety @@ -455,6 +508,25 @@ void Plansza::update() { } } + for (auto kamikadzeIt = KEnemies.begin(); kamikadzeIt != KEnemies.end();) { + bool hit = false; + for (auto rocketIt = ship.getRockets().begin(); rocketIt != ship.getRockets().end();) { + if (kamikadzeIt->getSprite().getGlobalBounds().intersects(rocketIt->getSprite().getGlobalBounds())) { + rocketIt = ship.getRockets().erase(rocketIt); + kamikadzeIt->takeDamage(); + hit = true; + break; + } else { + ++rocketIt; + } + } + if (hit && !kamikadzeIt->isAlive()) { + kamikadzeIt = KEnemies.erase(kamikadzeIt); + } else { + ++kamikadzeIt; + } + } + } @@ -486,7 +558,7 @@ void Plansza::spawn_enemy() { if (enemySpawnClock.getElapsedTime().asSeconds() >= 110) { // Spawn co 10 sekund int spawnX = RandomNumberGenerator::getRandomNumber(50, size.width - 50); enemies.emplace_back(spawnX, -50, enemyTexture); - + std::cout << "Spawned Basic Enemy at X: " << spawnX << std::endl; enemySpawnClock.restart(); } @@ -502,7 +574,7 @@ void Plansza::spawn_advanced_enemy() { } void Plansza::spawn_bomber() { - if (BomberSpawnClock.getElapsedTime().asSeconds() >= 10) { // Spawn co 10 sekund + if (BomberSpawnClock.getElapsedTime().asSeconds() >= 100) { // 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; @@ -510,6 +582,15 @@ void Plansza::spawn_bomber() { } } +void Plansza::spawn_kamikadze() { + if (KamikadzeSpawnClock.getElapsedTime().asSeconds() >= 5) { // 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; + KamikadzeSpawnClock.restart(); + } +} +