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

article/2025/9/30 13:44:56

运行截图

等待开始界面

运行过程

失败界面截图

SFML配置

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

代码部分

下面贴上各个部分的代码

头文件和全局常量

#include <SFML/Graphics.hpp>
#include <time.h>
#include<iostream>
#include<conio.h>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 = 1int 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;
}

 

欢迎大家一起讨论!


http://chatgpt.dhexx.cn/article/Tf63yHkd.shtml

相关文章

VS2017、VS2019配置SFML

一、sfml官网下载32位的版本 一样的设置&#xff0c;64位的版本我没有成功&#xff0c;用不了。 https://www.sfml-dev.org/ bin目录下的文件拷贝到System32和SysWOW64里面。 二、 鼠标右击红色处&#xff0c;弹出菜单&#xff0c;点最后那个属性。 如果不是win32&#xff0c;…

VS2019配置SFML

VS2019配置SFML 1.下载安装SFML SDK 网址&#xff1a;https://www.sfml-dev.org/download.php 解压并放在文件夹里&#xff0c;记住这个路径。 在我的电脑中这个路径是F:\CProjects\_library\SFML-2.5.1 2.VS新建一个C控制台项目 我命名为SfmlTest&#xff0c;并放在常用的项…

sfml-tutorials 官方教程 windows篇

系列文章 SFML-windows 篇 SFML-Events explained 篇 SFML-Keyboard, mouse and joystick 篇 SFML-Using OpenGL in a SFML window 篇 SFML-Drawing 2D stuff 篇 SFML-Shapes 篇 SFML-Sprites and textures 篇 文章目录 系列文章打开一个windows执行windows绘制windows控制帧速…

SFML基础

原文地址&#xff1a;https://www.cnblogs.com/karl07/p/10285692.html (1) 窗口和交互 创建一个新窗口&#xff1a; sf::RenderWindow window(sf::VideoMode(500,500),"new window"); 但是光创建一个窗口并不能显示 还要加一个循环 while (window.isOpen()){sf:…

引擎开发四: SFML库及使用

SFML 是多媒体库&#xff0c;它为PC的各个组件提供简单的界面&#xff0c;用来简化游戏和多媒体应用程序的开发。 主要由五个模块组成&#xff0c;分别是&#xff1a;系统&#xff0c;窗口&#xff0c;图形&#xff0c;音频和网络。 SFML 是跨平台的&#xff0c;通过 SFML&…

【C++】开源:多媒体SFML库使用入门

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍SFML库使用。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习知识&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&#…

使用SFML框架打造属于自己的俄罗斯方块

目录 一、效果展示 二、游戏说明 三、开发环境 四、代码展示 五、代码详解 1.游戏区域表示 2.方块表示 3.方块旋转 4.消行处理 六、个性化定制 七、结语 一、效果展示 二、游戏说明 相信大家都玩过俄罗斯方块&#xff0c;五种按键就能带来极高的可玩性。如果想要开发…

超详细!SFML库vs2022配置教程

1.官网下载SFML 官方网址&#xff1a;SFML 点击下载 根据自己电脑选择合适的版本下载 我的电脑是64位的 下载完成之后将文件放在一个自己方便找到的地方 2.vs2022配置 选择空项目 添加cpp源文件 附加包含目录 添加你SFML中的include路径 例如&#xff1a; 添加SFML中的li…

SFML学习笔记(1)——初识SFML

一、SFML SFML 是多媒体库&#xff0c;它为PC的各个组件提供简单的界面&#xff0c;用来简化游戏和多媒体应用程序的开发。 SFML分成以下五个模块&#xff0c;这些模块相互独立&#xff0c;也可以根据需要组合在一起: System(系统)&#xff1a;一个核心模块&#xff0c;它定义…

找出数组中第k大的数

给定一个数组&#xff0c;找出数组中第k大的数。其实现代码如下: package com.threeTop.www;/*** 找出数组中第k大的数* author wjgs**/ public class FindK {public static void find(int[]array,int begin,int end,int k){int ipartition(array,begin,end);if(i1>k){//左半…

