贪吃蛇小游戏功能介绍和源代码_第1页
贪吃蛇小游戏功能介绍和源代码_第2页
贪吃蛇小游戏功能介绍和源代码_第3页
贪吃蛇小游戏功能介绍和源代码_第4页
贪吃蛇小游戏功能介绍和源代码_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

上一个帖子已经介绍了用uFun开发板制作的花里胡哨的“手柄”,这个帖子介绍一下贪吃蛇游戏界面的制作。两者之间采用串口通信,上个帖子介绍了数据发送的格式约定,这里就不在赘述了,详见帖子【uFun开发板评测】贪吃蛇(一):用uFun开发板做游戏手柄。

帖子内用的是开源版Qt,版本为Qt5.11.2

游戏界面及功能略为粗糙,文末提供了源码以及编译完成的程序下载附件。先来分析一下帖子内这款游戏想要实现的功能:首先实现串口通信是必须的。绘制一条能动的贪吃蛇和一个食物是游戏的基础。能判断游戏的结束,分为撞墙死和自闭而死。试图模仿以前小霸王之类的游戏机,uFun做的手柄也能即插即用。确定功能之后,就要构思怎么去实现了:串口通信可以采用Qt5提供的QSerialPort类轻松实现;为了能动,采用了定时器定时重绘的方法。每次重绘都更新一下贪吃蛇位置,这样贪吃蛇就动起来了;贪吃蛇的躯体可以用一个数组来存储每一节身体的位置坐标,为了方便,采用了Qt自带的QList+QPoint实现;食物被吃了之后需要随机出现,采用了QRandomGenerator随机数生成器来生成食物的坐标;既然已经存储了贪吃蛇身体的坐标,场地的坐标范围也是已知的,只要将贪吃蛇下一个行进的坐标和它们比较就能知道游戏有没有结束;为了实现即插即用,拔掉再插还能用,可以对QSerialPort类的errorOccurred信号进行处理,为了方便,只要串口出错就关闭串口。没有串口连接时就在游戏中不断尝试连接串口,遇到第一个能用的串口直接打开,之后停止尝试。(这里做了一个假设,就是按照常理游戏机上只会插手柄)其中:位置坐标并不是按像素算的。贪吃蛇的身体是由一个个小长方形构成的,长方形有一定的长和宽,位置坐标是以一个长方形为单位的,游戏界面的大小也是长方形的整数倍;#defineblock_width

15

//长方形的宽#defineblock_height

15

//长方形的高#definex_count

50

//游戏界面的宽为(block_width*x_count)#definey_count

40

//游戏界面的高为(block_height*y_count)>>>程序中定义了一个boolstartFlag变量用来标识游戏是否开始。

>>>我尝试着对实现贪吃蛇躯体做了个很不成熟的类封装,有些成员函数都是在编程过程中需要才加上的。#ifndefSNAKE_H#defineSNAKE_H#include<QPoint>#include<QList>//宏定义四个方向#definedir_up

1#definedir_down

2#definedir_left

3#definedir_right

