用c++和SFML实现简易的界面版贪吃蛇

用c++和SFML实现简易的界面版贪吃蛇运行截图等待开始界面运行过程失败界面截图 SFML 配置 csdn 上面已经有很多 SFML 配置的 blog 随便就能搜到 正常配置好 SFML 后 还需要将字体 ttf 文件放在源代码同一目录和 exe 同一目录中 不然无法显示字符代码部分下面贴上各个部分的代码头文件和全局常量 include SFML Graphics hpp include time h include iostream include iostream time h SFML

运行截图

等待开始界面

用c++和SFML实现简易的界面版贪吃蛇

运行过程

用c++和SFML实现简易的界面版贪吃蛇用c++和SFML实现简易的界面版贪吃蛇

失败界面截图

用c++和SFML实现简易的界面版贪吃蛇

SFML配置

csdn上面已经有很多SFML配置的blog,随便就能搜到。正常配置好SFML后,还需要将字体ttf文件放在源代码同一目录和exe同一目录中,不然无法显示字符

代码部分

下面贴上各个部分的代码

头文件和全局常量

#include 
  
    #include 
   
     #include 
    
      #include 
     
       const int BodyMaxLong = 2000; //最长蛇身 const int SnakeInitLongth = 10; //初始蛇身 const sf::Vector2f SnakeInitPos = {200,200}; //蛇头初始位置 const int BodyRadius = 5; //蛇身半径 const sf::Vector2i WindowSize = { 500,500 }; const int FoodRadius = 2; const int FoodNum = 30; #define SnakeColor sf::Color::Green #define FoodColor sf::Color::Red 
      
     
    
  

 

sfml中已经定义了颜色可以直接用,还有图形类和二维向量类(int型vector2i,float型vector2f),都在名称空间sf中。

既然是贪吃蛇游戏,那么一定有蛇啦。

