您的位置:首页 > 移动开发 > Unity3D

Unity制作扫雷游戏

2016-12-23 10:41 344 查看
曾经在网上看了一篇扫雷教程,链接如下: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还能优化,有建议的告诉我哈!

工程下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: