悲伤的现实

离期末第一场考试之剩下32天了,而oop的期中project还有24天截止。此刻,我们刚刚写完了人生中第一个c++程序,分数类的运算符重载。继承和多态还没学。尽管如此,也是时候作为全裸勇者勇敢地去挑战大魔王了。

目标

通过研究贪吃蛇小游戏的源码,学会用Qt进行游戏开发,并且完成期中Pro报告中挖下的2D Rougelike类小游戏第一关的大坑,并且写下博客给新鲜的学妹学弟留下可以借鉴的学习经验。

资料

Qt5贪吃蛇小游戏源代码下载处
来自Rimond_Jing的Qt5基本安装教程
来自 齐亮,非常棒的一个参考资料

高能预警

因为目前c++也没学好,Qt也刚开始学,所以本篇博客只适合和我一样什么都不会的人。而且很有可能错误连篇,期待有人能指正。
目前在一遍分析一遍写博客,所以会对内容进行不断地修正

以及非常啰嗦(和废话)

总体分析

注:纯新手一上来就看总体分析极有可能不懂,看看就好,不懂就跳过去看完全文回来再看。

界面转换

在本例子中,采取建立不同的界面类(mainWidget,开始界面,和GameWidget,游戏界面),通过接收事件(event,本例是按下按钮),利用信号和槽,来进行界面切换。

main函数分析

感觉并不需要分析:)

#include "mainWidget.h"
//自己写的主窗口的头文件
#include <QApplication>
//一个基础的类,所有工程(pro文件)都要include。
//有时候include这个文件会报错,可能是因为是Qt4的代码的原因int main(int argc, char *argv[])
{QApplication a(argc, argv);mainWidget w;w.show();return a.exec();
}

主窗口分析:mainWidget

头文件分析

#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include "GameWidget.h"
#include <QWidget>
#include <QIcon>
#include <QPalette>
#include <QBrush>
#include <QPixmap>
#include <QPushButton>
#include <QMessageBox>
#include <QLabel>
#include <QFont>
class mainWidget : public QWidget//继承了QWidget类
{Q_OBJECT
//只要有槽和信号机制,就要写Q_OBJECT
public:mainWidget(QWidget *parent = 0);~mainWidget();//void resizeEvent(QResizeEvent *);
private:QPushButton *startbtn;//一个按钮,用鼠标点击后会开始游戏QPushButton *exitbtn;//一个按钮,用鼠标点击后会退出GameWidget *g;QLabel *label;
signals://信号,mainWidget不会发出信号
public slots://可以接收所有信号的公共槽void exitSlot();//用来接收退出信号的槽void startSlot();//用来接收开始信号的槽
};#endif // MAINWIDGET_H

.cpp文件分析
注释的都是可以在自己的程序中使用的函数

