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++游戏开发的基本概念,你可以基于此代码进一步扩展和完善游戏功能。

相关推荐
Scott9999HH6 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
2401_841495647 小时前
【操作系统】进程同步与互斥实验报告
c++·算法·操作系统·进程·并发·同步·互斥
fqbqrr7 小时前
2607C++,soui与安卓
c++·soui
码智社7 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海7 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖8 小时前
JDK 26 新特性详解
java·开发语言
FairGuard手游加固9 小时前
2026年7月份国产游戏审批信息
游戏
马优晨9 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
fqbqrr11 小时前
2607C++,使用微软detours勾挂工具
c++
人邮异步社区11 小时前
怎么把C语言学到精通?
c语言·开发语言