使用Unity 2D实现经典的扫雷游戏(上)

相信我们很多人都玩过扫雷游戏,它是一个单人解谜游戏,最早于上世纪60年代发布。游戏的目标是探索雷区,努力不触发地雷。每显示一个无雷区域,游戏会显示一个数字,表明四周的地雷数量。这为游戏增加了一个不错的策略因素。

这篇教程使用Unity 2D实现经典的扫雷游戏将非常简单,仅有85行代码以及一些像素美术素材。我们将学习一些有关Unity编程以及如何实现广受欢迎的泛洪填充算法

开发准备
本篇教程无需任何特殊的Unity技巧,除了一些有关游戏对象和变换等内容的基本知识。理解递归的概念将对泛洪填充算法的实现很有帮助。

本篇教程可以使用Unity 5.0.0f4及更高版本来进行实现。

项目设置
启动Unity,选择New Project创建新项目,并将项目命名为minesweeper,选择任意一个保存位置,比如C:\,选择项目类型为2D,点击Create Project创建新项目。

 

现在我们可以修改摄像机,确保游戏处于屏幕中心。首先选择层级窗口中的Main Camera ,然后将Background Color设置为黑色。我们还需要将Size 与Position 修改设置为下图所示的样子。

基础项目设置就完成了。

默认元素
让我们把默认元素添加到游戏。默认元素是那些我们尚未点击的区块,用于隐藏它下面真实的内容。

首先我们需要一些可用的图片。为了简单起见,可以使用类似 Paint.NET这样的绘图工具,画一个16×16像素的图像。

保存到Assets文件夹后,我们可以在Project项目窗口选择它。

 

然后我们可以在检视窗口中修改它的导入设置。需要注意,导入设置指定了图像在最终游戏中的大小以及是否要进行压缩。

 

现在我们可以将图像从Project项目区域拖入到场景。

 

我们在场景窗口或层级窗口中选中默认元素,然后检查检视窗口。我们要将它的位置设为x=0,y=0。x是水平位置,而y是垂直位置。因为这是个2D游戏,不需要第三个维度,所以我们将z设为0。

我们希望能在用户单击一个元素时获得通知。Unity已经提供了一个函数可用于实现此目的,不过仅对有碰撞器的元素才有效。一个碰撞器可以使我们的对象成为物理世界的一部分。现在我们的默认元素只是游戏世界中的一个图像。一旦为它添加了碰撞器,它就能成为物理世界的一部分,就像一面墙一样。

要添加一个碰撞器,可以在检视窗口中选择:Add Component->Physics 2D->Box Collider 2D。这样,它现在是物理世界的一部分了。

 

如果我们点击运行,就能看到游戏中的第一个元素。

 

添加更多元素
我们的2D扫雷游戏如果只有一个元素那就太无聊了。我们可以通过刚才的流程,或者右击层级窗口中的default游戏对象并选择“Duplicate” 进行复制,以添加更多的元素。

 

我们将复制的元素放x=1,y=0的位置。

 

现在我们可以不停地复制元素,直到有10(水平)x 13(垂直)个元素。

 

底部元素的坐标是x=0,y=0。右上角的元素位于x=9,y=12。中间的元素位置坐标应当要四舍五入就像这样x=2,y=3,而非x=2.04,y=3.002。

现在我们的游戏界面是不是看上去已经有点像扫雷游戏的模样了!

关于邻接
让我们花点时间了解下邻接地雷的情况,这将是我们扫雷游戏的重要部分。

点击一个非地雷元素后,用户应当能看到一个指示邻接地雷数量的数字。我们将采取一种称为8向邻接检测的手段。或者换而言之,我们不仅会检测顶/底/左/右,同时还要检测左上/右上/左下/右下的元素。

这里使我们会遇到的九种不同情况:

 

所以我们要计算每个块的邻接地雷数量,然后绘制数字。如果没有邻接地雷,则什么也不绘制。

