QT开发实例(一):简单实现一个贪吃蛇游戏
QT开发实例
提示:本专栏所用版本仅供参考,其他版本也可
库 | 版本 |
---|---|
QT | 5.14:下载 |
源码下载 | 点击下载 |
游戏包下载 | 点击下载 |
QQ群 | 点击加群:928357277 |
开发目录
- <b><font size= "4" > 一:学前准备
- <b><font size= "4">二:实现
- 1、创建画布
- 2、创建一条4格原始小蛇
- 3、创建个豆子
- 4、定义键盘事件
- 5、控制小蛇移动
- 6、生成豆子
- 7、类的构造函数.cpp
- 8、类的定义文件.h
一:学前准备
本教程将讲述如下内容
1:如何在画布上绘制贪吃蛇的身体
2:如何生成豆子
3:如何让贪吃蛇被键盘控制
4:如何让贪吃蛇在固定画布内移动
5:键盘事件,定时器事件,画布事件的学习
关于本教程所需的源码及其EXE文件将打包上传,欢迎大家下载,也可以加群免费下载。
二:实现
1、创建画布
我们首先在类的protected成员中创建一个QT类中的画布事件,在事件函数内实现相关功能
//函数在类内申明
void paintEvent(QPaintEvent *event);//定义画笔事件
{QPainter painter(this);//创建一张画布QPen pen;//创建一只画笔对penpainter.setPen(pen);//将画笔设置到画布中去QBrush brs(Qt::black);//创建并设置笔刷为黑色QFont font("黑体",12,QFont::ExtraLight,false);//说明栏设置painter.setFont(font);//画布插入字体painter.drawText(20,40,QString("控制:")+QString("移动:上下左右——出豆子:空格——退出:ESC"));
}
2、创建一条4格原始小蛇
定义一个长10宽10,且初始长度为4(也就是4个10*1长度的小蛇),他的每个身体方块的坐标存入QLIST容器中
#define itsBoy 10//定义蛇的身体大小为
#define mapMin 40 //地图X坐标的最远距离
#define mapMax 490 //地图Y坐标的最远距离private:int snakeInit = 4;//定义初始化长度QList<int>snake_x;//用LIST保存蛇的身体QList<int>snake_y;int snake_boy=itsBoy; //蛇的身体大小
在画布中画出蛇的第一个身体
void paintEvent(QPaintEvent *event);//定义画笔事件
{QPainter painter(this);//定义一张画布QPen pen;//定义一张画笔painter.setPen(pen);//将画笔设置到画布中去pen.setWidth(snake_boy);//笔刷宽度设置为蛇的宽度QBrush brs(Qt::black);//设置笔刷为黑色QFont font("黑体",12,QFont::ExtraLight,false);//计数栏设置painter.setFont(font);//画布插入字体painter.drawText(20,40,QString("控制:")+QString("移动:上下左右——出豆子:空格——退出:ESC"));brs.setColor(Qt::darkGray);//改变笔刷颜色painter.setBrush(brs);//画出矩形,蛇for(int i=0;i<snake_x.length();i++){painter.setBrush(brs);//设置画笔笔刷painter.drawEllipse(snake_x.at(i),snake_y.at(i),snake_boy,snake_boy);//画出蛇的身体}
}
3、创建个豆子
创建一个大小等于蛇身体方块大小的方块作为豆子
private:int snakeBean=itsBoy;//豆子的身体int beanx=-100;//豆子的坐标int beany=-100;
在画布中绘制豆子
void mainUi::paintEvent(QPaintEvent *event) //画家函数
{QPainter painter(this);//定义一张画布QPen pen;//定义一张画笔painter.setPen(pen);//将画笔设置到画布中去pen.setWidth(snake_boy);//笔刷宽度设置为蛇的宽度QBrush brs(Qt::black);//设置笔刷为黑色QFont font("黑体",12,QFont::ExtraLight,false);//计数栏设置painter.setFont(font);//画布插入字体painter.drawText(20,40,QString("控制:")+QString("移动:上下左右——出豆子:空格——退出:ESC"));brs.setColor(Qt::darkGray);//改变笔刷颜色painter.setBrush(brs);//画出矩形,蛇for(int i=0;i<snake_x.length();i++){painter.setBrush(brs);//设置画笔笔刷painter.drawEllipse(snake_x.at(i),snake_y.at(i),snake_boy,snake_boy);//画出蛇的身体}//画豆子if(beanx>0&&beany>0){brs.setColor(Qt::darkMagenta);//设置豆子颜色brs.setStyle(Qt::ConicalGradientPattern);//设置笔刷样式painter.setBrush(brs);painter.drawRect(beanx,beany,snake_boy,snake_boy);//画出豆子的身体}}
4、定义键盘事件
需要注意的是,当小蛇头部朝下的时候,按照游戏的逻辑,不能直接控制小蛇朝上移动,所以,在写键盘事件的时候,我们应该判断小蛇的朝向问题
void mainUi::keyPressEvent(QKeyEvent *event) //定义键盘事件
{switch(event->key()){case Qt::Key_Up://枚举值为键盘上的向上方向键if(moveFlag!= 'D')//如果小蛇头没有朝下,则可以直接朝上移动,否则,小蛇不产生任何变化{moveFlag ='U';}break;case Qt::Key_Down:if(moveFlag !='U'){moveFlag ='D';}break;case Qt::Key_Right:if(moveFlag != 'L'){moveFlag ='R';}break;case Qt::Key_Left:if(moveFlag != 'R'){moveFlag='L';}break;case Qt::Key_Space://按下空格键getaBean();//生成豆子,大家也可以不写按下空格键,直接把该函数写在吃豆子的函数内,这样写是为了方便演示break;case Qt::Key_Escape://按下退出键,退出游戏this->close();}update();
}
5、控制小蛇移动
前面,我们已经在画布上绘制了一条小蛇,并且在键盘事件中写入了小蛇移动的条件。那么小蛇具体应该怎么移动呢?
写之前我们要明白如下原理
1、小蛇的移动首先应该判断他当前移动的方向,如左边,右边,我们用一个变量来保存这个这个方向。
2、小蛇在移动期间,除了头部,也就是第一个坐标需要判断下一个要移动的坐标,其他蛇身只需要将坐标移信息改变为前一个身体的信息即可。即第三个身体在向前移动后,他的坐标信息将变成第二个身体的坐标信息,不需要重新计算。
3、小蛇要在没有按下按键的清空下移动,就需要有一个一直更新画布的函数,在QT中,定时器可以完成这个动作。
5,、小蛇移动过过程中,判断窗口边界和吃豆子,只需要用头部所处的位置判断即可,因为后续所有身体的移动,都要经过头部。
//除了第一个,之后每次的坐标都和前一次坐标相等
void mainUi::moveUp()//要注意移动的时候的坐标
{int snakexbrfore[2]={0},snakeybrfore[2]={0},signale=0;if((snake_y[0]>snake_y[1]&&snake_x[0]==snake_x[1])||snake_y[0]<=mapMin){signale=1;}//判断边界,并且判断第二个身体在第一个身体的哪个位置for(int i=0;i<snake_y.length()&&signale==0;i++)//如果没有就吃豆子{if(i==0&&snake_y[i]<=snake_y[i+1]){snakexbrfore[0]=snake_x[i];snakeybrfore[0]=snake_y[i];snake_y[i]-=snake_boy;if(snake_x[i]==beanx&&snake_y[i]==beany){snake_x.append(beanx);snake_y.append(beany);beanx=-mapMax;beany=-mapMax;}continue;}movedll(snakexbrfore,snakeybrfore,i);//除头部以外的身体移动函数}
}
//向下移动
void mainUi::moveDown()
{int snakexbrfore[2]={0},snakeybrfore[2]={0},signale=0;if((snake_y[0]<snake_y[1]&&snake_x[0]==snake_x[1])||snake_y[0]>=mapMax){signale=1;}//判断边界,并且判断第二个身体在第一个身体的哪个位置for(int i=0;i<snake_y.length()&&signale==0;i++){if(i==0){snakexbrfore[0]=snake_x[i];snakeybrfore[0]=snake_y[i];snake_y[i]+=snake_boy;if(snake_x[i]==beanx&&snake_y[i]==beany){snake_x.append(beanx);snake_y.append(beany);beanx=-mapMax;beany=-mapMax;}continue;}movedll(snakexbrfore,snakeybrfore,i);//除头部以外的身体移动函数}
}
/*遍历整个列表:同X坐标判断,每次只移动一次
*/
void mainUi::moveLeft()//向左移动
{int snakexbrfore[2]={0},snakeybrfore[2]={0},signale=0;if((snake_x[0]>snake_x[1]&&snake_y[0]==snake_y[1])||snake_x[0]<=mapMin){signale=1;}for(int i=0;i<snake_y.length()&&signale==0;i++){if(i==0){snakexbrfore[0]=snake_x[i];snakeybrfore[0]=snake_y[i];snake_x[i]-=snake_boy;if(snake_x[i]==beanx&&snake_y[i]==beany){snake_x.append(beanx);snake_y.append(beany);beanx=-mapMax;beany=-mapMax;}continue;}movedll(snakexbrfore,snakeybrfore,i);}
}
void mainUi::moveRight()//向右移动
{int snakexbrfore[2]={0},snakeybrfore[2]={0},signale=0;if((snake_x[0]<snake_x[1]&&snake_y[0]==snake_y[1])||snake_x[0]>=mapMax){signale=1;}for(int i=0;i<snake_y.length()&&signale==0;i++){if(i==0){snakexbrfore[0]=snake_x[i];snakeybrfore[0]=snake_y[i];snake_x[i]+=snake_boy;if(snake_x[i]==beanx&&snake_y[i]==beany){snake_x.append(beanx);snake_y.append(beany);beanx=-mapMax;beany=-mapMax;}continue;}movedll(snakexbrfore,snakeybrfore,i);}
}void mainUi::movedll(int *x,int *y,int i)//公共函数部分//除头部以外的身体移动
{*(x+1)=snake_x[i];*(y+1)=snake_y[i];snake_x[i]=*x;snake_y[i]=*y;*x=*(x+1);*y=*(y+1);
}//定时器中断执行函数
void mainUi::timefoult()
{current_time++;if(moveFlag == 'D'){moveDown();}if(moveFlag == 'U'){moveUp();}if(moveFlag == 'L'){moveLeft();}if(moveFlag == 'R'){moveRight();}update();//更新画布
}
类中的相关构造和定义
#define mapMin 40 //地图X坐标的最远距离
#define mapMax 490 //地图Y坐标的最远距离private:char moveFlag ='u'; //定义初始化方向QTimer *timer = nullptr;//创建定时器对象
protected:void keyPressEvent(QKeyEvent *event);//定义键盘事件void paintEvent(QPaintEvent *event);//定义画笔事件
6、生成豆子
用C++提供的随机数生成器Srand()生成豆子的坐标
void mainUi::getaBean()//生成一个豆子,也就是随机生成一个整数坐标(位于500之内)
{//用四舍五入法生成坐标int x=40+(rand()%mapMax-40),y=rand()%mapMax;//X,Y的范围为40 ~ mapMax之间if((x%10)!=0){x+=(10-(x%10));}if((y%10)!=0){y+=(10-(y%10));}beanx=x,beany=y;//坐标保存至类中的beanx,beany变量中
}
7、类的构造函数.cpp
mainUi::mainUi(QWidget *parent) :QWidget(parent)
{// ui->setupUi(this);this->setWindowTitle("行走的小蜜蜂");this->setWindowIcon(QIcon(":/photo/green.jpg"));//加入图标resize(mapMax+10,mapMax+10);//窗口尺寸 X ,YsetStyleSheet("QWidget{background:white}"); //设置窗口颜色setWindowFlags(Qt::FramelessWindowHint);//去掉标题栏this->setAttribute(Qt::WA_TranslucentBackground);//设置背景透明srand((unsigned)time(NULL));//把时间作为随机数种子timer = new QTimer;//创建一个定时器对象timer->start(100);//开启定时器100msconnect(timer,&QTimer::timeout,this,&mainUi::timefoult);//定时器信号snake_x<<100<<100<<100<<100;//定义初始化坐标位置snake_y<<100<<110<<120<<130;
}
8、类的定义文件.h
//头文件中包含了其他项目的头文件,大家根据需要删除即可
#include "QKeyEvent"
#include <QWidget>
#include <QRectF>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QDebug>
#include <QTimer>
#include <QDebug>
#include <QPaintEvent>
#include <QTimerEvent>
#include <QIcon>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPalette>#define itsBoy 10
#define mapMin 40
#define mapMax 490namespace Ui {class mainUi;
}class mainUi : public QWidget
{Q_OBJECTpublic:explicit mainUi(QWidget *parent = 0);~mainUi();private:
/********************************
移动
********************************/void moveLeft();void moveRight();void moveUp();void moveDown();void movedll(int *x,int *y,int i);//公共函数部分用一个函数代替
/********************************
豆子
********************************/void getaBean();void timefoult();
private:Ui::mainUi *ui;char moveFlag ='u'; //定义初始化方向int snakeInit = 4;//定义初始化长度QTimer *timer = nullptr;QList<int>snake_x;//用LIST保存蛇的身体QList<int>snake_y;int snake_boy=itsBoy;int current_time=0;int snakeBean=itsBoy;int beanx=-100;//豆子的坐标int beany=-100;protected:void keyPressEvent(QKeyEvent *event);//定义键盘事件void paintEvent(QPaintEvent *event);//定义画笔事件
};
运行结果:(屏幕中间区域为游戏运行区域)
QT开发实例(一):简单实现一个贪吃蛇游戏相关推荐
- python游戏脚本实例-使用Python写一个贪吃蛇游戏实例代码
我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的类中,而不是在Snake类中. 特殊食物: 1.绿色:普通,吃了增加体型 2.红色:吃了减少体型 3.金色:吃了回到 ...
- python写一个游戏多少代码-使用Python写一个贪吃蛇游戏实例代码
我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的类中,而不是在Snake类中. 特殊食物: 1.绿色:普通,吃了增加体型 2.红色:吃了减少体型 3.金色:吃了回到 ...
- 使用C语言gtk编程一个贪吃蛇游戏设计与实现
使用C语言以及gtk编程设计一个贪吃蛇游戏. 功能需求: (1)窗口界面设计:创建各种窗口和按钮标签等: (2)小蛇移动控制:按键盘上的上下左右键控制小蛇上下左右移动: (3)游戏进程控制:若小蛇碰到 ...
- 如何用python开发一个贪吃蛇游戏_教你一步步利用python实现贪吃蛇游戏
教你一步步利用python实现贪吃蛇游戏 来源:中文源码网 浏览: 次 日期:2019年11月5日 [下载文档: 教你一步步利用python实现贪吃蛇游戏.txt ] (友情提示:右键点 ...
- 使用python game写一个贪吃蛇游戏
前言 最近在用python 做项目,也想对python有多一些了解,之前有用C语言和C++写过python游戏,刚好可以通过这个游戏来对python多一些了解. 文章内容翻译自以下链接 https:/ ...
- 手机java做贪吃蛇_如何用Java写一个贪吃蛇游戏
这是一位拓胜学员用Java写贪吃蛇游戏的心得:今天课程设计终于结束了自己学java没以前学C+那么用功了觉得我学习在哪里都是个开口向上的抛物线,现在应该在右半边吧,好了进入正题. 写java贪吃蛇也是 ...
- 语言写贪吃蛇墙角符号_从零基础到拥抱人工智能,您的孩子可能就差一个贪吃蛇游戏...
去年寒假档,有一部孩子们喜欢的电影上映. 不知道家长们有没有陪孩子一起看过这部<无敌破坏王2:大闹互联网> 在电影中有一个印象深刻的镜头, 吃豆人.泡泡龙.还有贪吃蛇 他们都因为很久没有客 ...
- 天才啊!仅用四个整数编写一个贪吃蛇游戏!
作者 | Andrei Cioban 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 记得上次编写贪吃蛇游戏还是很多年以前的事,如今我打算尽己所能,在一些很特别的方面做到极致: 将游戏的 ...
- 用c语言写一个贪吃蛇游戏代码
首先,贪吃蛇是一个经典的游戏,主要通过控制一条蛇在地图上吃食物,不断长长身体,最终实现最高分数. 以下是使用C语言编写贪吃蛇游戏的示例代码: ``` #include<stdio.h> # ...
最新文章
- Zencart获取PayPal PDT Token参数教程方法
- No Module Named '_pywrap_tensorflow_internal'
- (转)Android 判断用户2G/3G/4G移动数据网络
- springboot-数据访问
- 研发阶段模拟接口数据
- 【51Nod - 1272 】最大距离 (思维,排序sort的空间优化)
- 气象气候应用在Intel最新处理器Icelake上的性能测评
- 盘点那些让程序员目瞪口呆的奇葩Bug,最后一个什么梗
- 工商银行:应用多k8s集群管理及容灾实践
- Spring :Sprin体系
- 常见Linux版本概览
- [转]更改windows 2003远程桌面连接的端口
- vba自动生成html,动态生成嵌入在VBA电子邮件生成中的HTML表
- 微信小程序常用样式,特效,方法
- python怎么批量下载图片_批量下载网页图片(python)
- mysql got signal 6_[ERROR] mysqld got signal 6 错误
- 网站运营如何做好活动策划(转载)
- Dev-C++5.11游戏创作之简易小炸弹
- 《Introducing the Child Process Debugging Power Tool》学习
- 安装 ubuntu16.04 ROS2 超过5分钟你打我 后带 测试talker listener demo
热门文章
- 详细设计之(人机界面设计问题)
- 日语教程 早安日语 名古屋日语 日语mp3 日语教程word版
- linux下好用的超级终端,linux下使用超级终端minicom
- 【深度学习】特征融合的重要方法 | 张量的拼接 | torch.cat()函数 | torch.add(函数
- EasyMock测试
- 分享111个JS图片切换特效,总有一款适合您
- 《爱情公寓2》大结局引争议 将公布导演剪辑版
- 三星Galaxy Note20 Ultra手机UWB芯片信息
- pythonaccess系统_Win7(64位系统)中用Python连接access数据库(access2010)
- Mastercam2022程序单升级版