Unity3D_(游戏)甜品消消乐02_游戏核心算法

 

 

甜品消消乐01_游戏基础界面  传送门

甜品消消乐02_游戏核心算法  传送门

甜品消消乐03_游戏UI设计     传送门

 

 

 

  GameManager脚本上修改Fill Time可以改变消消乐移动速度 

 

实现过程

 

甜甜圈相邻与交换

 

  给甜甜圈添加Box Colliderz碰撞组件

 

  判断甜品是否相邻

    private bool IsFriend(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);
        
    }

 

  交换两个甜品的方法

 private void ExchangeSweets(GameSweet sweet1,GameSweet sweet2)
    {
        if(sweet1.CanMove()&&sweet2.CanMove())
        {
            sweets[sweet1.X, sweet1.Y] = sweet2;
            sweets[sweet2.X, sweet2.Y] = sweet1;

            int tempX = sweet1.X;
            int tempY = sweet1.Y;


            sweet1.MovedComponet.Move(sweet2.X, sweet2.Y, fillTime);
            sweet2.MovedComponet.Move(tempX, tempY, fillTime);
        }
    }

 

  定义要交换的两个甜品

    private GameSweet pressedSweet;
    private GameSweet enteredSweet;

 

  注册鼠标按下事件

    //鼠标点击
    private void OnMouseEnter()
    {
        gameManager.EnterSweet(this);
    }

    //鼠标按下
    private void OnMouseDown()
    {
        gameManager.PressSweet(this);
    }

    //鼠标抬起
    private void OnMouseUp()
    {
        gameManager.ReleaseSweet();
    }


   public void PressSweet(GameSweet sweet)
    {
        pressedSweet = sweet;

    }

    public void EnterSweet(GameSweet sweet)
    {
        enteredSweet = sweet;
    }

    public void ReleaseSweet()
    {
        if (IsFriend(pressedSweet, enteredSweet))
        {
            ExchangeSweets(pressedSweet, enteredSweet);
        }
    }

 

 

 

添加清除动画

   

  Create->Animation创建一个新的动画,将动画拖动到NormalSweetPrefab预制体上

 

  打开动画编辑器Window->Animator

 

  动画缩放第一个位置

 

  动画缩放第二个位置

 

  动画缩放第三个位置

 

  动画缩放第四个位置

 

 

  动画播放器中添加Color属性,在1:00下设置a(透明度)为0

 

 

 直线匹配的核心算法

 

  直线匹配检测方法

 public List<GameSweet> MatchSweets(GameSweet sweet,int newX,int newY)
    {
        if (sweet.CanColor())
        {
            ColorSweet.ColorType color = sweet.ColorComponet.Color;
            List<GameSweet> matchRowSweets = new List<GameSweet>();
            List<GameSweet> matchLineSweets = new List<GameSweet>();
            List<GameSweet> finishedMatchSweets = new List<GameSweet>();

            //行匹配
            matchRowSweets.Add(sweet);

            //i=0代表往左,i=1代表往右
            for(int i = 0; i <= 1; i++)
            {
                for(int xDistance = 1; xDistance < xColumn; xDistance++)
                {
                    int x;
                    if (i == 0)
                    {
                        x = newX - xDistance;
                    }
                    else
                    {
                        x = newX + xDistance;
                    }
                    if (x < 0 || x >= xColumn)
                    {
                        break;
                    }
                    if (sweets[x, newY].CanColor() && sweets[x, newY].ColorComponet.Color == color)
                    {
                        matchRowSweets.Add(sweets[x,newY]);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            //检查一下当前行遍历列表中的元素是否大于3
            if (matchRowSweets.Count >= 3)
            {
                for(int i = 0; i < matchRowSweets.Count; i++)
                {
                    finishedMatchSweets.Add(matchRowSweets[i]);
                }
            }

            if (finishedMatchSweets.Count >= 3)
            {
                return finishedMatchSweets;
            }

            //列匹配
            matchLineSweets.Add(sweet);

            //i=0代表往左,i=1代表往右
            for (int i = 0; i <= 1; i++)
            {
                for (int yDistance = 1; yDistance < yRow; yDistance++)
                {
                    int y;
                    if (i == 0)
                    {
                        y = newY - yDistance;
                    }
                    else
                    {
                        y = newY + yDistance;
                    }
                    if (y < 0 || y >= yRow)
                    {
                        break;
                    }
                    if (sweets[newX, y].CanColor() && sweets[newX, y].ColorComponet.Color == color)
                    {
                        matchLineSweets.Add(sweets[newX, y]);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            //检查一下当前行遍历列表中的元素是否大于3
            if (matchLineSweets.Count >= 3)
            {
                for (int i = 0; i < matchLineSweets.Count; i++)
                {
                    finishedMatchSweets.Add(matchLineSweets[i]);
                }
            }

            if (finishedMatchSweets.Count >= 3)
            {
                return finishedMatchSweets;
            }

        }
        return null;
    }

 

  满足交换条件时交换甜品

    private void ExchangeSweets(GameSweet sweet1, GameSweet sweet2)
    {
        if (sweet1.CanMove() && sweet2.CanMove())
        {
            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)
            {
                int tempX = sweet1.X;
                int tempY = sweet1.Y;


                sweet1.MovedComponet.Move(sweet2.X, sweet2.Y, fillTime);
                sweet2.MovedComponet.Move(tempX, tempY, fillTime);
            }
            else 
            {
                sweets[sweet1.X, sweet1.Y] = sweet1;
                sweets[sweet2.X, sweet2.Y] = sweet2;
            }

        }
    }

 

 

  当交换完成时能出现匹配个数大于等于三则允许交换,否者不能交换

  T型匹配和L型匹配

  

 public List<GameSweet> MatchSweets(GameSweet sweet, int newX, int newY)
    {
        if (sweet.CanColor())
        {
            ColorSweet.ColorType color = sweet.ColorComponet.Color;
            List<GameSweet> matchRowSweets = new List<GameSweet>();
            List<GameSweet> matchLineSweets = new List<GameSweet>();
            List<GameSweet> finishedMatchingSweets = new List<GameSweet>();

            //行匹配
            matchRowSweets.Add(sweet);

            //i=0代表往左,i=1代表往右
            for (int i = 0; i <= 1; i++)
            {
                for (int xDistance = 1; xDistance < xColumn; xDistance++)
                {
                    int x;
                    if (i == 0)
                    {
                        x = newX - xDistance;
                    }
                    else
                    {
                        x = newX + xDistance;
                    }
                    if (x < 0 || x >= xColumn)
                    {
                        break;
                    }

                    if (sweets[x, newY].CanColor() && sweets[x, newY].ColorComponet.Color == color)
                    {
                        matchRowSweets.Add(sweets[x, newY]);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (matchRowSweets.Count >= 3)
            {
                for (int i = 0; i < matchRowSweets.Count; i++)
                {
                    finishedMatchingSweets.Add(matchRowSweets[i]);
                }
            }

            //L T型匹配
            //检查一下当前行遍历列表中的元素数量是否大于3
            if (matchRowSweets.Count >= 3)
            {
                for (int i = 0; i < matchRowSweets.Count; i++)
                {
                    //行匹配列表中满足匹配条件的每个元素上下依次进行列遍历
                    // 0代表上方 1代表下方
                    for (int j = 0; j <= 1; j++)
                    {
                        for (int yDistance = 1; yDistance < yRow; yDistance++)
                        {
                            int y;
                            if (j == 0)
                            {
                                y = newY - yDistance;
                            }
                            else
                            {
                                y = newY + yDistance;
                            }
                            if (y < 0 || y >= yRow)
                            {
                                break;
                            }

                            if (sweets[matchRowSweets[i].X, y].CanColor() && sweets[matchRowSweets[i].X, y].ColorComponet.Color == color)
                            {
                                matchLineSweets.Add(sweets[matchRowSweets[i].X, y]);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    if (matchLineSweets.Count < 2)
                    {
                        matchLineSweets.Clear();
                    }
                    else
                    {
                        for (int j = 0; j < matchLineSweets.Count; j++)
                        {
                            finishedMatchingSweets.Add(matchLineSweets[j]);
                        }
                        break;
                    }
                }
            }

            if (finishedMatchingSweets.Count >= 3)
            {
                return finishedMatchingSweets;
            }

            matchRowSweets.Clear();
            matchLineSweets.Clear();

            matchLineSweets.Add(sweet);

            //列匹配

            //i=0代表往左,i=1代表往右
            for (int i = 0; i <= 1; i++)
            {
                for (int yDistance = 1; yDistance < yRow; yDistance++)
                {
                    int y;
                    if (i == 0)
                    {
                        y = newY - yDistance;
                    }
                    else
                    {
                        y = newY + yDistance;
                    }
                    if (y < 0 || y >= yRow)
                    {
                        break;
                    }

                    if (sweets[newX, y].CanColor() && sweets[newX, y].ColorComponet.Color == color)
                    {
                        matchLineSweets.Add(sweets[newX, y]);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (matchLineSweets.Count >= 3)
            {
                for (int i = 0; i < matchLineSweets.Count; i++)
                {
                    finishedMatchingSweets.Add(matchLineSweets[i]);
                }
            }

            //L T型匹配
            //检查一下当前行遍历列表中的元素数量是否大于3
            if (matchLineSweets.Count >= 3)
            {
                for (int i = 0; i < matchLineSweets.Count; i++)
                {
                    //行匹配列表中满足匹配条件的每个元素上下依次进行列遍历
                    // 0代表上方 1代表下方
                    for (int j = 0; j <= 1; j++)
                    {
                        for (int xDistance = 1; xDistance < xColumn; xDistance++)
                        {
                            int x;
                            if (j == 0)
                            {
                                x = newY - xDistance;
                            }
                            else
                            {
                                x = newY + xDistance;
                            }
                            if (x < 0 || x >= xColumn)
                            {
                                break;
                            }

                            if (sweets[x, matchLineSweets[i].Y].CanColor() && sweets[x, matchLineSweets[i].Y].ColorComponet.Color == color)
                            {
                                matchRowSweets.Add(sweets[x, matchLineSweets[i].Y]);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    if (matchRowSweets.Count < 2)
                    {
                        matchRowSweets.Clear();
                    }
                    else
                    {
                        for (int j = 0; j < matchRowSweets.Count; j++)
                        {
                            finishedMatchingSweets.Add(matchRowSweets[j]);
                        }
                        break;
                    }
                }
            }

            if (finishedMatchingSweets.Count >= 3)
            {
                return finishedMatchingSweets;
            }
        }

        return null;
    }
匹配方法

 

 

消除脚本

 

  添加ClearedSweet脚本

 

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

public class ClearedSweet : MonoBehaviour {

    //清除脚本的动画
    public AnimationClip clearAnimation;

    private bool isClearing;

    public bool IsClearing
    {
        get
        {
            return isClearing;
        }
    }

    //为了方便后期做拓展,设置成protected
    protected GameSweet sweet;

    public virtual void Clear()
    {
        isClearing = true;
        StartCoroutine(ClearCoroutine());
    }

    private IEnumerator ClearCoroutine()
    {
        Animator animator = GetComponent<Animator>();

        if (animator!=null)
        {
            animator.Play(clearAnimation.name);
            //玩家得分,播放清除声音
            yield return new WaitForSeconds(clearAnimation.length);
            Destroy(gameObject);
        }
    }

}
ClearedSweet.cs

 

  清除脚本的动画

 public AnimationClip clearAnimation;

 

  协成中清楚甜甜圈

  public virtual void Clear()
   {
        isClearing = true;
        StartCoroutine(ClearCoroutine());
    }

    private IEnumerator ClearCoroutine()
    {
        Animator animator = GetComponent<Animator>();

        if (animator!=null)
        {
            animator.Play(clearAnimation.name);
            //玩家得分,播放清除声音
            yield return new WaitForSeconds(clearAnimation.length);
            Destroy(gameObject);
        }
    }

 

 

消除甜品

 

  获得清除脚本

    public ClearedSweet ClearedCompent
    {
        get
        {
            return clearedCompent;
        }
    }

 

  判断是否可以清除

    public bool CanClear()
    {
        return clearedCompent != null;
    }

 

  注册清除甜甜圈方法

    private void Awake()
    {
        movedComponet = GetComponent<MovedSweet>();
        coloredCompent = GetComponent<ColorSweet>();
        clearedCompent = GetComponent<ClearedSweet>();
    }

 

  NormalSweetPrefab预制体上添加ClearedSweet脚本

 

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

public class ClearedSweet : MonoBehaviour {

    //清除脚本的动画
    public AnimationClip clearAnimation;

    private bool isClearing;

    public bool IsClearing
    {
        get
        {
            return isClearing;
        }
    }

    //为了方便后期做拓展,设置成protected
    protected GameSweet sweet;

    public virtual void Clear()
    {
        isClearing = true;
        StartCoroutine(ClearCoroutine());
    }

    private IEnumerator ClearCoroutine()
    {
        Animator animator = GetComponent<Animator>();

        if (animator!=null)
        {
            animator.Play(clearAnimation.name);
            //玩家得分,播放清除声音
            yield return new WaitForSeconds(clearAnimation.length);
            Destroy(gameObject);
        }
    }

}
ClearedSweet

 

   清除方法

    public bool ClearSweet(int x,int y)
    {
        if (sweets[x, y].CanClear()&&!sweets[x,y].ClearedCompent.IsClearing)
        {
            sweets[x, y].ClearedCompent.Clear();
            CreateNewSweet(x,y,SweetsType.EMPTY);

            return true;
        }
        return false;
    }

 

  清除全部完成匹配的甜品

 

private bool ClearAllMatchedSweet()
    {
        bool needRefill = false;

        for(int y = 0; y < yRow; y++)
        {
            for (int x=0;x<xColumn;x++)
            {
                if (sweets[x, y].CanClear())
                {
                     List<GameSweet> matchList = MatchSweets(sweets[x,y],x,y);

                    if (matchList != null)
                    {
                        for (int i=0;i<matchList.Count;i++)
                        {
                            if (ClearSweet(matchList[i].X, matchList[i].Y))
                            {
                                needRefill = true;
                            }
                        }
                    }
                }
            }
        }
        return needRefill;
    }

 

 private void ExchangeSweets(GameSweet sweet1, GameSweet sweet2)
    {
        if (sweet1.CanMove() && sweet2.CanMove())
        {
            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)
            {
                int tempX = sweet1.X;
                int tempY = sweet1.Y;


                sweet1.MovedComponet.Move(sweet2.X, sweet2.Y, fillTime);
                sweet2.MovedComponet.Move(tempX, tempY, fillTime);

                ClearAllMatchedSweet();
            }
            else 
            {
                sweets[sweet1.X, sweet1.Y] = sweet1;
                sweets[sweet2.X, sweet2.Y] = sweet2;
            }

        }
    }

 

 

   出现问题:

  1)初始游戏时甜品连接个数为三个的时候未进行消除

  2)  消除完三个甜品时两侧甜品未进行填充

 

  解决第1个问题_填充甜品的方法

 public IEnumerator AllFill()
    {
        bool needRefill = true;

        while(needRefill)
        {
            //完成上次填充动画
            yield return new WaitForSeconds(fillTime);
            while (Fill())
            {
                yield return new WaitForSeconds(fillTime);
            }

            //清除所有我们意见匹配好的甜品
            needRefill = ClearAllMatchedSweet();
        }

    }

 

  解决第2个问题_交换两个甜品

 if (MatchSweets(sweet1, sweet2.X, sweet2.Y) != null || MatchSweets(sweet2, sweet1.X, sweet1.Y) != null)
            {
                int tempX = sweet1.X;
                int tempY = sweet1.Y;


                sweet1.MovedComponet.Move(sweet2.X, sweet2.Y, fillTime);
                sweet2.MovedComponet.Move(tempX, tempY, fillTime);

                ClearAllMatchedSweet();
                //消除甜品时两侧甜品进行填充
                StartCoroutine(AllFill());

            }
            else 
            {
                sweets[sweet1.X, sweet1.Y] = sweet1;
                sweets[sweet2.X, sweet2.Y] = sweet2;
            }

 

 

 

 

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

public class MovedSweet : MonoBehaviour {

    private GameSweet sweet;

    private IEnumerator moveCoroutine;

    private void Awake()
    {
        sweet = GetComponent<GameSweet>();
    }

    //开启或者结束一个协成
    public void Move(int newX,int newY,float time)
    {
        if(moveCoroutine!=null)
        {
            StopCoroutine(moveCoroutine);
        }

        moveCoroutine = MoveCoroutine(newX,newY,time);
        StartCoroutine(moveCoroutine);
    }

    //负责移动的协成
    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;
    }
}
MovedSweet.cs

 

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

public class ClearedSweet : MonoBehaviour {

    //清除脚本的动画
    public AnimationClip clearAnimation;

    private bool isClearing;

    public bool IsClearing
    {
        get
        {
            return isClearing;
        }
    }

    //为了方便后期做拓展,设置成protected
    protected GameSweet sweet;

    public virtual void Clear()
    {
        isClearing = true;
        StartCoroutine(ClearCoroutine());
    }

    private IEnumerator ClearCoroutine()
    {
        Animator animator = GetComponent<Animator>();

        if (animator!=null)
        {
            animator.Play(clearAnimation.name);
            //玩家得分,播放清除声音
            yield return new WaitForSeconds(clearAnimation.length);
            Destroy(gameObject);
        }
    }

}
ClearedSweet.cs

 

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

public class ColorSweet : MonoBehaviour {

    public enum ColorType
    {
        YELLOW,
        PUPLE,
        RED,
        BLUE,
        GREEN,
        PNGK,
        ANY,
        COUNT
    }

    [System.Serializable]
    public struct ColorSprite
    {
        public ColorType color;
        public Sprite sprite;
    }

    public ColorSprite[] ColorSprites;

    private Dictionary<ColorType, Sprite> colorSpriteDict;

    private SpriteRenderer sprite;

    public int NumColors
    {
        get{ return ColorSprites.Length; }
    }

    public ColorType Color
    {
        get
        {
            return color;
        }

        set
        {
            SetColor(value);
        }
    }

    private ColorType color;



    public 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);
            }
        }
    }

    public void SetColor(ColorType newColor)
    {
        color = newColor;
        if (colorSpriteDict.ContainsKey(newColor))
        {
            sprite.sprite = colorSpriteDict[newColor];
        }
    }


}
ColorSweet.cs

 

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

public class GameSweet : MonoBehaviour {

    private int x;
    private int y;
    public int X
    {
        get
        {
            return x;
        }

        set
        {
            if (CanMove())
            {
                x = value;
            }
        }
    }
    public int Y
    {
        get
        {
            return y;
        }

        set
        {
            if (CanMove())
            {
                y = value;
            }
        }
    }

    private GameManager.SweetsType type;
    public GameManager.SweetsType Type
    {
        get
        {
            return type;
        }
    }


    [HideInInspector]
    public GameManager gameManager;

    public MovedSweet MovedComponet
    {
        get
        {
            return movedComponet;
        }
    }
    private MovedSweet movedComponet;


    public ColorSweet ColorComponet
    {
        get
        {
            return coloredCompent;
        }
    }

    public ClearedSweet ClearedCompent
    {
        get
        {
            return clearedCompent;
        }
    }

    private ColorSweet coloredCompent;

    private ClearedSweet clearedCompent;


    //判断甜品是否可以移动
    public bool CanMove()
    {
        return movedComponet != null;
    }

    //判断是否可以着色
    public bool CanColor()
    {
        return coloredCompent != null;
    }

    //判断是否可以清除
    public bool CanClear()
    {
        return clearedCompent != null;
    }

    private void Awake()
    {
        movedComponet = GetComponent<MovedSweet>();
        coloredCompent = GetComponent<ColorSweet>();
        clearedCompent = GetComponent<ClearedSweet>();
    }

    public void Init(int _x,int _y,GameManager _gameManager,GameManager.SweetsType _type)
    {
        x = _x;
        y = _y;
        gameManager = _gameManager;
        type = _type;
    }

    //鼠标点击
    private void OnMouseEnter()
    {
        gameManager.EnterSweet(this);
    }

    //鼠标按下
    private void OnMouseDown()
    {
        gameManager.PressSweet(this);
    }

    //鼠标抬起
    private void OnMouseUp()
    {
        gameManager.ReleaseSweet();
    }
}
GameSweet.cs

 

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

public class GameManager : MonoBehaviour {

    //甜品的种类
    public enum SweetsType
    {
        EMPTY,
        NORMAL,
        BARRIER,
        ROE_CLEAR,
        COLUMN_CLEAR,
        RAINBOWCANDY,
        COUNT   //标记类型
    }

    //甜品预制体的字典,我们可以通过甜品的种类来得到对应的甜品游戏物体
    public Dictionary<SweetsType, GameObject> sweetPrefabDict;

    [System.Serializable]
    public struct SweetPrefab
    {
        public SweetsType type;
        public GameObject prefab;
    }

    public SweetPrefab[] sweetPrefabs;

    //单例实例化
    private static GameManager _instance;
    public static GameManager Instance
    {
        get
        {
            return _instance;
        }

        set
        {
            _instance = value;
        }
    }

    //大网格的行列数
    public int xColumn;
    public int yRow;

    //填充时间
    public float fillTime;

    public GameObject gridPrefab;

    //甜品数组
    private GameSweet[,] sweets;

    //要交换的两个甜品对象
    private GameSweet pressedSweet;
    private GameSweet enteredSweet;

    private void Awake()
    {
        _instance = this;
    }

    // Use this for initialization
    void Start() {

        //字典的实例化
        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].prefab);
            }
        }

       for(int x = 0; x < xColumn; x++)
        {
            for (int y=0;y<yRow;y++)
            {
                GameObject chocolate = Instantiate(gridPrefab,CorrectPosition(x,y),Quaternion.identity);
                chocolate.transform.SetParent(transform);
            }
        }

        sweets = new GameSweet[xColumn, yRow];
        for (int x = 0; x < xColumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                CreateNewSweet(x, y, SweetsType.EMPTY);
            }
        }

        //在(4,4)这个坐标点生成障碍物
        Destroy(sweets[4, 4].gameObject);
        CreateNewSweet(4,4,SweetsType.BARRIER);

        StartCoroutine(AllFill());
    }
    
    // Update is called once per frame
    void Update () {
        
    }

    public Vector3 CorrectPosition(int x ,int y)
    {
        //实际需要实例化巧克力的X位置 = GameManager位置的X坐标-大网格长度的一半+行列对应的X坐标
        // 实际需要实例化巧克力的Y位置 = GameManager位置的Y坐标-大网格长度的一半+行列对应的Y坐标
        return new Vector3(transform.position.x-xColumn/2f+x,transform.position.y+yRow/2f-y);
    }

    //产生甜品的方法
    public GameSweet CreateNewSweet(int x,int y,SweetsType type)
    {
        GameObject newSweet =  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];
    }

    //填充甜品的方法
    public IEnumerator AllFill()
    {
        bool needRefill = true;

        while(needRefill)
        {
            //完成上次填充动画
            yield return new WaitForSeconds(fillTime);
            while (Fill())
            {
                yield return new WaitForSeconds(fillTime);
            }

            //清除所有我们意见匹配好的甜品
            needRefill = ClearAllMatchedSweet();
        }

    }

    //分布填充
    public bool Fill()
    {
        bool FilledNotFinshed = false;  //用来判断本次是否完成

        //行遍历
        for(int y=yRow-2;y>=0;y--)
        {
            for(int x=0;x<xColumn;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);
                        FilledNotFinshed = true;
                    }
                    else
                    {
                        //-1代表左,1代表右
                        for (int down = -1; down <= 1; down++)
                        {
                            if (down != 0)
                            {
                                int downX = x + down;
                                //排除边界的时候
                                //左下方
                                if (downX >= 0 && downX < xColumn)
                                {
                                    GameSweet downSweet = sweets[downX, y + 1];
                                    if (downSweet.Type == SweetsType.EMPTY)
                                    {
                                        bool canfill = true;    //用来判断垂直填充是否可以满足填充要求
                                        for (int aboutY = y; aboutY >= 0; aboutY--)
                                        {
                                            GameSweet sweetAbove = sweets[downX, aboutY];
                                            if (sweetAbove.CanMove())
                                            {
                                                break;
                                            }
                                            else if (!sweetAbove.CanMove() && sweetAbove.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);
                                            FilledNotFinshed = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
               
            }

        }
        //最上排的特殊情况
        for (int x = 0; x < xColumn; x++)
           {
               GameSweet sweet = sweets[x, 0];

              if(sweet.Type == SweetsType.EMPTY)
              {
                    GameObject newSweet = 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);
                    sweets[x, 0].ColorComponet.SetColor((ColorSweet.ColorType)Random.Range(0,sweets[x,0].ColorComponet.NumColors));
                FilledNotFinshed = true;      
              }
        }
        return FilledNotFinshed;
    }

    //甜品是否相邻的判断方法
    private bool IsFriend(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);
    }

    //交换两个甜品
    private void ExchangeSweets(GameSweet sweet1, GameSweet sweet2)
    {
        if (sweet1.CanMove() && sweet2.CanMove())
        {
            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)
            {
                int tempX = sweet1.X;
                int tempY = sweet1.Y;


                sweet1.MovedComponet.Move(sweet2.X, sweet2.Y, fillTime);
                sweet2.MovedComponet.Move(tempX, tempY, fillTime);

                ClearAllMatchedSweet();
                //消除甜品时两侧甜品进行填充
                StartCoroutine(AllFill());

            }
            else 
            {
                sweets[sweet1.X, sweet1.Y] = sweet1;
                sweets[sweet2.X, sweet2.Y] = sweet2;
            }

        }
    }

    public void PressSweet(GameSweet sweet)
    {
        pressedSweet = sweet;

    }

    public void EnterSweet(GameSweet sweet)
    {
        enteredSweet = sweet;
    }

    public void ReleaseSweet()
    {
        if (IsFriend(pressedSweet, enteredSweet))
        {
            ExchangeSweets(pressedSweet, enteredSweet);
        }
    }

    //匹配方法
    public List<GameSweet> MatchSweets(GameSweet sweet, int newX, int newY)
    {
        if (sweet.CanColor())
        {
            ColorSweet.ColorType color = sweet.ColorComponet.Color;
            List<GameSweet> matchRowSweets = new List<GameSweet>();
            List<GameSweet> matchLineSweets = new List<GameSweet>();
            List<GameSweet> finishedMatchingSweets = new List<GameSweet>();

            //行匹配
            matchRowSweets.Add(sweet);

            //i=0代表往左,i=1代表往右
            for (int i = 0; i <= 1; i++)
            {
                for (int xDistance = 1; xDistance < xColumn; xDistance++)
                {
                    int x;
                    if (i == 0)
                    {
                        x = newX - xDistance;
                    }
                    else
                    {
                        x = newX + xDistance;
                    }
                    if (x < 0 || x >= xColumn)
                    {
                        break;
                    }

                    if (sweets[x, newY].CanColor() && sweets[x, newY].ColorComponet.Color == color)
                    {
                        matchRowSweets.Add(sweets[x, newY]);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (matchRowSweets.Count >= 3)
            {
                for (int i = 0; i < matchRowSweets.Count; i++)
                {
                    finishedMatchingSweets.Add(matchRowSweets[i]);
                }
            }

            //L T型匹配
            //检查一下当前行遍历列表中的元素数量是否大于3
            if (matchRowSweets.Count >= 3)
            {
                for (int i = 0; i < matchRowSweets.Count; i++)
                {
                    //行匹配列表中满足匹配条件的每个元素上下依次进行列遍历
                    // 0代表上方 1代表下方
                    for (int j = 0; j <= 1; j++)
                    {
                        for (int yDistance = 1; yDistance < yRow; yDistance++)
                        {
                            int y;
                            if (j == 0)
                            {
                                y = newY - yDistance;
                            }
                            else
                            {
                                y = newY + yDistance;
                            }
                            if (y < 0 || y >= yRow)
                            {
                                break;
                            }

                            if (sweets[matchRowSweets[i].X, y].CanColor() && sweets[matchRowSweets[i].X, y].ColorComponet.Color == color)
                            {
                                matchLineSweets.Add(sweets[matchRowSweets[i].X, y]);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    if (matchLineSweets.Count < 2)
                    {
                        matchLineSweets.Clear();
                    }
                    else
                    {
                        for (int j = 0; j < matchLineSweets.Count; j++)
                        {
                            finishedMatchingSweets.Add(matchLineSweets[j]);
                        }
                        break;
                    }
                }
            }

            if (finishedMatchingSweets.Count >= 3)
            {
                return finishedMatchingSweets;
            }

            matchRowSweets.Clear();
            matchLineSweets.Clear();

            matchLineSweets.Add(sweet);

            //列匹配

            //i=0代表往左,i=1代表往右
            for (int i = 0; i <= 1; i++)
            {
                for (int yDistance = 1; yDistance < yRow; yDistance++)
                {
                    int y;
                    if (i == 0)
                    {
                        y = newY - yDistance;
                    }
                    else
                    {
                        y = newY + yDistance;
                    }
                    if (y < 0 || y >= yRow)
                    {
                        break;
                    }

                    if (sweets[newX, y].CanColor() && sweets[newX, y].ColorComponet.Color == color)
                    {
                        matchLineSweets.Add(sweets[newX, y]);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (matchLineSweets.Count >= 3)
            {
                for (int i = 0; i < matchLineSweets.Count; i++)
                {
                    finishedMatchingSweets.Add(matchLineSweets[i]);
                }
            }

            //L T型匹配
            //检查一下当前行遍历列表中的元素数量是否大于3
            if (matchLineSweets.Count >= 3)
            {
                for (int i = 0; i < matchLineSweets.Count; i++)
                {
                    //行匹配列表中满足匹配条件的每个元素上下依次进行列遍历
                    // 0代表上方 1代表下方
                    for (int j = 0; j <= 1; j++)
                    {
                        for (int xDistance = 1; xDistance < xColumn; xDistance++)
                        {
                            int x;
                            if (j == 0)
                            {
                                x = newY - xDistance;
                            }
                            else
                            {
                                x = newY + xDistance;
                            }
                            if (x < 0 || x >= xColumn)
                            {
                                break;
                            }

                            if (sweets[x, matchLineSweets[i].Y].CanColor() && sweets[x, matchLineSweets[i].Y].ColorComponet.Color == color)
                            {
                                matchRowSweets.Add(sweets[x, matchLineSweets[i].Y]);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    if (matchRowSweets.Count < 2)
                    {
                        matchRowSweets.Clear();
                    }
                    else
                    {
                        for (int j = 0; j < matchRowSweets.Count; j++)
                        {
                            finishedMatchingSweets.Add(matchRowSweets[j]);
                        }
                        break;
                    }
                }
            }

            if (finishedMatchingSweets.Count >= 3)
            {
                return finishedMatchingSweets;
            }
        }

        return null;
    }


    //清除方法
    public bool ClearSweet(int x,int y)
    {
        if (sweets[x, y].CanClear()&&!sweets[x,y].ClearedCompent.IsClearing)
        {
            sweets[x, y].ClearedCompent.Clear();
            CreateNewSweet(x,y,SweetsType.EMPTY);

            return true;
        }
        return false;
    }

    //清除全部完成匹配的甜品
    private bool ClearAllMatchedSweet()
    {
        bool needRefill = false;

        for(int y = 0; y < yRow; y++)
        {
            for (int x=0;x<xColumn;x++)
            {
                if (sweets[x, y].CanClear())
                {
                     List<GameSweet> matchList = MatchSweets(sweets[x,y],x,y);

                    if (matchList != null)
                    {
                        for (int i=0;i<matchList.Count;i++)
                        {
                            if (ClearSweet(matchList[i].X, matchList[i].Y))
                            {
                                needRefill = true;
                            }
                        }
                    }
                }
            }
        }
        return needRefill;
    }
}
GameManager.cs

 

posted @ 2018-09-02 16:23  Cynical丶Gary  阅读(1981)  评论(0编辑  收藏  举报