基于QT的飞行射击游戏的实现

2017-12-15 20:45成荣荣崔志斌杨克香
电脑知识与技术 2017年32期
关键词:计时器布局按钮

成荣荣++崔志斌+杨克香

摘要:飞行射击游戏因操作简单、娱乐性强而广受欢迎。在Linux操作系统下,以Qt为开发平台,采用C++语言设计了一款小型飞行射击类游戏,主要采用类Element和类GamePad来实现游戏的功能。

关键词:Qt;射击游戏;C++

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)32-0089-03

Realization of Flight Shooting Game Based on QT

CHENG Rong-rong1, CUI Zhi-bin2, YANG Ke-xiang1

(1.Kunshan dengyun college of science and technology, Kunshan 215300, China; 2.suzhou huatian shihang smart equipment technology CO.LTD, Kunshan 215300, China)

Abstrsct:The flight shooting game is very popular because of its simple,entertaining.In the Linux operating system,Qt as the development platform,using C++ language design a small flight shooting game,Mainly using class Element and class GamePad to achieve the function of the game.

Key words: Qt; shooting game; C++

Qt是一个跨平台应用程序和UI开发框架,具有完整的Qt集成开发环境,其中包括高级C++编译器、项目生成和管理工具,图形化调试器代码管理等等,适用于游戏界面的开发和应用,同时也适用于移动设备软件的设计,例如手机游戏方面[1-2]。在Linux操作系统下,执行完Qt安装包,导入库文件,对环境进行一定的配置之后,就可以在Qt环境中进行C++程序的编辑[3-4]。游戏包括开始(start)、暂停(pause)、结束(end)等,当进入游戏登陆界面时,点击开始(start)开始游戏,点击暂停(pause),可中途停止游戏,当异常或者游戏结束时,可选择结束退出,整个游戏结构如图1所示。

1 类的关系图和作用

游戏主要通过类Element和类GamePad来实现,其中类Element主要存放的是界面右侧的功能键(开始、暂停、结束)、计时器等功能组件。类GamePad的主要功能是生成游戏主界面比如游戏的背景地图等,Map类、Plane类和Bullet类分别在Gamepad类中实现。类的关系如图2所示,各类的作用如表1所示。由于篇幅限制,这里主要介绍类Element和Widget。

2 类Element

2.1 按钮组件

类Element所包含的内容包括:开始,暂停,结束按钮和计时器。定义代码如下:

QPushButton*startBtn;

QPushButton*pauseBtn;

QPushButton*ExitBtn;

QPixmapstartMap,pauseMap,exitMap;

QLabel*ScoreLab;

QLineEdit*ScorePad;

QLabel*TimeLab;

QLineEdit*TimePad;

QLabel*LifeLab;

QLineEdit*LifePad;

首先,startBtn,pauseBtn,ExitBtn聲明分别为开始、暂停、结束按钮,三个按钮的公共类为QpushButton,这是代表按钮的类,实例化的三个按钮,便作为游戏界面上的控制按钮。另外,由类QPixmap声明的StartMap,PauseMap,ExitMap导入的是三个绘图,用于按钮上的三个图标,Qpixmap的主要作用就是绘图,其主要依赖于硬件,与同作用的类QImage相比,类QPixMap是针对屏幕显示而最优化设计,而QImage主要是为图像I/O、图片访问和像素修改而设计的。当图片小的情况下,直接用QPixmap进行加载,画图时无所谓,当图片大的时候如果直接用QPixmap进行加载,会占很大的内存,一般一张几十K的图片,用QPixmap加载进来会放大很多倍,所以一般图片大的情况下,用QImage进行加载,然后转乘QPixmap用户绘制。QPixmap绘制效果是最好的。因此在按钮上绘制图标,便优先选择了QPixMap。

其次,TimeLab和LifeLab声明的是两个标签,分别代表时间和生命数,它们的公共类是QLabel类代表标签,其声明的两个类就是两个计数器前的标志。

最后,通过文本编辑器QLineEdit类声明了两个对象,分别为TimePad、LifePad分别代表时间、生命数的三个显示框,QLineEdit表示行编辑器,经过相应的处理最终显示在界面上的就像是LED的效果。

各项组件实例化之后,需要完成的工作就是进行布局安排,如何布局对于游戏的可视性极为重要,一般的布局管理方面,便利的方法是使用布局管理器,常用的布局管理有以下几种:

1) QVBoxLayout(垂直布局)用于位于竖直方向的组件的布局管理。

2) QHBoxLayout(水平布局)管理水平方向的布局。

3) QGridLayout(网格布局)可以在一个网格范围内进行布局管理。endprint

4) QstacketLayout(堆叠布局)管理位于同一坐标上的多个组件。

布局管理的弊端在于,布局呈现的外观略显生硬僵化,無法达到某些特定的预期,例如本游戏的相关组件布局,需要有大小、位置、美观上的严格要求,所以采用的布局是原始的布局方式,即按照坐标点,人为的进行安置,这样便可以随意愿,布置界面的格局。在各组件定义实例化之后,游戏布局的代码如下:

ScoreLab→setGeometry(0,30,50,40);

ScorePad→setGeometry(50,30,80,40);

LifeLab→setGeometry(0,90,50,40);

LifePad→setGeometry(50,90,80,40);

TimeLab→setGeometry(0,150,50,40);

TimePad→setGeometry(50,150,80,40);

pauseBtn→setGeometry(0,425,50,50);

