#include <SFML/Graphics.hpp> #include <SFML/Audio.hpp> #include #include #include #include

// 道具类型枚举 enum class PowerupType { HEALTH, // 生命恢复 DAMAGE, // 子弹伤害提升 SPEED, // 飞船速度提升 RATE, // 射击速率提升 MULTISHOT // 多重射击 };

// 游戏实体基类 class Entity { public: sf::Sprite sprite; float x, y; float dx, dy; int health; bool alive;

Entity(float x, float y, float dx, float dy, int health) 
    : x(x), y(y), dx(dx), dy(dy), health(health), alive(true) {}

virtual void update() {
    x += dx;
    y += dy;
    sprite.setPosition(x, y);
}

virtual void draw(sf::RenderWindow& window) {
    window.draw(sprite);
}

virtual void onCollision(Entity* other) {}

};

// 玩家类 class Player : public Entity { private: sf::Texture texture; sf::Clock shootClock; float shootCooldown; int score; float baseSpeed; float currentSpeed; int bulletDamage; bool multishot; sf::Clock powerupClock; PowerupType activePowerup; bool powerupActive;

public: Player() : Entity(400, 500, 0, 0, 3), shootCooldown(0.3f), score(0), baseSpeed(5.0f), currentSpeed(baseSpeed), bulletDamage(1), multishot(false), powerupActive(false) { if (!texture.loadFromFile("player.png")) { texture.create(50, 50); sf::Image img; img.create(50, 50, sf::Color::Blue); texture.update(img); } sprite.setTexture(texture); sprite.setOrigin(texture.getSize().x / 2, texture.getSize().y / 2); }

void update() override {
    // 处理输入
    dx = 0; dy = 0;
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) dx = -currentSpeed;
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) dx = currentSpeed;
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) dy = -currentSpeed;
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) dy = currentSpeed;

    // 边界检查
    if (x + dx < 0) dx = 0;
    if (x + dx > 800) dx = 0;
    if (y + dy < 0) dy = 0;
    if (y + dy > 600) dy = 0;

    // 检查增益效果是否过期
    if (powerupActive && powerupClock.getElapsedTime().asSeconds() > 10.0f) {
        resetPowerups();
    }

    Entity::update();
}

bool canShoot() {
    return shootClock.getElapsedTime().asSeconds() > shootCooldown;
}

void resetShootClock() {
    shootClock.restart();
}

void addScore(int points) {
    score += points;
}

int getScore() const {
    return score;
}

int getBulletDamage() const {
    return bulletDamage;
}

bool hasMultishot() const {
    return multishot;
}

void applyPowerup(PowerupType type) {
    // 如果已有增益效果,先重置
    if (powerupActive) {
        resetPowerups();
    }

    powerupActive = true;
    activePowerup = type;
    powerupClock.restart();

    switch (type) {
        case PowerupType::HEALTH:
            if (health < 3) health++;
            break;
        case PowerupType::DAMAGE:
            bulletDamage = 2;
            break;
        case PowerupType::SPEED:
            currentSpeed = baseSpeed * 1.5f;
            break;
        case PowerupType::RATE:
            shootCooldown = 0.15f;
            break;
        case PowerupType::MULTISHOT:
            multishot = true;
            break;
    }
}

void resetPowerups() {
    powerupActive = false;
    bulletDamage = 1;
    currentSpeed = baseSpeed;
    shootCooldown = 0.3f;
    multishot = false;
}

bool isPowerupActive() const {
    return powerupActive;
}

PowerupType getActivePowerup() const {
    return activePowerup;
}

};

// 子弹类 class Bullet : public Entity { private: sf::Texture texture; int damage;

public: Bullet(float x, float y, int damage = 1) : Entity(x, y, 0, -8, 1), damage(damage) { if (!texture.loadFromFile("bullet.png")) { texture.create(5, 15); sf::Image img; img.create(5, 15, sf::Color::Yellow); texture.update(img); } sprite.setTexture(texture); sprite.setOrigin(texture.getSize().x / 2, texture.getSize().y / 2); }

void update() override {
    Entity::update();
    if (y < 0) alive = false;
}

int getDamage() const {
    return damage;
}

};

