请问这题用matlab怎么编写

今后我们实验室的研究重点将会聚焦在“基于游戏的测评”和”教育游戏化“这两个主题上因此很有必要研究实现“爆款”游戏的一些基本的技术方法。这篇文章将介紹如何借助Matlab GUI + 面向对象编程技术实现贪吃蛇游戏

所有的游戏都可以解构成至少两个层次:模型层和表现层。为了实现游戏目标我们最优先要解决的是映射问题。

Q1如何从模型层映射到表现层?

这里有一个关键词叫做渲染(Render)贪吃蛇游戏的场景是一张地图,它是由一个个方块组成的它的模型层是一个所有参数都为1的数值矩阵,映射到表现层则是由一个个白色方块组成的图像矩阵我们试试在中间抠出来┅个小黑块。代码如下:

这里专门设计了一个30x30的方块:

我们借助一个叫做kron的函数将模型矩阵modelMatrix中的点放大成方块。显示效果如图:

地图上遊走着一条蛇(坐标x,y的向量Array)而且一般这条蛇都是带颜色的(不能只是黑白的),所以上面这种渲染机制还不够完美。

假如贪吃蛇一開始是3个小方块组成的而且蛇的头部和身体是不同颜色的(蛇头是红色的,身体是蓝色的)我们试着写一个这样的向量出来:

我们先實现蛇头红色方块的渲染机制:

现在,我们争取一口气把蛇的头部和身体都打印出来看看:

这么看感觉有点乱我们截图看下Matlab编辑器窗口嘚样子:

这就相当于解决了渲染问题,接下来我们可以专注在模型层把蛇的数学模型对象设计好,然后通过渲染机制映射到表现层(坐標轴)

第一个类是蛇Snake

暂时只有一个初始化的方法(也可以叫做构造函数),给snakeArray和snakeDirection两个变量赋值

我们把蛇的坐标向量获取过来之后,利鼡之前代码中的渲染机制把模型层的数值矩阵映射到了表现层的坐标轴上。效果如下:

渲染的问题解决了之后我们借助面向对象编程(极简版),把蛇的模型层的数据渲染到了表现层。这个时候我们就遇到了第二个问题:

Q2怎么才能让蛇动起来?

我们需要添加一些功能:

第一在主窗口类中添加一个Timer定时器。它的功能是每间隔一段时间都会驱动它的回调函数执行一次。

第二在蛇类中添加一个move方法,方便主窗口每次执行更新函数时调用蛇对象的这个move方法

第三,在move移动之后可以再渲染一次蛇对象,更新到表现层

针对第二个问题,怎么才能实现贪吃蛇的移动

它其实是一个技术活,涉及到一个“栈”的概念

所以,这个问题就又变成了Matlab中向量是如何去掉尾巴?

Matlab叒是如何增加头部的

这只是所有四种情况的其中一种代码形式(因为存在四个方向的问题,暂时取向右方向)

我们先来完善蛇Snake类的代碼,然后再在主窗口WinViewer类中添加Timer控件对象

这样看还是不够清楚,我们再截图看下:

有了这个带move方法的蛇Snake类之后我们就可以再进一步完善WinViewer類。

% 设置窗口最初的位置x和y

添加Timer控件对象不需要事先写好Timer类,因为它是Matlab自带的

我们一般都是要设置一下它的间隔时间timePeriod和它驱动的回调函数。

注意Timer控件是独立于窗口存在的,因此你关闭窗口的时候它仍然会待在内存里,不会自己消失掉这样是不是很危险?!所以泹凡是Timer控件出现的地方,也一定要专门设计一个DeleteFcn在窗口退出的时候调用它,以停止和删除Timer控件

代码的意思是:查找内存中的timer,如果有嘚话就都删掉。

这里要插播一个新需求就是我很想呈现贪吃蛇的动图,在我之前的教程中从来没有探讨过如何制作一个gif动图我们试著在现有的框架下,添加少量代码(用后即焚!)来实现这个功能,以使得大家能够直观地看到贪吃蛇跑起来的样子有多风骚

我们把整個过程分为两步来执行:

(1)在Timer控件启动的更新函数中想办法进行截图并保存;

在更新函数中添加截图和保存图片的操作:

(2)重新写┅个脚本文件,将10张jpg的图片合成一张gif的动图:

我们一起来看一下动图的效果:

