diff --git a/enemy.cpp b/enemy.cpp new file mode 100644 index 0000000..3057e53 --- /dev/null +++ b/enemy.cpp @@ -0,0 +1,58 @@ +#include "enemy.hpp" + +Enemy::Enemy(float x, float y, float leftB, float rightB) + : shape(sf::Vector2f(40.f, 50.f)), + leftBound(leftB), + rightBound(rightB), + speed(200.f), + movingRight(true), + aggro(false), + platformY(y) +{ + shape.setPosition(x, y); + shape.setFillColor(sf::Color::Red); // просто колір, без текстури +} + +void Enemy::update(float dt, const sf::Vector2f& playerPos) { + float x = shape.getPosition().x; + + if (aggro) { + if (playerPos.x < x) + x -= speed * dt; + else + x += speed * dt; + } else { + if (movingRight) { + x += speed * dt; + if (x + shape.getSize().x >= rightBound) movingRight = false; + } else { + x -= speed * dt; + if (x <= leftBound) movingRight = true; + } + } + + if (x < leftBound) x = leftBound; + if (x + shape.getSize().x > rightBound) x = rightBound - shape.getSize().x; + + shape.setPosition(x, platformY); +} + +void Enemy::draw(sf::RenderWindow& window) { + window.draw(shape); +} + +void Enemy::setAggro(bool value) { + aggro = value; +} + +float Enemy::getPlatformY() const { + return platformY; +} + +sf::FloatRect Enemy::getBounds() const { + return shape.getGlobalBounds(); +} + +sf::RectangleShape& Enemy::getShape() { + return shape; +} diff --git a/enemy.hpp b/enemy.hpp new file mode 100644 index 0000000..42276d9 --- /dev/null +++ b/enemy.hpp @@ -0,0 +1,25 @@ +#pragma once +#include + +class Enemy { +private: + sf::RectangleShape shape; + + float leftBound; + float rightBound; + float speed; + bool movingRight; + bool aggro; + float platformY; + +public: + Enemy(float x, float y, float leftB, float rightB); + + void update(float dt, const sf::Vector2f& playerPos); + void draw(sf::RenderWindow& window); + + void setAggro(bool value); + float getPlatformY() const; + sf::FloatRect getBounds() const; + sf::RectangleShape& getShape(); +}; diff --git a/game.cpp b/game.cpp index a9a3d5d..f3b3d6c 100644 --- a/game.cpp +++ b/game.cpp @@ -1,23 +1,52 @@ #include #include "vokzal.hpp" +#include "enemy.hpp" +#include +#include + using namespace std; int main() { - // Створюємо вікно 1950x1200 - sf::RenderWindow window(sf::VideoMode(1950, 1200), "Test Game Window"); -// + // Завантаження фону + sf::Texture backgroundTexture; + if (!backgroundTexture.loadFromFile("img/background.png")) { + cout << "ERROR: Cannot load background.png\n"; + } + sf::Sprite backgroundSprite; + backgroundSprite.setTexture(backgroundTexture); + float scaleX = 1950.f / backgroundTexture.getSize().x; + float scaleY = 1200.f / backgroundTexture.getSize().y; + backgroundSprite.setScale(scaleX, scaleY); + + sf::RenderWindow window(sf::VideoMode(1950, 1200), "2D Platformer"); + window.setFramerateLimit(65); + + // Платформи vector platforms; platforms.push_back(Platform(299.f, 900.f, 200.f, 40.f)); platforms.push_back(Platform(700.f, 725.f, 200.f, 40.f)); platforms.push_back(Platform(1300.f, 700.f, 300.f, 50.f)); platforms.push_back(Platform(400.f, 600.f, 250.f, 30.f)); - + platforms.push_back(Platform(700.f, 900.f, 400.f, 30.f)); Platform ground(100.f, 1050.f, 300.f, 50.f); - window.setFramerateLimit(90); //вище 200 не рокимендую піднімати частоту після 600 буде чути писк дроселів - + // Гравець Player player; + // Вороги + vector enemies; + for (auto& platform : platforms) { + float left = platform.getBounds().left; + float top = platform.getBounds().top; + float width = platform.getBounds().width; + enemies.push_back(Enemy(left + 10.f, top - 50.f, left, left + width)); + } + + // Кулі + vector bullets; + sf::Clock fireClock; + float fireCooldown = 0.3f; + sf::Clock gameClock; while (window.isOpen()) { @@ -29,22 +58,102 @@ int main() { float deltaTime = gameClock.restart().asSeconds(); - player.update(deltaTime, platforms); // логіка гравця + // Рух гравця + player.update(deltaTime, platforms); - window.clear(sf::Color::Black); // очистка вікна - - // малюємо платформи - for (auto& platform : platforms) { - platform.draw(window); + // Створення кулі при натиску пробілу + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) && + fireClock.getElapsedTime().asSeconds() >= fireCooldown) + { + fireClock.restart(); + sf::Vector2f playerPos( + player.getShape().getPosition().x + player.getShape().getSize().x / 2, + player.getShape().getPosition().y + player.getShape().getSize().y / 2 + ); + bullets.push_back(Bullet(playerPos, player.isFacingRight())); } + + // Оновлення і видалення куль + for (auto it = bullets.begin(); it != bullets.end(); ) { + it->update(deltaTime); + if (it->isOffScreen() || it->collidesWithPlatform(platforms)) { + it = bullets.erase(it); + } else ++it; + } + + // Оновлення ворогів (агро на гравця) + sf::Vector2f playerPosVec(player.getShape().getPosition().x, player.getShape().getPosition().y); + for (auto& enemy : enemies) { + float playerBottom = player.getShape().getPosition().y + player.getShape().getSize().y; + float platformY = enemy.getPlatformY(); + float tolerance = 10.f; + + // якщо гравець на тій же платформі + if (playerBottom >= platformY - tolerance && playerBottom <= platformY + tolerance) { + enemy.setAggro(true); + } else { + enemy.setAggro(false); + } + + enemy.update(deltaTime, playerPosVec); + } + + // Колізія куль з ворогами + for (auto it = bullets.begin(); it != bullets.end(); ) { + bool bulletRemoved = false; + for (auto enemyIt = enemies.begin(); enemyIt != enemies.end(); ++enemyIt) { + if (it->getBounds().intersects(enemyIt->getBounds())) { + it = bullets.erase(it); + enemies.erase(enemyIt); + bulletRemoved = true; + break; + } + } + if (!bulletRemoved) ++it; + } + + // Кінець гри, якщо всі вороги вбиті + if (enemies.empty()) { + cout << "Вітаємо! Ви перемогли всіх ворогів!\n"; + window.close(); + } + + // Колізія ворогів з гравцем + bool playerHit = false; + for (auto& enemy : enemies) { + if (enemy.getBounds().intersects(sf::FloatRect(player.getShape().getPosition(), player.getShape().getSize()))) { + playerHit = true; + break; + } + } + + // Ресет гри + if (playerHit) { + player.setPosition(sf::Vector2f(50.f, 1040.f)); + player.setVelocityY(0.f); + player.setOnGround(true); + + enemies.clear(); + for (auto& platform : platforms) { + float left = platform.getBounds().left; + float top = platform.getBounds().top; + float width = platform.getBounds().width; + enemies.push_back(Enemy(left + 10.f, top - 50.f, left, left + width)); + } + + bullets.clear(); + } + + // Відмалювання + window.clear(sf::Color::Black); + window.draw(backgroundSprite); + for (auto& platform : platforms) platform.draw(window); ground.draw(window); - - // малюємо гравця player.draw(window); - - window.display(); // відображення + for (auto& enemy : enemies) enemy.draw(window); + for (auto& bullet : bullets) bullet.draw(window); + window.display(); } return 0; } - diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..41730ef --- /dev/null +++ b/main.cpp @@ -0,0 +1,37 @@ +#include + +int main() +{ + // Create the main window + sf::RenderWindow app(sf::VideoMode(800, 600), "SFML window"); + + // Load a sprite to display + sf::Texture texture; + if (!texture.loadFromFile("cb.bmp")) + return EXIT_FAILURE; + sf::Sprite sprite(texture); + + // Start the game loop + while (app.isOpen()) + { + // Process events + sf::Event event; + while (app.pollEvent(event)) + { + // Close window : exit + if (event.type == sf::Event::Closed) + app.close(); + } + + // Clear screen + app.clear(); + + // Draw the sprite + app.draw(sprite); + + // Update the window + app.display(); + } + + return EXIT_SUCCESS; +}