1. 程式人生 > >2D獵寶行動(類掃雷小遊戲)DAY 9

2D獵寶行動(類掃雷小遊戲)DAY 9

1.製作道具欄的圖示

2.完成UI的繪製並建立UI指令碼

建立MainPanel類

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

public class MainPanel : MonoBehaviour {

    private static MainPanel _instance;

    public Image armorIcon;
    public Image keyIcon;
    public Image arrowIcon;
    public Image swordIcon;
    public Image hoeIcon;
    public Image hoeBag;
    public Image tntIcon;
    public Image tntBag;
    public Image mapIcon;
    public Image mapBag;
    public Image grassIcon;
    public Text levelText;
    public Text hpText;
    public Text armorText;
    public Text keyText;
    public Text weaponText;
    public Text hoeText;
    public Text tntText;
    public Text mapText;
    public Text goldText;

    private void Awake()
    {
        _instance = this;
    }
}

3.完成道具記錄變數和UI更新方法

完善UI程式碼

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;

public class MainPanel : MonoBehaviour {

    private static MainPanel _instance;

    public Image armorIcon;
    public Image keyIcon;
    public Image arrowIcon;
    public Image arrowBg;
    public Image swordIcon;
    public Image hoeIcon;
    public Image hoeBag;
    public Image tntIcon;
    public Image tntBag;
    public Image mapIcon;
    public Image mapBag;
    public Image grassIcon;
    public Text levelText;
    public Text hpText;
    public Text armorText;
    public Text keyText;
    public Text weaponText;
    public Text hoeText;
    public Text tntText;
    public Text mapText;
    public Text goldText;

    public bool isHide = false;

    private void Awake()
    {
        _instance = this;
    }

    void Start()
    {
        UpdateUI();
    }

    public void OnLevelButton()
    {
        if(isHide == false)
        {
            isHide = true;
            GetComponent<RectTransform>().DOAnchorPosY(-7, 0.5f);
        }
        else
        {
            isHide = false;
            GetComponent<RectTransform>().DOAnchorPosY(45, 0.5f);
        }
    }

    public void UpdateUI()
    {
        levelText.text = "Level" + GameManager._instance.lv;
        hpText.text = GameManager._instance.hp.ToString();
        if(GameManager._instance.armor == 0)
        {
            armorIcon.gameObject.SetActive(false);
            armorText.gameObject.SetActive(false);
        }
        else
        {
            armorIcon.gameObject.SetActive(true);
            armorText.gameObject.SetActive(true);
            armorText.text = GameManager._instance.armor.ToString();
        }

        if (GameManager._instance.key == 0)
        {
            keyIcon.gameObject.SetActive(false);
            keyText.gameObject.SetActive(false);
        }
        else
        {
            keyIcon.gameObject.SetActive(true);
            keyText.gameObject.SetActive(true);
            keyText.text = GameManager._instance.key.ToString();
        }

        switch (GameManager._instance.weaponType)
        {
            case WeaponType.None:
                arrowBg.gameObject.SetActive(true);
                arrowIcon.gameObject.SetActive(false);
                swordIcon.gameObject.SetActive(false);
                weaponText.gameObject.SetActive(false);
                break;
            case WeaponType.Arrow:
                arrowBg.gameObject.SetActive(true);
                arrowIcon.gameObject.SetActive(true);
                swordIcon.gameObject.SetActive(false);
                weaponText.gameObject.SetActive(true);
                weaponText.text = GameManager._instance.arrow.ToString();
                break;
            case WeaponType.Sword:
                arrowBg.gameObject.SetActive(false);
                arrowIcon.gameObject.SetActive(false);
                swordIcon.gameObject.SetActive(true);
                weaponText.gameObject.SetActive(false);
                break;
        }

        if (GameManager._instance.hoe == 0)
        {
            hoeIcon.gameObject.SetActive(false);
            hoeText.gameObject.SetActive(false);
            hoeBag.gameObject.SetActive(false);
        }
        else
        {
            hoeIcon.gameObject.SetActive(true);
            hoeText.gameObject.SetActive(true);
            hoeBag.gameObject.SetActive(true);
            hoeText.text = GameManager._instance.hoe.ToString();
        }

        if (GameManager._instance.tnt == 0)
        {
            tntIcon.gameObject.SetActive(false);
            tntText.gameObject.SetActive(false);
            tntBag.gameObject.SetActive(false);
        }
        else
        {
            tntIcon.gameObject.SetActive(true);
            tntText.gameObject.SetActive(true);
            tntBag.gameObject.SetActive(true);
            tntText.text = GameManager._instance.tnt.ToString();
        }

        if (GameManager._instance.map == 0)
        {
            mapIcon.gameObject.SetActive(false);
            mapText.gameObject.SetActive(false);
            mapBag.gameObject.SetActive(false);
        }
        else
        {
            mapIcon.gameObject.SetActive(true);
            mapText.gameObject.SetActive(true);
            mapBag.gameObject.SetActive(true);
            mapText.text = GameManager._instance.map.ToString();
        }

        grassIcon.gameObject.SetActive(GameManager._instance.isGrass);
        goldText.text = GameManager._instance.gold.ToString();
    }
}