#include "mainWidget.h"mainWidget::mainWidget(QWidget *parent): QWidget(parent)
{this->resize(480,270);//resize函数,用来设置mainWidget这个窗口的大小this->setMaximumSize(480,270);this->setWindowIcon(QIcon(":/new/prefix1/img/icon.png"));//设置ICONthis->setWindowTitle("贪吃蛇");QPalette palette;palette.setBrush(QPalette::Background,QBrush(QPixmap(":/new/prefix1/img/back.jpg").scaled(this->size())));this->setPalette(palette);startbtn=new QPushButton(this);startbtn->setIcon(QIcon(":/new/prefix1/img/start.png"));startbtn->setIconSize(QSize(75,75));startbtn->setGeometry(QRect(250,170,75,75));startbtn->setFlat(true);exitbtn=new QPushButton(this);exitbtn->setIcon(QIcon(":/new/prefix1/img/quit.png"));exitbtn->setIconSize(QSize(70,70));exitbtn->setGeometry(QRect(350,170,70,70));exitbtn->setFlat(true);//设置说明标签QFont font;font.setFamily("Consolas");font.setBold(true);font.setPixelSize(13);label=new QLabel(this);label->setText("游戏说明:贪吃蛇游戏可使用按钮或者w a s d控制蛇的走动");label->setFont(font);label->setGeometry(QRect(10,10,400,50));connect(exitbtn,SIGNAL(clicked()),this,SLOT(exitSlot()));connect(startbtn,SIGNAL(clicked()),this,SLOT(startSlot()));
}mainWidget::~mainWidget()
{delete startbtn;delete exitbtn;
}
void mainWidget::exitSlot()
{if(QMessageBox::question(this,"退出游戏","是否退出当前游戏",QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes){delete this;exit(0);}
}
void mainWidget::startSlot()
{g=new GameWidget(this);g->show();
}
//重写resizeEvent
/*void mainWidget::resizeEvent(QResizeEvent *)
{QPalette palette;palette.setBrush(QPalette::Background,QBrush(QPixmap("img/back.jpg").scaled(this->size())));this->setPalette(palette);startbtn->setGeometry(QRect(this->size().width()-230,this->size().height()-100,75,75));exitbtn->setGeometry(QRect(this->size().width()-130,this->size().height()-100,70,70));
}*/

QMessageBox的初始化及效果

void mainWidget::exitSlot()
{if(QMessageBox::question(this,"退出游戏","是否退出当前游戏",QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes){delete this;exit(0);//直接结束进程}//生成一个弹窗。question的初始化为(链接的窗口,"标题","示意文字",QMessageBox::Yes|QMessageBox::No)
}

游戏窗口分析:GameWidgit

游戏窗口是这个程序的主体部分,各种复杂的事件(槽和信号机制),状态的更新,动画、碰撞检测都是在这个类(游戏窗口就是一个继承了普通窗口< Widget >的派生类)中完成的。

头文件分析

#ifndef GAMEWIDGET_H
#define GAMEWIDGET_H#include <QWidget>
//既然继承自QWidget,肯定需要include相关的头文件
#include <QPalette>
#include <QIcon>
//这些是为了让你在显示背景图片和窗口图标,一般做游戏(自己设计UI)都要用
#include <QPushButton>
//这个库在你有鼠标事件的事后非常好用
#include <QPainter>
//如果有动画,需要包含QPainter库(如果只是显示图片可以用其他方法,但游戏一般都有动画)
#include <QDebug>
//主要用于调试代码,类似于std::cout的替代品,支持QT的数据类型。
#include <QTime>
#include <QTimer>
//和计时有关的库,做游戏也一般都要用到
#include <QMessageBox>
//如果你的游戏有弹出框,就要包含(非必须)
#include <QKeyEvent>
//如果你的游戏可以用键盘操纵,需要包含
#include <QLabel>
//可以用来显示字(也可以显示图片)
#include <QFont>
//如果你要用Qt绘制字(而不是用自己设计的UI)时,需要包含
#include <QSound>
//音频相关,游戏一般必须class GameWidget : public QWidget
{Q_OBJECT
public://构造函数explicit GameWidget(QWidget *parent = 0);~GameWidget();//绘制事件,游戏中非常重要的函数void paintEvent(QPaintEvent *);//键盘事件void keyPressEvent(QKeyEvent *);
private://按钮相当于鼠标事件QPushButton *upbtn;QPushButton *leftbtn;QPushButton *downbtn;QPushButton *rightbtn;QPushButton *startbtn;QPushButton *returnbtn;//记录蛇目前运动方向int direction;//用来记录蛇xy坐标,可以看出最大能得100分int snake[100][2];int snake1[100][2];//计算吃过了几个食物int foodcount;//计时器!和动画的帧数也有关QTimer *timer;//食物的属性int foodx,foody;int score;int level;QLabel *scorelabel;QLabel *levellabel;QLabel *scoreshow;QLabel *levelshow;QString str1,str2;QSound *sound;QSound *sound1;
signals:
//因为有键盘事件(KeyPressEvent),键盘事件要发射不同的信号void UpSignal();void DownSignal();void LeftSignal();void RightSignal();
public slots://一般来说有几个按钮就要有几个槽函数void upbtnSlot();void leftbtnSlot();void rightbtnSlot();void downbtnSlot();void startbtnSlot();void returnbtnSlot();//本例的主函数,和timer结合使用(比较复杂,之后会详细讲)void timeoutSlot();
};#endif // GAMEWIDGET_H

QDebug的说明

.c文件分析
因为GameWidget略长,且有一些部分和MainWidget用法一致,就不放上来全部代码(想要自己运行的可以从之前附上的链接下载,记得只适用于QT5
注: 需要include相应的库文件

1.如何让你的游戏发出声音
首先要载入音频

    //声音区:载入音频,注意音频文件要加入.qrc文件中sound=new QSound(":/listen/img/5611.wav");sound1=new QSound(":/listen/img/die.wav");

在什么时候播放声音,使用if语句判断,一般是一个可以update()的槽函数中(本例为timeoutSlot(),见下文)

sound->play();

2.如何即时显示得分

    str1=QString::number(score);//转化为字符串scoreshow=new QLabel(this);//用Label输出scoreshow->setFont(font);scoreshow->setGeometry(QRect(385,1,60,30));scoreshow->setText(str1);

3.如何设置交互(信号和槽机制)

    //设置按钮操作connect(leftbtn,SIGNAL(clicked()),this,SLOT(leftbtnSlot()));connect(rightbtn,SIGNAL(clicked()),this,SLOT(rightbtnSlot()));connect(upbtn,SIGNAL(clicked()),this,SLOT(upbtnSlot()));connect(downbtn,SIGNAL(clicked()),this,SLOT(downbtnSlot()));connect(startbtn,SIGNAL(clicked()),this,SLOT(startbtnSlot()));connect(returnbtn,SIGNAL(clicked()),this,SLOT(returnbtnSlot()));//设置键盘操作connect(this,SIGNAL(UpSignal()),upbtn,SLOT(click()));connect(this,SIGNAL(DownSignal()),downbtn,SLOT(click()));connect(this,SIGNAL(LeftSignal()),leftbtn,SLOT(click()));connect(this,SIGNAL(RightSignal()),rightbtn,SLOT(click()));

connect的使用

connect(发射信号的类,SIGNAL(信号函数),接收信号的类,SLOT(槽函数));

按钮操作的实现
QPushButton这个类中有click()的信号函数和槽函数,如果发生了鼠标点击事件,被点击的Button就发射click()信号,因为我们用connect将这个信号和GameWidget中的槽函数(比如leftbtnSlot())连接起来,GameWidget就能接收到这个信号并且调用相应的槽函数。
键盘操作同理,因为KeyPressEvent是我们自己写在GameWidget类中,所以为 ‘this’ 指针。这次connect是把键盘事件和按钮联系了起来。

4.如何设置随机数

    QTime t;t= QTime::currentTime();qsrand(t.msec()+t.second()*1000);

5.如何update程序

    timer=new QTimer(this);timer->setInterval(500);//设置时间间隔connect(timer,SIGNAL(timeout()),this,SLOT(timeoutSlot()));

该程序设置了一个timer(一个定时触发器,参考这里),并且设置了时间间隔,每过一次时间间隔发送一个timeout()信号。
而GameWidget类中定义了timeoutSlot()槽函数,每过一定时间间隔被调用,执行update()操作,来更新界面状态,下文会讲

6.(重点)timeoutSlot分析
因为这一段很长,也只写出代码结构(需要完整代码见开头链接)

void GameWidget::timeoutSlot()
{//判断是否吃到食物的代码块(判断蛇的坐标和食物的坐标是否重合)//其中包含,发出声音、更新食物坐标(随机更新,食物不能出现在蛇身上)、如果分数到达一定的档次,就提升游戏等级(改变时间间隔)memcpy(snake1,snake,sizeof(snake));//不能直接对目前显示的数组进行操作,因此一开始就定义了两个数组存放当前状态和改变后的状态,用memcpy拷贝//实现蛇的游动for(int i=foodcount;i>=1;i--){snake[i][0]=snake[i-1][0];snake[i][1]=snake[i-1][1];}switch(direction){case UP:snake[0][1]--;break;case DOWN:snake[0][1]++;break;case LEFT:snake[0][0]--;break;case RIGHT:snake[0][0]++;break;}//判断蛇是否撞到自身的代码块,如果撞到,显示游戏结束的弹窗,并重置游戏//判断蛇是否撞到墙体的代码块//最关键,调用update()函数,更新窗口状态this->update();
}

memcpy辅助理解
update辅助理解
其中的碰撞检测机制是通过判断xy坐标是否相同来进行的。
Qt工具书上似乎有其他碰撞检测的办法,挖个坑

7.(重点)paintEvent分析
函数声明

void GameWidget::paintEvent(QPaintEvent *);

要定义一个绘制器painter

QPainter painter(this);

画一个小方格(长方形)的代码(该游戏画了很多很多小方格),只摘取一个:j,i是坐标,20, 20是方格的大小

painter.drawRect(j,i,20,20);

读取素材绘制
foodx要乘20的原因是这是相对坐标,而不是绝对坐标

painter.drawImage(foodx*20,foody*20,QImage(":/new/prefix1/img/apple.png").scaled(QSize(20,20)));

该游戏主要用到的就是这两种绘制方式、当然还有更多的绘制方式:参考这里

今日学习获得的一些经验

  • Qt4和Qt5虽然用法差别不大,但是Qt4的代码在Qt5上很难跑通。Qt4的游戏源代码值得参考,但要自己尝试运行,还是去找Qt5的源代码吧。
  • Qt的各种参考书和博客中给的代码多是模板,不要直接放在Qt中运行
  • Qt中读取资源(图片、音频etc)都要把文件加入qrc文件中以获取相对路径

吐槽:根本不是今日获得的经验,从上周开始写一直拖到现在orz

end

【游戏制作】 从零开始的Qt5贪吃蛇代码分析相关推荐

  1. python制作贪吃蛇游戏下载_自动玩贪吃蛇,满屏的蛇影当然由python制作AI贪吃蛇!...

    image 前提:本文实现AI贪吃蛇自行对战,加上人机对战,文章末尾附上源代码以及各位大佬的链接,还有一些实现步骤,读者可再次基础上自行添加电脑VS电脑和玩家VS玩家(其实把人机对战写完,这2个都没什 ...

  2. html游戏贪吃蛇代码,html5贪吃蛇游戏使用63行代码完美实现

    以前也很少关注html5,感觉选择html已经慢慢成为趋势,想了解下.就找了个游戏学习了,写完这个游戏感觉html5和js结合很紧密,如果js不是特别好.估计需要先补习下js,这个只是个人的建议,不一 ...

  3. 面向对象编程java小游戏_JavaScript面向对象编程小游戏---贪吃蛇代码实例

    1 面向对象编程思想在程序项目中有着非常明显的优势: 1- 1 代码可读性高.由于继承的存在,即使改变需求,那么维护也只是在局部模块 1-2 维护非常方便并且成本较低. ​2 这个demo是采用了面向 ...

  4. 【Python游戏】pygame模块制作飞机大战、贪吃蛇(多模式)含源码

    pygame模块制作飞机大战.贪吃蛇(多版本) 本章意在学习pygame模块以及巩固python语法. 若有需请转去个人github:https://github.com/onlyhyl/pyGame

  5. C语言小游戏大全,C语言贪吃蛇小游戏(附源码)

    一.C语言小游戏大全,C语言贪吃蛇小游戏(附源码) 贪吃蛇小游戏源码和更多C语言课设项目小游戏源码免 费 下 载 链 接 如下: c语言项目课设小游戏源码资料压缩包.zip-C文档类资源-CSDN下载 ...

  6. 单片机设计 游戏_五子棋+黄金矿工+贪吃蛇(STM32、4.3寸电容屏)

    单片机设计 游戏_五子棋+黄金矿工+贪吃蛇(STM32.4.3寸电容屏) 想要更多项目私wo!!! 一.电路设计 此电路由STM32F1精英版和4.3寸电容屏TFTLCD组成. 二.运行效果 三.部分 ...

  7. 贪吃蛇的c语言程序码,C语言贪吃蛇代码下载_C语言贪吃蛇代码官方下载-太平洋下载中心...

    C语言编写贪吃蛇源代码,简单易懂,文件为VC源代码.如果你正在学习c语言,就来下载吧.很经典的. C语言贪吃蛇代码原理: 产生一个固定大小没有边界的游戏区域,蛇从区域的中心开始,由玩家通过键盘控制蛇的 ...

  8. SwiftUI 游戏源码大全之贪吃蛇游戏基于GeometryReader和Preference

    实战需求 SwiftUI 游戏源码大全之贪吃蛇游戏基于GeometryReader和Preference 本文价值与收获 看完本文后,您将能够作出下面的界面 游戏规则 你抓住一个圆圈时,蛇会增长一段. ...

  9. c语言程序的英式棋盘,使用棋盘法的贪吃蛇代码

    使用棋盘法的贪吃蛇代码 在我此前发了一篇对其他人的贪吃蛇C代码的分析和注释,在那个代码中的算法主要是用一个线性表存储蛇的所有身体节点的位置.然后随着游戏进行,需要把相应的蛇身节点依次平移一次(把数组里 ...

最新文章

  1. C# ref和out关键字
  2. 网页制作中绝对路径和相对路径的区别
  3. js取整、四舍五入等数学函数
  4. s11.9 sar:收集系统信息
  5. Socket通信 客户端加密数据,传递数据密文到服务端,服务端解密密文 输出明文
  6. visio图标_弱电间机柜原型图整理,可编辑!(Excel,visio,CAD)
  7. sevlet中web.xml 文件
  8. c#使用类库nthereum在.net上开发以太坊的实战示例
  9. 排列组合公式及排列组合算法
  10. html好看的后台页面布局,25 个精美的后台管理界面模板和布局
  11. java判断闰年条件
  12. 计算机系统分别由,计算机系统由两部分组成它们分别是什么
  13. win7怎么修改系统语言
  14. 普华永道-开放数据资产估值白皮书,首创“数据势能”估值模型
  15. oeasy教您玩转vim - 21 - 状态横条
  16. 基于距离传感器的I2C通信(一)
  17. mp4视频太大怎么压缩?
  18. 如何培养对编程开发的兴趣
  19. 循环函数:while循环和for循环及函数定义
  20. 商城系统开发使用微信服务号和小程序那个好?

热门文章

  1. 打造一支有战斗力的团队
  2. C# 对word 页眉页脚处理注意点
  3. lastlog命令系统安全
  4. 使用Python批量下载无版权图片
  5. 计算机专业朋友圈文案,2020毕业朋友圈文案 毕业分别时发朋友圈的句子
  6. 高考400分计算机专业,高考400分 计算机专业
  7. php获取时间不准,php获取时间不准确怎么办
  8. 线性渐变—发廊灯/扫描灯
  9. 傻叉iphone一直输的锁屏密码突然变了
  10. CF #580 Div. 2 D. Shortest Cycle//floyd求最小正环(模板