消消乐核心功能是消除物品的生成,是一个很有画面感的生成,而不是一下子生成,那么就需要考虑使用协程或Invoke定时调用方法执行生成要消除的物品A(后称'A'),一般都是SpriteRenderer。如果地图上没有所谓的“障碍物”的话,将会非常简单这个生成过程。
(1)、首先得将地图划分为[x,y]数组,假设地图左下角为(0,0),右上角为(x,y),看你习惯怎么把地图划分,注意这些坐标都是与实际坐标关联的。
(2)、先为整个地图的每个坐标都放一个空的物品B,物品B可理解为只是一个空物体,把地图填满。
(3)、开始从下到上、从左到右遍历地图数组,第一行不用进行判断,因为第一行的物品A不用下落了,注意:物品A有分很多种颜色的,游戏是根据颜色(三个相同或三个以上相同)来判断是否可以消除的。
(3.1)、假设当前遍历到(x,y)物品A,先判断它的下面一个物品是否为空物体B,若是与它交换位置(或者删掉下面的物品B,把A挪过去,在A原来的位置再生成一个空物品B补充)下面这蓝色的部分是游戏有障碍物的情况下!障碍物是不能移动的,但是可以被消除,只要它周围的一个物品A被消除的话,物品A周围的障碍物都会被清除掉。
(3.2)、假设游戏有“障碍物”的话,填充方法就要变得有些许复杂,因为如果下面是一个障碍物,单纯地往下填充是填不满的,需要斜着填充,也就是判断左下或右下是否为空物体B,如果是,还需要继续判断空物体B的上方是否有可以补充它的物品A,若有,那么就不需要斜着补充(不进行移动该(x,y)物品A,其实也就是物品B本来就能够被它上方的物品A补充,那么就不需要这个的(x,y)物品A去斜着补充了!若没有,那么(x,y)物品A要斜着移动到该空物品B上(交换)。你以为这样就结束了?假如当前物品A的左下角、下面、右下角都是障碍物,那么就要考虑水平方向的移动,也就是判断左边和右边是否为空物体B,若是,继续判断其空物体B上方是否有物体A补充它,如果有,那就不需要移动 (x,y)物品A补充了,如果没有,那将(x,y)物品A移动到空物体B处。
(注意:空物体B和物品A的交换是涉及到逻辑交换和物理交换,逻辑交换是指地图数组上进行交换,物理交换是指在游戏场景的位置交换)
(4)、经过(3)的遍历后,所有物品A都会进行下移,那么最顶行(y-1)行肯定是会有空一部分出来的,那么这时候再去开启第二个遍历,最顶行所有元素,发现有空物品B的话,就在空物品B上方一个单位处生成一个物品A,再进行一个交换,实现比较有画面感的下落过程,而不是突然生成在最顶行,其实上面所说的交换物品也是这样的,不是一下子交换位置的,而是用差值运算,来慢慢地把2个物体进行交换。
(5)、经过(3)和(4)遍历后,一次填充就完成了,但是因为实际填充的部分只有最顶行要有空物品B才会生成,那么一次填充只会生成一行物品A,那么是有可能还没完成填充的,可以理解在(4)遍历时如果没有生成新物品A 或者 没有进行过交换,那就说明填充已经完毕,其实还可以更暴力一点,再来次遍历整张地图,看看是否有空物品B。如果还没填充完毕,继续回到(3)进行执行,这个过程放在协程里面比较好,假设把(3)(4)封装成一个方法Fill(),返回值是一个布尔值代表是否填充完成,如果返回false 表示没有完成, 那直接在协程这样写 :
while(Fill()==false){ yield return new WaitForSeconds(0.1s); }
这句代码的意思是指只要填充没有完成,就0.1秒进行一次填充,直至完成跳出循环。
(6)、到达(5)后,我们就已经实现了比较有画面感的填充整张地图的效果了,之后的工作就是实现消除!其实填充是填充结束了,但是,可能会偶然系统自动填充的地图会有一些物品符合消除条件,进行消除,那么还需要进行填充,直至整张地图稳定为止,那么(5)的协程方法体就需要改动,再while结束后,对整张地图进行处理,将那些符合消除条件的物品消除,之后继续进行(5)所写的while,也就是说要改为下面那样:
bool needReFill = true;
while(needReFill)
{
//进行一次填充后,地图还没被填满(还有空物体B)
while(Fill()==false)
{
yiled return new WaitForSeconds(0.1s);
}
needReFill = ClearAllMatchedObjectA();//清除地图上所有符合消除条件的物品A,若有清除则返回
//true,否则为false
}
上面代码都是随便写写的,以上就是消消乐的整个系统自动填充物品过程,只要把这个协程开启了,地图就绝对会被填充到稳定的状态,接着就可以由玩家进行交换物品之类的逻辑处理了,下面将会讲解这方面的工作。
(7)、物品A与玩家进行交互可参考背包物品的交互,但是也有一个奇葩的方式进行交互,那就是Unity的Monobehaviour的OnMouseDown方法、OnMouseUp方法、OnMouseEnter方法,要在物品A挂上一个2D碰撞器,才可以使用它们,这样当玩家左击一个物品A后,按住左键不放,再移动到另一个物品A上方松开左键,这个过程会先进入OnMouseDown先把鼠标点击的物品获取,再移动到另一个物品A,会触发OnMouseEnter方法获取到另一个物品A,注意这个获取是指将物品A和另一个物品A传递到一个控制器脚本进行处理后续逻辑的,最后松开左键,执行控制器脚本里的方法对刚刚获取到的两个物品A进行处理,首先判断2个物品是否相邻,再判断交换后是否可以消除,若可以就进行消除,否则不进行任何操作。其实这个消除,直接暴力点,在判断出这2个物品交换后是会产生消除后,就将这2个物品交换后,执行(6)所写的ClearAllMatchedObjectA()方法就OK了,然后再执行填充协程,把地图再次填充到稳定状态即可。
总结,消消乐基本上就以上比较核心的部分,其他的例如:物品A有一些特殊的物品,当玩家消除后会产生一些如:行消除、列消除、同色消除、一个范围的消除等等一系列就不补充了,大体上只要你实现了一个物品的消除,这些都只是判断加执行的事情,写的很累,看的人更累,只适合作者看的一篇垃圾文章,以后有时间再自己写个,其实这个东西是我在SIKI学院上面看的视频,然后总结下。