執行程式,如下圖:

3.處理道具的拾取

分別在金錢和道具類裡邊新增獲取方法

    private void GetGold()
    {
        int x = 1;
        if (GameManager._instance.isGrass == true) x = 2;
        switch (goldType)
        {
            case GoldType.One:
                GameManager._instance.gold += 30 * x;
                break;
            case GoldType.Two:
                GameManager._instance.gold += 60 * x;
                break;
            case GoldType.Three:
                GameManager._instance.gold += 100 * x;
                break;
            case GoldType.Four:
                GameManager._instance.gold += 150 * x;
                break;
            case GoldType.Five:
                GameManager._instance.gold += 450 * x;
                break;
            case GoldType.Six:
                GameManager._instance.gold += 600 * x;
                break;
            case GoldType.Seven:
                GameManager._instance.gold += 1000 * x;
                break;
        }
        MainPanel._instance.UpdateUI();
    }
 private void GetTool()
    {
        switch (toolType)
        {
            case ToolType.Hp:
                GameManager._instance.hp++;
                break;
            case ToolType.Armor:
                GameManager._instance.armor++;
                break;
            case ToolType.Sword:
                GameManager._instance.weaponType = WeaponType.Sword;
                GameManager._instance.armor = 0;
                break;
            case ToolType.Map:
                GameManager._instance.map++;
                break;
            case ToolType.Arrow:
                GameManager._instance.weaponType = WeaponType.Arrow;
                GameManager._instance.arrow++;
                break;
            case ToolType.Key:
                GameManager._instance.key++;
                break;
            case ToolType.Tnt:
                GameManager._instance.tnt++;
                break;
            case ToolType.Hoe:
                GameManager._instance.hoe++;
                break;
            case ToolType.Grass:
                GameManager._instance.isGrass = true;
                break;
        }
        MainPanel._instance.UpdateUI();
    }

在GamaManager中新增受到傷害的方法

 public void TakeDamage()
    {
        if(armor > 0)
        {
            armor--;

        }
        else
        {
            hp--;
        }
        if(hp == 0)
        {
            DisplayAllTraps();
            ani.SetBool("Die", true);
        }
        else
        {
            ani.SetTrigger("TakeDamage");
        }
    }

4.使用鑰匙和武器道具

修改門中的方法和製作開門特效預製體

    public override void OnLeftMouseButton()
    {
        if (Vector3.Distance(transform.position, GameManager._instance.player.transform.position) < 1.5f)
        {
            if (GameManager._instance.key > 0)
            {
                GameManager._instance.key--;
                MainPanel._instance.UpdateUI();
                Instantiate(GameManager._instance.doorOpenEffect, transform);
                ToNumberElement(true);
            }
            else
            {
                base.OnLeftMouseButton();
            }
        }
        else
        {
            base.OnLeftMouseButton();
        }
    }

5.製作道具使用的範圍提示效果

6.使用單選按鈕組來選擇道具的使用

7.使用鋤頭、炸藥和地圖道具

新增使用道具的方法SelectGizmos

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

public class SelectGizmos : MonoBehaviour {