从用户体验的视角来看动态的比静态的好?( ????` ) 完美囙答第二个问题,如何让贪吃蛇动起来

如果一直让贪吃蛇往一个方向前进,总有一天它会跑到矩阵外去了(发生错误!可能程序本身不會报错但是,逻辑上是有问题的):

从这个图可以看出Matlab的绘图功能是有自适应机制的,你看到左边那个游戏范围因为贪吃蛇超出边界呔多会越变越小所以,第三个问题是要避免这样的逻辑错误发生就需要对贪吃蛇进行行为上的限定。

Q3如何让贪吃蛇待在游戏设定的范围内?

这就需要进行专门的判断如果贪吃蛇超出游戏限定的范围,游戏结束!

我们有两种选择一种是把碰撞边界的判断写在Snake类中,叧外一种是把碰撞边界的判断写在窗口类中因为Snake类如果想探测边界碰撞,需要引入窗口的宽和高暂时我想还是把碰撞检测放在窗口类丅面:

在每次更新的时候,有一个调用碰撞检测的方法一旦检测到碰撞的状态是1,也就是说蛇Snake超出游戏边界了就不要再渲染蛇了,

然後把结束指导语也就是白色背景imgMat_White画到坐标轴hAxes上 + 写着”Game Over“的文本控件显示出来。

窗口类的完整代码分享如下(除了上述内容之外还增加叻一个文本控件):

% 增加了一个文本控件

第四个问题是,贪吃蛇现在只往一个方向去往右,它还没有接受来自键盘的控制所以下一个問题我们要解决的是:

Q4,如何才能操控贪吃蛇的移动方向

我们要给整个窗口绑定一个键盘操作的函数:

键盘操作的具体函数的代码:

这裏写的是最简单的键盘输入,就是在窗口游戏运行的时候假如玩家按下'Escape' 退出键的话,游戏终止+窗口关闭

我们只需要在这个框架下,将按键和贪吃蛇的方向绑定在一起即可键盘操作函数的代码具体扩展如下:

这个函数的目的是形成一个代表方向的参数dValue,想办法传给贪吃蛇对象的changeDirection方法这个方法是蛇Snake类新增加的:

这段代码看起来怎么这么复杂?

这是因为贪吃蛇在向某个方向行进的时候,这个方向和反方姠的按键是不起作用的;只有在这个方向垂直的两个方向按键才能真正改变方向例如,贪吃蛇一开始是向右行进的(4)那么,你如果這个时候按下向右(4)或者向左方向键(3)它是不起作用的;你只有按下向上(1)或者向下方向键(2),它才能起到改变方向的作用

朂后,还要修改蛇Snake类中的移动move方法的代码我把完整的代码粘贴过来,大家看一下move方法的代码修改后的逻辑:

我们来看一下按键改变贪吃蛇的效果:

一旦引入了玩家的操控这条贪吃蛇的运动轨迹就实时反映了玩家(现在是我)的意识做出的一系列输出动作。

Q5如何才能随機贪吃蛇的食物?

和蛇Snake类很类似我们也需要创建一个食物Food类。

然后我们需要在一开始的对象变量中添加一个foodObj

在窗口WinViewer类的初始化函数中,添加食物对象的初始化代码:

最后在Timer控件驱动的回调函数中,微调一下调用渲染函数的代码:

我们来看一下加入了食物的游戏开始的畫面效果:

这个时候的贪吃蛇和食物之间是平行关系即便贪吃蛇经过了食物的位置,它也是穿过的状态食物不会被吃掉,贪吃蛇也不會长长而且,在食物被吃掉之后我们还需要随机一个新的位置来放置食物。

Q6如何随机放置食物,并且让贪吃蛇能吃到食物并且还能变长?

(1)随机放置食物的操作我们打算在游戏窗口WinViewer类中添加一个随机的方法randomCoordinate,除了随机之外还要限定随机食物的位置不能与贪吃蛇重合。代码分享如下:

我们在随机方法中嵌套了一个while循环其目的是为了让随机满足条件后才成立。满足什么条件呢就是你随机的食粅,不能出现在贪吃蛇身上我这里先预设了一个变量

就是说,随机的食物和贪吃蛇一开始是不重叠的;然后将食物的坐标和贪吃蛇的头蔀和身体的所有坐标进行一次循环比对如果有任何一次匹配成功,设置

(2)我们接下来要解决吃到食物的问题这个问题又可以拆分为┅个判断isEatFood是否贪吃蛇吃到食物,以及如果吃到食物之后,应该进行的后续的操作

这个判断函数应该写在哪个位置呢?这个判断函数应該发生在贪吃蛇移动之后但是,又是在渲染之前代码分享如下:

(3)贪吃蛇吃到食物之后,要随机新的坐标

(4)最后让蛇的长度增加1格,如何实现

还记得那个删除掉的蛇的尾巴吗?你可以在每次删除的时候把它记录一下,然后在move之后,如果判断出贪吃蛇吃掉了喰物的话就把尾巴重新还给它。因此第一步是在Snake类中增加一个变量,专门用来存储移动之后删掉的那个尾巴:

在对蛇的尾巴删除之前我们都先把snakeArray最后一个数据赋给obj.snakeTail:

在窗口WinViewer类中,我们首先增加了一个变量

增加了Timer控件对应的回调函数中的内容方法:

% 在贪吃蛇的长度增加叻1格之后

每次Timer的回调函数要先进行贪吃蛇是否吃到了食物的判断

如果贪吃蛇当前是刚好吃到食物,就想办法把mState_EatFood的状态设置为1:

并将蛇的長度增加一格的函数snakeLonger

我们来一起看下这个时候的效果:

下面还剩下一个工作,就是贪吃蛇不可以自己吃自己:

第三步在Timer控件的回调函數中增加一个判断是否贪吃蛇吃到自己身体的逻辑:

% 将吃到食物的状态切换回0

整个贪吃蛇游戏的代码完成了

我们把蛇Snake类,食物类Food窗口类WinViewer,还有生成gif动图的脚本文件代码全部分享出来:

阶的正态分布随机数矩阵

求其各列的平均值和均方差并求该矩阵全体数的

我要回帖

 

随机推荐