// 敌人类 class Enemy : public Entity { private: sf::Texture texture;

public: Enemy(float x, float y) : Entity(x, y, 0, 2, 1) { if (!texture.loadFromFile("enemy.png")) { texture.create(40, 40); sf::Image img; img.create(40, 40, sf::Color::Red); texture.update(img); } sprite.setTexture(texture); sprite.setOrigin(texture.getSize().x / 2, texture.getSize().y / 2); }

void update() override {
    Entity::update();
    if (y > 600) alive = false;
}

void onCollision(Entity* other) override {
    if (Bullet* bullet = dynamic_cast<Bullet*>(other)) {
        health -= bullet->getDamage();
        if (health <= 0) alive = false;
    }
}

};

// 爆炸效果类 class Explosion : public Entity { private: sf::Texture texture; sf::Clock lifeClock; float lifetime;

public: Explosion(float x, float y) : Entity(x, y, 0, 0, 1), lifetime(0.5f) { if (!texture.loadFromFile("explosion.png")) { texture.create(60, 60); sf::Image img; img.create(60, 60, sf::Color::Orange); texture.update(img); } sprite.setTexture(texture); sprite.setOrigin(texture.getSize().x / 2, texture.getSize().y / 2); }

void update() override {
    if (lifeClock.getElapsedTime().asSeconds() > lifetime) {
        alive = false;
    }
}

};

// 道具类 class Powerup : public Entity { private: sf::Texture texture; PowerupType type;

public: Powerup(float x, float y, PowerupType type) : Entity(x, y, 0, 1.5f, 1), type(type) { if (!texture.loadFromFile(getTextureFilename())) { texture.create(30, 30); sf::Image img; img.create(30, 30, getColor()); texture.update(img); } sprite.setTexture(texture); sprite.setOrigin(texture.getSize().x / 2, texture.getSize().y / 2); }

PowerupType getType() const {
    return type;
}

void update() override {
    Entity::update();
    if (y > 600) alive = false;
}

private: std::string getTextureFilename() const { switch (type) { case PowerupType::HEALTH: return "powerup_health.png"; case PowerupType::DAMAGE: return "powerup_damage.png"; case PowerupType::SPEED: return "powerup_speed.png"; case PowerupType::RATE: return "powerup_rate.png"; case PowerupType::MULTISHOT: return "powerup_multishot.png"; default: return ""; } }

sf::Color getColor() const {
    switch (type) {
        case PowerupType::HEALTH: return sf::Color::Green;
        case PowerupType::DAMAGE: return sf::Color::Red;
        case PowerupType::SPEED: return sf::Color::Blue;
        case PowerupType::RATE: return sf::Color::Yellow;
        case PowerupType::MULTISHOT: return sf::Color::Magenta;
        default: return sf::Color::White;
    }
}

};

// 将道具类型转换为字符串显示 std::string powerupTypeToString(PowerupType type) { switch (type) { case PowerupType::HEALTH: return "生命恢复"; case PowerupType::DAMAGE: return "伤害提升"; case PowerupType::SPEED: return "速度提升"; case PowerupType::RATE: return "射速提升"; case PowerupType::MULTISHOT: return "多重射击"; default: return ""; } }

