zoukankan      html  css  js  c++  java
  • Unity 3D游戏-消消乐(三消类)教程和源码

    Unity 消消乐教程和源码


    本文提供全流程,中文翻译。

    Chinar坚持将简单的生活方式,带给世人!

    (拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)




    1

    Start Game —— 游戏逻辑稍复杂,先贴代码,抽空慢慢讲


    喜欢的朋友,跳转到SiKi学院,观看最新视频:SiKi学院

    SiKi学院——是本人发现的网络教程做的很完善的网络课堂,推荐大家多学,多看

    举个栗子黑白88

    using UnityEngine;
    using UnityEngine.SceneManagement;
    using UnityEngine.UI;
    
    /// <summary>
    /// 开始游戏脚本
    /// </summary>
    public class StartGame : MonoBehaviour {
        /// <summary>
        /// 加载游戏
        /// </summary>
        public void LoadTheGame()
        {
            SceneManager.LoadScene(1);
        }
    
        /// <summary>
        /// 退出游戏
        /// </summary>
        public void ExitGame()
        {
            Application.Quit();
        }
    
        /// <summary>
        /// 初始化函数
        /// </summary>
        void Start()
        {
            Button button = GameObject.Find("Exit_Button").GetComponent<Button>();
            button.onClick.AddListener(ExitGame);
            button = GameObject.Find("Start_Button").GetComponent<Button>();
            button.onClick.AddListener(LoadTheGame);
        }
    }
    

    2

    GameManager —— 游戏总控类脚本


    控制游戏所有逻辑的实现

    举个栗子黑白88

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine.UI;
    using UnityEngine.SceneManagement;
    
    
    /// <summary>
    /// 游戏控制脚本
    /// </summary>
    public class GameManager : MonoBehaviour
    {
        private static GameManager _instance; //单例
        public static  GameManager Instance
        {
            get { return _instance; }
            set { _instance = value; }
        }
    
    
        private void Awake()
        {
            _instance = this;
        }
    
    
        //大网格的行列数
        public int        xLie;
        public int        yHang;
        public float      fillTime;   //填充时间
        public GameObject gridPrefab; //背景块
    
    
        //消消乐物品的种类
        public enum SweetsType
        {
            EMPTY,        //空物体
            NORMAL,       //普通
            BARRIER,      //障碍物
            HANG_CLEAR,   //行消除
            LIE_CLEAR,    //列消除
            RAINBOWCANDY, //彩虹糖
            COUNT         //标记类型
        }
    
    
        //物品的预制体的字典 —— 可以通过物品的种类,来得到相对应的物体
        private Dictionary<SweetsType, GameObject> sweetPrefabDict;
    
    
        //由于字典不会直接在 Inspector面板上显示,所以需要用结构体(因为结构体,经过序列化,可以显示)
        [System.Serializable] //加上可序列化特性
        public struct SweetPrefab
        {
            public SweetsType type;
            public GameObject prefabs;
        }
    
    
        public                   SweetPrefab[]  sweetPrefabs;       //结构体数组
        private                  GameSweet[ , ] sweets;             //物品的数组,二维数组,中间必须加逗号
        private                  GameSweet      pressedSweet;       //按下的物品
        private                  GameSweet      enterSweet;         //松开的物品
        private                  Text           TimeText;           //倒计时文本框
        private                  float          TimeCountDown = 60; //倒计时,时间
        private                  bool           IsGameOver;         //是否结束游戏
        [HideInInspector] public int            PlayerScore;        //分数
        private                  Text           PlayerScoreText;    //玩家分数文本框
        private                  float          AddScoreTime;       //累加时间
        private                  float          CurrentScore;       //当前分数
        public                   GameObject     GameOverPanel;      //结束游戏界面
        private                  Text           FinalScoreText;     //最终得分
    
    
        /// <summary>
        /// 初始化函数
        /// </summary>
        void Start()
        {
            TimeText        = GameObject.Find("Time_Text").GetComponent<Text>(); //获取文本框
            PlayerScoreText = GameObject.Find("Score_Internal_Text").GetComponent<Text>();
            Button button   = GameObject.Find("ReTurn_Button").GetComponent<Button>(); //添加重玩按钮方法
            button.onClick.AddListener(RePlay);
    
            //实例化字典
            sweetPrefabDict = new Dictionary<SweetsType, GameObject>();
            for (int i = 0; i < sweetPrefabs.Length; i++) //遍历结构体数组
            {
                if (!sweetPrefabDict.ContainsKey(sweetPrefabs[i].type)) //如果字典里,不包含结构体里 对应的类型
                {
                    sweetPrefabDict.Add(sweetPrefabs[i].type, sweetPrefabs[i].prefabs); //添加 结构体 到字典里
                }
            }
    
    
            sweets = new GameSweet[ xLie, yHang ]; //实例化二维数据,第一个维度是列,第二个是行
            for (int x = 0; x < xLie; x++)
            {
                for (int y = 0; y < yHang; y++)
                {
                    CreateNewSweet(x, y, SweetsType.EMPTY); //调用创建按钮的方法
                }
            }
    
            Destroy(sweets[4, 4].gameObject);
            CreateNewSweet(4, 4, SweetsType.BARRIER);
            Destroy(sweets[4, 3].gameObject);
            CreateNewSweet(4, 3, SweetsType.BARRIER);
            Destroy(sweets[1, 1].gameObject);
            CreateNewSweet(1, 1, SweetsType.BARRIER);
            Destroy(sweets[7, 1].gameObject);
            CreateNewSweet(7, 1, SweetsType.BARRIER);
            Destroy(sweets[1, 6].gameObject);
            CreateNewSweet(1, 6, SweetsType.BARRIER);
            Destroy(sweets[7, 6].gameObject);
            CreateNewSweet(7, 6, SweetsType.BARRIER);
    
            for (int x = 0; x < xLie; x++) //实例化背景
            {
                for (int y = 0; y < yHang; y++)
                {
                    //实例化方块背景
                    GameObject chocolate       = (GameObject) Instantiate(gridPrefab, CorrectPosition(x, y), Quaternion.identity);
                    chocolate.transform.parent = transform; //设置父物体
                }
            }
    
    
    
    
    
            StartCoroutine(AllFill()); //开启协成
        }
    
    
        /// <summary>
        /// 更新函数
        /// </summary>
        void Update()
        {
            if (IsGameOver) return;          //如果游戏结束,直接跳出
            TimeCountDown -= Time.deltaTime; //倒计时
            if (TimeCountDown <= 0)
            {
                TimeCountDown = 0;
    
                IsGameOver = true;
                GameOverPanel.SetActive(true); //激活结束游戏界面
    
                FinalScoreText      = GameObject.Find("LastScore_Text").GetComponent<Text>();
                FinalScoreText.text = PlayerScore.ToString(); //最终得分:赋值
    
                Button button = GameObject.Find("RePlay_Button").GetComponent<Button>(); //添加游戏结束界面:按钮方法
                button.onClick.AddListener(RePlay);
                button = GameObject.Find("ReturnMain_Button").GetComponent<Button>();
                button.onClick.AddListener(ReturnToMain);
                return;
            }
            TimeText.text = TimeCountDown.ToString("0"); //由于,是浮点型变量,所以强转取整数
            if (AddScoreTime <= 0.03f)
            {
                AddScoreTime += Time.deltaTime;
            }
            else
            {
                if (CurrentScore < PlayerScore)
                {
                    CurrentScore++;
                    PlayerScoreText.text = CurrentScore.ToString();
                    AddScoreTime         = 0;
                }
            }
        }
    
    
        /// <summary>
        /// 背景块的实际位置
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public Vector3 CorrectPosition(int x, int y)
        {
            //实例化巧克力的实际位置
            return new Vector3(transform.position.x - xLie / 2f + x, transform.position.y + yHang / 2f - y);
        }
    
    
        /// <summary>
        /// 生成物品方法
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public GameSweet CreateNewSweet(int x, int y, SweetsType type)
        {
            GameObject newSweet =
                (GameObject) Instantiate(sweetPrefabDict[type], CorrectPosition(x, y), Quaternion.identity); //实例化+强转
            newSweet.transform.parent = transform;
            sweets[x, y]              = newSweet.GetComponent<GameSweet>();
            sweets[x, y].Init(x, y, this, type);
            return sweets[x, y];
        }
    
    
        /// <summary>
        /// 协成-全部填充
        /// </summary>
        public IEnumerator AllFill()
        {
            bool needRefill = true; //需要重填
    
            while (needRefill)
            {
                yield return new WaitForSeconds(fillTime); //等待
    
                while (Fill()) //本次填充
                {
                    yield return new WaitForSeconds(fillTime);
                }
    
                needRefill = ClearAllMatchedSweet();
            }
        }
    
    
        /// <summary>
        /// 分步填充
        /// </summary>
        public bool Fill()
        {
            bool filledNotFinished = false;      //判断本次否填,是否完成
            for (int y = yHang - 2; y >= 0; y--) //从下往上
            {
                for (int x = 0; x < xLie; x++) //从左到右
                {
                    GameSweet sweet = sweets[x, y]; //得到当前元素位置的物品对象
                    if (sweet.CanMove())            //如果能移动就填充
                    {
                        GameSweet sweetBelow = sweets[x, y + 1]; //下边元素位置
                        if (sweetBelow.Type == SweetsType.EMPTY) //如果下方是空格子,就垂直向下填充
                        {
                            Destroy(sweetBelow.gameObject);
                            sweet.MovedComponet.Move(x, y + 1, fillTime); //上边的元素,往下移动
                            sweets[x, y                   + 1] = sweet;   //二维数组,对应位置更新。
                            CreateNewSweet(x, y, SweetsType.EMPTY);
                            filledNotFinished = true;
                        }
                        else //斜着填充
                        {
                            for (int down = -1; down < 1; down++)
                            {
                                if (down != 0) //不是正下方
                                {
                                    int downX = x + down;
                                    if (downX >= 0 && downX < xLie) //规定范围,排除边缘情况
                                    {
                                        GameSweet downSweet = sweets[downX, y + 1]; //左下方甜品
                                        if (downSweet.Type == SweetsType.EMPTY)     //左下方为空
                                        {
                                            bool canfill = true; //用来判断是否可以垂直填充
                                            for (int upY = y; upY >= 0; upY--)
                                            {
                                                GameSweet upSweet = sweets[downX, upY]; //正上方元素
                                                if (upSweet.CanMove())
                                                {
                                                    break; //能移动直接跳出
                                                }
                                                else if (!upSweet.CanMove() && upSweet.Type != SweetsType.EMPTY)
                                                {
                                                    canfill = false;
                                                    break;
                                                }
                                            }
    
                                            if (!canfill) //不能垂直填充
                                            {
                                                Destroy(downSweet.gameObject); //删除下边游戏的物体
                                                sweet.MovedComponet.Move(downX, y + 1, fillTime);
                                                sweets[downX, y                   + 1] = sweet;
                                                CreateNewSweet(x, y, SweetsType.EMPTY);
                                                filledNotFinished = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
    
            //最上排的特殊情况
            for (int x = 0; x < xLie; x++)
            {
                GameSweet sweet = sweets[x, 0];
                if (sweet.Type == SweetsType.EMPTY)//第一行,只要有空格子
                {
                    Destroy(sweet.gameObject);
                    GameObject newSweet =
                        (GameObject) Instantiate(sweetPrefabDict[SweetsType.NORMAL], CorrectPosition(x, -1), Quaternion.identity);//就实例化一个普通物品
                    newSweet.transform.parent = transform;
                    sweets[x, 0]              = newSweet.GetComponent<GameSweet>();
                    sweets[x, 0].Init(x, -1, this, SweetsType.NORMAL);
                    sweets[x, 0].MovedComponet.Move(x, 0, fillTime);//移动-1行物品,到第一行
                    sweets[x, 0].ColorComponet.SetColor((ColorSweet.ColorType)Random.Range(0, sweets[x, 0].ColorComponet.NumColors));
                    filledNotFinished = true;
                }
            }
    
            return filledNotFinished;
        }
    
    
        /// <summary>
        /// 物品是否相邻
        /// </summary>
        /// <param name="sweet1"></param>
        /// <param name="sweet2"></param>
        /// <returns></returns>
        private bool IsAdjacent(GameSweet sweet1, GameSweet sweet2)
        {
            return sweet1.X == sweet2.X && Mathf.Abs(sweet1.Y - sweet2.Y) == 1 ||
                   sweet1.Y == sweet2.Y && Mathf.Abs(sweet1.X - sweet2.X) == 1;
        }
    
    
        /// <summary>
        /// 交换物品位置
        /// </summary>
        /// <param name="sweet1"></param>
        /// <param name="sweet2"></param>
        private void ExChangeSweets(GameSweet sweet1, GameSweet sweet2)
        {
            if (sweet1.CanMove() && sweet2.CanMove()) //如果2个物品都能移动
            {
                sweets[sweet1.X, sweet1.Y] = sweet2;
                sweets[sweet2.X, sweet2.Y] = sweet1;
    
                if (MatchSweets(sweet1, sweet2.X, sweet2.Y) != null                    ||
                    MatchSweets(sweet2, sweet1.X, sweet1.Y) != null                    ||
                    sweet1.Type                             == SweetsType.RAINBOWCANDY ||
                    sweet2.Type                             == SweetsType.RAINBOWCANDY) //如果完成匹配
                {
    
    
                    int tempX = sweet1.X;
                    int tempY = sweet1.Y;
    
                    sweet1.MovedComponet.Move(sweet2.X, sweet2.Y, fillTime);
                    sweet2.MovedComponet.Move(tempX, tempY, fillTime);
    
                    if (sweet1.Type == SweetsType.RAINBOWCANDY && sweet1.CanClear() && sweet2.CanClear()) //如果物品1是 特殊物品:消除颜色
                    {
                        ClearColorSweet clearColor = sweet1.GetComponent<ClearColorSweet>();
                        if (clearColor != null) //容错
                        {
                            clearColor.ClearColor = sweet2.ColorComponet.Color;
                        }
                        ClearSweet(sweet1.X, sweet1.Y);
                    }
                    if (sweet2.Type == SweetsType.RAINBOWCANDY && sweet2.CanClear() && sweet2.CanClear()) //如果物品2是 特殊物品:消除颜色
                    {
                        ClearColorSweet clearColor = sweet2.GetComponent<ClearColorSweet>();
                        if (clearColor != null)
                        {
                            clearColor.ClearColor = sweet1.ColorComponet.Color;
                        }
                        ClearSweet(sweet2.X, sweet2.Y);
                    }
    
    
                    ClearAllMatchedSweet();    //交换位置后,清除物品,并生成空格
                    StartCoroutine(AllFill()); //交换位置后填充
    
                    pressedSweet = null;
                    enterSweet = null;
                }
                else
                {
                    sweets[sweet1.X, sweet1.Y] = sweet1;
                    sweets[sweet2.X, sweet1.Y] = sweet2;
                }
            }
        }
    
    
        /// <summary>
        /// 按下物品
        /// </summary>
        public void PressedSweet(GameSweet sweet)
        {
            if (IsGameOver) return; //如果游戏结束,直接跳出
            pressedSweet = sweet;
        }
    
    
        /// <summary>
        /// 进入物品
        /// </summary>
        public void EnterSweet(GameSweet sweet)
        {
            if (IsGameOver) return; //如果游戏结束,直接跳出
            enterSweet = sweet;
        }
    
    
        /// <summary>
        /// 释放物品
        /// </summary>
        public void ReleaseSweet()
        {
            if (IsGameOver) return;                   //如果游戏结束,直接跳出
            if (IsAdjacent(pressedSweet, enterSweet)) //如果相邻
            {
                ExChangeSweets(pressedSweet, enterSweet); //调用改变位置的方法
            }
        }
    
    
        /// <summary>
        /// 匹配消除方法
        /// </summary>
        /// <param name="sweet"></param>
        /// <param name="newX"></param>
        /// <param name="newY"></param>
        /// <returns></returns>
        public List<GameSweet> MatchSweets(GameSweet sweet, int newX, int newY)
        {
            if (sweet.CanColor()) //如果可以着色
            {
                ColorSweet.ColorType color               = sweet.ColorComponet.Color; //上色
                List<GameSweet>      matchHangSweets     = new List<GameSweet>();     //物品行 列表
                List<GameSweet>      matchLieSweets      = new List<GameSweet>();     //物品列 列表
                List<GameSweet>      finishedMatchSweets = new List<GameSweet>();     //完成待删物品 列表
    
                //检查行消除匹配
                matchHangSweets.Add(sweet);
                for (int i = 0; i <= 1; i++) //i等于0,往左,1往右
                {
                    for (int xDistance = 1; xDistance < xLie; xDistance++)
                    {
                        int x; //偏移后的 x 坐标
                        if (i == 0)
                        {
                            x = newX - xDistance;
                        }
                        else
                        {
                            x = newX + xDistance;
                        }
                        if (x < 0 || x >= xLie)
                        {
                            break; //限定边界
                        }
    
    
                        if (sweets[x, newY].CanColor() && sweets[x, newY].ColorComponet.Color == color) //如果物品颜色一样
                        {
                            matchHangSweets.Add(sweets[x, newY]);
                            //如果添加其他类型消除,在这里判断
                        }
                        else
                        {
                            break;
                        }
                    }
                }
    
                if (matchHangSweets.Count >= 3) //行列表元素的添加
                {
                    for (int i = 0; i < matchHangSweets.Count; i++)
                    {
                        finishedMatchSweets.Add(matchHangSweets[i]);
                    }
                }
    
    
                //L T形状匹配
                //遍历后,检测当前行遍历元素数量是否大于3
                if (matchHangSweets.Count >= 3)
                {
                    for (int i = 0; i < matchHangSweets.Count; i++)
                    {
                        //行检查后,检测L和T形状。 检查元素上下元素,是否可以消除:0是上,1是下
                        for (int j = 0; j <= 1; j++)
                        {
                            for (int yDistance = 1; yDistance < yHang; yDistance++)
                            {
                                int y;      //被检测物体的,Y轴偏移坐标
                                if (j == 0) //如果是上方
                                {
                                    y = newY - yDistance; //每次向上递增(物体Y轴坐标,自上而下是0--10)
                                }
                                else
                                {
                                    y = newY + yDistance; //每次向下递增()
                                }
                                if (y < 0 || y >= yHang)
                                {
                                    break; //限定边界
                                }
    
                                if (sweets[matchHangSweets[i].X, y].CanColor() &&
                                    sweets[matchHangSweets[i].X, y].ColorComponet.Color == color) //如果列方向,颜色一致
                                {
                                    matchLieSweets.Add(sweets[matchHangSweets[i].X, y]); //添加甜品对象到 列表中 
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
    
                        if (matchLieSweets.Count < 2) //如果在 行列表中的,垂直方向列 数组中,相同元素小于2
                        {
                            matchLieSweets.Clear(); //清除
                        }
                        else //满足条件就加到完成列表
                        {
                            for (int j = 0; j < matchLieSweets.Count; j++)
                            {
                                finishedMatchSweets.Add(matchLieSweets[j]);
                            }
                            break;
                        }
                    }
                }
    
                if (finishedMatchSweets.Count >= 3)
                {
                    return finishedMatchSweets; //返回  行LT 列表
                }
    
                matchHangSweets.Clear(); //开始列检查之前:清除列表
                matchLieSweets.Clear();
    
    
                //列消除匹配
                matchLieSweets.Add(sweet);
                for (int i = 0; i <= 1; i++) //i等于0,往左,1往右
                {
                    for (int yDistance = 1; yDistance < yHang; yDistance++)
                    {
                        int y; //偏移后的 y 坐标
                        if (i == 0)
                        {
                            y = newY - yDistance;
                        }
                        else
                        {
                            y = newY + yDistance;
                        }
                        if (y < 0 || y >= yHang)
                        {
                            break; //限定边界
                        }
    
    
                        if (sweets[newX, y].CanColor() && sweets[newX, y].ColorComponet.Color == color) //如果物品颜色一样
                        {
                            matchLieSweets.Add(sweets[newX, y]);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
    
                if (matchLieSweets.Count >= 3) //LIE 列表元素的添加
                {
                    for (int i = 0; i < matchLieSweets.Count; i++)
                    {
                        finishedMatchSweets.Add(matchLieSweets[i]);
                    }
                }
    
    
                //垂直列表中,横向L T形状匹配
                //遍历后,检测当前行遍历元素数量是否大于3
                if (matchLieSweets.Count >= 3)
                {
                    for (int i = 0; i < matchLieSweets.Count; i++)
                    {
                        //行检查后,检测L和T形状。 检查元素上下元素,是否可以消除:0是上,1是下
                        for (int j = 0; j <= 1; j++)
                        {
                            for (int xDistance = 1; xDistance < xLie; xDistance++)
                            {
                                int x;      //被检测物体的,Y轴偏移坐标
                                if (j == 0) //如果是上方
                                {
                                    x = newX - xDistance; //每次向上递增(物体Y轴坐标,自上而下是0--10)
                                }
                                else
                                {
                                    x = newX + xDistance; //每次向下递增()
                                }
                                if (x < 0 || x >= xLie)
                                {
                                    break; //限定边界
                                }
    
                                if (sweets[x, matchLieSweets[i].Y].CanColor() &&
                                    sweets[x, matchLieSweets[i].Y].ColorComponet.Color == color) //如果列方向,颜色一致
                                {
                                    matchHangSweets.Add(sweets[x, matchLieSweets[i].Y]); //添加甜品对象到 列表中 
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
    
                        if (matchHangSweets.Count < 2) //如果在 列列表中的,左右方向行 数组中,相同元素小于2
                        {
                            matchHangSweets.Clear(); //清除
                        }
                        else //满足条件就加到完成列表
                        {
                            for (int j = 0; j < matchHangSweets.Count; j++)
                            {
                                finishedMatchSweets.Add(matchHangSweets[j]);
                            }
                            break;
                        }
                    }
                }
    
                //这里
                if (finishedMatchSweets.Count >= 3)
                {
                    return finishedMatchSweets;
                }
            }
    
            return null;
        }
    
    
        /// <summary>
        /// 清除物品方法
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool ClearSweet(int x, int y)
        {
            if (sweets[x, y].CanClear() && !sweets[x, y].ClearedComponet.IsClearing)
            {
                sweets[x, y].ClearedComponet.Clear(); //调用自身方法,开始清除
                CreateNewSweet(x, y, SweetsType.EMPTY);
                ClearBarrier(x, y); //调用清除障碍物函数
                return true;
            }
            return false;
        }
    
    
        /// <summary>
        /// 清除 障碍物
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        private void ClearBarrier(int X, int Y) //传入坐标是:消除掉物品的坐标
        {
            for (int friendX = X - 1; friendX <= X + 1; friendX++) //左右遍历
            {
                if (friendX != X && friendX >= 0 && friendX < xLie)
                {
                    if (sweets[friendX, Y].Type == SweetsType.BARRIER && sweets[friendX, Y].CanClear()) //判断
                    {
                        sweets[friendX, Y].ClearedComponet.Clear();
                        CreateNewSweet(friendX, Y, SweetsType.EMPTY);
                    }
                }
            }
    
            for (int friendY = Y - 1; friendY <= Y + 1; friendY++) //上下遍历
            {
                if (friendY != Y && friendY >= 0 && friendY < yHang)
                {
                    if (sweets[X, friendY].Type == SweetsType.BARRIER && sweets[X, friendY].CanClear()) //判断
                    {
                        sweets[X, friendY].ClearedComponet.Clear();
                        CreateNewSweet(X, friendY, SweetsType.EMPTY);
                    }
                }
            }
        }
    
    
        /// <summary>
        /// 清除规则里物品的方法
        /// </summary>
        /// <returns></returns>
        private bool ClearAllMatchedSweet()
        {
            bool needRefill = false; //是否需要填充
            for (int y = 0; y < yHang; y++)
            {
                for (int x = 0; x < xLie; x++)
                {
                    if (sweets[x, y].CanClear()) //如果可以清除
                    {
                        List<GameSweet> matchList = MatchSweets(sweets[x, y], x, y);
    
                        if (matchList != null) //需要消除
                        {
                            SweetsType specialSweetsType = SweetsType.COUNT; //定义一个枚举类型:COUNT——是否产生特殊甜品:默认是Count类型
    
                            GameSweet randomSweet   = matchList[Random.Range(0, matchList.Count)]; //随机产生位置
                            int       specialSweetX = randomSweet.X;
                            int       specialSweetY = randomSweet.Y;
    
    
                            if (matchList.Count == 4) //消除的4个物品
                            {
                                specialSweetsType = (SweetsType) Random.Range( (int) SweetsType.HANG_CLEAR,(int) SweetsType.LIE_CLEAR+1); //特殊类型赋值:取左不取右,所以+1
                            }
                            if (matchList.Count >= 5)
                            {
                                specialSweetsType = SweetsType.RAINBOWCANDY;
                            }
                            //5个
    
                            for (int i = 0; i < matchList.Count; i++) //遍历数组:清楚元素
                            {
                                if (ClearSweet(matchList[i].X, matchList[i].Y))
                                {
                                    needRefill = true; //填充
                                }
                            }
    
    
                            if (specialSweetsType != SweetsType.COUNT) //有特殊类型
                            {
                                Destroy(sweets[specialSweetX, specialSweetY]);                                        //删除空白物品
                                GameSweet newSweet = CreateNewSweet(specialSweetX, specialSweetY, specialSweetsType); //生成特殊甜品
    
    
                                //给特殊物品着色
                                if (specialSweetsType == SweetsType.HANG_CLEAR || specialSweetsType == SweetsType.LIE_CLEAR &&
                                    newSweet.CanColor()                                                                     &&
                                    matchList[0].CanColor()) //种类的确定
                                {
                                    newSweet.ColorComponet.SetColor(matchList[0].ColorComponet.Color); //给特殊物品,着色:第一个物品的颜色
                                }
                                if (specialSweetsType == SweetsType.RAINBOWCANDY && newSweet.CanColor()) //如果是彩虹堂
                                {
                                    newSweet.ColorComponet.SetColor(ColorSweet.ColorType.ANY);
                                }
                            }
    
    
    
    
    
                        }
                    }
                }
            }
            return needRefill;
        }
    
    
        /// <summary>
        /// 消除整行
        /// </summary>
        /// <param name="hang"></param>
        /// <returns></returns>
        public void ClearHang(int hang)
        {
    
            for (int order = 0; order <= 1; order++)
            {
                for (int xoffset = 0; xoffset <= xLie; xoffset++)
                {
                    int xPos;
                    if (order==0)//左边
                    {
                        xPos = hang - xoffset;
                    }
                    else
                    {
                        xPos = hang + xoffset;
                    }
                    if (xPos<0||xPos>=xLie)
                    {
                        break;
                    }
    
                    if (sweets[xPos,hang].CanClear())
                    {
    
                        SweetsType type = sweets[xPos, hang].Type;
                        ClearSweet(xPos, hang);
                        print("消除整行");
    
                        //if (type=="扩展类性")
                        //{
                        //  break;
                        //}
                    }
                }
            }
    
            //for (int x = 0; x < xLie; x++)
            //{
            //  ClearSweet(x, hang);
            //}
        }
    
    
        /// <summary>
        /// 消除整列
        /// </summary>
        /// <param name="lie"></param>
        public void ClearLie(int lie)
        {
            for (int order = 0; order <= 1; order++)
            {
                for (int xoffset = 0; xoffset <= yHang; xoffset++)
                {
                    int xPos;
                    if (order == 0) //左边
                    {
                        xPos = lie - xoffset;
                    }
                    else
                    {
                        xPos = lie + xoffset;
                    }
                    if (xPos < 0 || xPos >= yHang)
                    {
                        break;
                    }
    
                    if (sweets[lie, xPos].CanClear())
                    {
                        SweetsType type = sweets[lie,xPos].Type;
                        ClearSweet(lie, xPos);
                        print("消除整列");
                        //if (type=="扩展类性")
                        //{
                        //  break;
                        //}
                    }
                }
            }
        }
    
    
        /// <summary>
        /// 清除颜色
        /// </summary>
        /// <param name="color"></param>
        public void ClearColor(ColorSweet.ColorType color)
        {
            for (int x = 0; x < xLie; x++)
            {
                for (int y = 0; y < yHang; y++)
                {
                    if (sweets[x, y].CanColor() && (sweets[x, y].ColorComponet.Color == color || color == ColorSweet.ColorType.ANY))
                    {
                        ClearSweet(x, y); //清除颜色
                    }
                }
            }
        }
    
    
        /// <summary>
        /// 返回主界面
        /// </summary>
        public void ReturnToMain()
        {
            SceneManager.LoadScene(0);
        }
    
    
        /// <summary>
        /// 重玩
        /// </summary>
        public void RePlay()
        {
            SceneManager.LoadScene(1);
        }
    }

    3

    GameSweet —— 物品基础脚本


    控制物品的属性

    举个栗子黑白88

    using UnityEngine;
    
    
    /// <summary>
    /// 物品基础脚本
    /// </summary>
    public class GameSweet : MonoBehaviour
    {
        private int x; //物品列数量
        public  int X
        {
            get { return x; }
    
            set
            {
                if (CanMove())
                {
                    x = value;
                }
            }
        }
        private int y; //物品行数量
        public  int Y
        {
            get { return y; }
    
            set
            {
                if (CanMove())
                {
                    y = value;
                }
            }
        }
        private GameManager.SweetsType type; //物品种类
        public  GameManager.SweetsType Type
        {
            get { return type; }
        }
        private MovedSweet movedComponet; //移动组件
        public  MovedSweet MovedComponet
        {
            get { return movedComponet; }
        }
        private ColorSweet colorComponet; //颜色组件
        public  ColorSweet ColorComponet
        {
            get { return colorComponet; }
        }
        private ClearedSweet clearedComponet; //消除组件
        public  ClearedSweet ClearedComponet
        {
            get { return clearedComponet; }
        }
    
        [HideInInspector]               //在Inspector面板隐藏
        public GameManager gameManager; //控制脚本对象
    
    
        private void Awake()
        {
            movedComponet   = GetComponent<MovedSweet>(); //初始化之前就获取移动组件
            colorComponet   = GetComponent<ColorSweet>();
            clearedComponet = GetComponent<ClearedSweet>();
        }
    
    
        /// <summary>
        /// 初始化函数
        /// </summary>
        /// <param name="_x"></param>
        /// <param name="_y"></param>
        /// <param name="_gameManager"></param>
        /// <param name="_type"></param>
        public void Init(int _x, int _y, GameManager _gameManager, GameManager.SweetsType _type)
        {
            x           = -x; //当前的 x 就等于初始化函数,传进来的传入参数的值
            y           = _y;
            gameManager = _gameManager;
            type        = _type;
        }
    
    
        /// <summary>
        /// 判断物品能否移动
        /// </summary>
        /// <returns></returns>
        public bool CanMove()
        {
            return movedComponet != null;
        }
    
    
        /// <summary>
        /// 判断物品能否作色
        /// </summary>
        /// <returns></returns>
        public bool CanColor()
        {
            return colorComponet != null;
        }
    
        /// <summary>
        /// 判断是否可以清除
        /// </summary>
        /// <returns></returns>
        public bool CanClear()
        {
            return clearedComponet != null;
        }
    
    
        void Update()
        {
            transform.Rotate(new Vector3(0, 0, 0));
        }
    
    
        /// <summary>
        /// 鼠标进入
        /// </summary>
        private void OnMouseEnter()
        {
            gameManager.EnterSweet(this);
            print("进入");
        }
    
    
        /// <summary>
        /// 鼠标按下
        /// </summary>
        private void OnMouseDown()
        {
            gameManager.PressedSweet(this);
            print("按下");
        }
    
    
        /// <summary>
        /// 鼠标抬起
        /// </summary>
        private void OnMouseUp()
        {
            gameManager.ReleaseSweet();
            print("抬起");
        }
    }

    4

    MovedSweet —— 控制物体的移动


    控制物体的移动是否可行

    举个栗子黑白88

    using UnityEngine;
    using System.Collections;
    
    
    /// <summary>
    /// 控制移动脚本
    /// </summary>
    public class MovedSweet : MonoBehaviour
    {
        private GameSweet   sweet;
        private IEnumerator moveCoroutine; //这样得到其他指令的时候,我们可以终止这个协成
    
    
        private void Awake()
        {
            sweet = GetComponent<GameSweet>(); //获取组件
        }
    
    
        /// <summary>
        /// 开启,或者关闭协成
        /// </summary>
        /// <param name="newx"></param>
        /// <param name="newy"></param>
        public void Move(int newx, int newy, float time)
        {
            if (moveCoroutine != null)
            {
                StopCoroutine(moveCoroutine);//停止协成
            }
            moveCoroutine = MoveCoroutine(newx, newy, time);
            StartCoroutine(moveCoroutine);//重开协成
        }
    
    
        /// <summary>
        /// 负责移动的协成
        /// </summary>
        /// <param name="newx"></param>
        /// <param name="newy"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        private IEnumerator MoveCoroutine(int newx, int newy, float time)
        {
            sweet.X          = newx;
            sweet.Y          = newy;
            Vector3 startPos = transform.position;//每一帧移动一点
            Vector3 endPos   = sweet.gameManager.CorrectPosition(newx, newy);
            for (float t = 0; t < time; t += Time.deltaTime)
            {
                sweet.transform.position = Vector3.Lerp(startPos, endPos, t / time);
                yield return 0;//等待一帧
            }
            sweet.transform.position = endPos; //如果发生意外 没移动,就直接赋值
        }
    
    
    
    }

    5

    ClearedSweet —— 清除管控类脚本


    控制物品是否可以被清除

    举个栗子黑白88

    using UnityEngine;
    using System.Collections;
    
    
    /// <summary>
    /// 清除管控类脚本
    /// </summary>
    public class ClearedSweet : MonoBehaviour
    {
        public  AnimationClip clearAnimation; //动画
        public  AudioClip     DestoryClip;    //消除音效
        private bool          isClearing=false;     //是否正在清除
        public  bool          IsClearing
        {
            get { return isClearing; }
        }
    
        protected GameSweet sweet; //可扩充
    
    
        /// <summary>
        /// 唤醒函数
        /// </summary>
        private void Awake()
        {
            sweet = GetComponent<GameSweet>();
        }
    
    
        /// <summary>
        /// 清除
        /// </summary>
        public virtual void Clear()
        {
            isClearing = true; //正在被清除
            StartCoroutine(ClearCoroutine());
        }
    
    
        /// <summary>
        /// 清除动画协成
        /// </summary>
        /// <returns></returns>
        private IEnumerator ClearCoroutine()
        {
            BoxCollider collider = GetComponent<BoxCollider>();
            if (collider!=null)//容错
            {
                collider.enabled = false;
            }
    
            Animator animator = GetComponent<Animator>();
            if (animator != null)
            {
                animator.Play(clearAnimation.name); //播放清除动画
    
                GameManager.Instance.PlayerScore++;                           //得分
                AudioSource.PlayClipAtPoint(DestoryClip, transform.position); //播放消除音效
                yield return new WaitForSeconds(clearAnimation.length);
    
                Destroy(gameObject);
            }
        }
    }

    6

    ClearColorSweet —— 清除颜色相同的物品


    举个栗子黑白88

    public class ClearColorSweet : ClearedSweet
    {
        private ColorSweet.ColorType clearColor; //颜色类型对象
    
        public ColorSweet.ColorType ClearColor
        {
            get { return clearColor; }
    
            set { clearColor = value; }
        }
    
    
        /// <summary>
        /// 重写清除方法
        /// </summary>
        public override void Clear()
        {
            base.Clear();
            sweet.gameManager.ClearColor(clearColor);
        }
    }

    7

    ColorSweet —— 颜色脚本


    管理物品颜色的脚本

    举个栗子黑白88

    using UnityEngine;
    using System.Collections.Generic;
    
    
    /// <summary>
    /// 颜色脚本
    /// </summary>
    public class ColorSweet : MonoBehaviour
    {
        public enum ColorType
        {
            YELLOW, //黄
            PURPLE, //紫
            RED,    //红
            BLUE,   //蓝
            GREEN,  //绿
            PINK,   //棒棒糖
            ANY,    //彩虹糖
            COUNT   //预留
        }
    
        private Dictionary<ColorType, Sprite> colorSpriteDict; //颜色字典
        public  ColorSprite[]                 ColorSprites;    //结构体数组
        [System.Serializable]                                  //序列化
        public struct ColorSprite                              //结构体
        {
            public ColorType color;
            public Sprite    sprite;
        }
    
        private SpriteRenderer sprite;   //渲染器对象
        public  int            NumColors //颜色长度:多少种颜色
        {
            get { return ColorSprites.Length; }
        }
    
        private ColorType color; //物品颜色
        public  ColorType Color
        {
            get { return color; }
    
            set { SetColor(value); }
        }
    
    
        private void Awake()
        {
            sprite          = transform.Find("Sweet").GetComponent<SpriteRenderer>(); //获取渲染组件
            colorSpriteDict = new Dictionary<ColorType, Sprite>();                    //实例化字典对象
            for (int i = 0; i < ColorSprites.Length; i++)                             //遍历字典,在字典中添加图片
            {
                if (!colorSpriteDict.ContainsKey(ColorSprites[i].color))
                {
                    colorSpriteDict.Add(ColorSprites[i].color, ColorSprites[i].sprite);
                }
            }
        }
    
    
        /// <summary>
        /// 设置颜色
        /// </summary>
        /// <param name="newColor"></param>
        public void SetColor(ColorType newColor)
        {
            color = newColor;
            if (colorSpriteDict.ContainsKey(newColor))
            {
                sprite.sprite = colorSpriteDict[newColor];
            }
        }
    
    
    
    }

    8

    ClearLineSweet —— 清除整行,整列


    有耐心的朋友可以跳转到SiKi学院,观看视频:SiKi学院
    举个栗子黑白88

    public class ClearLineSweet : ClearedSweet
    {
        public bool IsHang;//是不是行
    
    
        /// <summary>
        /// 重写清除虚方法
        /// </summary>
        public override void Clear()
        {
            base.Clear();
            if (IsHang)//是行
            {
                sweet.gameManager.ClearHang(sweet.Y);
                print("消除整行新");
    
            }
            else
            {
                sweet.gameManager.ClearLie(sweet.X);
                print("消除整列新");
    
            }
        }
    }
    
    

    支持

    May Be —— 搞开发,总有一天要做的事!


    拥有自己的服务器,无需再找攻略!

    Chinar 提供一站式教程,闭眼式创建!

    为新手节省宝贵时间,避免采坑!


    先点击领取 —— 阿里全产品优惠卷 (享受最低优惠)


    1 —— 云服务器超全购买流程 (新手必备!)

    2 —— Windows 服务器配置、运行、建站一条龙 !

    3 —— Linux 服务器配置、运行、建站一条龙 !





    技术交流群:806091680 ! Chinar 欢迎你的加入


    END

    本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

    对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

    对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址
    >

  • 相关阅读:
    zabbix微信报警 风行天下
    centos7环境下的Mysql5.7.22安装 风行天下
    任务计划程序Windows2008及win2016计划任务定时重启 风行天下
    zabbix监控windows磁盘空间 风行天下
    redhat 7安装CentOS 7 yum源 风行天下
    rhel7配置yum的方法 风行天下
    centos7防火墙使用方法 风行天下
    rhel7配置ELK过程 风行天下
    windows巡检 风行天下
    MapX+VB 前一视图功能
  • 原文地址:https://www.cnblogs.com/chinarbolg/p/9601470.html
Copyright © 2011-2022 走看看