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

// 窗口大小 const int WINDOW_WIDTH = 800; const int WINDOW_HEIGHT = 600;

// 飞机大小 const int PLANE_WIDTH = 50; const int PLANE_HEIGHT = 50;

// 子弹大小 const int BULLET_WIDTH = 5; const int BULLET_HEIGHT = 10;

// 敌机大小 const int ENEMY_WIDTH = 50; const int ENEMY_HEIGHT = 50;

// 障碍物大小 const int OBSTACLE_WIDTH = 30; const int OBSTACLE_HEIGHT = 30;

// 飞机类 class Plane { public: sf::RectangleShape shape; float speed;

Plane() {
    shape.setSize(sf::Vector2f(PLANE_WIDTH, PLANE_HEIGHT));
    shape.setFillColor(sf::Color::Green);
    shape.setPosition(WINDOW_WIDTH / 2 - PLANE_WIDTH / 2, WINDOW_HEIGHT - PLANE_HEIGHT - 10);
    speed = 5.0f;
}

void moveLeft() {
    if (shape.getPosition().x > 0) {
        shape.move(-speed, 0);
    }
}

void moveRight() {
    if (shape.getPosition().x < WINDOW_WIDTH - PLANE_WIDTH) {
        shape.move(speed, 0);
    }
}

void shoot(std::vector<sf::RectangleShape>& bullets) {
    sf::RectangleShape bullet;
    bullet.setSize(sf::Vector2f(BULLET_WIDTH, BULLET_HEIGHT));
    bullet.setFillColor(sf::Color::Yellow);
    bullet.setPosition(shape.getPosition().x + PLANE_WIDTH / 2 - BULLET_WIDTH / 2, shape.getPosition().y);
    bullets.push_back(bullet);
}

};

// 障碍物类 class Obstacle { public: sf::RectangleShape shape;

Obstacle() {
    shape.setSize(sf::Vector2f(OBSTACLE_WIDTH, OBSTACLE_HEIGHT));
    shape.setFillColor(sf::Color::Black);
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> xDis(0, WINDOW_WIDTH - OBSTACLE_WIDTH);
    std::uniform_int_distribution<> yDis(0, WINDOW_HEIGHT / 2);
    shape.setPosition(xDis(gen), yDis(gen));
}

};

// 基础敌机类 class BaseEnemy { public: sf::RectangleShape shape; float speed; std::random_device rd; std::mt19937 gen; std::uniform_int_distribution<> moveDirDis; std::uniform_int_distribution<> moveProbDis; std::uniform_real_distribution<> speedChangeDis;

BaseEnemy() : gen(rd()), moveDirDis(0, 3), moveProbDis(0, 1), speedChangeDis(0.8, 1.2) {
    shape.setSize(sf::Vector2f(ENEMY_WIDTH, ENEMY_HEIGHT));
    shape.setFillColor(sf::Color::Red);
    shape.setPosition(rand() % (WINDOW_WIDTH - ENEMY_WIDTH), -rand() % 200);
    speed = 2.0f;
}

virtual void move(const std::vector<Obstacle>& obstacles) {
    if (moveProbDis(gen) == 1) {
        speed *= speedChangeDis(gen);
        int dir = moveDirDis(gen);
        sf::Vector2f newPos = shape.getPosition();
        switch (dir) {
            case 0: // 向下
                newPos.y += speed;
                break;
            case 1: // 向左下
                if (shape.getPosition().x > 0) {
                    newPos.x -= speed;
                    newPos.y += speed;
                }
                break;
            case 2: // 向右下
                if (shape.getPosition().x < WINDOW_WIDTH - ENEMY_WIDTH) {
                    newPos.x += speed;
                    newPos.y += speed;
                }
                break;
            case 3: // 暂停
                return;
        }

        sf::RectangleShape tempShape = shape;
        tempShape.setPosition(newPos);
        bool willCollide = false;
        for (const auto& obstacle : obstacles) {
            if (checkCollision(tempShape, obstacle.shape)) {
                willCollide = true;
                break;
            }
        }

        if (!willCollide) {
            shape.setPosition(newPos);
        }
    }
}

};

// 快速敌机类,继承自基础敌机类 class FastEnemy : public BaseEnemy { public: FastEnemy() { shape.setFillColor(sf::Color::Magenta); speed = 4.0f; }

void move(const std::vector<Obstacle>& obstacles) override {
    BaseEnemy::move(obstacles);
}

};

