Unity制作扫雷游戏

来源:互联网 发布:男宝胶囊和知柏地黄丸 编辑:程序博客网 时间:2024/06/11 21:58

曾经在网上看了一篇扫雷教程,链接如下:https://noobtuts.com/unity/2d-minesweeper-game

但是照着做出来有点问题,后来自己尝试的做了一个,效果如图:



主要有三个代码,一个是排序代码,一个是管理脚本,还有一个是子物体属性脚本,脚本内容如下:


GridTransform.cs

using UnityEngine;using System.Collections;public class GridTransform : MonoBehaviour{    //排序的列数    public int column = 1;    //间距的宽和高    public float space_w;    public float space_h;    //组件对象的宽和高    public float width;    public float Height;    //排序对象的数目    public int itemNumber;    public bool Direction;    //字段封装实时排序    public bool repositionNow    {        set        {            _repositionNow = value;            if (value)            {                Sort();                _repositionNow = false;            }        }        get        {            return _repositionNow;        }    }    private bool _repositionNow;    //排序方法    void Sort()    {        itemNumber = transform.childCount; ;        for (int i = 0; i < itemNumber; i++)        {            transform.GetChild(i).localPosition = new Vector3((width + space_w) * ((i) % (column)), (Direction?1:-1)*((i) / column) * (Height + space_h), 0);        }    }}

Element.cs

using UnityEngine;using System.Collections;public enum MineState{    Empty = 0,    Mine = 1,    Num = 2,    MaybeMine = 3}public class Element : MonoBehaviour{    /// <summary>    /// current box mine state    /// </summary>    public MineState mine;    public Sprite[] emptyTextures;    public Sprite mineTexture;    public void loadTexture(int mineCount = 0)    {        if ((int)mine == 1)            GetComponent<SpriteRenderer>().sprite = mineTexture;        else            GetComponent<SpriteRenderer>().sprite = emptyTextures[mineCount];    }    public bool isCovered()    {        return GetComponent<SpriteRenderer>().sprite.texture.name == "default";    }    void OnMouseUpAsButton()    {        Debug.Log(transform.localPosition.x + "   " + transform.localPosition.y+"    "+mine);        if ((int)mine == 1)        {            MineManager.Instance.uncoverMines();            print("you lose");        }        else        {            int x = (int)transform.localPosition.x;            int y = (int)transform.localPosition.y;            loadTexture(MineManager.Instance.MineCount(x, y));            MineManager.Instance.FFuncover(x, y, new bool[MineManager.Instance.width, MineManager.Instance.height]);            if (MineManager.Instance.isFinished())            {                print("you win");            }        }    }}

MineManager.cs

using UnityEngine;using System.Collections;using System.Collections.Generic;public class MineManager : MonoBehaviour{    public GameObject elementPrefab;    public GridTransform grid;    public int width;    public int height;    public Element[,] elements;    public int mineNumber;    public ArrayList MineLocation;    public static MineManager Instance;    // Use this for initialization    void Start()    {        Instance = this;        elements = new Element[width, height];        MineLocation = new ArrayList();        Init();    }    void Init()    {        //create element        for (int j = 0; j < height; j++)        {            for (int i = 0; i < width; i++)            {                elements[i, j] = CreateElement();                elements[i, j].mine = MineState.Empty;            }        }        //reset position        grid.repositionNow = true;        //random mine in the current elements        for (int n = 0; n < mineNumber; n++)        {            int k = Random.Range(0, width);            int m = Random.Range(0, height);            Vector2 temp = new Vector2(k, m);            if (MineLocation.Contains(temp))            {                n--;                continue;            }            elements[k, m].mine = MineState.Mine;            Debug.Log(elements[k, m].mine);            //elements[k, m].loadTexture();            var c = new Vector2(k, m);            Debug.Log(c);            MineLocation.Add(c);        }        //set numbers near mine        foreach (var item in MineLocation)        {            Vector2 t = (Vector2)item;            int x = (int)t.x;            int y = (int)t.y;            JudegeMinesNear(x - 1, y + 1);            JudegeMinesNear(x, y + 1);            JudegeMinesNear(x + 1, y + 1);            JudegeMinesNear(x - 1, y);            JudegeMinesNear(x + 1, y);            JudegeMinesNear(x - 1, y - 1);            JudegeMinesNear(x, y - 1);            JudegeMinesNear(x + 1, y - 1);        }    }    // Find out if a mine is at the coordinates    public bool mineAt(int x, int y)    {        // Coordinates in range? Then check for mine.        if (x >= 0 && y >= 0 && x < width && y < height)            return (int)elements[x, y].mine == 1;        return false;    }    public bool IsInclude(int x, int y)    {        if (x >= 0 && y >= 0 && x < width && y < height)            return true;        return false;    }    public void JudegeMinesNear(int x, int y)    {        if (IsInclude(x, y) == false)            return;        if ((int)elements[x, y].mine != 1)        {            elements[x, y].mine = MineState.Num;            //elements[x, y].loadTexture(MineCount(x, y));        }    }    // Count adjacent mines for an element    public int MineCount(int x, int y)    {        int count = 0;        if (mineAt(x, y + 1)) ++count; // top        if (mineAt(x + 1, y + 1)) ++count; // top-right        if (mineAt(x + 1, y)) ++count; // right        if (mineAt(x + 1, y - 1)) ++count; // bottom-right        if (mineAt(x, y - 1)) ++count; // bottom        if (mineAt(x - 1, y - 1)) ++count; // bottom-left        if (mineAt(x - 1, y)) ++count; // left        if (mineAt(x - 1, y + 1)) ++count; // top-left        return count;    }    // Flood Fill empty elements    public void FFuncover(int x, int y, bool[,] visited)    {        // Coordinates in Range?        if (IsInclude(x,y))        {            // visited already?            if (visited[x, y])                return;            // uncover element            elements[x, y].loadTexture(MineCount(x, y));            Debug.Log("            " + x + "   " + y);            // close to a mine? then no more work needed here            if (MineCount(x, y) > 0)                return;            // set visited flag            visited[x, y] = true;            // recursion            FFuncover(x - 1, y + 1, visited);            FFuncover(x, y + 1, visited);            FFuncover(x + 1, y + 1, visited);            FFuncover(x - 1, y, visited);            FFuncover(x + 1, y, visited);            FFuncover(x - 1, y - 1, visited);            FFuncover(x, y - 1, visited);            FFuncover(x + 1, y - 1, visited);            Debug.Log("----------------------------------------");        }    }    // Uncover all Mines    public void uncoverMines()    {        foreach (Element elem in elements)            if (elem.mine == MineState.Mine)                elem.loadTexture(0);    }    Element CreateElement()    {        GameObject temp = Instantiate(elementPrefab) as GameObject;        temp.transform.parent = grid.transform;        temp.transform.position = Vector3.zero;        return temp.GetComponent<Element>();    }    public bool isFinished()    {        // Try to find a covered element that is no mine        foreach (Element elem in elements)            if (elem.isCovered() && (int)elem.mine != 1)                return false;        // There are none => all are mines => game won.        return true;    }}


最终运行起来有点卡,也许MineManager还能优化,有建议的告诉我哈!


工程下载

0 0