C++ 游戏开发示例:简单的贪吃蛇游戏

下面是一个使用C++和SFML库实现的简单贪吃蛇游戏。这个示例展示了游戏开发的基本概念,包括游戏循环、图形渲染、用户输入处理和游戏逻辑。

cpp

复制代码
#include <SFML/Graphics.hpp>
#include <vector>
#include <random>

// 游戏常量
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const int GRID_SIZE = 20;
const int GRID_WIDTH = WINDOW_WIDTH / GRID_SIZE;
const int GRID_HEIGHT = WINDOW_HEIGHT / GRID_SIZE;

// 方向枚举
enum class Direction { Up, Down, Left, Right };

class Snake {
public:
    Snake() {
        // 初始化蛇身,从屏幕中央开始
        body.push_back(sf::Vector2i(GRID_WIDTH / 2, GRID_HEIGHT / 2));
        direction = Direction::Right;
        growPending = 3; // 初始长度为4
    }

    void changeDirection(Direction newDirection) {
        // 防止直接反向移动
        if ((direction == Direction::Up && newDirection != Direction::Down) ||
            (direction == Direction::Down && newDirection != Direction::Up) ||
            (direction == Direction::Left && newDirection != Direction::Right) ||
            (direction == Direction::Right && newDirection != Direction::Left)) {
            direction = newDirection;
rd.xjyl.gov.cn/upload/1982074940999303168.html
rd.xjyl.gov.cn/upload/1982074941032857600.html
rd.xjyl.gov.cn/upload/1982074941074800640.html
rd.xjyl.gov.cn/upload/1982074941158686720.html
rd.xjyl.gov.cn/upload/1982074941171269633.html
rd.xjyl.gov.cn/upload/1982074941171269632.html
rd.xjyl.gov.cn/upload/1982074941234184192.html
rd.xjyl.gov.cn/upload/1982074941485842432.html
rd.xjyl.gov.cn/upload/1982074941506813952.html
rd.xjyl.gov.cn/upload/1982074941515202560.html
rd.xjyl.gov.cn/upload/1982074941544562688.html
rd.xjyl.gov.cn/upload/1982074941607477248.html
rd.xjyl.gov.cn/upload/1982074941670391808.html
rd.xjyl.gov.cn/upload/1982074941792026624.html
rd.xjyl.gov.cn/upload/1982074941850746880.html
rd.xjyl.gov.cn/upload/1982074942056267776.html
rd.xjyl.gov.cn/upload/1982074942106599424.html
rd.xjyl.gov.cn/upload/1982074942135959552.html
rd.xjyl.gov.cn/upload/1982074942144348160.html
rd.xjyl.gov.cn/upload/1982074942190485504.html
rd.xjyl.gov.cn/upload/1982074942307926016.html
rd.xjyl.gov.cn/upload/1982074942505058304.html
rd.xjyl.gov.cn/upload/1982074942484086784.html
        }
    }

    void update() {
        // 移动蛇身
        sf::Vector2i newHead = body.front();
        
        switch (direction) {
            case Direction::Up:
                newHead.y--;
                break;
            case Direction::Down:
                newHead.y++;
                break;
            case Direction::Left:
                newHead.x--;
                break;
            case Direction::Right:
                newHead.x++;
                break;
        }
        
        // 检查边界碰撞
        if (newHead.x < 0 || newHead.x >= GRID_WIDTH || 
            newHead.y < 0 || newHead.y >= GRID_HEIGHT) {
            reset();
            return;
        }
        
        // 检查自身碰撞
        for (auto segment : body) {
            if (segment == newHead) {
                reset();
                return;
            }
        }
        
        // 添加新头部
        body.insert(body.begin(), newHead);
        
        // 如果不需要增长,移除尾部
        if (growPending > 0) {
            growPending--;
        } else {
            body.pop_back();
        }
    }

    void grow() {
        growPending++;
    }

    void reset() {
        body.clear();
        body.push_back(sf::Vector2i(GRID_WIDTH / 2, GRID_HEIGHT / 2));
        direction = Direction::Right;
        growPending = 3;
    }

    const std::vector<sf::Vector2i>& getBody() const {
        return body;
    }

    sf::Vector2i getHead() const {
        return body.front();
    }

private:
    std::vector<sf::Vector2i> body;
    Direction direction;
    int growPending;
};

class Food {
public:
    Food() {
        respawn();
    }

    void respawn() {
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> disX(0, GRID_WIDTH - 1);
        std::uniform_int_distribution<> disY(0, GRID_HEIGHT - 1);
        
        position.x = disX(gen);
        position.y = disY(gen);
    }

    sf::Vector2i getPosition() const {
        return position;
    }

private:
    sf::Vector2i position;
};

class Game {
public:
    Game() : window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Snake Game"), 
             snake(), food(), score(0) {
        // 设置帧率限制
        window.setFramerateLimit(10);
        
        // 加载字体
        if (!font.loadFromFile("arial.ttf")) {
            // 如果无法加载字体,使用默认字体
            font.loadFromFile("C:/Windows/Fonts/arial.ttf");
        }
        
        scoreText.setFont(font);
        scoreText.setCharacterSize(24);
        scoreText.setFillColor(sf::Color::White);
        scoreText.setPosition(10, 10);
        updateScoreText();
    }

