Download

经典游戏 ue4 重制(4)扫雷 - 上

这次我们来看看如何在 UE4 中做个扫雷。之前介绍的打砖块、贪吃蛇、小蜜蜂,依赖 UE4 提供的碰撞就能基本打造出基本的游戏框架,不过这次的扫雷就没这么简单了,我们将要实现相对复杂的蓝图,还需要用到递归。

在扫雷中,我们需要添加一个 Actor,命名为 BP_Block,用来表示扫雷的一个格子。其 Component 如下。

我们添加了一个正方体,同时附加了一个 Text,方便显示文字。

BP_Block 中的变量如下,

X,Y 表示该 block 在扫雷棋盘的坐标,HasMine 表示这个位置是否有雷,marked 表示用户已通过右键标注,uncovered 表示用户有没有点开这个格子。X,Y 我们设成 Editable,并且将 Expose on Spawn 置成 True,方便我们在生成棋盘时设置。

有了 BP_Block 这个基本元素,我们就能构建棋盘了。由于 UE4 中不支持多维数组,为了保存棋盘的状态,我们先建立一个以 BP_Block 数组为成员的结构,命名为 BlockLine,表示棋盘中的一行。

之后我们在 Controller 中建立一个 BlockLine 的数组,命名为 Matrix,用它就额可以表示整个棋盘了。

除了 Matrix 外,Controller 中其他变量如下。

其中 MineCount 表示我们将在地图中放置的地雷总数,MineLeft 表示还有多少个雷没有挖掉。SurroundingDelta 表示每个格子周围的八个点相对于它的偏移量,是个 Vector2D 的数组,内容如下。当用户点开地雷时,我们需要借助它来看看周围有没有地雷。

e6f98e7ef6.png

Controller 中的变量如上,接下去让我们看看 Controller 中的函数。

首先是 EventBeginPlay。

基本操作就是生成整个棋盘,然后在其中布置一些地雷。我们看下 GenerateBlocks。

在 GenerateBlocks 中,我们通过内外两层循环生成整个棋盘。外循环控制行数,内循环控制一行中的每个地雷。在内循环中,我们根据当前地雷的 X,Y 值,计算得到它的位置,并且 Spawn 一个 BP_Block,最后我们把这些 BP_Block 都保存入 Matrix。

生成完棋盘之后我们就能放置地雷。这是在 PutMines 中完成的。

我们已经在 Matrix 中保存了所有地雷的格子,为了让地雷的放置尽可能的简单与平均,我们先通过内外两层循环,把二维的 Matrix 压成一维的、包含左右 BP_Block 的数组,其次我们对该数组进行乱序,然后将其中前 MineCount 个 BP_Block 的 HasMine 置为 True。这样我们便放置了 MineCount 个地雷。

初始过程到此结束。接下去我们介绍几个工具函数,我们把这些工具函数都放在 Controller 中,方便使用。

首先是 ValidXY,用于判定给定的 X,Y 是否是合法的坐标值。当我们使用 SurroundingDelta 取得某个点周围的坐标时,可能会出现负数或者超出棋盘的情况,都可以通过这个函数判定。

其次是 GetBlock 函数。该函数的目的在于从 Matrix 中取得 X,Y 对应的 BP_Block。

有了 ValidXY 和 GetBlock,我们就可以生成 BlockXYHasMine。正如名字所表达的意思一样,这个函数告诉我们 X,Y 对应的位置是否有地雷,其内容如下。

基本上是先判断 X,Y 是否有效,若无效则直接返回没有地雷。如果为有效坐标,则调用 GetBlock 取得 BP_Block,最后根据 BP_Block 中的 hasMine 返回结果。

另外,我们在 Controller 中还添加了个名为 GetSurroundingCount 的函数。用途是取得 X,Y 周围的八个格子中包含了几颗地雷。

我们对 SurroundingDelta 中的八个坐标偏移量逐一循环,依次得到 X,Y 周围的八个 BP_Block,然后通过调用BlockXYHasMine 即可得到周围的地雷数。写到这里的时候觉得这个函数放在 BP_Block 中也许更自然一点,不过既然都截了图了就先这样吧。

Controller 中主要的函数就是上面这些。下次我们将介绍如何处理用户输入,以及 BP_Block 中的各个函数,完成扫雷的剩余部分。

很不错的小教学,多谢分享了。 等我最近空了,把你这个项目做好打包丢上来,

不敢有劳!改天我把项目清清干净放到 github 上吧~~主要是 starter content 太大了。。

没事,一般新建都是空文档比较好,Starter Contet实在是占位子

您好,我看UE4新建项目puzzlegame的那个示例中,初始化棋盘的步骤是使用格子actor外的另一个actor。像楼主这样吧初始化棋盘的步骤写在controller里面,我把gamemode里面的controller改好,把一个格子的actor拖到场景中,怎么无法根据controller里面的generateblock来生成棋盘啊?

这个项目的源代码放在这里了,请参考下。

https://forums.unrealengine.com/showthread.php?114517

https://s26.postimg.org/awr3ebjft/QQ_20160810181753.png

你好,请问你这里设置的布尔uncovered 是怎么打出来的,我只能弄出没有target的uncovered值,因为这个变量是在bp_block里面设置的啊?

PS:我现在知道怎么打出来了,但是不明白为什么不能直接在bp_block里面get和set(不显示target)