int main() { // 初始化随机数生成器 std::srand(static_cast(std::time(nullptr)));

// 创建游戏窗口
sf::RenderWindow window(sf::VideoMode(800, 600), "太空射击游戏");
window.setFramerateLimit(60);

// 加载背景
sf::Texture backgroundTexture;
if (!backgroundTexture.loadFromFile("background.png")) {
    backgroundTexture.create(800, 600);
    sf::Image img;
    img.create(800, 600, sf::Color(10, 10, 50));
    backgroundTexture.update(img);
}
sf::Sprite background(backgroundTexture);

// 创建玩家
Player player;

// 创建实体容器
std::vector<Entity*> entities;
std::vector<Bullet*> bullets;
std::vector<Enemy*> enemies;
std::vector<Explosion*> explosions;
std::vector<Powerup*> powerups;

// 添加玩家到实体容器
entities.push_back(&player);

// 创建字体
sf::Font font;
if (!font.loadFromFile("arial.ttf")) {
    // 使用默认字体
}

// 创建文本对象
sf::Text scoreText;
scoreText.setFont(font);
scoreText.setCharacterSize(24);
scoreText.setFillColor(sf::Color::White);
scoreText.setPosition(10, 10);

sf::Text healthText;
healthText.setFont(font);
healthText.setCharacterSize(24);
healthText.setFillColor(sf::Color::White);
healthText.setPosition(10, 40);

sf::Text powerupText;
powerupText.setFont(font);
powerupText.setCharacterSize(24);
powerupText.setFillColor(sf::Color::Yellow);
powerupText.setPosition(10, 70);

sf::Text gameOverText;
gameOverText.setFont(font);
gameOverText.setCharacterSize(72);
gameOverText.setFillColor(sf::Color::Red);
gameOverText.setString("游戏结束!");
gameOverText.setPosition(250, 250);
gameOverText.setStyle(sf::Text::Bold);

sf::Text restartText;
restartText.setFont(font);
restartText.setCharacterSize(24);
restartText.setFillColor(sf::Color::White);
restartText.setString("按R键重新开始");
restartText.setPosition(330, 350);

// 游戏时钟
sf::Clock clock;
sf::Clock enemySpawnClock;
sf::Clock powerupSpawnClock;
float enemySpawnRate = 1.0f;
float powerupSpawnRate = 10.0f;

// 游戏循环
bool gameOver = false;
while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
        if (event.type == sf::Event::Closed)
            window.close();
        
        // 游戏结束后按R键重新开始
        if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::R && gameOver) {
            gameOver = false;
            player.health = 3;
            player.resetPowerups();
            player.score = 0;
            player.x = 400;
            player.y = 500;
            
            // 清空所有实体
            for (auto e : entities) {
                if (e != &player) delete e;
            }
            entities.clear();
            bullets.clear();
            enemies.clear();
            explosions.clear();
            powerups.clear();
            entities.push_back(&player);
            
            // 重置生成速率
            enemySpawnRate = 1.0f;
            powerupSpawnRate = 10.0f;
        }
    }

    if (!gameOver) {
        // 更新游戏状态
        float deltaTime = clock.restart().asSeconds();

        // 更新玩家
        player.update();

        // 发射子弹
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) && player.canShoot()) {
            if (player.hasMultishot()) {
                // 多重射击
                Bullet* bullet1 = new Bullet(player.x - 15, player.y - 30, player.getBulletDamage());
                Bullet* bullet2 = new Bullet(player.x, player.y - 30, player.getBulletDamage());
                Bullet* bullet3 = new Bullet(player.x + 15, player.y - 30, player.getBulletDamage());
                
                bullets.push_back(bullet1);
                bullets.push_back(bullet2);
                bullets.push_back(bullet3);
                
                entities.push_back(bullet1);
                entities.push_back(bullet2);
                entities.push_back(bullet3);
            } else {
                // 普通射击
                Bullet* bullet = new Bullet(player.x, player.y - 30, player.getBulletDamage());
                bullets.push_back(bullet);
                entities.push_back(bullet);
            }
            
            player.resetShootClock();
        }

        // 生成敌人
        if (enemySpawnClock.getElapsedTime().asSeconds() > enemySpawnRate) {
            float enemyX = static_cast<float>(std::rand() % 700 + 50);
            Enemy* enemy = new Enemy(enemyX, -50);
            enemies.push_back(enemy);
            entities.push_back(enemy);
            enemySpawnClock.restart();
            
            // 随时间增加敌人生成速度
            if (enemySpawnRate > 0.3f) {
                enemySpawnRate -= 0.01f;
            }
        }

        // 生成道具
        if (powerupSpawnClock.getElapsedTime().asSeconds() > powerupSpawnRate) {
            float powerupX = static_cast<float>(std::rand() % 700 + 50);
            int type = std::rand() % 5;
            PowerupType powerupType = static_cast<PowerupType>(type);
            
            Powerup* powerup = new Powerup(powerupX, -50, powerupType);
            powerups.push_back(powerup);
            entities.push_back(powerup);
            powerupSpawnClock.restart();
        }

        // 更新所有子弹
        for (auto bullet : bullets) {
            bullet->update();
        }

        // 更新所有敌人
        for (auto enemy : enemies) {
            enemy->update();
        }

        // 更新所有爆炸效果
        for (auto explosion : explosions) {
            explosion->update();
        }

        // 更新所有道具
        for (auto powerup : powerups) {
            powerup->update();
        }

        // 碰撞检测
        for (auto enemy : enemies) {
            // 子弹与敌人碰撞
            for (auto bullet : bullets) {
                if (bullet->alive && enemy->alive &&
                    bullet->sprite.getGlobalBounds().intersects(enemy->sprite.getGlobalBounds())) {
                    enemy->onCollision(bullet);
                    bullet->alive = false;
                    
                    if (!enemy->alive) {
                        player.addScore(10);
                        Explosion* explosion = new Explosion(enemy->x, enemy->y);
                        explosions.push_back(explosion);
                        entities.push_back(explosion);
                    }
                }
            }
            
            // 玩家与敌人碰撞
            if (enemy->alive && player.alive &&
                enemy->sprite.getGlobalBounds().intersects(player.sprite.getGlobalBounds())) {
                enemy->alive = false;
                player.health--;
                
                if (player.health <= 0) {
                    player.alive = false;
                    gameOver = true;
                }
                
                Explosion* explosion = new Explosion(enemy->x, enemy->y);
                explosions.push_back(explosion);
                entities.push_back(explosion);
            }
        }

        // 玩家与道具碰撞
        for (auto powerup : powerups) {
            if (powerup->alive && player.alive &&
                powerup->sprite.getGlobalBounds().intersects(player.sprite.getGlobalBounds())) {
                player.applyPowerup(powerup->getType());
                powerup->alive = false;
                
                // 添加获得道具的特效
                Explosion* explosion = new Explosion(powerup->x, powerup->y);
                explosions.push_back(explosion);
                entities.push_back(explosion);
            }
        }

        // 移除死亡实体
        entities.erase(
            std::remove_if(entities.begin(), entities.end(), 
                [](Entity* e) { 
                    if (!e->alive) {
                        delete e;
                        return true;
                    }
                    return false;
                }),
            entities.end()
        );
        
        bullets.erase(
            std::remove_if(bullets.begin(), bullets.end(), 
                [](Bullet* b) { return !b->alive; }),
            bullets.end()
        );
        
        enemies.erase(
            std::remove_if(enemies.begin(), enemies.end(), 
                [](Enemy* e) { return !e->alive; }),
            enemies.end()
        );
        
        explosions.erase(
            std::remove_if(explosions.begin(), explosions.end(), 
                [](Explosion* e) { 
                    if (!e->alive) {
                        delete e;
                        return true;
                    }
                    return false;
                }),
            explosions.end()
        );
        
        powerups.erase(
            std::remove_if(powerups.begin(), powerups.end(), 
                [](Powerup* p) { 
                    if (!p->alive) {
                        delete p;
                        return true;
                    }
                    return false;
                }),
            powerups.end()
        );

        // 更新文本
        scoreText.setString("分数: " + std::to_string(player.getScore()));
        healthText.setString("生命: " + std::to_string(player.health));
        
        if (player.isPowerupActive()) {
            float remainingTime = 10.0f - powerupClock.getElapsedTime().asSeconds();
            powerupText.setString("增益: " + powerupTypeToString(player.getActivePowerup()) + 
                                 " (剩余: " + std::to_string(static_cast<int>(remainingTime + 1)) + "s)");
        } else {
            powerupText.setString("");
        }
    }

    // 绘制游戏
    window.clear();
    window.draw(background);
    
    // 绘制所有实体
    for (auto entity : entities) {
        entity->draw(window);
    }
    
    // 绘制文本
    window.draw(scoreText);
    window.draw(healthText);
    window.draw(powerupText);
    
    // 游戏结束画面
    if (gameOver) {
        window.draw(gameOverText);
        window.draw(restartText);
    }
    
    window.display();
}

// 清理内存
for (auto entity : entities) {
    if (entity != &player) delete entity;
}

return 0;

}

0 条评论

目前还没有评论...