Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: First SFML project  (Read 878 times)

0 Members and 1 Guest are viewing this topic.

ledmer

  • Newbie
  • *
  • Posts: 1
    • View Profile
    • Email
First SFML project
« on: January 30, 2024, 05:16:35 pm »
This is my first project could you guys help me to optimize the code? thx ;D
#include <SFML/Graphics.hpp>
#include <vector>
#include <memory>
#include <cstdlib>
#include <ctime>
#include <cmath>

class Weapon {
public:
    float bulletSpeed;
    Weapon(float speed) : bulletSpeed(speed) {}
};

class Bullet {
public:
    sf::RectangleShape shape;
    sf::Vector2f velocity;
    const Weapon& weapon;

    Bullet(float x, float y, const Weapon& w) : weapon(w) {
        shape.setSize(sf::Vector2f(10, 10));
        shape.setPosition(x, y);
        shape.setFillColor(sf::Color::Yellow);
        velocity = sf::Vector2f(0.0f, 0.0f);
    }

    void update() {
        shape.move(velocity);
    }

    void setDirection(sf::Vector2f direction) {
        velocity = direction * weapon.bulletSpeed;
    }
};

class Player {
public:
    sf::RectangleShape shape;
    sf::Vector2f velocity;
    std::vector<std::unique_ptr<Bullet>> bullets;
    sf::Clock shootTimer;

    std::vector<Weapon> weapons;
    int currentWeaponIndex;

    Player(float x, float y) : currentWeaponIndex(0) {
        shape.setSize(sf::Vector2f(50, 50));
        shape.setPosition(x, y);
        shape.setFillColor(sf::Color::Green);

        weapons.push_back(Weapon(5.0f * 1.5f));  // Weapon 1 with 1.5 times speed
    }

    void update() {
        shape.move(velocity * 3.0f);

        sf::Vector2f newPosition = shape.getPosition();
        const float sizeX = shape.getSize().x;
        const float sizeY = shape.getSize().y;

        if (newPosition.x < 0) newPosition.x = 0;
        if (newPosition.x > 800 - sizeX) newPosition.x = 800 - sizeX;
        if (newPosition.y < 0) newPosition.y = 0;
        if (newPosition.y > 600 - sizeY) newPosition.y = 600 - sizeY;

        shape.setPosition(newPosition);

        for (auto& bullet : bullets) {
            bullet->update();
        }
    }

    void shoot(sf::Keyboard::Key directionKey) {
        if (shootTimer.getElapsedTime().asSeconds() >= 1.0) {
            sf::Vector2f direction(0.0f, 0.0f);

            switch (directionKey) {
                case sf::Keyboard::W: direction.y = -1.0f; break;
                case sf::Keyboard::S: direction.y = 1.0f; break;
                case sf::Keyboard::A: direction.x = -1.0f; break;
                case sf::Keyboard::D: direction.x = 1.0f; break;
            }

            if (currentWeaponIndex == 0) {
                float spreadAngleBase = ((std::rand() % 5) - 2) * 5.0f;
                sf::Vector2f baseDirection = rotateVector(direction, spreadAngleBase);

                for (int i = 0; i < 3; ++i) {
                    float spreadAngle = spreadAngleBase + i * 10.0f; // Adjust spread
                    sf::Vector2f spreadDirection = rotateVector(baseDirection, spreadAngle);

                    bullets.push_back(std::make_unique<Bullet>(
                        shape.getPosition().x + shape.getSize().x / 2,
                        shape.getPosition().y + shape.getSize().y / 2,
                        weapons[currentWeaponIndex]
                    ));
                    bullets.back()->setDirection(spreadDirection);
                }
            } else {
                bullets.push_back(std::make_unique<Bullet>(
                    shape.getPosition().x + shape.getSize().x / 2,
                    shape.getPosition().y + shape.getSize().y / 2,
                    weapons[currentWeaponIndex]
                ));
                bullets.back()->setDirection(direction);
            }

            shootTimer.restart();
        }
    }

private:
    sf::Vector2f rotateVector(const sf::Vector2f& vector, float degrees) {
        float radians = degrees * (3.14159265f / 180.0f);
        float cosine = std::cos(radians);
        float sine = std::sin(radians);
        return sf::Vector2f(vector.x * cosine - vector.y * sine, vector.x * sine + vector.y * cosine);
    }
};

class Enemy {
public:
    sf::RectangleShape shape;
    float speed;

    Enemy(float x, float y, float spd) : speed(spd * 3.0f) {  // Enemy speed multiplied by 1.5
        shape.setSize(sf::Vector2f(50, 50));
        shape.setPosition(x, y);
        shape.setFillColor(sf::Color::Red);
    }

    void update(const sf::Vector2f& playerPos) {
        sf::Vector2f direction = playerPos - shape.getPosition();
        direction /= std::sqrt(direction.x * direction.x + direction.y * direction.y);
        shape.move(direction * speed);
    }

    bool checkCollision(const Player& player, sf::FloatRect Bounds) {
        return shape.getGlobalBounds().intersects(Bounds);
    }
};

class Game {
public:
    sf::RenderWindow window;
    Player player;
    std::vector<Enemy> enemies;
    bool gameRunning;
    bool startScreen;
    sf::Clock enemySpawnTimer;
    sf::Font font;
    Game() : window(sf::VideoMode(800, 600), "SFML Game"), player(100, 100),
             gameRunning(false), startScreen(true) {
        std::srand(std::time(0));
   
        if (font.loadFromFile("universal-serif.ttf")) {

        }
    }
    void run() {
        while (window.isOpen()) {
            handleEvents();
            update();
            window.clear();
            draw();
            window.display();
        }
    }

private:
    sf::Clock movementClock;  
    float movementCooldown = 1.0f;
    int botsKilled = 0;
    int actualbotskilled = 0;
    void handleEvents() {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
            if (event.type == sf::Event::KeyPressed) {
                if (startScreen) {
                    if (event.key.code == sf::Keyboard::Num1) {
                        player.currentWeaponIndex = 0;
                        startScreen = false;
                        gameRunning = true;
                    }
                } else if (!gameRunning) {
                    handleKeyInNonRunningState(event.key.code);
                } else if (gameRunning) {
                    handleKeyInRunningState(event.key.code);
                }
            }
        }

