1
General / 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
#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;
}
#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;
}