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开发实例(一):简单实现一个贪吃蛇游戏相关推荐

  1. python游戏脚本实例-使用Python写一个贪吃蛇游戏实例代码

    我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的类中,而不是在Snake类中. 特殊食物: 1.绿色:普通,吃了增加体型 2.红色:吃了减少体型 3.金色:吃了回到 ...

  2. python写一个游戏多少代码-使用Python写一个贪吃蛇游戏实例代码

    我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的类中,而不是在Snake类中. 特殊食物: 1.绿色:普通,吃了增加体型 2.红色:吃了减少体型 3.金色:吃了回到 ...

  3. 使用C语言gtk编程一个贪吃蛇游戏设计与实现

    使用C语言以及gtk编程设计一个贪吃蛇游戏. 功能需求: (1)窗口界面设计:创建各种窗口和按钮标签等: (2)小蛇移动控制:按键盘上的上下左右键控制小蛇上下左右移动: (3)游戏进程控制:若小蛇碰到 ...

  4. 如何用python开发一个贪吃蛇游戏_教你一步步利用python实现贪吃蛇游戏

    教你一步步利用python实现贪吃蛇游戏 来源:中文源码网    浏览: 次    日期:2019年11月5日 [下载文档:  教你一步步利用python实现贪吃蛇游戏.txt ] (友情提示:右键点 ...

  5. 使用python game写一个贪吃蛇游戏

    前言 最近在用python 做项目,也想对python有多一些了解,之前有用C语言和C++写过python游戏,刚好可以通过这个游戏来对python多一些了解. 文章内容翻译自以下链接 https:/ ...

  6. 手机java做贪吃蛇_如何用Java写一个贪吃蛇游戏

    这是一位拓胜学员用Java写贪吃蛇游戏的心得:今天课程设计终于结束了自己学java没以前学C+那么用功了觉得我学习在哪里都是个开口向上的抛物线,现在应该在右半边吧,好了进入正题. 写java贪吃蛇也是 ...

  7. 语言写贪吃蛇墙角符号_从零基础到拥抱人工智能,您的孩子可能就差一个贪吃蛇游戏...

    去年寒假档,有一部孩子们喜欢的电影上映. 不知道家长们有没有陪孩子一起看过这部<无敌破坏王2:大闹互联网> 在电影中有一个印象深刻的镜头, 吃豆人.泡泡龙.还有贪吃蛇 他们都因为很久没有客 ...

  8. 天才啊!仅用四个整数编写一个贪吃蛇游戏!

    作者 | Andrei Cioban 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 记得上次编写贪吃蛇游戏还是很多年以前的事,如今我打算尽己所能,在一些很特别的方面做到极致: 将游戏的 ...

  9. 用c语言写一个贪吃蛇游戏代码

    首先,贪吃蛇是一个经典的游戏,主要通过控制一条蛇在地图上吃食物,不断长长身体,最终实现最高分数. 以下是使用C语言编写贪吃蛇游戏的示例代码: ``` #include<stdio.h> # ...

最新文章

  1. Zencart获取PayPal PDT Token参数教程方法
  2. No Module Named '_pywrap_tensorflow_internal'
  3. (转)Android 判断用户2G/3G/4G移动数据网络
  4. springboot-数据访问
  5. 研发阶段模拟接口数据
  6. 【51Nod - 1272 】最大距离 (思维,排序sort的空间优化)
  7. 气象气候应用在Intel最新处理器Icelake上的性能测评
  8. 盘点那些让程序员目瞪口呆的奇葩Bug,最后一个什么梗
  9. 工商银行:应用多k8s集群管理及容灾实践
  10. Spring :Sprin体系
  11. 常见Linux版本概览
  12. [转]更改windows 2003远程桌面连接的端口
  13. vba自动生成html,动态生成嵌入在VBA电子邮件生成中的HTML表
  14. 微信小程序常用样式,特效,方法
  15. python怎么批量下载图片_批量下载网页图片(python)
  16. mysql got signal 6_[ERROR] mysqld got signal 6 错误
  17. 网站运营如何做好活动策划(转载)
  18. Dev-C++5.11游戏创作之简易小炸弹
  19. 《Introducing the Child Process Debugging Power Tool》学习
  20. 安装 ubuntu16.04 ROS2 超过5分钟你打我 后带 测试talker listener demo

热门文章

  1. 详细设计之(人机界面设计问题)
  2. 日语教程 早安日语 名古屋日语 日语mp3 日语教程word版
  3. linux下好用的超级终端,linux下使用超级终端minicom
  4. 【深度学习】特征融合的重要方法 | 张量的拼接 | torch.cat()函数 | torch.add(函数
  5. EasyMock测试
  6. 分享111个JS图片切换特效,总有一款适合您
  7. 《爱情公寓2》大结局引争议 将公布导演剪辑版
  8. 三星Galaxy Note20 Ultra手机UWB芯片信息
  9. pythonaccess系统_Win7(64位系统)中用Python连接access数据库(access2010)
  10. Mastercam2022程序单升级版