郭子豪,李灿苹
(广东海洋大学电子与信息工程学院,湛江 524008)
Unity3D是由丹麦Unity公司开发的游戏开发工具,作为一款跨平台的游戏开发工具,从一开始就被设计成易于使用的产品[1]。Unity3D引擎[2]十分强大,可以开发2D、2.5D、3D游戏,同时在市场经济应用上也十分广泛,例如应用于VR(虚拟现实)、3D设计、建筑业、医疗成像等方面[3]。在这种大势所趋之下,市场越来越完善,Unity功能也越来越强大。
电子游戏自上世纪60年代诞生以来,短短的几十年得到迅速的发展,极大地推动了软硬件行业发展[4]。与此同时,互联网迅速发展的今天,电子游戏具有很大的市场潜力,而5G时代的到来,更多互联网企业开始涉及游戏制作、VR制作方面的业务,更是促进了电子游戏行业的发展。
利用Unity3D引擎制作的这款复古版2D像素游戏,很多90后可能都玩过,这款游戏每局操作时间短,按键简单方便,工作学习之余能给人们带来消遣,另外该款游戏最大的改进是可以在PC端、移动设备端及PCE端等上运行,可以满足各类人群的使用。
首先玩家进入游戏后需要用鼠标点击画面上的Start按钮进入游戏,然后有4秒的游戏倒计时画面,倒计时结束后正式进入游戏,如果玩家在游戏中被淘汰,画面跳出Game Over定格3秒后将回到游戏开始界面;如果玩家胜利,将会弹出Win的庆祝画面,按任意键回到开始界面;如果玩家要退出界面,可以直接点击开始界面的Exit按钮。
玩家通过W、A、S、D(或者对应的方向键)控制吃豆人按照方向移动,吃掉关卡里的全部豆子即闯关成功,期间也要躲避敌人的攻击,若是Pacman与敌人的路径重合,玩家就会被淘汰。另外每隔10秒将从剩下的豆子中刷新一个超级豆子,Pacman吃到该豆子在3秒内将会变成超级吃豆人,可以吃到敌人,敌人就会回到老巢。
《Pacman吃豆人》的计分面板由Remain、Eaten、Score组成,分别代表着剩余豆子,吃掉的豆子以及分数,其中吃掉一个普通豆子+100分,吃掉一个超级豆子+300分,吃掉一个敌人+500分。游戏也加入了音乐以及随机刷新的超级豆子奖励,增加和保证了游戏的趣味性以及平衡性,不至于玩家控制的Pacman在游戏迷宫里一直被敌人“追杀”,并且计分面板记录了玩家的分数,可以增加玩家与其他玩家的互动性。
(1)玩家可以控制Pacman在迷宫内按上下左右方向自由移动。
(2)敌人四个小鬼会随机选择预设路径自动巡逻,可以吃掉Pacman。
(3)每隔10秒在剩下豆子中随机刷新出一颗超级豆子,Pacman吃了超级豆子后在3秒内变成超级Pac⁃man,可以吃掉敌人。
(4)游戏拥有计分面板,实时计算玩家得分。
(5)点击Start后有倒计时以及倒计时音效,点击Exit可直接退出游戏。
(1)游戏地图的初始化
在Maze中添加Box Collider 2D组件,将迷宫的墙都包围出来,如图1所示,该组件用于检测物体之间的碰撞情况,让游戏里面的人物都无法穿过墙。
图2 是Box Collider 2D组件的配置,其中is Trig⁃ger属性默认不打勾,它表示是否启用触发器。是否启用触发器主要与脚本有关系,启动触发器之后碰撞检测会触发脚本的相关方法,地图不需要添加脚本也不需要做碰撞检测,故不需要勾上is Trigger属性。
(2)游戏人物的初始化
首先是Pacman,如图3,先对Pacman的素材进分割,然后制作成动画,每个动画对应拥有一个动画特效以及一个动画状态机,并且利用动画状态机设置动画的Entry(初始状态)、AnyState(任意时刻)的状态。在状态机内定义两个Float类型的数值DirX和DirY,赋初值分别为1.0与0.0,表示Pacman向右的初始状态。
同理,将Ghost按照Pacman的方法进行设置,再向地图里面添加Pacdot,把豆子的素材一颗一颗按照单位像素填进地图里,最后得到的游戏场景效果如图4所示。
第一个游戏人物是玩家控制的主角:吃豆人Pac⁃man。
首先对Pacman的prefab预制体增加几项组件:Circle Collider 2D、Rigidbody 2D。其中 Circle Collider 2D为圆碰撞器,如图5所示,并将其半径设为0.95,是为了避免其他误差。Rigidbody 2D为刚体类型,如图6所示,这种类型是为了物理仿真运动而设计的(让物体看起来更像现实世界行为),它的运动受重力、质量、其他因素的影响。因为此款游戏为2D像素游戏,故将Gravity Scale设置为0,并且冻结Z轴。
图6 Rigidbody 2D刚体组件
然后编写控制Pacman移动的C#脚本,将脚本放在Scr文件夹下,在Visual Studio 2017下编写运行。脚本代码中涉及到一些脚本生命周期的方法,即挂载到的游戏物体“从出生到死亡”所经历的一些事件。这些生命周期事件,是一些特定的方法,而且是由Unity引擎事先定义好,在游戏的运行过程中,由引擎自动调用。Start()方法是开始事件,只执行一次;FixedUpdate()方法是固定更新事件,执行N次,0.02秒执行一次,所有物理组件相关的更新都在这个事件中处理,通过差值方法实现Pacman的移动。
下面是控制Pacman移动的核心代码。
//使用差值移动的方法获取到达目的地
Vector2 temp=Vector2.MoveTowords(transform.position,dest,speed);
//将刚体移动到目标位置
GetComponent<Ridgidbody2D>().MovePosition(temp);
第二个游戏人物是游戏里的敌人:Blinky、Clyde、Inky、Pinky。
首先给 Blinky、Clyde、Inky、Pinky 四个人物均加上Circle Collider 2D以及Rigidbody 2D组件,并设置is Trigger以及将Gravity Scale设置为0和冻结Z轴。
然后在这些敌人对象中添加Ghost脚本组件。在对Ghost设置巡逻路径时,应将路径做成预制件素材,这是为了更加方便地导入脚本方法和导入存储着路径坐标的数组。其中GameObject类型的wayPointsGos[]数组存储的是一组路线(waypoints1,2,3,4),ways集合存储的是一组路线的具体某一位置。
下面的代码主要是一种伪AI算法,实现的是Ghost按照固定的四组路线随机地进行巡逻。四组巡逻路径区域分布在以Ghost老家为原点坐标,建立二维坐标系的四个象限上,每一组路线就是一个位置的集合,选择其中一组路径,遍历该组路径。
if(transform.position!=ways[curr])
{
//ways[]数组存储的是某一确定坐标
Vector2 temp=Vector2.MoveTowards(transform.position,ways[curr],speed);
GetComponent<Rigidbody2D>().MovePosition(temp);
}else
{
curr++;
if(curr>=ways.Count)
{
curr=0;
//wayPointsGos[]数组存储的是任意一组路线(waypoints1,2,3,4)
LoadPath(wayPointsGos[Random.Rage(0,wayPointsGos.length)]);
}
第三个游戏人物是游戏里的豆子Pacdot。
给780颗Pacdot prefab预制体都增加Box Collid⁃er 2D组件,勾上is Trigger以启动触发器,以便在脚本中通过调用OnTriggerEnter2D()方法来做碰撞检测,此款游戏主要是对Pacman和Pacdot进行碰撞检测。
if(collider.gameObct.name=="Pacman")
{
//如果碰撞检测为超级豆子
if(isSuperPacdot)
{
GameManager.Instance.OnEatPacdot(gameObject);
//调用OnEatSuperPacdot()函数实现对应功能
GameManager.Instance.OnEatSuperPacdot();
//销毁游戏对象
Destory(gameObject);
}
else
{
GameManager.Instance.OnEatPacdot(gameObject);
Destory(gameObject);
}
}
(1)游戏的UI交互(包括开始画面、实时计分画面、游戏输赢效果提示)
StartPanel界面中Start和Exit按钮分别代表进入游戏和退出游戏。在GamePanel界面中添加Remain、Eaten、Score文本,分别用以显示剩余的豆子、吃掉的豆子以及获得的分数。界面效果如图7和图8所示。
图7 StartPanel界面
图8 GamePanel界面
当吃完所有的豆子后,取得胜利,实现的是隐藏GamePanel画面,实例化winPrefab画面,取消所有协程并将游戏状态设置为false,效果如图9所示。
当 Pacman被 Ghost吃掉后,游戏结束,隐藏GamePanel画面,实例化gameOverPrefab画面,并且画面停留3秒后,回到游戏初始画面,效果如图10所示。
图9 Win效果
图10 GameOver效果
(2)游戏的音效交互(包括游戏背景音乐、游戏开始音效等)
音效在整个游戏过程中占有极其重要的地位,直接关系到玩家的感观享受与游戏体验。有特色的音效交互能够非常生动地描绘出游戏所在场景的环境氛围和背景氛围,增强游戏的场景感,令人身临其境[5]。
在该游戏里,主要有两个音效:一个是背景音乐,另一个是游戏开始倒计时音效。其中背景音乐是给GameManager预制体中添加组件Audio Source,并且将素材里的bgm文件导入到该组件中,当开启GamePan⁃el游戏画面时播放该bgm;倒计时音效是在游戏开始时点击Start按钮时,开始播放startClip音乐。
游戏开始界面测试:游戏开始界面以及倒计时界面播放背景音乐的画面,点击Start按钮之后播放倒计时动画。倒计时功能画面,如图11所示。
图11 倒计时功能测试
游戏计分界面测试:游戏中计分板画面,计分面板由Remain、Eaten、Score组成,分别代表剩余的豆子,吃掉的豆子以及分数,其中吃掉一个普通豆子+100分,吃掉一个超级豆子+300分,吃掉一个敌人+500分。计分UI系统测试界面如图12所示。
图12 计分UI系统测试
游戏主要功能测试:每隔10秒从剩下的豆子中刷新一个超级豆,Pacman吃到该豆子在3秒内将会变成超级吃豆人,吃掉Superdot之后,Ghost会变虚,静止在地图的画面上,在SuperPacman状态下可以吃掉Ghost,Ghost就会回到初始位置上。吃到Pacdot效果和Ghost回到老家功能测试界面如图13所示。
图13 吃掉Superdot后的效果
游戏结束测试:游戏胜利以及游戏失败画面。如果玩家在游戏中被Ghost碰到,Pacman被淘汰,画面将跳出Game Over画面,定格3秒后将回到游戏开始界面,如果玩家将地图上所有的Pacdot吃完,将会弹出Win的庆祝画面,按任意键回到开始界面。游戏胜利画面和游戏失败画面如图9和图10所示。
借助Unity3D引擎开发的2D复古游戏——《Pac⁃man吃豆人》,这款游戏从最初的游戏规则、场景及人物的设计,到场景、人物以及功能的实现,再到UI以及音效的优化,整个制作流程按照游戏开发规范进行开发,并且测试效果达到了功能设计的要求。
虽然这款游戏基本复原了童年的像素游戏,但是也存在很多不足,尤其是在对Ghost的移动控制,现阶段只做到伪AI的巡逻路径,可以优化为更加智能的自动规划路线。因此,此款游戏还有很大的优化空间。