#include #include #include "../headers/Plansza.h" #include "../headers/ObjectItem.hpp" Plansza::Plansza(unsigned int windowHeight, unsigned int windowWidth, sf::RenderWindow *mainWindow, 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) { window = mainWindow; size.height = static_cast(windowHeight); size.width = static_cast(windowWidth); ship.setMovingSpeed(8); ship.setFirerate(200); audioManager.loadBackgroundMusic("../assets/music/background.ogg"); audioManager.playBackgroundMusic(); audioManager.loadSoundEffect("shoot", "../assets/sounds/shoot.ogg"); audioManager.loadSoundEffect("shoot_alt", "../assets/sounds/shoot_alt.ogg"); audioManager.loadSoundEffect("fail", "../assets/sounds/fail.mp3"); meteorTexture1.loadFromFile("../assets/img/meteors/meteor-1.png"); meteorTexture2.loadFromFile("../assets/img/meteors/meteor-2.png"); // Ładowanie tekstur wrogów if (!enemyTexture.loadFromFile("../assets/img/enemy/enemy.png")) { std::cerr << "Failed to load enemy 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/bomber.png")) { 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); } if (!WiazkowiecTexture.loadFromFile("../assets/img/enemy/wiazkowiec.png")) { std::cerr << "Failed to load Wiazkowiec texture!" << std::endl; exit(-1); } spawnClock.restart(); } void Plansza::update() { // tło background.update(); background.draw(*window); // poruszanie się statkiem if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)) { if(ship.getPosition().x > 50) { ship.moveLeft(); } } if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) { if(ship.getPosition().y > 80) { ship.moveUp(); } } if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { if(ship.getPosition().y < 720) { ship.moveDown(); } } if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) { if(ship.getPosition().x < 550) { ship.moveRight(); } } // TODO: Przenieść obiekt dźwięku wewnątrz klasy Bullet if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) { ship.shoot(); audioManager.playSoundEffect("shoot", 70.f); // Odtworzenie dźwięku wystrzału } if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) { ship.alternate_shoot(); audioManager.playSoundEffect("shoot_alt", 70.f); // Odtworzenie dźwięku dla alternatywnego strzału } // generowanie nowego meteoru ship.update(); spawn_meteor(); spawn_enemy(); spawn_advanced_enemy(); spawn_wiazkowiec(); spawn_bomber(); spawn_kamikadze(); // utrzymanie meteorów i pocisków w ruchu for (auto& meteor : getMeteors()) { meteor.update(); window->draw(meteor.getSprite()); } for (auto& bullet : ship.getBullets()) { bullet.update(); window->draw(bullet.getSprite()); } for (auto& rocket : ship.getRockets()) { rocket.update(); window->draw(rocket.getSprite()); } // Sprawdzenie czy meteory i pociski są poza granicami ekranu update_meteors(); ship.updateBullets(); window->draw(ship.getSprite()); // trochę dziwny sposób ale jednak działa for (auto& meteor : getMeteors()) { if(ship.getSprite().getGlobalBounds().intersects(meteor.getSprite().getGlobalBounds())) { std::cout << "You lost the game!\n"; sf::RenderWindow errorWindow(sf::VideoMode(350, 200), "The end"); sf::Font font; if (!font.loadFromFile("../assets/fonts/arial.ttf")) { std::cerr << "Error loading font\n"; exit(-500); } sf::Text text("Your ship is destroyed!", font, 24); text.setFillColor(sf::Color::Red); text.setPosition(50, 80); // zatrzymanie muzyki i odtworzenie dźwięku przegranej audioManager.playSoundEffect("fail", 70.f); audioManager.stopBackgroundMusic(); sf::Event event{}; while (errorWindow.isOpen()) { while (errorWindow.pollEvent(event)) { if (event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) { errorWindow.close(); window->close(); exit(-2); } } errorWindow.clear(); errorWindow.draw(text); errorWindow.display(); } } } if (!ship.isAlive()) { std::cout << "Game Over! Player is dead." << std::endl; std::cout << "You lost the game!\n"; sf::RenderWindow errorWindow(sf::VideoMode(350, 200), "The end"); sf::Font font; if (!font.loadFromFile("../assets/fonts/arial.ttf")) { std::cerr << "Error loading font\n"; exit(-500); } sf::Text text("Your ship is destroyed!", font, 24); text.setFillColor(sf::Color::Red); text.setPosition(50, 80); // zatrzymanie muzyki i odtworzenie dźwięku przegranej audioManager.playSoundEffect("fail", 70.f); audioManager.stopBackgroundMusic(); sf::Event event{}; while (errorWindow.isOpen()) { while (errorWindow.pollEvent(event)) { if (event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) { errorWindow.close(); window->close(); exit(-2); } } errorWindow.clear(); errorWindow.draw(text); errorWindow.display(); } } for (auto meteorIt = getMeteors().begin(); meteorIt != getMeteors().end(); ) { bool meteorHit = false; for (auto rocketIt = ship.getBullets().begin(); rocketIt != ship.getBullets().end(); ) { if (meteorIt->getSprite().getGlobalBounds().intersects(rocketIt->getSprite().getGlobalBounds())) { ship.getBullets().erase(rocketIt); meteorIt = getMeteors().erase(meteorIt); meteorHit = true; break; } else { ++rocketIt; } } if (!meteorHit) { ++meteorIt; } } for (auto meteorIt = getMeteors().begin(); meteorIt != getMeteors().end(); ) { bool meteorHit = false; for (auto rocketIt = ship.getRockets().begin(); rocketIt != ship.getRockets().end(); ) { if (meteorIt->getSprite().getGlobalBounds().intersects(rocketIt->getSprite().getGlobalBounds())) { ship.getRockets().erase(rocketIt); meteorIt = getMeteors().erase(meteorIt); meteorHit = true; break; } else { ++rocketIt; } } if (!meteorHit) { ++meteorIt; } } // Ruch i render przeciwnika for (auto it = enemies.begin(); it != enemies.end();) { it->update(); // Aktualizacja kierunku i ruchu it->shoot(); window->draw(it->getSprite()); // Usunięcie martwych przeciwników if (!it->isAlive()) { std::cout << "Basic Enemy has been eliminated." << std::endl; it = enemies.erase(it); } else { ++it; } } for (auto it = AEnemies.begin(); it != AEnemies.end();) { it->update(); // Ruch zaawansowanego przeciwnika it->shoot(); // Strzał przeciwnika window->draw(it->getSprite()); // Rysowanie na ekranie if (!it->isAlive()) { std::cout << "Advanced Enemy has been eliminated." << std::endl; it = AEnemies.erase(it); // Usunięcie martwych przeciwników } else { ++it; } } for (auto it = BEnemies.begin(); it != BEnemies.end();) { it->update(); // Ruch bombera 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; } } for (auto it = KEnemies.begin(); it != KEnemies.end();) { sf::Vector2f playerPosition = ship.getSprite().getPosition(); // Aktualna pozycja gracza bool playerHit = false; it->update(playerPosition); // Wybuch, gdy Kamikadze dotknie gracza if (ship.getSprite().getGlobalBounds().intersects(it->getSprite().getGlobalBounds())) { it->explode(playerPosition, playerHit); if (playerHit) { ship.takeDamage(); // Gracz otrzymuje obrażenia std::cout << "Gracz został trafiony przez eksplozję Kamikadze!" << std::endl; } } // Kamikadze eksploduje po aktywacji niezależnie od obecności gracza if (it->isExploding()) { it->explode(playerPosition, playerHit); // Eksplozja trwa } // Usunięcie martwego Kamikadze if (it->isAlive()) { window->draw(it->getSprite()); ++it; } else { std::cout << "Kamikadze 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();) { if (ship.getSprite().getGlobalBounds().intersects(it->getSprite().getGlobalBounds())) { ship.takeDamage(); // Zadanie obrażeń graczowi it = aEnemy.getBullets().erase(it); // Usuwanie pocisku po trafieniu } else { ++it; } } } // 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 { ++it; } } } for (auto& enemy : enemies) { enemy.shoot(); enemy.updateBullets(); for (auto& bullet : enemy.getBullets()) { bullet.update(); window->draw(bullet.getSprite()); } } for (auto& advancedEnemy : AEnemies) { advancedEnemy.updateBullets(); // Obsługuje pociski zaawansowanych przeciwników for (auto& bullet : advancedEnemy.getBullets()) { bullet.update(); window->draw(bullet.getSprite()); } } 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())) { // Kolizja wykryta std::cout << "Player hit by enemy bullet!\n"; ship.takeDamage(); // Usuwanie pocisku it = enemy.getBullets().erase(it); } else { ++it; // Brak kolizji, przechodzimy do kolejnego pocisku } } } 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; } } } } 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); } // 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()) { bulletIt = enemyIt->getBullets().erase(bulletIt); // Usuwamy pocisk, który wyszedł poza ekran } else { ++bulletIt; } } ++enemyIt; } // Kolizje między pociskami gracza a przeciwnikami for (auto enemyIt = enemies.begin(); enemyIt != enemies.end();) { bool hit = false; for (auto bulletIt = ship.getBullets().begin(); bulletIt != ship.getBullets().end();) { if (enemyIt->getSprite().getGlobalBounds().intersects(bulletIt->getSprite().getGlobalBounds())) { bulletIt = ship.getBullets().erase(bulletIt); enemyIt->takeDamage(); hit = true; break; } else { ++bulletIt; } } if (hit && !enemyIt->isAlive()) { enemyIt = enemies.erase(enemyIt); } else { ++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 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; } } for (auto wiazkowiecIt = WEnemies.begin(); wiazkowiecIt != WEnemies.end();) { bool hit = false; for (auto bulletIt = ship.getBullets().begin(); bulletIt != ship.getBullets().end();) { if (wiazkowiecIt->getSprite().getGlobalBounds().intersects(bulletIt->getSprite().getGlobalBounds())) { bulletIt = ship.getBullets().erase(bulletIt); wiazkowiecIt->takeDamage(); hit = true; break; } else { ++bulletIt; } } if (hit && !wiazkowiecIt->isAlive()) { wiazkowiecIt = WEnemies.erase(wiazkowiecIt); // Usunięcie przeciwnika Wiazkowiec } else { ++wiazkowiecIt; } } //oblsuga dla rakiety for (auto enemyIt = enemies.begin(); enemyIt != enemies.end();) { bool hit = false; for (auto rocketIt = ship.getRockets().begin(); rocketIt != ship.getRockets().end();) { if (enemyIt->getSprite().getGlobalBounds().intersects(rocketIt->getSprite().getGlobalBounds())) { rocketIt = ship.getRockets().erase(rocketIt); enemyIt->takeDamage(); hit = true; break; } else { ++rocketIt; } } if (hit && !enemyIt->isAlive()) { enemyIt = enemies.erase(enemyIt); } else { ++enemyIt; } } for (auto advancedIt = AEnemies.begin(); advancedIt != AEnemies.end();) { bool hit = false; for (auto rocketIt = ship.getRockets().begin(); rocketIt != ship.getRockets().end();) { if (advancedIt->getSprite().getGlobalBounds().intersects(rocketIt->getSprite().getGlobalBounds())) { rocketIt = ship.getRockets().erase(rocketIt); advancedIt->takeDamage(); hit = true; break; } else { ++rocketIt; } } if (hit && !advancedIt->isAlive()) { advancedIt = AEnemies.erase(advancedIt); } else { ++advancedIt; } } 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; } } 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; } } for (auto wiazkowiecIt = WEnemies.begin(); wiazkowiecIt != WEnemies.end();) { bool hit = false; for (auto rocketIt = ship.getRockets().begin(); rocketIt != ship.getRockets().end();) { if (wiazkowiecIt->getSprite().getGlobalBounds().intersects(rocketIt->getSprite().getGlobalBounds())) { rocketIt = ship.getRockets().erase(rocketIt); wiazkowiecIt->takeDamage(); hit = true; break; } else { ++rocketIt; } } if (hit && !wiazkowiecIt->isAlive()) { wiazkowiecIt = WEnemies.erase(wiazkowiecIt); } else { ++wiazkowiecIt; } } } // Meteor-related niżej void Plansza::spawn_meteor() { if (spawnClock.getElapsedTime().asSeconds() > rand() % 10 + 1) { // randomowy spawn meteorytów od 10 do 1 sekundy if (meteors.size() < 5) { // jeśli jest mniej niż 5 meteorów na planszy if(rand() % 2 == 1) { meteors.emplace_back(RandomNumberGenerator::getRandomNumber(50,499), -100, meteorTexture2); } else { meteors.emplace_back(RandomNumberGenerator::getRandomNumber(50,499), -100, meteorTexture1); } } spawnClock.restart(); } } void Plansza::update_meteors() { // usuwanie meteorów które wyleciały poza ekran for (auto& meteor : meteors) { if(meteor.getStatus()) { meteors.erase(meteors.begin()); } } } 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(); } } void Plansza::spawn_advanced_enemy() { if (AenemySpawnClock.getElapsedTime().asSeconds() >= 80) { // Spawn co 10 sekund int spawnX = RandomNumberGenerator::getRandomNumber(50, size.width - 50); 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() >= 10) { // Spawn co 10 sekund int spawnX = RandomNumberGenerator::getRandomNumber(50, size.width - 50); Bomber bomber(spawnX, -50, BomberEnemyTexture, BombaTexture); bomber.setPlanszaHeight(size.height, size.width); // Przekazanie wysokości i szerokości okna BEnemies.push_back(bomber); std::cout << "Spawned Bomber Enemy at X: " << spawnX << std::endl; BomberSpawnClock.restart(); } } void Plansza::spawn_kamikadze() { 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; KamikadzeSpawnClock.restart(); } } void Plansza::spawn_wiazkowiec() { if (WiazkowiecSpawnClock.getElapsedTime().asSeconds() >= 110) { // Spawn co 10 sekund int spawnX = RandomNumberGenerator::getRandomNumber(50, size.width - 50); Wiazkowiec wiazkowiec(spawnX, -50, WiazkowiecTexture); wiazkowiec.setPlanszaHeight(size.height, size.width); // Przekazanie wysokości i szerokosci okna WEnemies.push_back(wiazkowiec); std::cout << "Spawned Wiazkowiec Enemy at X: " << spawnX << std::endl; WiazkowiecSpawnClock.restart(); } } Size Plansza::getSize() { return size; } std::vector &Plansza::getMeteors() { return meteors; }