添加更多图像:数字与地雷
为了要绘制那些数字,我们可以使用Unity的GUI系统或为简单地为每个数字快速绘制一个纹理。然后将它们保存到项目的Assets文件夹中。

 

我们还需要用到一个地雷的图像 。将它们保存到项目的Assets文件夹中。

我们将所有那些图像保存到Project窗口中后,要选择它们,并在检视窗口中为它们应用以下这些导入设置。

 

开始编码
现在开始编写代码。右击Project窗口,选择Create->C# Script,并命名为Element。

 

这个脚本目前没有任何作用,让我们选择层级窗口中的所有default元素,然后通过点击检视窗口中的Add Component->Script->Element,将脚本添加到它们上面。

 

在Project项目窗口中双击并打开脚本。

我们可以移除Update函数,因为不需要它。然后我们添加一个变量,表明当前元素是否是一个地雷。

 

变量mine是公共的,这样其它元素才能看到它。Start函数会在游戏开始时被调用。

通过在Start函数中使用Random.value,现在我们可以随机决定这个元素是否是一颗地雷。Random.value总会返回一个介于0和1之间的新随机数。如果我们希望元素有15%的概率是一颗地雷,所以我们将使用Random.value<0.15。

 

现在让我们创建一个小小的辅助函数。我们希望能随时从默认纹理切换为空纹理、某个数字纹理或地雷纹理。首先我们要定义一些纹理变量。

 

 

Sprite是纹理的另一种说法。Sprite[]则是一个数组,也就是不止一个Sprite。

现在我们可以在检视窗口中看到一些新的栏位。

 

可以将纹理拖动其中。让我们把Project项目窗口中的纹理一个个拖入到这些栏位。

 

现在我们可以通过loadTexture函数使用我们的Sprite变量了。

 

这个函数会首先检测元素是不是地雷。如果是,就加载地雷纹理。如果不是,就加载emptyTextures(数字)中的一个,具体根据adjacentCount而定。GetComponent<SpriteRenderer>().sprite 就是我们更改当前纹理的方式。

可以对Start函数暂时做下修改,以测试我们的函数。

 

 

如果按下运行,我们可以看到每个元素都载入了数字1的纹理,如下图所示,则代表正确。

 

现在我们可以把Start函数还原回去了。

 

随后我们将需要知道某个元素是否仍被覆盖,例如:尚未点击。所以让我们添加一个小函数,简单地将当前纹理名与默认名做下比较。

 

只要默认纹理还在就说明元素还未被显示。反之,如果我们加载了一个不同的纹理,比如地雷或某个数字,就说明它已被显示。

我们还要给Element脚本添加一个函数,用于检测鼠标的点击。每个元素都已经附加了一个Collider2D组件,这意味着只要点击某个元素,Unity就会调用函数OnMouseUpAsButton。当然,这首先要在脚本中有这么一个函数:

 

当点击一个元素时,可能会发生二种情况:要么是地雷,要么不是。

 

如果这是个地雷,那应当显示所有地雷,然后游戏结束。

 

如果不是地雷,那可能会发生好几种情况。首先,我们要根据邻接地雷数量载入正确数字的空纹理。如果点击的元素没有任何邻接地雷,那我们应该显示整个没有地雷的元素区域。

 

我们还应该判断是否所有除地雷外的元素都已被显示,这种情况下游戏就已获胜。这是第一个版本的代码。

 

我们所有的ToDo功能都有一个共同点:它们除了需要元素本身的信息之外,都需要访问其它元素。所以让我们再创建一个脚本,用来处理所有元素。

小结
使用Unity 2D实现经典扫雷游戏的上篇,就为大家介绍到这里。在下篇中将采用网格来处理更加复杂的游戏逻辑,从而完整的实现游戏。尽请期待

 

原文地址:http://forum.china.unity3d.com/thread-32181-1-1.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注

一条评论 “使用Unity 2D实现经典的扫雷游戏(上)”