diff --git a/enemy.cpp b/enemy.cpp deleted file mode 100644 index 3057e53..0000000 --- a/enemy.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#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 deleted file mode 100644 index 42276d9..0000000 --- a/enemy.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#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 f3b3d6c..a9a3d5d 100644 --- a/game.cpp +++ b/game.cpp @@ -1,52 +1,23 @@ #include #include "vokzal.hpp" -#include "enemy.hpp" -#include -#include - using namespace std; int main() { - // Завантаження фону - 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); - - // Платформи + // Створюємо вікно 1950x1200 + sf::RenderWindow window(sf::VideoMode(1950, 1200), "Test Game Window"); +// 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()) { @@ -58,102 +29,22 @@ int main() { float deltaTime = gameClock.restart().asSeconds(); - // Рух гравця - player.update(deltaTime, platforms); + player.update(deltaTime, platforms); // логіка гравця - // Створення кулі при натиску пробілу - 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())); + window.clear(sf::Color::Black); // очистка вікна + + // малюємо платформи + for (auto& platform : platforms) { + platform.draw(window); } - - // Оновлення і видалення куль - 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); - for (auto& enemy : enemies) enemy.draw(window); - for (auto& bullet : bullets) bullet.draw(window); - window.display(); + + window.display(); // відображення } return 0; } + diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 41730ef..0000000 --- a/main.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#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; -} diff --git a/player.cpp b/player.cpp index 4f2392f..300a984 100644 --- a/player.cpp +++ b/player.cpp @@ -1,140 +1,99 @@ -#include "player.hpp" -#include +#include "player.hpp" // Включаємо заголовок класу Player, щоб компілятор знав про його методи та змінні. using namespace std; +// Конструктор класу Player. Він автоматично викликається при створенні об'єкта Player. Player::Player() - : shape(sf::Vector2f(60.f, 60.f)), - speed(500.f), + : shape(sf::Vector2f(50.f, 50.f)), // тут лише "чисте" створення + speed(500.f), //швидкість velocityY(0.f), - jumpStrength(700.f), + jumpStrength(700.f), // пиржок onGround(true), gravity(1500.f), - groundLevel(1040.f), - facingRight(true), - runFrames(), - idleFrame(), - sprite(), - currentFrame(0), - animationTimer(0.f), - animationSpeed(0.1f), - isMoving(false) + groundLevel(1040.f) { + // А тут уже викликаємо методи, які налаштовують shape shape.setFillColor(sf::Color::Green); - shape.setPosition(50.f, groundLevel); - - loadIdleFrame(); - loadRunAnimation(); - - sprite.setTexture(idleFrame); - sprite.setOrigin(idleFrame.getSize().x / 2.f, idleFrame.getSize().y / 2.f); - - float scaleX = shape.getSize().x / idleFrame.getSize().x; - float scaleY = shape.getSize().y / idleFrame.getSize().y; - - // Початкове віддзеркалення: PNG дивиться вліво, потрібно вправо - sprite.setScale(-scaleX, scaleY); - - sprite.setPosition( - shape.getPosition().x + shape.getSize().x / 2.f, - shape.getPosition().y + shape.getSize().y / 2.f - ); + shape.setPosition(50.f, 1040.f); } -void Player::loadIdleFrame() { - if (!idleFrame.loadFromFile("img/FA_PENGUIN_Idle_000.png")) { - cout << "Cannot load idle frame\n"; - } -} -void Player::loadRunAnimation() { - runFrames.clear(); - for (size_t i = 0; i < 10; ++i) { // припустимо 10 кадрів - sf::Texture tex; - string filename = "img/04-Run/FA_PENGUIN_Run_00" + to_string(i) + ".png"; - if (!tex.loadFromFile(filename)) { - cout << "Cannot load " << filename << "\n"; - } else { - runFrames.push_back(tex); - } - } -} -void Player::update(float deltaTime, const std::vector& platforms) { - float moveX = 0.f; - isMoving = false; +// Закоментований метод `update` (робота на потім). +// Він призначений для оновлення логіки гравця у кожному кадрі гри. +// Усередині цього методу, ви будете обробляти рух, зіткнення, анімацію тощо. +// `deltaTime` — це час, що минув з попереднього кадру, і він забезпечує плавний рух незалежно від швидкості комп'ютера. +void Player::update(float deltaTime, const std::vector& platforms) { // Тут буде логіка руху гравця + float moveX = 0.f; - if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) { - moveX -= speed * deltaTime; - facingRight = false; - isMoving = true; - } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) { - moveX += speed * deltaTime; - facingRight = true; - isMoving = true; - } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) && onGround) + + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)){ + moveX -= speed * deltaTime;} //рух вліво + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)){ + moveX += speed * deltaTime;} //рух вправо + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) && onGround==true) { velocityY = -jumpStrength; + } + velocityY += gravity * deltaTime; - velocityY += gravity * deltaTime; - shape.move(moveX, 0.f); - shape.move(0.f, velocityY * deltaTime); + shape.move(moveX, 0.f); + shape.move(0.f , velocityY * deltaTime); - // Земля - if (shape.getPosition().y + shape.getSize().y >= groundLevel) { - shape.setPosition(shape.getPosition().x, groundLevel - shape.getSize().y); + //перевірка чи є земля та обмеження щоб фігура не вилитіла + + if(shape.getPosition().y + shape.getSize().y >= groundLevel){ + shape.setPosition(shape.getPosition().x, groundLevel -shape.getSize().y); + velocityY = 0; + onGround = true; + }else{ + onGround = false; + } + ///////////////////////////////////////////////////// + + sf::FloatRect playerBounds = shape.getGlobalBounds(); + + for (const auto& platform : platforms) { + sf::FloatRect platformBounds = platform.getBounds(); + if (playerBounds.intersects(platformBounds)){ + if (playerBounds.intersects(platformBounds)) { + // Додатковий if — перевіряємо, чи гравець зверху + if (playerBounds.top + playerBounds.height <= platformBounds.top + 20.f) { + shape.setPosition(shape.getPosition().x, platformBounds.top - shape.getSize().y); velocityY = 0.f; onGround = true; - } else onGround = false; - - // Колізії з платформами - for (const auto& platform : platforms) { - sf::FloatRect playerBounds = shape.getGlobalBounds(); - sf::FloatRect platBounds = platform.getBounds(); - if (playerBounds.intersects(platBounds)) { - if (playerBounds.top + playerBounds.height <= platBounds.top + 20.f) { - shape.setPosition(shape.getPosition().x, platBounds.top - shape.getSize().y); - velocityY = 0.f; - onGround = true; - } else if (playerBounds.top > platBounds.top) { - shape.setPosition(shape.getPosition().x, platBounds.top + platBounds.height); - velocityY = 0.f; + }else if(playerBounds.top> platformBounds.top){shape.setPosition(shape.getPosition().x, platformBounds.top +platformBounds.height); + velocityY =0.f;} + } + } } + + + + + + ///////////////////////////////////////////////////// + + if(shape.getPosition().x < 0.f) + shape.setPosition(0.f, shape.getPosition().y); + + if(shape.getPosition().x+shape.getSize().x>1925.f) + shape.setPosition(1925.f - shape.getSize().x ,shape.getPosition().y); + + + if(shape.getPosition().y < 0.f) + shape.setPosition(shape.getPosition().x,0.f); + + if(shape.getPosition().y+shape.getSize().y>1200.f) + shape.setPosition(shape.getPosition().x, 1200.f - shape.getSize().y); } - } - // Межі екрану - if (shape.getPosition().x < 0.f) shape.setPosition(0.f, shape.getPosition().y); - if (shape.getPosition().x + shape.getSize().x > 1925.f) - shape.setPosition(1925.f - shape.getSize().x, shape.getPosition().y); - // Анімація - animationTimer += deltaTime; - if (isMoving && !runFrames.empty()) { - if (animationTimer >= animationSpeed) { - animationTimer = 0.f; - currentFrame = (currentFrame + 1) % runFrames.size(); - sprite.setTexture(runFrames[currentFrame]); - } - } else { - sprite.setTexture(idleFrame); - } - - // Центруємо спрайт по хітбоксу - sprite.setOrigin(sprite.getTexture()->getSize().x / 2.f, - sprite.getTexture()->getSize().y / 2.f); - - sprite.setPosition(shape.getPosition().x + shape.getSize().x / 2.f, - shape.getPosition().y + shape.getSize().y / 2.f); - - float scaleX = shape.getSize().x / sprite.getTexture()->getSize().x; - float scaleY = shape.getSize().y / sprite.getTexture()->getSize().y; - - // Віддзеркалення за напрямком погляду - sprite.setScale(facingRight ? -scaleX : scaleX, scaleY); +// Метод `draw` для відмальовування гравця на екрані. +// Приймає посилання на вікно, щоб знати, де малювати. +void Player::draw(sf::RenderWindow& window) +{ + // Викликаємо метод `draw` вікна, щоб намалювати наш об'єкт `shape`. + window.draw(shape); } - -void Player::draw(sf::RenderWindow& window) { - window.draw(sprite); -} - diff --git a/player.hpp b/player.hpp index 3d1e4cd..49557f5 100644 --- a/player.hpp +++ b/player.hpp @@ -1,45 +1,33 @@ + #pragma once #include #include #include "platform.hpp" + +//float velocityY; +//float gravity; +//float jumpStrength; +//bool isOnGround; + + class Player { - sf::RectangleShape shape; - float speed; - float velocityY; - float jumpStrength; - bool onGround; - float gravity; - float groundLevel; - bool facingRight; - std::vector runFrames; - sf::Texture idleFrame; - sf::Sprite sprite; +private: + sf::RectangleShape shape; // форма гравця + float speed; //швидкість гравця + float velocityY; // швидкість по вертикалі + float jumpStrength; // сила стрибка + bool onGround; //чи стоїть на землі + float gravity; // сила гравітації + float groundLevel; // висота "землі" - size_t currentFrame; - float animationTimer; - float animationSpeed; - bool isMoving; - void loadRunAnimation(); - void loadIdleFrame(); public: - Player(); - + Player(); // порожній конструктор void update(float deltaTime, const std::vector& platforms); + void draw(sf::RenderWindow& window); - // Геттери - sf::RectangleShape& getShape() { return shape; } - float getVelocityY() const { return velocityY; } - bool isOnGround() const { return onGround; } - - // Сеттери - void setPosition(const sf::Vector2f& pos) { shape.setPosition(pos); } - void setVelocityY(float v) { velocityY = v; } - void setOnGround(bool val) { onGround = val; } - - bool isFacingRight() const { return facingRight; } }; diff --git a/vokzal.hpp b/vokzal.hpp index b0bd00d..02bef39 100644 --- a/vokzal.hpp +++ b/vokzal.hpp @@ -5,3 +5,4 @@ #include "platform.hpp" #include "bullet.hpp" +