    public ToolType toolType;

    private void OnMouseUp()
    {
        int x = (int)transform.position.x;
        int y = (int)transform.position.y;
        switch (toolType)
        {
            case ToolType.Map:
                MainPanel._instance.hoeToggle.isOn = false;
                GameManager._instance.map--;
                MainPanel._instance.UpdateUI();
                for (int i = x - 3; i < x + 3; i++)
                {
                    for (int j = y - 3; j < y + 3; j++)
                    {
                        if (i >= 0 && i < GameManager._instance.w && j >= 0 && j < GameManager._instance.h && GameManager._instance.mapArray[i, j].elementContent != ElementContent.Exit)
                        {
                            if(GameManager._instance.mapArray[i, j].elementContent ==ElementContent.Trap&& GameManager._instance.mapArray[i, j].elementState != ElementState.Marked)
                            {
                                GameManager._instance.mapArray[i, j].OnRightMouseButton();
                            }
                            if (GameManager._instance.mapArray[i, j].elementContent != ElementContent.Trap && GameManager._instance.mapArray[i, j].elementState == ElementState.Marked)
                            {
                                GameManager._instance.mapArray[i, j].OnRightMouseButton();
                            }
                        }

                    }
                }
                break;
            case ToolType.Tnt:
                MainPanel._instance.tntToggle.isOn = false;
                GameManager._instance.tnt--;
                MainPanel._instance.UpdateUI();
                for(int i = x - 1; i < x + 1; i++)
                {
                    for(int j = y - 1; j < y + 1; j++)
                    {
                        if (i >= 0 && i < GameManager._instance.w && j >= 0 && j < GameManager._instance.h &&GameManager._instance.mapArray[i,j].elementContent!=ElementContent.Exit)
                        {
                            if(GameManager._instance.mapArray[i, j].elementType == ElementType.DoubleCovered)
                            {
                                ((DoubleCoveredElement)GameManager._instance.mapArray[i, j]).UncoverElementSingle();
                            }
                            else
                            {
                                GameManager._instance.mapArray[i, j].ToNumberElement(true);
                            }
                            
                        }   
                    }
                }
                break;
            case ToolType.Hoe:
                MainPanel._instance.hoeToggle.isOn = false;
                GameManager._instance.hoe--;
                MainPanel._instance.UpdateUI();
                for (int i = x - 1; i < x + 1; i++)
                {
                    for (int j = y - 1; j < y + 1; j++)
                    {
                        if (i >= 0 && i < GameManager._instance.w && j >= 0 && j < GameManager._instance.h && GameManager._instance.mapArray[i, j].elementContent != ElementContent.Exit)
                        {
                            if (GameManager._instance.mapArray[i, j].elementType != ElementType.CantCovered)
                            {
                                ((SingleCoveredElement)GameManager._instance.mapArray[i, j]).UncoverElementSingle();
                            }
                            else
                            {
                                if (GameManager._instance.mapArray[i, j].elementContent == ElementContent.SmallWall)
                                {
                                    GameManager._instance.mapArray[i, j].ToNumberElement(true);
                                }
                            }
                        }
                    }
                }
                break;
            default:
                break;
        }
    }
}

執行程式,結果如下:

8.製作UI動效

修改更新UI的方法,並在其他地方進行引數修改

public void UpdateUI(params RectTransform[] rts)
{
    foreach(RectTransform rt in rts)
        {
            rt.DOShakeScale(0.5f).onComplete += () =>
            {
                rt.localScale = new Vector3(1, 1, 1);
            };
            
        }
}

9.資源池的簡介與簡單資源池的建立

什麼是資源池

將一定數量的物件預先儲存在資源池中,當需要的時候使用,而不是每次都例項化一個物件,不用的時候再放回。例如一款射擊類遊戲,需要不斷的發射子彈,如果每發射一顆子彈,都要例項化一個物件,隨後再銷燬物件,再例項化物件,必然會消耗較大的記憶體。如果預先就將子彈例項化出一定的數量,並儲存在彈夾中,發射的時候,取出來發射,不用的時候,再放回彈夾。如此反覆利用,可以避免頻繁例項化和銷燬帶來的效能消耗。這裡的彈夾的概念就是資源池模式!
 

