当前位置: 首页 > news >正文

C++写有一个2D 小游戏(贪吃蛇)

用 C++ 开发游戏需要结合图形库、输入处理、游戏逻辑等模块,以下以2D 小游戏(贪吃蛇)为例,展示 C++ 游戏开发的核心流程,使用跨平台图形库SFML(简单易用,适合入门)。

一、准备工作

1. 安装 SFML 库

  • 下载地址:SFML 官网
  • 配置环境:将 SFML 的 include 目录添加到编译器包含路径,lib 目录添加到库路径,链接对应库文件(如sfml-graphics.libsfml-window.libsfml-system.lib)。

二、贪吃蛇游戏实现代码

cpp
 
运行
 
 
 
 
#include <SFML/Graphics.hpp>
#include <vector>
#include <random>
#include <iostream>// 方向枚举
enum Direction { UP, DOWN, LEFT, RIGHT };// 蛇节点结构体
struct SnakeSegment {sf::Vector2i position;SnakeSegment(int x, int y) : position(x, y) {}
};class SnakeGame {
private:sf::RenderWindow window;          // 游戏窗口std::vector<SnakeSegment> snake;  // 蛇的身体Direction dir;                    // 当前方向sf::Vector2i food;                // 食物位置int gridSize;                     // 网格大小int windowSize;                   // 窗口大小bool gameOver;                    // 游戏结束标志std::random_device rd;            // 随机数生成器std::mt19937 rng;                 // 随机数引擎public:SnakeGame(int gridSize = 20, int windowSize = 600) : gridSize(gridSize), windowSize(windowSize), dir(RIGHT), gameOver(false), rng(rd()) {// 初始化窗口window.create(sf::VideoMode(windowSize, windowSize), "Snake Game | C++ SFML");window.setFramerateLimit(10); // 控制游戏帧率// 初始化蛇(3个节点)snake.emplace_back(windowSize/2, windowSize/2);snake.emplace_back(windowSize/2 - gridSize, windowSize/2);snake.emplace_back(windowSize/2 - 2*gridSize, windowSize/2);// 生成初始食物spawnFood();}// 生成食物(随机位置,不与蛇身重叠)void spawnFood() {std::uniform_int_distribution<int> dist(0, (windowSize / gridSize) - 1);int x = dist(rng) * gridSize;int y = dist(rng) * gridSize;// 检查是否与蛇身重叠for (const auto& segment : snake) {if (segment.position.x == x && segment.position.y == y) {spawnFood(); // 重叠则重新生成return;}}food = sf::Vector2i(x, y);}// 处理输入void handleInput() {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::Up && dir != DOWN)dir = UP;else if (event.key.code == sf::Keyboard::Down && dir != UP)dir = DOWN;else if (event.key.code == sf::Keyboard::Left && dir != RIGHT)dir = LEFT;else if (event.key.code == sf::Keyboard::Right && dir != LEFT)dir = RIGHT;else if (event.key.code == sf::Keyboard::R && gameOver)restart(); // 重新开始游戏}}}// 更新游戏逻辑void update() {if (gameOver) return;// 移动蛇头sf::Vector2i newHead = snake.front().position;switch (dir) {case UP: newHead.y -= gridSize; break;case DOWN: newHead.y += gridSize; break;case LEFT: newHead.x -= gridSize; break;case RIGHT: newHead.x += gridSize; break;}snake.insert(snake.begin(), SnakeSegment(newHead.x, newHead.y));// 检查是否吃到食物if (snake.front().position == food) {spawnFood(); // 生成新食物(蛇身不缩短)} else {snake.pop_back(); // 没吃到则缩短尾部}// 检查碰撞(边界或自身)checkCollision();}// 碰撞检测void checkCollision() {// 边界碰撞if (snake.front().position.x < 0 || snake.front().position.x >= windowSize ||snake.front().position.y < 0 || snake.front().position.y >= windowSize) {gameOver = true;}// 自身碰撞for (size_t i = 1; i < snake.size(); ++i) {if (snake.front().position == snake[i].position) {gameOver = true;break;}}}// 重新开始游戏void restart() {snake.clear();dir = RIGHT;gameOver = false;// 重新初始化蛇snake.emplace_back(windowSize/2, windowSize/2);snake.emplace_back(windowSize/2 - gridSize, windowSize/2);snake.emplace_back(windowSize/2 - 2*gridSize, windowSize/2);spawnFood();}// 渲染画面void render() {window.clear(sf::Color::Black); // 清空窗口(黑色背景)// 绘制蛇for (const auto& segment : snake) {sf::RectangleShape rect(sf::Vector2f(gridSize - 1, gridSize - 1)); // -1留间隙rect.setPosition(segment.position.x, segment.position.y);rect.setFillColor(sf::Color::Green);window.draw(rect);}// 绘制食物sf::RectangleShape foodRect(sf::Vector2f(gridSize - 1, gridSize - 1));foodRect.setPosition(food.x, food.y);foodRect.setFillColor(sf::Color::Red);window.draw(foodRect);// 游戏结束提示if (gameOver) {sf::Font font;if (font.loadFromFile("arial.ttf")) { // 需确保字体文件存在sf::Text text("Game Over! Press R to Restart", font, 24);text.setPosition(windowSize/2 - text.getLocalBounds().width/2, windowSize/2);text.setFillColor(sf::Color::White);window.draw(text);}}window.display(); // 显示画面}// 游戏主循环void run() {while (window.isOpen()) {handleInput();update();render();}}
};int main() {SnakeGame game;game.run();return 0;
}
 