n个数中找最大数c语言,N个数中找到第K大的数值(C语实现)

N个数中找到第K大的数值(C语实现) N个数中找到第K大的数值(C语实现) 研究生了,选了计算机算法这门课程,这周布置了一个作业,在OJ上做:**N个数中找到第K大的数值**。大一简单学过C语言基础,目前只能用C语言编程,后续会学C++编程。 分享一份不超时的C语代码~ 测试例子: 思…

快速排序计算第K大的数

先说结论&#xff0c;最终版本代码如下&#xff1a; public class KthNum {public static int k 2;public static boolean bigK false;public static void main(String[] args) {int arr[] {3, 2, 3, 1, 7, 4, 5, 5, 6};int kNum quickSort(arr);System.out.println("…

寻找第K大的数 C语言实现的一种方法

描述 在一个数组中&#xff0c;找到第K 大的数值一个数组&#xff0c;如&#xff1a;[3,2,1,5,6,4] &#xff0c;输入 2&#xff0c;返回&#xff1a;5也就是这个K的取值&#xff0c;是从 1 开始的&#xff0c;不超过数组的最大个数 解决思路 可以使用任意的排查函数&#x…

C++——寻找第k大的数

给出一个数组&#xff0c;找出数组的第k大的数&#xff1a;基于快速排序的思路&#xff0c;每次快排后&#xff0c;基准的左边都是比其小的数&#xff0c;右边都是比其大的数&#xff0c;一次快排结束后&#xff0c;若基准所处的位置正好是第k大&#xff08;即基准右边有k-1个数…

面试题:从n个数中找出第K大的数

参考https://blog.csdn.net/orangefly0214/article/details/84997668的思路 从有n个元素的乱序数组中找出第k大的元素 方法1&#xff1a;基于冒泡排序和简单选择排序&#xff0c;时间复杂度o(n*k) 我们知道&#xff0c;在冒泡排序和简单选择排序中&#xff0c;最外层的循环每…

在N个数中查找第K大的数字(Top K问题)

在N个乱序数字中查找第k大的数字&#xff0c;时间复杂度可以减小至 O(N*logN)O(N)O(1)O(2) 答案&#xff1a;B 所谓“第&#xff08;前&#xff09;k大数问题”指的是在长度为n(n>k)的乱序数组中S找出从大到小顺序的第&#xff08;前&#xff09;k个数的问题。 注意&…

idea控制台乱码解决方法

一、问题情况&#xff1a; IntelliJ IDEA 控制台输出中文乱码部分如图所示&#xff1a; 二、解决方法&#xff1a; 1.打开tomcat配置页面&#xff0c;Edit Configurations。 2.选择项目部署的tomcat&#xff0c;在配置项VM options文本框中输入-Dfile.encodingUTF-8,点击Appl…

idea 控制台乱码问题的问题

工程(环境window10&#xff0c;gradle-6.8.3版本&#xff0c;编辑器IntelliJ IDEA 2019.3.4&#xff09; 一&#xff09;问题表现编译build的时候控制台带中文信息的会乱码 1、 找到Help->Editor Custom VM Options 2、 添加 -Dfile.encodingUTF-8 该设置是针对编辑器级别…

IDEA中控制台乱码的解决方式

1.在设置中的“文件编码”中将3个位置设为UTF-8&#xff0c;注&#xff1a;此处设置与控制台乱码无关&#xff0c;3处可均设为UTF-8或均设为系统默认值。 2.在Tomcat的“编辑配置”中&#xff0c;将VM options设为-Dfile.encodingGBK(与第三步类似&#xff0c;默认即为GBK)。…

IDEA控制台乱码终极解决办法

【关于IDEA中文乱码的终极解决方法】 查了很多资料&#xff0c;大多数博主都是修改四个地方&#xff1a;&#xff08;前四步&#xff09;如果前四步还是不行&#xff0c;可以看五、六步。第一步&#xff1a;idea 安装目录下/bin/idea.exe.vmoptions 和/bin/idea64.exe.vmoption…