    void run() {
        while (window.isOpen()) {
            handleEvents();
            update();
            render();
        }
    }

private:
    void handleEvents() {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            } else if (event.type == sf::Event::KeyPressed) {
                switch (event.key.code) {
                    case sf::Keyboard::Up:
                        snake.changeDirection(Direction::Up);
                        break;
                    case sf::Keyboard::Down:
                        snake.changeDirection(Direction::Down);
                        break;
                    case sf::Keyboard::Left:
                        snake.changeDirection(Direction::Left);
                        break;
                    case sf::Keyboard::Right:
                        snake.changeDirection(Direction::Right);
                        break;
                    case sf::Keyboard::Escape:
                        window.close();
                        break;
                    default:
                        break;
                }
            }
        }
    }

    void update() {
        snake.update();
        
        // 检查是否吃到食物
        if (snake.getHead() == food.getPosition()) {
            snake.grow();
            food.respawn();
            score += 10;
            updateScoreText();
        }
    }

    void render() {
        window.clear(sf::Color::Black);
        
        // 绘制蛇
        sf::RectangleShape segment(sf::Vector2f(GRID_SIZE - 1, GRID_SIZE - 1));
        segment.setFillColor(sf::Color::Green);
        
        for (auto pos : snake.getBody()) {
            segment.setPosition(pos.x * GRID_SIZE, pos.y * GRID_SIZE);
            window.draw(segment);
        }
        
        // 绘制食物
        sf::CircleShape foodShape(GRID_SIZE / 2 - 1);
        foodShape.setFillColor(sf::Color::Red);
        foodShape.setPosition(food.getPosition().x * GRID_SIZE, food.getPosition().y * GRID_SIZE);
        window.draw(foodShape);
        
        // 绘制分数
        window.draw(scoreText);
        
        window.display();
rd.xjyl.gov.cn/upload/1982074942513446912.html
rd.xjyl.gov.cn/upload/1982074942693801984.html
rd.xjyl.gov.cn/upload/1982074942681219072.html
rd.xjyl.gov.cn/upload/1982074942777688064.html
rd.xjyl.gov.cn/upload/1982074942765105152.html
rd.xjyl.gov.cn/upload/1982074942828019712.html
rd.xjyl.gov.cn/upload/1982074942953848832.html
rd.xjyl.gov.cn/upload/1982074942949654528.html
rd.xjyl.gov.cn/upload/1982074943130009601.html
rd.xjyl.gov.cn/upload/1982074943150981120.html
rd.xjyl.gov.cn/upload/1982074943130009600.html
rd.xjyl.gov.cn/upload/1982074943176146944.html
rd.xjyl.gov.cn/upload/1982074943272615936.html
rd.xjyl.gov.cn/upload/1982074943339724800.html
rd.xjyl.gov.cn/upload/1982074943490719744.html
rd.xjyl.gov.cn/upload/1982074943520079872.html
rd.xjyl.gov.cn/upload/1982074943608160256.html
rd.xjyl.gov.cn/upload/1982074943629131776.html
rd.xjyl.gov.cn/upload/1982074943801098240.html
rd.xjyl.gov.cn/upload/1982074943935315968.html
rd.xjyl.gov.cn/upload/1982074943981453312.html
rd.xjyl.gov.cn/upload/1982074944308609024.html
rd.xjyl.gov.cn/upload/1982074944455409664.html
rd.xjyl.gov.cn/upload/1982074944560267264.html
rd.xjyl.gov.cn/upload/1982074944606404608.html
    }

    void updateScoreText() {
        scoreText.setString("Score: " + std::to_string(score));
    }

    sf::RenderWindow window;
    Snake snake;
    Food food;
    int score;
    sf::Font font;
    sf::Text scoreText;
};

int main() {
    Game game;
    game.run();
    return 0;
}

如何运行这个游戏

  1. 确保安装了SFML库。你可以从SFML官网下载并安装。

  2. 使用以下命令编译(假设使用g++):

    text

    复制代码
    g++ -c snake_game.cpp -I/path/to/SFML/include
    g++ snake_game.o -o snake_game -L/path/to/SFML/lib -lsfml-graphics -lsfml-window -lsfml-system
  3. 运行游戏:

    text

    复制代码
    ./snake_game

游戏功能

  • 使用方向键控制蛇的移动

  • 吃到红色食物会增加蛇的长度和分数

  • 撞到墙壁或自身会重置游戏

  • 按ESC键退出游戏

扩展建议

  1. 添加游戏开始和结束界面

  2. 实现难度级别(通过改变蛇的移动速度)

  3. 添加音效和更多视觉效果

  4. 实现高分记录功能

  5. 添加不同类型的食物,具有不同的效果

这个示例展示了C++游戏开发的基本概念,你可以基于此代码进一步扩展和完善游戏功能。

相关推荐
Summer_Uncle3 小时前
【C++学习】指针
c++·学习
兰亭妙微4 小时前
2026年UX/UI五大趋势:AI、AR与包容性设计将重新定义用户体验
开发语言·ui·1024程序员节·界面设计·设计趋势
蜗牛沐雨4 小时前
详解C++中的字符串流
c++·1024程序员节
蜗牛沐雨4 小时前
详解C++中的流
c++·1024程序员节
懒羊羊不懒@4 小时前
Java—枚举类
java·开发语言·1024程序员节
scx201310044 小时前
20251025 分治总结
数据结构·c++·算法
m0_748240254 小时前
C++智能指针使用指南(auto_ptr, unique_ptr, shared_ptr, weak_ptr)
java·开发语言·c++
Evand J4 小时前
【MATLAB例程】自适应渐消卡尔曼滤波,背景为二维雷达目标跟踪,基于扩展卡尔曼(EKF)|附完整代码的下载链接
开发语言·matlab·目标跟踪·1024程序员节
百锦再5 小时前
低代码开发的约束性及ABP框架的实践解析
android·开发语言·python·低代码·django·virtualenv·rxjava