三、代码解析

1. 核心模块

  • 窗口管理:使用sf::RenderWindow创建游戏窗口,设置帧率限制(10FPS,控制蛇的移动速度)。
  • 蛇的逻辑:用std::vector存储蛇的身体节点,通过插入头部、删除尾部实现移动;吃到食物时不删除尾部,实现蛇身增长。
  • 食物生成:利用随机数生成食物位置,确保不与蛇身重叠。
  • 碰撞检测:检测蛇头是否撞边界或自身,触发游戏结束。
  • 渲染系统:通过sf::RectangleShape绘制蛇和食物,游戏结束时显示提示文字。

2. 运行说明

  • 确保 SFML 库配置正确,且项目目录下有arial.ttf字体文件(或修改字体路径)。
  • 编译运行后,用方向键控制蛇的移动,吃到红色食物得分,撞边界 / 自身则游戏结束(按 R 重启)。

四、进阶扩展方向

  1. 添加计分系统:记录吃到的食物数量,显示在窗口中。
  2. 难度递增:随着分数增加,提高游戏帧率(蛇移动速度加快)。
  3. 音效与音乐:使用 SFML 的sf::Soundsf::Music添加音效(如吃到食物、游戏结束)。
  4. 3D 游戏开发:若需开发 3D 游戏,可使用OpenGL或引擎(如 Unreal Engine、Unity,底层用 C++)。
  5. 物理引擎集成:引入 Box2D 等物理引擎,实现更复杂的碰撞和运动(如格斗游戏、赛车游戏)。

五、C++ 游戏开发的优势

  • 性能高效:C++ 是编译型语言,直接操作内存,适合对帧率和响应速度要求高的游戏。
  • 底层控制:可直接调用图形 API(如 DirectX、OpenGL),定制化程度高。
  • 生态丰富:有 SFML、SDL、Qt 等图形库,以及 Unreal Engine 等成熟游戏引擎支持。
通过这个贪吃蛇示例,可快速掌握 C++ 游戏开发的基础框架,后续可根据需求扩展更复杂的游戏逻辑!
http://www.jsqmd.com/news/53240/

相关文章:

  • NOIP day -2 笔记
  • 专精
  • 对比说明Java NIO框架和传统的IO框架的优缺点
  • CF2157C Meximum Array 2
  • 如何在实际项目中选择使用Java NIO框架还是传统IO框架?
  • AT_fps_24_b 整数の組
  • 详细介绍:【数据结构初阶】单链表
  • 第五十篇
  • 每日随笔
  • 2025年日语自学软件推荐:最适合零基础与进阶者的优质口碑选择
  • ABC386 VP总结
  • tarjan 强连通分量、缩点、点双、割点、割边(桥)
  • 我踩坑后总结:企业微信客服API接入客服系统,90%的人都搞错了!
  • 香橙派上进行MQTT数据存储客户端开发(一)基本环境配置
  • GEO 优化价格大比拼,哪家最便宜?三大高性价比机构推荐
  • 2025年AI学习机哪个品牌好?热门品牌功能与效果全解析
  • 2025年知名的长租公寓有哪些:权威榜单与精选解析
  • 编程中的枚举法与数学上的穷举法有何区别?
  • 如百钱百鸡问题,枚举法和穷举法有何不同
  • 根本魔法语言数组 (一) (C语言)
  • 《程序员修炼之道:从小工到专家》阅读笔记5
  • Spring Cloud工程中使用Nacos配置中心的2种方式
  • 人工智能之数据分析 Matplotlib:第三章 基本属性
  • 那为什么go 就能用同步的写法,而且不用协程的情况下,实现异步编程,而且还不阻塞os线程
  • URL地址转base64
  • 2025年租房去哪里找房源:独家榜单与深度解析
  • C# 图片加载引发的内存溢出异常
  • 实用指南:LV.5 文件IO
  • CSS视图过渡入门指南:让多页面应用拥有丝滑动画
  • 《ROS1学习笔记8——自定义服务素材》