// 斜向敌机类,继承自基础敌机类 class DiagonalEnemy : public BaseEnemy { public: DiagonalEnemy() { shape.setFillColor(sf::Color::Cyan); speed = 2.5f; }

void move(const std::vector<Obstacle>& obstacles) override {
    BaseEnemy::move(obstacles);
}

};

// 检查碰撞 bool checkCollision(const sf::RectangleShape& a, const sf::RectangleShape& b) { return a.getGlobalBounds().intersects(b.getGlobalBounds()); }

int main() { sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Aircraft War");

Plane player;
std::vector<sf::RectangleShape> bullets;
std::vector<std::unique_ptr<BaseEnemy>> enemies;
std::vector<Obstacle> obstacles;

sf::Clock clock;
sf::Time enemySpawnTimer = sf::Time::Zero;
sf::Time obstacleSpawnTimer = sf::Time::Zero;

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> enemyTypeDis(0, 2);
std::uniform_int_distribution<> enemySpawnIntervalDis(500, 2000);
std::uniform_int_distribution<> obstacleSpawnIntervalDis(3000, 5000); // 障碍物生成时间间隔范围
sf::Time enemySpawnInterval = sf::milliseconds(enemySpawnIntervalDis(gen));
sf::Time obstacleSpawnInterval = sf::milliseconds(obstacleSpawnIntervalDis(gen));

while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
        if (event.type == sf::Event::Closed) {
            window.close();
        }
        if (event.type == sf::Event::KeyPressed) {
            if (event.key.code == sf::Keyboard::Left) {
                player.moveLeft();
            }
            if (event.key.code == sf::Keyboard::Right) {
                player.moveRight();
            }
            if (event.key.code == sf::Keyboard::Space) {
                player.shoot(bullets);
            }
        }
    }

    // 生成敌机
    enemySpawnTimer += clock.restart();
    if (enemySpawnTimer >= enemySpawnInterval) {
        int enemyType = enemyTypeDis(gen);
        switch (enemyType) {
            case 0:
                enemies.emplace_back(std::make_unique<BaseEnemy>());
                break;
            case 1:
                enemies.emplace_back(std::make_unique<FastEnemy>());
                break;
            case 2:
                enemies.emplace_back(std::make_unique<DiagonalEnemy>());
                break;
        }
        enemySpawnTimer = sf::Time::Zero;
        enemySpawnInterval = sf::milliseconds(enemySpawnIntervalDis(gen));
    }

    // 生成障碍物
    obstacleSpawnTimer += clock.getElapsedTime();
    if (obstacleSpawnTimer >= obstacleSpawnInterval) {
        obstacles.emplace_back();
        obstacleSpawnTimer = sf::Time::Zero;
        obstacleSpawnInterval = sf::milliseconds(obstacleSpawnIntervalDis(gen));
    }

    // 移动子弹
    for (auto it = bullets.begin(); it != bullets.end();) {
        it->move(0, -5);
        if (it->getPosition().y < 0) {
            it = bullets.erase(it);
        } else {
            ++it;
        }
    }

    // 移动敌机
    for (auto enemyIt = enemies.begin(); enemyIt != enemies.end();) {
        (*enemyIt)->move(obstacles);
        if ((*enemyIt)->shape.getPosition().y > WINDOW_HEIGHT) {
            enemyIt = enemies.erase(enemyIt);
        } else {
            // 检查子弹与敌机的碰撞
            for (auto bulletIt = bullets.begin(); bulletIt != bullets.end();) {
                if (checkCollision((*enemyIt)->shape, *bulletIt)) {
                    enemyIt = enemies.erase(enemyIt);
                    bulletIt = bullets.erase(bulletIt);
                    break;
                } else {
                    ++bulletIt;
                }
            }
            // 检查敌机与玩家的碰撞
            if (checkCollision((*enemyIt)->shape, player.shape)) {
                std::cout << "Game Over!" << std::endl;
                window.close();
            }
            if (enemyIt != enemies.end()) {
                ++enemyIt;
            }
        }
    }

    window.clear();

    // 绘制玩家飞机
    window.draw(player.shape);

    // 绘制子弹
    for (const auto& bullet : bullets) {
        window.draw(bullet);
    }

    // 绘制敌机
    for (const auto& enemy : enemies) {
        window.draw(enemy->shape);
    }

    // 绘制障碍物
    for (const auto& obstacle : obstacles) {
        window.draw(obstacle.shape);
    }

    window.display();
}

return 0;

}

0 条评论

目前还没有评论...

信息

ID
1976
时间
1000ms
内存
256MiB
难度
5
标签
递交数
64
已通过
25
上传者