startBtn→setGeometry(0,425,50,50);

ExitBtn→setGeometry(75,425,50,50);

其中,startBtn和pauseBtn所处的坐标位置一致,利用setShown方法设置按钮的可见性,即当点击按钮时该按钮就会消失,相应的同位置的另一个组件就会显示出来,这样就实现了按钮的切换,实现方法如下:

1) 在文件定义两个槽函数,分别为pauseBtnClicked()和startBtnClicked(),定义代码如下:

void Element::startBtnClicked()

{startBtn→setShown(0);

pauseBtn→setShown(1);}

void Element::pauseBtnClicked()

{pauseBtn→setShown(0);

startBtn→setShown(1);}

2) 使用connect方法,将信号与槽相连接,实现如下:

connect(startBtn,SIGNAL(clicked()),this,SLOT(startBtnClicked()));

connect(pauseBtn,SIGNAL(clicked()),this,SLOT(pauseBtnClicked()));

当setShown()参数为0时表示,组件为不可视,为一时则显现出来,当按钮被点击时,会发出信号,如代码中SIGNAL中的clicked()参数,接受到信号后就会自动调用SLOT中的函数,即先前定义的槽函数。

信号和槽有以下几种关联情况:1)一个信号可以连接多个槽;2)多个信号可以连接一个槽;3)一个信号可以与另外一个信号连接;4)连接可以解除[3]。

所有从Qobject或其子类(例如Qwidget)派生的类都能够包含信号和槽。当对象改变其状态时,信号就由该对象发射(emit)出去,这就是对象所要做的全部事情,它不知道另一端是谁在接收这个信号。这就是真正的信息封装,它确保对象被当作一个真正的软件组件来使用。槽用于接收信号,但它们是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。

2.2 计时器

点击startBtn的同时,计时器响应。首先,我们在主函数中声明并定义几个整型数hour、min、sec分别代表时、分、秒,并将它们初始化为0,所以在未开始之前,计时器的表盘始终是“00:00:00”显示。

其次,利用QTimer定义一个计时器,命名为timer,方法如下:

timer = new QTimer(this);

timer→setInterval(1000);

setInterval()方法的作用是设定响应的时间,时间单位为毫秒(ms),因此设定时间为1000毫秒,1秒钟响应一次。

实现计时器,还需要几组功能函数,用于显示数字,定义一个槽函数,命名为updateTime用于时分秒的转换,再定义一个函数flushTime()用于更新显示的数字,如代码所示:

void Element::flushTime()

{QString timestr;

timestr.sprintf("%02d:%02d:%02d",hour,min,sec);

TimePad→setText(timestr);}

void Element::updateTime()

{sec++;

if(sec == 60)

{ sec = 0;

min++;

if(min == 60)

{min = 0;

hour++;} }

flushTime();}

connect(timer,SIGNAL(timeout()),this,SLOT(updateTime()));

计时器效果如图3所示:

3 类Widget

Widget是一个组件类,GamePad和Element可以理解为两个组件,实例化之后进行布局安排。

resize(650,500);

gamePad = new GamePad(this);

selectionPad = new Element(this);endprint

gamePad→setGeometry(0,0,500,500);

selectionPad→setGeometry(510,0,200,500);

键盘触发事件,实现角色控制与键盘同步,主要通过系统调用的保护函数keyPressEvent(QKeyEvent *event)实现:

void Widget::keyPressEvent(QKeyEvent *event)

{ if(event→isAutoRepeat())

return;

switch(event→key())

{case Qt::Key_W:

gamePad→RoleMOveCtl(Up);

break;

case Qt::Key_S:

gamePad→RoleMOveCtl(Down);

break;

case Qt::Key_A:

gamePad→RoleMOveCtl(Left);

break;

case Qt::Key_D:

gamePad→RoleMOveCtl(Right);

break;

case Qt::Key_J:

gamePad→RoleMOveCtl(Other);

default:

break;}}

其中对应的Key_A,Key_W,Key_S,Key_S,Key_D是对应的键位(A,W,S,D),用于控制角色的上下左右的移动,Key_J对应键位J用于控制子弹射击。敌方爆炸效果如图4所示,我方爆炸效果如图5所示。

4 结束语

本文实现了基于QT的飞行射击游戏的开发,程序中包含的类有Element,GamePad,Map,Plane,Bullet,ResultDialog,Widget,不同的类实现了游戏中的不同功能,这些类的灵活性强,可扩展性高,明显提高了游戏的可操作性,增加了游戏的真实感体验,也在一定程度上实现了玩家的满意度。

参考文献:

[1] 郑阿奇. Qt4开发实践[M]. 北京: 电子工业出版社, 2011.

[2] 杨盛毅, 文方, 师娇. 实时数据曲线绘制的Qt编程实现[J]. 四川大学学报:自然科学版, 2008, 45(2):61-64.

[3] 譚浩强. C++程序设计[M]. 北京: 清华大学出版社, 2006.

[4] 杨宗德, 邓玉春. Linux高级程序设计[M]. 北京: 人民邮电出版社, 2009.

[5] Jasmin Blanchette, Mark Summerfield. C++GUI编程[M]. 北京: 电子工业出版社, 2008.endprint

猜你喜欢
计时器布局按钮
松鼠的计时器
抗缪勒氏管激素:卵巢功能的计时器!
VR布局
2015 我们这样布局在探索中寻找突破
Face++:布局刷脸生态