4classSnake{public:

Snake(QPointheadLocation,intlenth=3,intcur_dir=dir_right);

intgetLenth();

//获取贪吃蛇长度

intgetCurDirecton();

//获取当前前进方向

QList<QPoint>&getBody();

//获取贪吃蛇的整个身体,主要在绘制里用

QPointgetHeadLocation();

//获取贪吃蛇头部的坐标位置

booladdBlock(intcurDir);

//添加一块身体

boolmakeStep(intdir);

//向某个方向前进一步

boolisInSnake(QPoint&point);

//判断某一点是否在蛇的身体内

boolisInSnake(intx,inty);

//判断某一点是否在蛇的身体内

voidtryGo(QPoint*point,intdir);

//尝试走一步,输入一个坐标和前进方向,获取走一步之后的新坐标点private:

intcurDirection;

//用来记录当前前进的方向

QList<QPoint>snake_body;

//用来存储贪吃蛇的身体各单元坐标点};#endif//SNAKE_H说明一下其中addBlock()和makeStep()函数,实际上实现过程就是把身体最后一个坐标位置去除,并在列表中加入新的头位置。

>>>串口初始化中主要需要连接处理串口的两个信号:一个是出错信号errorOccurred,主要做的工作是把出错时已经打开的串口关闭,这样程序循环内才会继续尝试打开串口。(在初始化时也会有一次尝试寻找可用的串口);另一个是接收到数据的信号readyRead,其中的数据处理思路和uFun开发板处理思路相同,不再赘述。当接收到信息之后,会把方向暂存在一个变量里,只有当定时器到点重绘时才会真正更新前进方向,也就是说只认重绘前最后一次方向。//帧信息处理过程if(ch=='>'){

//一帧接收结束

//当停在游戏开始界面时,检测到按键就直接置位开始游戏

if(this->startFlag==false){

this->startFlag=true;

if(pTimer->isActive()==false)

pTimer->start();

return;

}

//A-left

D-rightW-up

S-down

switch(rcvData.toUtf8().at(0)){

case'A':case'a':

if(this->curDirection!=dir_right)

this->preDirection=dir_left;

break;

case'D':case'd':

if(this->curDirection!=dir_left)

this->preDirection=dir_right;

break;

case'W':case'w':

if(this->curDirection!=dir_down)

this->preDirection=dir_up;

break;

case'S':case's':

if(this->curDirection!=dir_up)

this->preDirection=dir_down;

break;

}

frameFlag=false;

}>>>采用随机数生成器生成食物的坐标。当生成食物不合理时,会重复生成。(此处随机种子很简单,但效果看起来也无大碍,此外没有处理食物生在死角那种极端情况)voidWidget::makeFood(){

QRandomGeneratorgenerator;

quint32x,y;

while(true){

generator.seed(static_cast<quint32>(QTime::currentTime().second()));

x=generator.generate();

y=generator.generate();

x%=x_count;

y%=y_count;

if(pSnake->isInSnake(static_cast<int>(x),static_cast<int>(y))==false)

break;

}

foodPoint.setX(static_cast<int>(x));

foodPoint.setY(static_cast<int>(y));

DEBUG_cout(x<<y);}

>>>界面动起来的核心是重绘定时器。每次定时器到点触发timeout信号,都会进行判断游戏是否结束,是否吃到食物,并且会调用addBlock()或makeStep()函数更新一下贪吃蛇的位置,最后重绘界面。每局游戏结束后会直接开始下一轮游戏。(调节定时器时间就可以加快游戏速度,提升难度)pTimer=newQTimer(this);

pTimer->setInterval(150);

//控制重绘的时间间隔,可以控制游戏难度

connect(pTimer,&QTimer::timeout,this,

[=](){

//如果串口没有连接成功,则一直尝试

if(pSerialPort->isOpen()==false){

DEBUG_cout("stilltry");

QList<QSerialPortInfo>infoList=QSerialPortInfo::availablePorts();

//如果连接上一个串口直接跳出,没有可用串口会在程序中不断循环查找串口并尝试连接

QSerialPortInfoinfo;

foreach(info,infoList){

pSerialPort->setPortName(info.portName());

if(pSerialPort->open(QIODevice::ReadWrite))

break;

}

}

if(this->startFlag==true){

//只有每次绘制的时候才会真正修改蛇的前进方向

this->curDirection=this->preDirection;

//判断是否增加长度以及是否游戏结束

if(this->isGameOver()){

//游戏结束后清除标志变量,以进行下一场游戏

this->startFlag=false;

pSnake=newSnake(QPoint(x_count/2,y_count/2),5,curDirection);

makeFood();

}

else{

QPointpoint=pSnake->getHeadLocation();

pSnake->tryGo(&point,this->curDirection);

//尝试前进一步

if(point==foodPoint){

//判断有没有吃到食物

pSerialPort->write("<F>");

//发送<F>表示吃到食物

pSnake->addBlock(this->curDirection);

//更新食物的位置

this->makeFood();

}

else{

pSnake->makeStep(curDirection);

}

}

this->update();

}

});

pTimer->start();>>>游戏界面的绘制都在绘制事件响应函数paintEvent函数内完成。绘制过程很简单,就是把蛇和食物画出来,在游戏没开始时,多绘制一行提示文字。voidWidget::paintEvent(QPaintEvent*event){

QPainterpainter(this);

painter.setBrush(QColor("#ff0000"));

QList<QPoint>snake_body=pSnake->getBody();

QPointpoint;

foreach(point,snake_body){

painter.drawRect(point.x()*block_width,point.y()*block_height,block_width,block_height);

}

painter.drawEllipse(foodP

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论