class Snake { //蛇 private: int longth; //蛇身长度 sf::Vector2f dir; //蛇当前行进方向 sf::CircleShape body[BodyMaxLong]; //用圆形类来建造蛇身 public: Snake() { longth = SnakeInitLongth; dir = { 5 , 0 }; //初始方向 for (int i = 0;i < 5;i++) { //初始化位置和蛇身每个圆形之间的间距 sf::Vector2f pos = { SnakeInitPos.x - i * 5, SnakeInitPos.y }; body[i].setPosition(pos); } for (int i = 0;i < BodyMaxLong;i++) { //初始化蛇身半径和颜色 body[i].setRadius(BodyRadius); body[i].setFillColor(SnakeColor); } } void SnakeMove() { //整体移动蛇身函数,用一个循环依次移动每一个蛇身 for (int i = longth - 1;i > 0;i--) { body[i].setPosition(body[i - 1].getPosition().x,body[i - 1].getPosition().y); } body[0].move(dir); } void SnakeHolding(sf::Event &event) { //控制蛇行进方向 switch (event.key.code) { case sf::Keyboard::Up: case sf::Keyboard::W:if (dir.x != 0 && dir.y != 5) { dir = { 0,-5 }; }break; case sf::Keyboard::Left: case sf::Keyboard::A:if (dir.x != 5 && dir.y != 0) { dir = { -5,0 }; }break; case sf::Keyboard::Right: case sf::Keyboard::D:if (dir.x != -5 && dir.y != 0) { dir = { 5,0 }; }break; case sf::Keyboard::Down: case sf::Keyboard::S:if (dir.x != 0 && dir.y != -5) { dir = { 0 , 5 }; }break; default: break; } } sf::CircleShape PreDrawSnake(int i) { //在主函数绘制蛇时需要返回每个圆形对象 return this->body[i]; } int GetSnakeLongth() { return this->longth; } void UpLevel() { this->longth++; } //吃到食物升级,长度自增 sf::Vector2f GetDir() { return dir; } };

食物

typedef struct { //一个包含下x,y两个整型的结构体,用于表示坐标,本来可以用vector2i的,发现下面老是报错就尝试自己写个结构体,发现可以运行就这么运行了 int x; int y; }PosData; class Food { //食物类 private: PosData pos; sf::CircleShape Body; public: Food() { pos = { rand() % 500,rand() % 500 }; //初始化随机食物位置 Body.setFillColor(FoodColor); //初始化食物颜色 Body.setPosition({(float)pos.x,(float)pos.y}); //将位置设置进图形对象中 Body.setRadius(FoodRadius); //初始化食物的图形半径 } sf::Vector2f GetFoodPos() { //返回食物位置的函数 return { (float)this->pos.x+FoodRadius,(float)this->pos.y+FoodRadius }; } void SetFoodPos() { //一旦被吃掉,重新随机获得一个位置 pos = { rand() % WindowSize.x, rand() % WindowSize.y }; Body.setPosition({(float)pos.x,(float)pos.y}); } sf::CircleShape PreDraFood() { return this->Body; } //返回图形对象,以便绘制和其他功能 };

判断函数

检查有没有吃到食物用的函数

void GetFoodCheck(Snake& snake, Food& food) { sf::Vector2f snakepos = { snake.PreDrawSnake(0).getPosition().x+BodyRadius,snake.PreDrawSnake(0).getPosition().y+BodyRadius}; sf::Vector2f foodpos = food.GetFoodPos(); if (foodpos.x >= snakepos.x - BodyRadius && foodpos.x <= snakepos.x + BodyRadius && foodpos.y>=snakepos.y - BodyRadius && foodpos.y<=snakepos.y + BodyRadius) { snake.UpLevel(); food.SetFoodPos(); } }

检查有没有撞墙或者咬到尾巴的函数,都没有则返回1,有其一则返回0

bool CollideCheck(Snake& snake) { sf::CircleShape head = snake.PreDrawSnake(0); if (head.getPosition().x >= WindowSize.x || head.getPosition().x <= 0 || head.getPosition().y >= WindowSize.y || head.getPosition().y <= 0) { return 0; } int longth = snake.GetSnakeLongth(); for (int i = 1;i < longth;i++) { if (snake.GetDir().x == 0) { if (snake.PreDrawSnake(0).getPosition().x + BodyRadius >= snake.PreDrawSnake(i).getPosition().x && snake.PreDrawSnake(0).getPosition().x + BodyRadius <= snake.PreDrawSnake(i).getPosition().x + BodyRadius * 2) { if (snake.GetDir().y > 0) { if (snake.PreDrawSnake(0).getPosition().y + BodyRadius * 2 >= snake.PreDrawSnake(i).getPosition().y && snake.PreDrawSnake(0).getPosition().y + BodyRadius * 2 <= snake.PreDrawSnake(i).getPosition().y + BodyRadius * 2) { return 0; } } else { if (snake.PreDrawSnake(0).getPosition().y >= snake.PreDrawSnake(i).getPosition().y && snake.PreDrawSnake(0).getPosition().y <= snake.PreDrawSnake(i).getPosition().y + BodyRadius * 2) { return 0; } } } } if (snake.GetDir().y == 0) { if (snake.PreDrawSnake(0).getPosition().y + BodyRadius >= snake.PreDrawSnake(i).getPosition().y && snake.PreDrawSnake(0).getPosition().y + BodyRadius <= snake.PreDrawSnake(i).getPosition().y + BodyRadius * 2) { if (snake.GetDir().x > 0) { if (snake.PreDrawSnake(0).getPosition().x + BodyRadius * 2 >= snake.PreDrawSnake(i).getPosition().x && snake.PreDrawSnake(0).getPosition().x + BodyRadius * 2 <= snake.PreDrawSnake(i).getPosition().x + BodyRadius * 2) { return 0; } } else { if (snake.PreDrawSnake(0).getPosition().x >= snake.PreDrawSnake(i).getPosition().x && snake.PreDrawSnake(0).getPosition().x <= snake.PreDrawSnake(i).getPosition().x + BodyRadius * 2) { return 0; } } } } } return 1; }

main函数

int main() { sf::Text text,score,pretext; sf::Font font,cnfont; font.loadFromFile("arial.ttf"); //加载字体文件 cnfont.loadFromFile("hpsimplifiedhans-light.ttf"); text.setPosition(1, 1); //设置字体的位置 score.setPosition(100, 1); pretext.setPosition(20,150); pretext.setString("Welcome to shushuSnake Game\npress space button\n start the game"); //设置字符内容 pretext.setFont(font); pretext.setFillColor(sf::Color::Blue); text.setString("Score:"); text.setFont(font);score.setFont(font); text.setFillColor(sf::Color::Black);score.setFillColor(sf::Color::Black); std::string str; srand((int)time(0)); sf::RenderWindow window(sf::VideoMode(WindowSize.x,WindowSize.y),"shushuSnake"); Snake snake; //创建蛇 Food food[FoodNum]; //创建食物 sf::Clock clock; // double timer = 0, delay = 0.05; // bool prep = 0; //若prep = 0 等待玩家按空格开始游戏,开始游戏后prep = 1 int longth; while (window.isOpen()) { if (!prep) { 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::Space) { prep = 1; } } } window.clear(sf::Color::White); window.draw(text); score.setString("0"); window.draw(score); window.draw(pretext); window.display(); } if (prep) { float time = clock.getElapsedTime().asSeconds(); // clock.restart(); // timer += time; sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) { window.close(); } if (event.type == sf::Event::KeyPressed) { snake.SnakeHolding(event); } } longth = snake.GetSnakeLongth(); window.clear(sf::Color::White); for (int i = 0;i < FoodNum; i++) //食物绘制 { window.draw(food[i].PreDraFood()); } if (timer > delay) { timer = 0;snake.SnakeMove(); for (int i = 0; i < FoodNum;i++) { GetFoodCheck(snake, food[i]); } if (CollideCheck(snake) == 0) //咬到尾巴或者撞到墙失败了 { sf::Text endtext; endtext.setString("Game Over!!"); endtext.setPosition(100, 150); endtext.setFont(font); endtext.setCharacterSize(50); endtext.setFillColor(sf::Color::Red); window.clear(sf::Color::White); window.draw(text); window.draw(score); window.draw(endtext); longth = snake.GetSnakeLongth(); for (int i = 0; i < longth;i++) //蛇身绘制 window.draw(snake.PreDrawSnake(i)); window.display(); if (_getch())return 0; } str = std::to_string(snake.GetSnakeLongth() - SnakeInitLongth); score.setString(str); } for (int i = 0; i < longth;i++) //蛇身绘制 window.draw(snake.PreDrawSnake(i)); window.draw(text); window.draw(score); window.display(); } } return 0; }

 

欢迎大家一起讨论!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/218415.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午7:19
下一篇 2026年3月18日 上午7:19


相关推荐

  • QT学习笔记15绘图和绘图设备

    QT学习笔记15绘图和绘图设备1QPainterQt的绘图系统允许使用相同的API在屏幕和其它打印设备上进行绘制。整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类。QPainter用来执行绘制的操作;QPaintDevice是一个二维空间的抽象,这个二维空间允许QPainter在其上面进行绘制,也就是QPainter工作的空间;QPaintEngine提供了画笔(Q

    2022年4月18日
    44
  • MySQL安装配置教程(超级详细、保姆级)

    MySQL安装配置教程(超级详细、保姆级)一、下载MySQLMysql官网下载地址https://downloads.mysql.com/archives/installer/1.选择想要安装的版本,本篇文章选择的是5.7.31版本,下面的那个文件,点击Download下载二、安装MySQL1.选择设置类型双击运行mysql-installer-community-5.7.31.0.msi这里选择是自定义安装,所以直接选择“Custom”,点击“Next”“DeveloperDefault”是开发者默认

    2022年5月31日
    44
  • ubuntu 设置不见了_微信莫名其妙的被注销了

    ubuntu 设置不见了_微信莫名其妙的被注销了        今天学习GTK+,所以下载了源码包,然后安装了必要的依赖,装好后,因为默认安装是安装在/usr/local/include/目录下了,为了编程的方便,所以就建立了符号链接到/usr/include/目录下。       一晃就是一天了,现在打开某些程序,发现怎么显示不对,跟我的gentoo安装了gnome时的默认界面一样,很朴素的样子,怎么回事?一看Firefox还好,还没

    2025年11月26日
    6
  • Eclipse使用Maven创建Web时错误:Could not resolve archetype org.apache.maven.archetypes:maven-archetype-webap

    Eclipse使用Maven创建Web时错误:Could not resolve archetype org.apache.maven.archetypes:maven-archetype-webap问题描述:使用Eclipse自带的Maven插件创建Web项目时报错:Couldnotresolvearchetypeorg.apache.maven.archetypes:maven-archetype-webapp:RELEASEfromanyoftheconfiguredrepositories.Couldnotresolveartifa

    2022年7月24日
    11
  • 算法的力量

    算法的力量李开复 算法是计算机科学领域最重要的基石之一,但却受到了国内一些程序员的冷落。许多学生看到一些公司在招聘时要求的编程语言五花八门就产生了一种误解,认为学计算机就是学各种编程语言,

    2021年12月26日
    44
  • python 结巴分词学习

    python 结巴分词学习https www toutiao com a nbsp 2019 01 0610 14 00 结巴分词 自然语言处理之中文分词器 jieba 分词算法使用了基于前缀词典实现高效的词图扫描 生成句子中汉字所有可能生成词情况所构成的有向无环图 DAG 再采用了动态规划查找最大概率路径 找出基于词频的最大切分组合 对于未登录词 采用了基于汉字成词能力

    2026年3月20日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号