        if (gameRunning) {
            handleRunningStateKeys();
            player.update();

            if (enemySpawnTimer.getElapsedTime().asSeconds() >= 2.0) {
                spawnEnemy();
                enemySpawnTimer.restart();
            }

            if (movementClock.getElapsedTime().asSeconds() >= movementCooldown) {
                sf::Vector2 player_position = player.shape.getPosition();
                for (auto& enemy : enemies) {
                    enemy.update(player_position);
                    if (enemy.checkCollision(player, player.shape.getGlobalBounds())) {
                        gameRunning = false;
                    }
                }

                movementClock.restart();  // Restart the clock after enemy movement
            }

            handleBulletEnemyCollision();

            // Remove off-screen bullets
            player.bullets.erase(
                std::remove_if(player.bullets.begin(), player.bullets.end(), [](const auto& bullet) {
                    const auto& pos = bullet->shape.getPosition();
                    return pos.x < 0 || pos.x > 800 || pos.y < 0 || pos.y > 600;
                }),
                player.bullets.end()
            );
        }
    }

    void handleKeyInNonRunningState(sf::Keyboard::Key keyCode) {
        if (keyCode == sf::Keyboard::Escape) {
            window.close();
        } else if (keyCode == sf::Keyboard::Enter) {
            startScreen = true;
            gameRunning = false;
            player = Player(100, 100);
            enemies.clear();
            enemySpawnTimer.restart();
        }
    }

    void handleKeyInRunningState(sf::Keyboard::Key keyCode) {
        switch (keyCode) {
            case sf::Keyboard::W:
            case sf::Keyboard::S:
            case sf::Keyboard::A:
            case sf::Keyboard::D:
                player.shoot(keyCode);
                break;
            default:
                break;
        }
    }

    void handleRunningStateKeys() {
            if (movementClock.getElapsedTime().asSeconds() >= movementCooldown) {
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::H)) {
                    player.velocity.x = -2.0f;
                } else if (sf::Keyboard::isKeyPressed(sf::Keyboard::L)) {
                    player.velocity.x = 2.0f;
                } else {
                    player.velocity.x = 0.0f;
                }

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::K)) {
                    player.velocity.y = -2.0f;
                } else if (sf::Keyboard::isKeyPressed(sf::Keyboard::J)) {
                    player.velocity.y = 2.0f;
                } else {
                    player.velocity.y = 0.0f;
                }

                movementClock.restart();  // Restart the clock after movement
            }
        }
    void handleBulletEnemyCollision() {
        for (auto& bullet : player.bullets) {
            for (auto it = enemies.begin(); it != enemies.end();) {
                if (bullet->shape.getGlobalBounds().intersects(it->shape.getGlobalBounds())) {
                    it = enemies.erase(it);
                    botsKilled++;
                } else {
                    ++it;
                }
            }
        }
    }

    void update() {
        // Additional game-specific updates can be added here
    }

    void draw() {
        if (startScreen) {
            sf::Text text("Press 1 to start", font, 30);
            text.setFillColor(sf::Color::Green);
            text.setPosition(250, 300);
            window.draw(text);
        } else if (gameRunning) {
            window.draw(player.shape);
            for (const auto& enemy : enemies) {
                window.draw(enemy.shape);
            }
            for (const auto& bullet : player.bullets) {
                window.draw(bullet->shape);
            }
            if (!(actualbotskilled == botsKilled)){
                sf::Text text("Bots Killed: " + std::to_string(botsKilled), font, 20);
                text.setFillColor(sf::Color::White);
                text.setPosition(window.getSize().x - text.getLocalBounds().width - 10, 10);
                window.draw(text);
                actualbotskilled = botsKilled;  
            }
           
        } else if (!gameRunning) {
            sf::Text text("You lost press esc to exit", font, 30);
            sf::Text text2("Press enter to try again", font, 30);
            text2.setFillColor(sf::Color::Green);
            text2.setPosition(160, 300);
            text.setFillColor(sf::Color::Green);
            text.setPosition(150, 250);
            window.draw(text);  
            window.draw(text2);
        }
    }

    void spawnEnemy() {
        constexpr int maxAttempts = 10;
        int pos_x = player.shape.getPosition().x;
        int pos_y = player.shape.getPosition().y;
        for (int attempt = 0; attempt < maxAttempts; ++attempt) {
            float x = static_cast<float>(std::rand() % 800);
            float y = static_cast<float>(std::rand() % 600);

            if (std::abs(x - pos_x) >= 120 && y >= pos_y + 120) {
                enemies.push_back(Enemy(x, y, 10.0f));
                return;
            }
        }

        float x = static_cast<float>(std::rand() % 800);
        float y = static_cast<float>(std::rand() % 600);
        enemies.push_back(Enemy(x, y, 1.0f));
    }
};

int main() {
    Game game;
    game.run();
    return 0;
}
« Last Edit: January 30, 2024, 11:05:25 pm by eXpl0it3r »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11033
    • View Profile
    • development blog
    • Email
Re: First SFML project
« Reply #1 on: January 30, 2024, 11:35:08 pm »
Congrats on getting the first project done! :)

Can you a bit more specific, what exactly you're looking for with "optimize the code"?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

 

anything