[Unity] Cómo agrego la salida y la entrada en el laberinto Unity?
Este es un laberinto random, pero no tiene salida ni entrada, en la siguiente esta el código, alquien me puede ayudar con esto?
Gracias!!
En esta clase ListExtensions, como su nombre indica, esta clase es una extensión de la clase genérica "List". Esta clase sólo tiene un método para mezclar una lista. Será útil en la clase MazeGenerator.
using System.Collections.Generic;
public static class ListExtensions
{
public static IList<T> Shuffle<T> (this IList<T> list)
{
int n = list.Count;
while (n > 1) {
n--;
int k = UnityEngine.Random.Range(0, n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
VisualCell
Este script servirá para contener los componentes Transform de las paredes de prefab "Cell" que tengo creado.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class VisualCell : MonoBehaviour
{
#region Attributs
public Transform _Est;
public Transform _West;
public Transform _North;
public Transform _South;
#endregion
}
Arrastre y suelte el script en el prefab "Cell" y luego arrastre las paredes del prefabricado en el script.
Cell
Este clase se representa una celda en el laberinto con las paredes. Su posición así como su "estado" si fue visitado o no y por supuesto es constructor.
public class Cell
{
#region Attributs
public bool _West, _North, _Est, _South; // Oeste, Norte, Este y Sur.
public bool _visited; // Vamos a saber si la celda estaba visitando o no.
public int xPos, zPos; // Posición en X y Z.
// Constructor.
public Cell (bool west, bool north, bool est, bool south, bool visited)
{
this._West = west;
this._North = north;
this._Est = est;
this._South = south;
this._visited = visited;
}
}
CellAndRelativePosition
Este script contiene una celda, una enumeración de dirección, que servirá para saber en qué dirección recorrer para construir nuestro laberinto, y su constructor.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class CellAndRelativePosition
{
#region Attributs
public Cell cell; // Celda.
public Direction direction; // Dirección a tomar al quitar la pared.
#endregion
public enum Direction
{
North,
South,
East,
West
}
public CellAndRelativePosition (Cell cell, Direction direction)
{
this.cell = cell;
this.direction = direction;
}
}
MazeGenerator
Atributos
#region Attributs
public int _width, _height; //Anchura y altura del laberinto.
public VisualCell visualCellPrefab; // Prefab que sirve de modelo para la instancia.
public Cell[,] cells; //La tabla de celdas tiene dos dimensiones.
private Vector2 _randomCellPos; //Posición de la celda aleatoria que iniciará la generación.
private VisualCell visualCellInst; // Contiene la copia prefabricada de la instancia.
private List<CellAndRelativePosition> neighbors; //Lista de celdas vecinas
#endregion
Start()
void Start ()
{
cells = new Cell[_width, _height]; //Initialisation du tableau de cellules
Init(); //Lance la fonction Init
}
Init()
void Init ()
{
for(int i = 0; i < _width; i++)
{
for(int j = 0; j < _height; j++)
{
cells[i, j] = new Cell(false, false, false, false, false);
cells[i, j].xPos = i;
cells[i, j].zPos = j;
}
}
RandomCell(); //Inicia la función RandomCell.
InitVisualCell(); //Inicia la instanciación de celdas visuales.
}
RandomCell ()
void RandomCell (){
//Recupera una posición aleatoria X e Y
_randomCellPos = new Vector2((int)UnityEngine.Random.Range(0, _width), (int)UnityEngine.Random.Range(0, _height));
//Inicia la función GenerateMaze con las posiciones aleatorias X e Y.
GenerateMaze((int)_randomCellPos.x, (int)_randomCellPos.y);
}
GenerateMaze ()
void GenerateMaze (int x, int y)
{
// Debug.Log("Doing " + x + " " + y);
Cell currentCell = cells[x, y]; //Define la celda actual
neighbors = new List<CellAndRelativePosition>(); //Inicializar la lista
if(currentCell._visited == true) return;
currentCell._visited = true;
if(x + 1 < _width && cells[x + 1, y]._visited == false)
{ //Si no estamos en el ancho límite máximo de la laberinto y la celda derecha no es visita entonces podemos ir a la derecha
neighbors.Add(new CellAndRelativePosition(cells[x + 1, y], CellAndRelativePosition.Direction.East)); //Agrega la celda vecina a la derecha en la lista de vecinos
}
if(y + 1 < _height && cells[x, y + 1]._visited == false)
{ //Si uno no está en el límite del laberinto y la celda inferior no es visita entonces uno puede bajar
neighbors.Add(new CellAndRelativePosition(cells[x, y + 1], CellAndRelativePosition.Direction.South)); //Agrega la celda vecina en la parte inferior a la lista de vecinos
}
if(x - 1 >= 0 && cells[x - 1, y]._visited == false)
{ //Si no estamos en el ancho mini límite de la laberinto y la celda izquierda no está visitando entonces podemos ir a la izquierda
neighbors.Add(new CellAndRelativePosition(cells[x - 1, y], CellAndRelativePosition.Direction.West)); //Agrega la celda vecina a la izquierda en la lista de vecinos
}
if(y - 1 >= 0 && cells[x, y - 1]._visited == false)
{ //Si no estamos en la longitud de mini límite de la laberinto y la celda superior no está visitando entonces podemos subir
neighbors.Add(new CellAndRelativePosition(cells[x, y - 1], CellAndRelativePosition.Direction.North)); //Agregue la celda superior vecina a la lista de vecinos
}
if(neighbors.Count == 0) return; // Si hay 0 vecinos en la lista dejamos el método.
neighbors.Shuffle(); // Mezclar la lista de vecinos
foreach(CellAndRelativePosition selectedcell in neighbors)
{
if(selectedcell.direction == CellAndRelativePosition.Direction.East)
{ // A la derecha
if(selectedcell.cell._visited) continue;
currentCell._Est = true; //Detrúe la pared derecha de la celda actual
selectedcell.cell._West = true; //Detrúe la pared izquierda de la celda vecina seleccionada
GenerateMaze(x + 1, y); //Reinicia la función con la posición de la celda vecina
}
else if(selectedcell.direction == CellAndRelativePosition.Direction.South)
{ // Abajo
if(selectedcell.cell._visited) continue;
currentCell._South = true; //Destruye la pared inferior de la celda actual
selectedcell.cell._North = true; //Detrúe la pared superior de la celda vecina seleccionada
GenerateMaze(x, y + 1); //Reinicia la función con la posición de la celda vecina
}
else if(selectedcell.direction == CellAndRelativePosition.Direction.West)
{ // A la izquierda
if(selectedcell.cell._visited) continue;
currentCell._West = true; //Destruye la pared izquierda de la celda actual
selectedcell.cell._Est = true; //Destruye la pared derecha de la celda vecina seleccionada
GenerateMaze(x - 1, y); //Reinicia la función con la posición de la celda vecina
}
else if(selectedcell.direction == CellAndRelativePosition.Direction.North)
{ // Arriba
if(selectedcell.cell._visited) continue;
currentCell._North = true; //Destruye la pared superior de la celda actual
selectedcell.cell._South = true; //Detrue la pared inferior de la celda vecina seleccionada
GenerateMaze(x, y - 1); //Reinicia la función con la posición de la celda vecina
}
}
}
InitVisualCell ()
void InitVisualCell ()
{
// Inicializar las células visuales y destruir las paredes de acuerdo con las celdas virtuales
foreach (Cell cell in cells)
{
visualCellInst = Instantiate(visualCellPrefab, new Vector3(cell.xPos * 3, 0, _height * 3f - cell.zPos * 3), Quaternion.identity) as VisualCell;
visualCellInst.transform.parent = transform;
visualCellInst._North.gameObject.SetActive(!cell._North);
visualCellInst._South.gameObject.SetActive(!cell._South);
visualCellInst._Est.gameObject.SetActive(!cell._Est);
visualCellInst._West.gameObject.SetActive(!cell._West);
visualCellInst.transform.name = cell.xPos.ToString() + "_" + cell.zPos.ToString();
}
}