於是首先先給特效建立一個列舉型別

public enum EffectType
{
    SmokeEffect,
    UncoveredEffect,
    GoldEffect,
    DoorOpenEffect
}

然後建立資源池管理類,並進行初始化

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

public class PoolManager : MonoBehaviour {

    public static PoolManager _instance;

    Dictionary<EffectType, List<GameObject>> poolListDic = new Dictionary<EffectType, List<GameObject>>();
    List<GameObject> uncoveredEffectList = new List<GameObject>();
    List<GameObject> smokeEffectList = new List<GameObject>();
    List<GameObject> goldEffectList = new List<GameObject>();
    List<GameObject> doorOpenEffectList = new List<GameObject>();
    Dictionary<EffectType, int> poolListCapacityDic = new Dictionary<EffectType, int>();
    int uncoveredEffectCapacity;
    int smokeEffectCapacity = 5;
    int goldEffectCapacity = 20;
    int doorOpenEffectCapacity = 5;
    Dictionary<EffectType, GameObject> effectGoDic = new Dictionary<EffectType, GameObject>();

    private void Awake()
    {
        _instance = this;
        poolListDic.Add(EffectType.UncoveredEffect, uncoveredEffectList);
        poolListDic.Add(EffectType.SmokeEffect, uncoveredEffectList);
        poolListDic.Add(EffectType.GoldEffect, uncoveredEffectList);
        poolListDic.Add(EffectType.DoorOpenEffect, uncoveredEffectList);
        uncoveredEffectCapacity = (int)(GameManager._instance.w * GameManager._instance.h * 0.2f);
        poolListCapacityDic.Add(EffectType.UncoveredEffect, uncoveredEffectCapacity);
        poolListCapacityDic.Add(EffectType.SmokeEffect, smokeEffectCapacity);
        poolListCapacityDic.Add(EffectType.GoldEffect, goldEffectCapacity);
        poolListCapacityDic.Add(EffectType.DoorOpenEffect, doorOpenEffectCapacity);
        effectGoDic.Add(EffectType.UncoveredEffect, GameManager._instance.uncoveredEffect);
        effectGoDic.Add(EffectType.SmokeEffect, GameManager._instance.smokeEffect);
        effectGoDic.Add(EffectType.GoldEffect, GameManager._instance.goldEffect);
        effectGoDic.Add(EffectType.DoorOpenEffect, GameManager._instance.doorOpenEffect);
    }

    
}

10.完成資源池的功能

完成資源池的新增,重置。

 public GameObject GetInstance(EffectType type, Transform t = null,bool worldPosStays = false)
    {
        List<GameObject> list;
        poolListDic.TryGetValue(type, out list);
        if (list.Count > 0)
        {
            GameObject tempGo = list[list.Count - 1];
            tempGo.SetActive(true);
            ResetInstance(tempGo);
            if(t!= null)
            {
                tempGo.transform.SetParent(t, worldPosStays);
            }
            list.RemoveAt(list.Count - 1);
            return tempGo;
        }
        else
        {
            GameObject go;
            effectGoDic.TryGetValue(type, out go);
            if (t != null)
            {
                return Instantiate(go, t, worldPosStays);
            }
            else
            {
                return Instantiate(go);
            }
        }
        
    }

    public void StoreInstance(EffectType type,GameObject go)
    {
        List<GameObject> list;
        poolListDic.TryGetValue(type, out list);
        int listCap;
        poolListCapacityDic.TryGetValue(type, out listCap);
        if (list.Count < listCap)
        {
            go.SetActive(false);
            list.Add(go);
        }
        else
        {
            Destroy(go);
        }
    }

    private void ResetInstance(GameObject go)
    {
        ParticleSystem ps = go.GetComponent<ParticleSystem>();
        if(ps != null)
        {
            ps.Stop();
            ps.Play();
        }
        foreach(Transform t in go.transform)
        {
            ParticleSystem tps = go.GetComponent<ParticleSystem>();
            if (tps != null)
            {
                tps.Stop();
                tps.Play();
            }
        }
    }