1.制作金光闪闪的特效
2.设计金币元素类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GoldElement : DoubleCoveredElement {
public GoldType goldType;
public override void Awake()
{
base.Awake();
elementContent = ElementContent.Gold;
}
public override void OnUnCovered()
{
Transform goldEffect = transform.Find("GoldEffect");
if (goldEffect != null)
{
Destroy(goldEffect.gameObject);
}
//TODO 获得金币
Debug.Log("Get a Gold");
base.OnUnCovered();
}
public override void ConfirmSprite()
{
Transform goldEffect = transform.Find("GoldEffect");
if (goldEffect == null)
{
Instantiate(GameManager._instance.goldEffect,transform).name = "GoldEffect";
}
LoadSprite(GameManager._instance.goldSprites[(int)goldType]);
}
}
3.设计剩余的所有不可翻开的元素类
创建五个类,分别为BigWall,SmallWall,Door,Enemy
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BigWallElement : CantCoveredElement {
public override void Awake()
{
base.Awake();
elementContent = ElementContent.BigWall;
LoadSprite(GameManager._instance.bigwallSprites[Random.Range(0, GameManager._instance.bigwallSprites.Length)]);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmallWallElement : CantCoveredElement {
public override void Awake()
{
base.Awake();
elementContent = ElementContent.SmallWall;
ClearShadow();
LoadSprite(GameManager._instance.smallwallSprites[Random.Range(0, GameManager._instance.smallwallSprites.Length)]);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoorElement : CantCoveredElement {
public override void Awake()
{
base.Awake();
elementContent = ElementContent.Door;
LoadSprite(GameManager._instance.doorSprite);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyElement : CantCoveredElement {
public override void Awake()
{
base.Awake();
elementContent = ElementContent.Enemy;
ClearShadow();
LoadSprite(GameManager._instance.enemySprites[Random.Range(0, GameManager._instance.enemySprites.Length)]);
}
}
4.关卡出口的生成
建立关卡出口的类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExitElement : CantCoveredElement
{
public override void Awake()
{
base.Awake();
elementContent = ElementContent.Exit;
ClearShadow();
name = "Exit";
LoadSprite(GameManager._instance.exitSprite);
}
}
在GameManager中写生成出口的方法
/// <summary>
/// 生成出口
/// </summary>
/// <param name="availableIndex">尚未初始化的地图元素的索引值</param>
private void GenerateExit(List<int> availableIndex)
{
float x = w - 1.5f;
float y = Random.Range(1, h) - 0.5f;
BaseElement exit = SetElement(GetIndex((int)(x + 0.5), (int)(y - 0.5)), ElementContent.Exit);
exit.transform.position = new Vector3(x, y, 0);
Destroy(exit.GetComponent<BoxCollider2D>());
exit.gameObject.AddComponent<BoxCollider2D>();
availableIndex.Remove(GetIndex((int)(x + 0.5), (int)(y - 0.5)));
availableIndex.Remove(GetIndex((int)(x + 0.5), (int)(y + 0.5)));
availableIndex.Remove(GetIndex((int)(x - 0.5), (int)(y - 0.5)));
availableIndex.Remove(GetIndex((int)(x - 0.5), (int)(y + 0.5)));
Destroy(mapArray[(int)(x + 0.5), (int)(y + 0.5)].gameObject);
Destroy(mapArray[(int)(x - 0.5), (int)(y - 0.5)].gameObject);
Destroy(mapArray[(int)(x - 0.5), (int)(y + 0.5)].gameObject);
mapArray[(int)(x + 0.5), (int)(y + 0.5)] = exit;
mapArray[(int)(x - 0.5), (int)(y - 0.5)] = exit;
mapArray[(int)(x - 0.5), (int)(y + 0.5)] = exit;
}
运行程序,结果如下:
5.障碍物生成策略简介
6.设计闭合区域信息结构体
/// <summary>
/// 生成障碍物区
/// </summary>
/// <param name="availableIndex">尚未初始化的地图元素的索引值</param>
private void GenerateObstacleArea(List<int> availableIndex)
{
for(int i = 0; i < obstacleAreaNum; i++)
{
if (Random.value < 0.5f)
{
CreateCloseArea(i, availableIndex);
}
else
{
CreateRandomWall(i, availableIndex);
}
}
}
private struct CloseAreaInfo
{
int x, y, sx, ex, sy, ey;
public int doorType;
public Vector2 doorPos;
public int tx, ty;
public ToolElement t;
public int gx, gy;
public GoldElement g;
public int innerCount, goldNum;
}
/// <summary>
/// 生成闭合障碍物区域
/// </summary>
/// <param name="nowArea">当前障碍物区域的索引值</param>
/// <param name="availableIndex">尚未初始化的地图元素的索引值列表</param>
private void CreateCloseArea(int nowArea, List<int> availableIndex)
{
int shape = Random.Range(0, 2);
switch (shape)
{
case 0:
break;
case 1:
break;
}
}
/// <summary>
/// 生成随机障碍物区域
/// </summary>
/// <param name="nowArea">当前障碍物区域的索引值</param>
/// <param name="availableIndex">尚未初始化的地图元素的索引值列表</param>
private void CreateRandomWall(int nowArea, List<int> availableIndex)
{
}
7.生成闭合区域信息
/// <summary>
/// 生成闭合区域信息
/// </summary>
/// <param name="type">闭合区域类型,0:与边界闭合;1:自闭和</param>
/// <param name="nowArea">闭合区域索引值</param>
/// <param name="info">要生成的闭合区域信息结构体</param>
private void GenerateCloseAreaInfo(int type,int nowArea,ref CloseAreaInfo info)
{
switch (type)
{
case 0:
info.x = Random.Range(3, obstacleAreaW - 2);
info.y = Random.Range(3, h - 3);
info.sx = standAreaW + nowArea * obstacleAreaW + 1;
info.ex = info.sx + info.x;
info.doorType = Random.Range(4, 8);
break;
case 1:
break;
}
}
/// <summary>
/// 生成闭合障碍物区域
/// </summary>
/// <param name="nowArea">当前障碍物区域的索引值</param>
/// <param name="availableIndex">尚未初始化的地图元素的索引值列表</param>
private void CreateCloseArea(int nowArea, List<int> availableIndex)
{
int shape = Random.Range(0, 2);
CloseAreaInfo info = new CloseAreaInfo();
switch (shape)
{
case 0:
GenerateCloseAreaInfo(0, nowArea, ref info);
int dir = Random.Range(0, 4);
switch (dir)//四种样子的障碍物区域
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
}
break;
case 1:
break;
}
}
8.生成闭合区域的门和墙
/// <summary>
/// 生成闭合障碍物区域
/// </summary>
/// <param name="nowArea">当前障碍物区域的索引值</param>
/// <param name="availableIndex">尚未初始化的地图元素的索引值列表</param>
private void CreateCloseArea(int nowArea, List<int> availableIndex)
{
int shape = Random.Range(0, 2);
CloseAreaInfo info = new CloseAreaInfo();
switch (shape)
{
case 0:
GenerateCloseAreaInfo(0, nowArea, ref info);
int dir = Random.Range(0, 4);
switch (dir)
{
case 0:
info.doorPos = Random.value < 0.5f ? new Vector2(Random.Range(info.sx + 1, info.ex), info.y) : new Vector2(Random.value < 0.5f ? info.sx : info.ex, Random.Range(info.y, h));
CreateULShapeAreaDoor(info, availableIndex);
for(int i = h - 1; i > info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.sx, i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
}
for (int i = info.sx; i < info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.y)))
{
availableIndex.Remove(GetIndex(i, info.y));
SetElement(GetIndex(i, info.y), ElementContent.BigWall);
}
}
for (int i = h-1; i >= info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
break;
case 1:
break;
case 2:
break;
case 3:
break;
}
break;
case 1:
break;
}
}
/// <summary>
/// 生成U或L闭合障碍物区域的门
/// </summary>
/// <param name="info">闭合区域信息</param>
/// <param name="availableIndex">要生成的闭合区域信息结构体</param>
private void CreateULShapeAreaDoor(CloseAreaInfo info,List<int> availableIndex)
{
availableIndex.Remove(GetIndex((int)info.doorPos.x, (int)info.doorPos.y));
SetElement(GetIndex((int)info.doorPos.x, (int)info.doorPos.y), (ElementContent)info.doorType);
}
/// <summary>
/// 生成U或L闭合障碍物区域的奖励物品
/// </summary>
/// <param name="info">闭合区域信息</param>
/// <param name="availableIndex">要生成的闭合区域信息结构体</param>
private void CreateCloseAreaRewards(CloseAreaInfo info, List<int> availableIndex)
{
info.innerCount = info.x * info.y;
info.goldNum = Random.Range(1, Random.value < 0.5 ? info.innerCount + 1 : info.innerCount / 2);
for(int i = 0; i < info.goldNum; i++)
{
}
}
9.生成闭合区域的奖励
/// <summary>
/// 生成闭合障碍物区域
/// </summary>
/// <param name="nowArea">当前障碍物区域的索引值</param>
/// <param name="availableIndex">尚未初始化的地图元素的索引值列表</param>
private void CreateCloseArea(int nowArea, List<int> availableIndex)
{
int shape = Random.Range(0, 2);
CloseAreaInfo info = new CloseAreaInfo();
switch (shape)
{
case 0:
GenerateCloseAreaInfo(0, nowArea, ref info);
int dir = Random.Range(0, 4);
switch (dir)
{
case 0:
info.doorPos = Random.value < 0.5f ? new Vector2(Random.Range(info.sx + 1, info.ex), info.y) : new Vector2(Random.value < 0.5f ? info.sx : info.ex, Random.Range(info.y, h));
CreateULShapeAreaDoor(info, availableIndex);
for(int i = h - 1; i > info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.sx, i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
}
for (int i = info.sx; i < info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.y)))
{
availableIndex.Remove(GetIndex(i, info.y));
SetElement(GetIndex(i, info.y), ElementContent.BigWall);
}
}
for (int i = h-1; i >= info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
info.sy = info.y;
info.ey = h - 1;
info.y = h - 1 - info.y;
CreateCloseAreaRewards(info, availableIndex);
break;
case 1:
info.doorPos = Random.value < 0.5f ? new Vector2(Random.Range(info.sx + 1, info.ex), info.y) : new Vector2(Random.value < 0.5f ? info.sx : info.ex, Random.Range(0, info.y));
CreateULShapeAreaDoor(info, availableIndex);
for (int i = 0; i < info.y; i++)
{
if (availableIndex.Contains(GetIndex(info.sx, i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
}
for (int i = info.sx; i < info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.y)))
{
availableIndex.Remove(GetIndex(i, info.y));
SetElement(GetIndex(i, info.y), ElementContent.BigWall);
}
}
for (int i = 0; i <= info.y; i++)
{
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
info.sy = 0;
info.ey = info.y;
CreateCloseAreaRewards(info, availableIndex);
break;
case 2:
info.doorPos = Random.value < 0.5f ? new Vector2(Random.Range(info.sx + 1, info.ex), info.y) : new Vector2(info.sx , Random.Range(info.y, h));
CreateULShapeAreaDoor(info, availableIndex);
for (int i = h - 1; i > info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.sx, i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
}
for (int i = info.sx; i < info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.y)))
{
availableIndex.Remove(GetIndex(i, info.y));
SetElement(GetIndex(i, info.y), ElementContent.BigWall);
}
}
for (int i = 0; i <= info.y; i++)
{
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
break;
case 3:
info.doorPos = Random.value < 0.5f ? new Vector2(Random.Range(info.sx + 1, info.ex), info.y) : new Vector2(info.sx, Random.Range(0, info.y));
CreateULShapeAreaDoor(info, availableIndex);
for (int i = 0; i < info.y; i++)
{
if (availableIndex.Contains(GetIndex(info.sx, i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
}
for (int i = info.sx; i < info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.y)))
{
availableIndex.Remove(GetIndex(i, info.y));
SetElement(GetIndex(i, info.y), ElementContent.BigWall);
}
}
for (int i = h - 1; i >= info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
break;
}
break;
case 1:
break;
}
}
10.完成闭合区域的生成
添加自闭和区域的结构体和生成代码
/// <summary>
/// 生成闭合区域信息
/// </summary>
/// <param name="type">闭合区域类型,0:与边界闭合;1:自闭和</param>
/// <param name="nowArea">闭合区域索引值</param>
/// <param name="info">要生成的闭合区域信息结构体</param>
private void GenerateCloseAreaInfo(int type,int nowArea,ref CloseAreaInfo info)
{
switch (type)
{
case 0:
info.x = Random.Range(3, obstacleAreaW - 2);
info.y = Random.Range(3, h - 3);
info.sx = standAreaW + nowArea * obstacleAreaW + 1;
info.ex = info.sx + info.x;
info.doorType = Random.Range(4, 8);
break;
case 1:
info.x = Random.Range(3, obstacleAreaW - 2);
info.y = Random.Range(3, info.x + 1);
info.sx = standAreaW + nowArea * obstacleAreaW + 1;
info.ex = info.sx + info.x;
info.sy = Random.Range(3, h - info.y - 1);
info.ey = info.sy + info.y;
info.doorType = (int)ElementContent.BigWall;
break;
}
}
/// <summary>
/// 生成闭合障碍物区域
/// </summary>
/// <param name="nowArea">当前障碍物区域的索引值</param>
/// <param name="availableIndex">尚未初始化的地图元素的索引值列表</param>
private void CreateCloseArea(int nowArea, List<int> availableIndex)
{
int shape = Random.Range(0, 2);
CloseAreaInfo info = new CloseAreaInfo();
switch (shape)
{
case 0:
GenerateCloseAreaInfo(0, nowArea, ref info);
int dir = Random.Range(0, 4);
switch (dir)
{
case 0:
info.doorPos = Random.value < 0.5f ? new Vector2(Random.Range(info.sx + 1, info.ex), info.y) : new Vector2(Random.value < 0.5f ? info.sx : info.ex, Random.Range(info.y, h));
CreateULShapeAreaDoor(info, availableIndex);
for(int i = h - 1; i > info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.sx, i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
}
for (int i = info.sx; i < info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.y)))
{
availableIndex.Remove(GetIndex(i, info.y));
SetElement(GetIndex(i, info.y), ElementContent.BigWall);
}
}
for (int i = h-1; i >= info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
info.sy = info.y;
info.ey = h - 1;
info.y = h - 1 - info.y;
CreateCloseAreaRewards(info, availableIndex);
break;
case 1:
info.doorPos = Random.value < 0.5f ? new Vector2(Random.Range(info.sx + 1, info.ex), info.y) : new Vector2(Random.value < 0.5f ? info.sx : info.ex, Random.Range(0, info.y));
CreateULShapeAreaDoor(info, availableIndex);
for (int i = 0; i < info.y; i++)
{
if (availableIndex.Contains(GetIndex(info.sx, i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
}
for (int i = info.sx; i < info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.y)))
{
availableIndex.Remove(GetIndex(i, info.y));
SetElement(GetIndex(i, info.y), ElementContent.BigWall);
}
}
for (int i = 0; i <= info.y; i++)
{
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
info.sy = 0;
info.ey = info.y;
CreateCloseAreaRewards(info, availableIndex);
break;
case 2:
info.doorPos = Random.value < 0.5f ? new Vector2(Random.Range(info.sx + 1, info.ex), info.y) : new Vector2(info.sx , Random.Range(info.y, h));
CreateULShapeAreaDoor(info, availableIndex);
for (int i = h - 1; i > info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.sx, i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
}
for (int i = info.sx; i < info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.y)))
{
availableIndex.Remove(GetIndex(i, info.y));
SetElement(GetIndex(i, info.y), ElementContent.BigWall);
}
}
for (int i = 0; i <= info.y; i++)
{
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
break;
case 3:
info.doorPos = Random.value < 0.5f ? new Vector2(Random.Range(info.sx + 1, info.ex), info.y) : new Vector2(info.sx, Random.Range(0, info.y));
CreateULShapeAreaDoor(info, availableIndex);
for (int i = 0; i < info.y; i++)
{
if (availableIndex.Contains(GetIndex(info.sx, i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
}
for (int i = info.sx; i < info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.y)))
{
availableIndex.Remove(GetIndex(i, info.y));
SetElement(GetIndex(i, info.y), ElementContent.BigWall);
}
}
for (int i = h - 1; i >= info.y; i--)
{
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
break;
}
CreateCloseAreaTool(info, availableIndex);
break;
case 1:
GenerateCloseAreaInfo(1, nowArea, ref info);
for(int i = info.sx; i<= info.ex; i++)
{
if (availableIndex.Contains(GetIndex(i, info.sy)))
{
availableIndex.Remove(GetIndex(i, info.sy));
SetElement(GetIndex(i, info.sy), ElementContent.BigWall);
}
if (availableIndex.Contains(GetIndex(i, info.ey)))
{
availableIndex.Remove(GetIndex(i, info.ey));
SetElement(GetIndex(i, info.ey), ElementContent.BigWall);
}
}
for (int i = info.sy + 1; i < info.ey; i++)
{
if (availableIndex.Contains(GetIndex(info.sx,i)))
{
availableIndex.Remove(GetIndex(info.sx, i));
SetElement(GetIndex(info.sx, i), ElementContent.BigWall);
}
if (availableIndex.Contains(GetIndex(info.ex, i)))
{
availableIndex.Remove(GetIndex(info.ex, i));
SetElement(GetIndex(info.ex, i), ElementContent.BigWall);
}
}
CreateCloseAreaRewards(info,availableIndex);
CreateCloseAreaTool(info, availableIndex);
break;
}
}
11.完成地图的创建
完成生成道具和生成金币的方法
/// <summary>
/// 生成道具
/// </summary>
/// <param name="availableIndex">尚未初始化的地图元素的索引值</param>
private void GenerateTool(List<int> availableIndex)
{
for (int i = 0; i < 3; i++)
{
int tempIndex = availableIndex[Random.Range(0, availableIndex.Count)];
availableIndex.Remove(tempIndex);
ToolElement t = (ToolElement)SetElement(tempIndex, ElementContent.Tool);
t.toolType = (ToolType)Random.Range(0, 9);
if (t.isHide == false)
{
t.ConfirmSprite();
}
}
}
/// <summary>
/// 生成金币
/// </summary>
/// <param name="availableIndex">尚未初始化的地图元素的索引值</param>
private void GenerateGold(List<int> availableIndex)
{
for (int i = 0; i < obstacleAreaNum * 3; i++)
{
int tempIndex = availableIndex[Random.Range(0, availableIndex.Count)];
availableIndex.Remove(tempIndex);
GoldElement g = (GoldElement)SetElement(tempIndex, ElementContent.Gold);
g.goldType = (GoldType)Random.Range(0, 7);
if (g.isHide == false)
{
g.ConfirmSprite();
}
}
}
运行程序,结果如下:
12.为玩家创建站立区域
在生成陷阱的方法中添加一条语句,使初始的地方没有陷阱
/// <summary>
/// 生成陷阱
/// </summary>
/// <param name="standAreaY">站立区域的y坐标</param>
/// <param name="availableIndex">尚未初始化的地图元素的索引值</param>
private void GenerateTrap(int standAreaY, List<int> availableIndex)
{
float trapProbability = Random.Range(minTrapProbability, maxTrapProbability);
int trapNum = (int)(availableIndex.Count * trapProbability);
for (int i = 0; i < trapNum; i++)
{
int tempIndex = availableIndex[Random.Range(0, availableIndex.Count)];
int x, y;
GetPosition(tempIndex, out x, out y);
if (x >= 0 && x < standAreaW && y >= standAreaY - 1 && y <= standAreaY + 1) continue;
availableIndex.Remove(tempIndex);
SetElement(tempIndex, ElementContent.Trap);
}
}
添加生成初始空位的方法
/// <summary>
/// 生成站立区域
/// </summary>
/// <param name="y">站立区域中心y坐标</param>
private void GenerateStandArea(int y)
{
for(int i = 0; i < standAreaW; i++)
{
for(int j = y - 1; j <= y + 1; j++)
{
((SingleCoveredElement)mapArray[i, j]).UncoverElementSingle();
}
}
}
运行程序,结果如下: