2019-04-27 11:38:29 +00:00
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
2019-04-27 14:15:38 +00:00
|
|
|
|
[System.Serializable]
|
|
|
|
|
public class ImpossibleCorridorError : System.Exception
|
|
|
|
|
{
|
|
|
|
|
public ImpossibleCorridorError() { }
|
|
|
|
|
public ImpossibleCorridorError(string message) : base(message) { }
|
|
|
|
|
public ImpossibleCorridorError(string message, System.Exception inner) : base(message, inner) { }
|
|
|
|
|
protected ImpossibleCorridorError(
|
|
|
|
|
System.Runtime.Serialization.SerializationInfo info,
|
|
|
|
|
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class MapRoom {
|
2019-04-27 15:20:25 +00:00
|
|
|
|
public readonly Vector2Int start;
|
|
|
|
|
public readonly Vector2Int end;
|
2019-04-27 14:15:38 +00:00
|
|
|
|
public readonly int mapSize;
|
|
|
|
|
|
2019-04-27 17:04:27 +00:00
|
|
|
|
public MapRoom(int mapSize, int maxRoomSize, int minRoomSize) {
|
2019-04-27 14:15:38 +00:00
|
|
|
|
this.mapSize = mapSize;
|
2019-04-27 17:04:27 +00:00
|
|
|
|
start = new Vector2Int(Random.Range(1, mapSize-1), Random.Range(1, mapSize-1));
|
|
|
|
|
end = new Vector2Int(Random.Range(1, mapSize-1), Random.Range(1, mapSize-1));
|
2019-04-27 14:15:38 +00:00
|
|
|
|
if(start.x > end.x) {
|
|
|
|
|
int swap = start.x;
|
|
|
|
|
start.x = end.x;
|
|
|
|
|
end.x = swap;
|
|
|
|
|
}
|
|
|
|
|
if(start.y > end.y) {
|
|
|
|
|
int swap = start.y;
|
|
|
|
|
start.y = end.y;
|
|
|
|
|
end.y = swap;
|
|
|
|
|
}
|
2019-04-27 15:18:09 +00:00
|
|
|
|
while(end.x - start.x > maxRoomSize) {
|
2019-04-27 14:48:37 +00:00
|
|
|
|
end.x--;
|
|
|
|
|
start.x++;
|
|
|
|
|
}
|
2019-04-27 15:18:09 +00:00
|
|
|
|
while(end.y - start.y > maxRoomSize) {
|
2019-04-27 14:48:37 +00:00
|
|
|
|
end.y--;
|
|
|
|
|
start.y++;
|
|
|
|
|
}
|
2019-04-27 17:04:27 +00:00
|
|
|
|
while(end.x - start.x < minRoomSize) {
|
|
|
|
|
end.x++;
|
|
|
|
|
start.x--;
|
|
|
|
|
}
|
|
|
|
|
while(end.y - start.y < minRoomSize) {
|
|
|
|
|
end.y++;
|
|
|
|
|
start.y--;
|
|
|
|
|
}
|
|
|
|
|
start.Clamp(new Vector2Int(1, 1), new Vector2Int(mapSize-1, mapSize-1));
|
|
|
|
|
end.Clamp(new Vector2Int(1, 1), new Vector2Int(mapSize-1, mapSize-1));
|
2019-04-27 14:15:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 17:19:37 +00:00
|
|
|
|
public Vector2Int RandomPoint() {
|
|
|
|
|
return new Vector2Int(Random.Range(start.x, end.x+1), Random.Range(start.y, end.y+1));
|
2019-04-27 14:15:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class MapCorridor {
|
2019-04-27 15:20:25 +00:00
|
|
|
|
public readonly Vector2Int start;
|
|
|
|
|
public readonly Vector2Int end;
|
2019-04-27 14:15:38 +00:00
|
|
|
|
public readonly bool horizontal_priority;
|
|
|
|
|
|
|
|
|
|
public MapCorridor(MapRoom from, MapRoom to, int mapSize) {
|
2019-04-27 17:19:37 +00:00
|
|
|
|
start = from.RandomPoint();
|
|
|
|
|
end = to.RandomPoint();
|
2019-04-27 14:15:38 +00:00
|
|
|
|
//50%
|
|
|
|
|
horizontal_priority = Random.Range(0f, 1f) >= 0.5f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 11:38:29 +00:00
|
|
|
|
public class Map : MonoBehaviour
|
|
|
|
|
{
|
2019-04-27 12:21:33 +00:00
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public int mapSize = 30;
|
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public int roomsToGenerate = 5;
|
|
|
|
|
|
2019-04-27 17:04:27 +00:00
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public int minRoomSize = 2;
|
|
|
|
|
|
2019-04-27 14:48:37 +00:00
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public int maxRoomSize = 6;
|
|
|
|
|
|
2019-04-27 15:18:09 +00:00
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public int maxRoomIterations = 100;
|
|
|
|
|
|
2019-04-27 12:21:33 +00:00
|
|
|
|
[BeforeStartAttribute]
|
2019-04-27 23:34:30 +00:00
|
|
|
|
public List<Sprite> floorSprites;
|
2019-04-27 14:15:38 +00:00
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
2019-04-27 23:34:30 +00:00
|
|
|
|
public List<Sprite> topWallSprites;
|
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public List<Sprite> botWallSprites;
|
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public List<Sprite> leftWallSprites;
|
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public List<Sprite> rightWallSprites;
|
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public List<Sprite> lCornerWallSprites;
|
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public List<Sprite> rCornerWallSprites;
|
2019-04-27 14:15:38 +00:00
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
2019-04-27 11:38:29 +00:00
|
|
|
|
public GameObject tilePrefab;
|
|
|
|
|
|
2019-04-27 20:19:35 +00:00
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public GameObject playerPrefab;
|
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public List<GameObject> enemyPrefabs;
|
|
|
|
|
|
|
|
|
|
[BeforeStartAttribute]
|
|
|
|
|
public int enemiesToSpawn = 10;
|
|
|
|
|
|
2019-04-27 14:15:38 +00:00
|
|
|
|
private GameObject[,] tiles;
|
|
|
|
|
private List<MapRoom> rooms;
|
2019-04-27 20:19:35 +00:00
|
|
|
|
private TurnHandler turnHandler;
|
2019-04-27 14:15:38 +00:00
|
|
|
|
|
2019-04-27 15:24:26 +00:00
|
|
|
|
public Tile GetTile(Vector2Int position) {
|
2019-04-27 23:34:30 +00:00
|
|
|
|
try {
|
|
|
|
|
GameObject tileObject = tiles[position.x, position.y];
|
|
|
|
|
return tileObject.GetComponent<Tile>();
|
|
|
|
|
}
|
|
|
|
|
catch(System.IndexOutOfRangeException) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2019-04-27 11:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 20:19:35 +00:00
|
|
|
|
public bool CanMoveTo(Vector2Int position)
|
2019-04-27 15:57:01 +00:00
|
|
|
|
{
|
2019-04-27 17:04:27 +00:00
|
|
|
|
try {
|
2019-04-27 20:19:35 +00:00
|
|
|
|
bool walkable = GetTile(position).walkable;
|
2019-04-28 14:28:31 +00:00
|
|
|
|
List<Entity> entities = turnHandler.GetEntitiesAtPosition(position);
|
2019-04-28 12:11:21 +00:00
|
|
|
|
bool free = true;
|
|
|
|
|
foreach(Entity entity in entities) {
|
|
|
|
|
free &= entity.overlappable;
|
|
|
|
|
}
|
2019-04-27 20:19:35 +00:00
|
|
|
|
return walkable && free;
|
2019-04-27 17:04:27 +00:00
|
|
|
|
}
|
2019-04-27 20:19:35 +00:00
|
|
|
|
catch(System.IndexOutOfRangeException) {
|
2019-04-27 17:04:27 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-27 15:57:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 23:34:30 +00:00
|
|
|
|
private void EditTile(Vector2Int position, bool walkable, bool roomPart) {
|
2019-04-27 15:28:38 +00:00
|
|
|
|
Tile tile = GetTile(position);
|
2019-04-27 14:15:38 +00:00
|
|
|
|
tile.walkable = walkable;
|
2019-04-27 18:13:28 +00:00
|
|
|
|
tile.roomPart |= roomPart;
|
2019-04-27 11:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FillWithWalls() {
|
2019-04-27 12:21:33 +00:00
|
|
|
|
for(int x = 0; x < mapSize; x++) {
|
|
|
|
|
for(int y = 0; y < mapSize; y++) {
|
|
|
|
|
GameObject tileObject = Instantiate(tilePrefab, transform);
|
|
|
|
|
tileObject.transform.position = new Vector3(x, y, 0);
|
|
|
|
|
tiles[x, y] = tileObject;
|
2019-04-27 15:18:09 +00:00
|
|
|
|
tileObject.name = "Tile [" + x.ToString() + ", " + y.ToString() + "]";
|
2019-04-27 12:21:33 +00:00
|
|
|
|
Tile tile = tileObject.GetComponent<Tile>();
|
|
|
|
|
tile.walkable = false;
|
2019-04-27 11:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 14:15:38 +00:00
|
|
|
|
private void PlaceRoom(MapRoom mr) {
|
|
|
|
|
for(int x = mr.start.x; x <= mr.end.x; x++) {
|
|
|
|
|
for(int y = mr.start.y; y <= mr.end.y; y++) {
|
2019-04-27 23:34:30 +00:00
|
|
|
|
EditTile(new Vector2Int(x, y), true, true);
|
2019-04-27 11:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 14:15:38 +00:00
|
|
|
|
private bool ScanRoom(MapRoom mr) {
|
|
|
|
|
//Returns true if the room can be safely placed
|
|
|
|
|
for(int x = Mathf.Clamp(mr.start.x-1, 0, mapSize-1); x <= Mathf.Clamp(mr.end.x+1, 0, mapSize-1); x++) {
|
|
|
|
|
for(int y = Mathf.Clamp(mr.start.y-1, 0, mapSize-1); y <= Mathf.Clamp(mr.end.y+1, 0, mapSize-1); y++) {
|
2019-04-27 15:28:38 +00:00
|
|
|
|
if(GetTile(new Vector2Int(x, y)).roomPart) {
|
2019-04-27 14:15:38 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-27 11:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-27 14:15:38 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void PlaceCorridor(MapCorridor mc) {
|
2019-04-27 15:20:25 +00:00
|
|
|
|
Vector2Int cursor = new Vector2Int(mc.start.x, mc.start.y);
|
2019-04-27 23:34:30 +00:00
|
|
|
|
EditTile(cursor, true, false);
|
2019-04-27 14:15:38 +00:00
|
|
|
|
if(mc.horizontal_priority) {
|
|
|
|
|
while(cursor.x != mc.end.x) {
|
|
|
|
|
if(cursor.x > mc.end.x) cursor.x--;
|
|
|
|
|
else cursor.x++;
|
2019-04-27 23:34:30 +00:00
|
|
|
|
EditTile(cursor, true, false);
|
2019-04-27 14:15:38 +00:00
|
|
|
|
}
|
|
|
|
|
while(cursor.y != mc.end.y) {
|
|
|
|
|
if(cursor.y > mc.end.y) cursor.y--;
|
|
|
|
|
else cursor.y++;
|
2019-04-27 23:34:30 +00:00
|
|
|
|
EditTile(cursor, true, false);
|
2019-04-27 11:38:29 +00:00
|
|
|
|
}
|
2019-04-27 14:15:38 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while(cursor.y != mc.end.y) {
|
|
|
|
|
if(cursor.y > mc.end.y) cursor.y--;
|
|
|
|
|
else cursor.y++;
|
2019-04-27 23:34:30 +00:00
|
|
|
|
EditTile(cursor, true, false);
|
2019-04-27 14:15:38 +00:00
|
|
|
|
}
|
|
|
|
|
while(cursor.x != mc.end.x) {
|
|
|
|
|
if(cursor.x > mc.end.x) cursor.x--;
|
|
|
|
|
else cursor.x++;
|
2019-04-27 23:34:30 +00:00
|
|
|
|
EditTile(cursor, true, false);
|
2019-04-27 11:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void GenerateMap() {
|
|
|
|
|
FillWithWalls();
|
2019-04-27 15:18:09 +00:00
|
|
|
|
int roomIterations = 0;
|
|
|
|
|
while(rooms.Count < roomsToGenerate && roomIterations < maxRoomIterations) {
|
|
|
|
|
roomIterations++;
|
2019-04-27 17:04:27 +00:00
|
|
|
|
MapRoom room = new MapRoom(mapSize, maxRoomSize, minRoomSize);
|
2019-04-27 14:15:38 +00:00
|
|
|
|
if(ScanRoom(room)) {
|
2019-04-27 17:04:27 +00:00
|
|
|
|
//Fill with the room
|
2019-04-27 14:15:38 +00:00
|
|
|
|
PlaceRoom(room);
|
|
|
|
|
rooms.Add(room);
|
|
|
|
|
}
|
2019-04-27 17:04:27 +00:00
|
|
|
|
//Place a corridor
|
2019-04-27 14:15:38 +00:00
|
|
|
|
if(rooms.Count > 1) {
|
2019-04-27 15:18:09 +00:00
|
|
|
|
MapRoom from = rooms[rooms.Count-2];
|
|
|
|
|
MapRoom to = rooms[rooms.Count-1];
|
2019-04-27 14:48:37 +00:00
|
|
|
|
try {
|
|
|
|
|
MapCorridor corridor = new MapCorridor(from, to, mapSize);
|
|
|
|
|
PlaceCorridor(corridor);
|
|
|
|
|
}
|
2019-04-27 17:04:27 +00:00
|
|
|
|
catch (ImpossibleCorridorError) {
|
|
|
|
|
}
|
2019-04-27 14:15:38 +00:00
|
|
|
|
}
|
2019-04-27 12:21:33 +00:00
|
|
|
|
}
|
2019-04-27 11:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 20:19:35 +00:00
|
|
|
|
private void PlacePlayer() {
|
|
|
|
|
MapRoom room = rooms[Random.Range(0, rooms.Count)];
|
|
|
|
|
Vector2Int point = room.RandomPoint();
|
|
|
|
|
GameObject playerObject = Instantiate(playerPrefab, turnHandler.transform);
|
|
|
|
|
playerObject.name = "Player";
|
|
|
|
|
playerObject.transform.position = new Vector3(point.x, point.y, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void PlaceEnemies() {
|
|
|
|
|
for(int i = 0; i < enemiesToSpawn; i++) {
|
|
|
|
|
MapRoom room = rooms[Random.Range(0, rooms.Count)];
|
|
|
|
|
Vector2Int point = room.RandomPoint();
|
|
|
|
|
GameObject enemyPrefab = enemyPrefabs[Random.Range(0, enemyPrefabs.Count)];
|
|
|
|
|
GameObject enemyObject = Instantiate(enemyPrefab, turnHandler.transform);
|
|
|
|
|
enemyObject.name = "Enemy " + i.ToString();
|
|
|
|
|
enemyObject.transform.position = new Vector3(point.x, point.y, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 23:34:30 +00:00
|
|
|
|
public static Sprite SampleSprite(List<Sprite> list) {
|
|
|
|
|
return list[Random.Range(0, list.Count)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void GenerateTileSprites() {
|
|
|
|
|
for(int x = 0; x < mapSize; x++) {
|
|
|
|
|
for(int y = 0; y < mapSize; y++) {
|
|
|
|
|
Tile tile = GetTile(new Vector2Int(x, y));
|
|
|
|
|
Tile otherTile;
|
|
|
|
|
if(tile.walkable) tile.sprite = SampleSprite(floorSprites);
|
|
|
|
|
else if((bool)(otherTile = GetTile(new Vector2Int(x, y+1))) && otherTile.walkable) tile.sprite = SampleSprite(botWallSprites);
|
|
|
|
|
else if((bool)(otherTile = GetTile(new Vector2Int(x, y+1))) && otherTile.walkable) tile.sprite = SampleSprite(topWallSprites);
|
|
|
|
|
//TODO: corners
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-27 17:04:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 11:38:29 +00:00
|
|
|
|
private void Start()
|
|
|
|
|
{
|
2019-04-27 14:15:38 +00:00
|
|
|
|
//Initialize everything
|
2019-04-27 12:21:33 +00:00
|
|
|
|
tiles = new GameObject[mapSize, mapSize];
|
2019-04-27 14:15:38 +00:00
|
|
|
|
rooms = new List<MapRoom>();
|
2019-04-27 20:19:35 +00:00
|
|
|
|
turnHandler = GameObject.FindGameObjectWithTag("GameController").GetComponentInChildren<TurnHandler>();
|
|
|
|
|
|
2019-04-27 23:34:30 +00:00
|
|
|
|
GenerateMap();
|
|
|
|
|
GenerateTileSprites();
|
2019-04-27 20:19:35 +00:00
|
|
|
|
PlacePlayer();
|
|
|
|
|
PlaceEnemies();
|
2019-04-27 11:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|