Unity制作 最强大脑.华容道游戏

最近看最强大脑第五季,其中是数字华容道和我在高中手机游戏还不多的时候玩的拼图游戏,那时候与同学相互比较,最后都可以在1~2秒内完成游戏,然后就渐渐对这种游戏失去兴趣.现在我对他又突然产生了新的兴趣,就是自己动手把他做出来,前前后后不过两三个小时就完成了.当然时间短促,游戏也不完善,只能算是个Demo,今天拿出来跟大家分享下.

先来看看效果
这里写图片描述

下面正式开始

1.图片的制作

首先我们需要九张分割好的图片的,我们可以提前准备好九张切好的图,但是这样不但浪费资源,而且不易扩展,所以我的做法是导入一张整图,然后制作九个材质球,利用shader的Tilling和offset实现图片的切分.后面如果提供切换图片的功能,就只用替换材质球里面的图片就好了.

先看下面板
这里写图片描述

这里简单介绍下在shader里面Tilling和offset参数

offset:指明使用贴图的起始位置,取值范围为0-1,假如位置超过了1,就会对1取余。

这里写图片描述

如图中,左上角的图片起始位置就是图中橙色的点,以整张图片为左下角为(0,0)点,所以橙色点的offset为(0,0.66666)。

其余的分别为(0.333,0.666)(0.666,0.666)(0,0.333)(0.333,0.333)(0.666,0.333)
最底下的一排大家很容易就可以推出来了,这里留给大家自己填充

tiling:指明从offset位置处的大小区域,区域的取值范围一般为(-1,1),超过的话部分会按比例生成新的区域拼接上原先的

因为每一个小图都占大图1/3,所以tiling都是(0.333,0.333)。

主要代码

因为游戏并不完善,所有只有游戏逻辑的代码,并没有各种模块管理的脚本。
这里主要就是两个脚本,一个是GameManager,负责游戏的主要逻辑,一个是block,负责各个方块自己的交换。
其实主要的逻辑就只有两个,一个是如何打乱拼图,一个就是方块的移动。
所以GameManager主要是打乱拼图,检测游戏状态,而block脚本则只负责响应自己的点击事件,并进行位置的移动。

下面开始上代码


GameManager

using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections.Generic;

public class GameManager : MonoBehaviour {

//单例模式
#region single instance

    private static GameManeger instance;
    public static GameManeger Instance { get { return instance; } }

    void Awake()
    {
        instance = this;
    }

#endregion

    public Transform emptyTransform;//记录一开始的空位置的坐标

    [HideInInspector]//在面板上隐藏掉这个公共变量
    public Vector3 empty;//方块移动时存储的空位置的坐标

    public GameObject[] pieces;//存储各个方块
    private Vector3[] piecePositions;//存储各个方块的位置,用作判断是否完成游戏
    private bool isSwaped = false;//记录是否调用SwapPiece()方法,用作判断是否完成游戏
    void Start () {
        //初始化empty,piecePositions的值
        empty = emptyTransform.position;
        piecePositions = new Vector3[pieces.Length];
        for (int i = 0; i < pieces.Length; i++)
        {
            piecePositions[i] = pieces[i].transform.position;
        }
        SwapPiece();
    }
   public void SwapPiece()//打乱方块的方法
    {
        int[] step = { -1, 1, -3, 3 };
        int emptyIndex = pieces.Length - 1;//空白方块的索引
        int i = 0;
        while( i < 1000)//随机点击各个方块,每点击一次就交换了一次方块
        {
            var index = emptyIndex + step[Random.Range(0, 4)];
            if (index < 8 && index >=0)
            {
                pieces[index].GetComponent<Piece>().OnMouseDown();
                i++;
            }
            emptyIndex = index;
        }
        isSwaped = true;
    }
     public void SwapEmpty(Vector3 targer)//主要是判断游戏结果
    {
        empty = targer;
        if (emptyTransform.position == empty)
        {
            bool isWin = true;
            for (int i = 0; i < pieces.Length; i++)
            {
                if (pieces[i].transform.position != piecePositions[i])
                {
                    isWin = false;
                    break;
                }
            }
            if (isWin && isSwaped)
            {
                print("Win");
                isSwaped = false;
            }
        }
    }
}

Block

using UnityEngine;
using System.Collections;

public class Block : MonoBehaviour {
 public void OnMouseDown()
    {
        //判断与空方块的距离,如果不是与空方块相邻的物体这不能交换
        if (Vector3.Distance(transform.position,GameManager.Instance.empty) <= 3.8f)
        {
            var temp = transform.position;
            transform.position = GameManager.Instance.empty;//交换位置
            GameManager.Instance.SwapEmpty(temp);//每次交换都需要根据空方块的位置,进行判定是否已经完成游戏
        }
    }

}


代码其实很简单,游戏的主要流程大家看代码和注释应该就能明白了,但是GameManager里面的只有一个个方法需要重点讲一下.

SwapPiece(),交换方块

int[] step = { -1, 1, -3, 3 };

这第一句大家可能就看不懂了,不知道是干嘛用的.但是只要把这个搞懂了,这个算法就算是搞懂了.
来,先上图

一图
这里写图片描述
二图
这里写图片描述
本来我以为打乱拼图只需要将pieces数组里面的物体随机分布在这9个位置上就可以了,但是这样就会出现拼图不能还原的问题,因为拼图的方块位置是固定的.比如,会出现上面一图中7,8位置互换的情况,这样就光靠移动时还原不了的.
所以的换了一个思路,就是随机点击各个方块,使用移动,因为是靠移动打乱,这样靠移动就一定可以还原拼图,但是移动也不是直接在8张图上随机点,如图1情况,只有6,8是可以移动的,而其他的方块点击是无效的,所以我们需要在有效的方块里面进行随机.
因为每次交换都是与empty进行交换,所以我们可以以empty作为标志.如图1情况,empty是9,有效方块是6,8.,如图2情况,empty5,有效情况是2,4,6,8.所以规律是有效的方块永远只会出现在empty的上下左右,而换成对应的索引就是empty-1.+1.-3.+3.所以我们只需在empty加上{ -1, 1, -3, 3 }这四个数,就可以进行有效随机.但是要注意做一下范围判断,索引要保证在[0,7]


然后就是SwapEmpty()方法,其实很简单.所以也简单说下,
就是每次交换都做一下判断,如果empty在上图9的位置,就比对所有的方块位置与最开始的位置,判断胜利,胜利后,要重新打乱才可再次判定


最后附上Dome

猜你喜欢

转载自blog.csdn.net/kill566666/article/details/77171299
今日推荐