// Perimeter protected bool ConvertPerimeterWall(VirtualMap map, VirtualCell conversion_cell) { if (!behaviour.usePerimeter) { return(false); } if (map.LocationIsInPerimeter(conversion_cell.location)) { conversion_cell.Type = VirtualCell.CellType.PerimeterWall; if (conversion_cell.location.x == 0) { conversion_cell.Orientation = VirtualMap.DirectionType.East; } else if (conversion_cell.location.x == map.Width - 1) { conversion_cell.Orientation = VirtualMap.DirectionType.West; } else if (conversion_cell.location.y == 0) { conversion_cell.Orientation = VirtualMap.DirectionType.North; } else if (conversion_cell.location.y == map.Height - 1) { conversion_cell.Orientation = VirtualMap.DirectionType.South; } return(true); } return(false); }
// Returns true if this passage cell can be removed from the map (i.e. not shown) public bool IsPassageRemovable(CellLocation l) { VirtualCell cell = this.GetCell(l); if (cell.IsWall() || cell.IsEmpty()) { // We count how many valid neighs are floors, and how many are nones int validNeigh = 0; int floorCount = 0; int noneCount = 0; CellLocation n; foreach (DirectionType dir in directions) { n = GetNeighbourCellLocation(l, dir); if (!LocationIsOutsideBounds(n)) { validNeigh++; VirtualCell neigh_cell = GetCell(n); if (neigh_cell.IsFloor()) { floorCount++; } else if (neigh_cell.IsNone() || neigh_cell.IsRock()) { noneCount++; } } } //Debug.Log(l + " Valid neighs: " + validNeigh + " floorCount: " + floorCount + " noneCount: " + noneCount); return(floorCount == 0); } return(false); }
// The first pass will fill the tilemap intersection cells, so that it can be used similarly to the standard map interpreter private void PerformTilemapConversion(VirtualMap map, VirtualMap[] maps, int storey) { VirtualCell conversion_cell; VirtualCell[,] output_cells = new VirtualCell[map.Width, map.Height]; for (int i = 0; i < map.Width; i++) { for (int j = 0; j < map.Height; j++) { CellLocation loc = new CellLocation(i, j); conversion_cell = VirtualCell.Copy(map.GetCell(loc)); ConvertTileIntersections(map, conversion_cell); output_cells[i, j] = conversion_cell; } } // We can now override the initial map! for (int i = 0; i < map.Width; i++) { for (int j = 0; j < map.Height; j++) { map.SetCell(i, j, output_cells[i, j]); } } }
protected void ConvertFixedWallOrientation(VirtualMap map, VirtualCell conversion_cell) { if (!behaviour.randomOrientations && !behaviour.useDirectionalFloors) { conversion_cell.Orientation = VirtualMap.DirectionType.North; } }
// 3D protected void ConvertCeiling(VirtualMap map, VirtualCell conversion_cell) { // Checking if we need to add a ceiling VirtualCell.CellType cell_type = conversion_cell.Type; //Debug.Log(conversion_cell); if (conversion_cell.IsFloor()) { VirtualCell.CellType ceiling_type = VirtualCell.CellType.None; if (VirtualCell.IsRoomFloor(cell_type)) { if (behaviour.addCeilingToRooms) { ceiling_type = VirtualCell.CellType.RoomCeiling; } } else { if (behaviour.addCeilingToCorridors) { ceiling_type = VirtualCell.CellType.CorridorCeiling; } } if (ceiling_type != VirtualCell.CellType.None) { conversion_cell.AddCellInstance(ceiling_type, conversion_cell.Orientation); } } }
public void MarkAsVisited(CellLocation l) { VirtualCell cell = GetCell(l); cell.visited = true; visitedCells.Add(l); }
protected void ConvertTileIntersections(VirtualMap map, VirtualCell conversion_cell) { if (conversion_cell.IsEmpty()) { // Empty passages should be filled with floors, unless removable (and thus become rock) if (map.IsPassageRemovable(conversion_cell.location)) { conversion_cell.Type = VirtualCell.CellType.Rock; } else { if (CheckRoom(map, conversion_cell.location)) { AddToCorrectRoom(map, conversion_cell.location); conversion_cell.Type = VirtualCell.CellType.RoomFloor; } else { conversion_cell.Type = VirtualCell.CellType.CorridorFloor; } } } else { // 'None' cells will remain as such, since they will be converted to columns later (or to floors), if needed. } }
private bool ExistsPathBetweenLocationsRecursive(CellLocation s, CellLocation e, List <CellLocation> visited) { //Debug.Log("Visiting " + s); visited.Add(s); VirtualCell s_cell = GetCell(s); foreach (CellLocation c in s_cell.connectedCells) { if (c == e) { //Debug.Log("Found the end!"); return(true); // Found this! } else { if (!visited.Contains(c)) { bool foundEnd = ExistsPathBetweenLocationsRecursive(c, e, visited); //if (foundEnd) Debug.Log("Found the end in child!"); if (foundEnd) { return(true); // Found connected! } } } } return(false); // Not here! }
/************ * Checks ************/ protected void CheckOrientationRandomization(VirtualMap map, VirtualCell conversion_cell) { if (conversion_cell.Orientation == VirtualMap.DirectionType.None && behaviour.randomOrientations) { conversion_cell.Orientation = (VirtualMap.DirectionType)DungeonGenerator.Random.Instance.Next(map.nDirections); } // Debug.Log (conversion_cell.Orientation); }
public void BuildObjectsOfCell(VirtualMap map, VirtualCell cell, int storey) { // BuildObject(map,cell.starting_location,storey,cell.Type,cell.Orientation); // foreach(VirtualCell.CellType t in cell.GetSubTypes()) BuildObject(map,cell.starting_location,storey,t,cell.Orientation); foreach (CellInstance ci in cell.GetCellInstances()) { BuildObject(map, cell.location, storey, ci.type, ci.dir); } }
/***************** * Conversions *****************/ // Standard protected void ConvertRock(VirtualMap map, VirtualCell conversion_cell) { if (!behaviour.drawRocks) { conversion_cell.Type = VirtualCell.CellType.None; } else { conversion_cell.Type = VirtualCell.CellType.Rock; } }
// The second pass will update the different tiles as needed private void PerformSpecificConversions(VirtualMap map, VirtualMap[] maps, int storey) { VirtualCell conversion_cell; VirtualCell[,] output_cells = new VirtualCell[map.Width, map.Height]; for (int i = 0; i < map.Width; i++) { for (int j = 0; j < map.Height; j++) { CellLocation loc = new CellLocation(i, j); conversion_cell = VirtualCell.Copy(map.GetCell(loc)); if (conversion_cell.IsFloor()) { ConvertFloor(map, conversion_cell); } else if (conversion_cell.IsDoor()) { ConvertDoor(map, conversion_cell); } else if (conversion_cell.IsWall()) { // All walls are rocks here ConvertRock(map, conversion_cell); } else if (conversion_cell.IsNone()) { // All nones are rocks here ConvertRock(map, conversion_cell); } else if (conversion_cell.IsRock()) { // All is rock! ConvertRock(map, conversion_cell); } // Final pass on orientation randomization CheckOrientationRandomization(map, conversion_cell); // We save it in the initial map output_cells[i, j] = conversion_cell; } } // We can now override the initial map! for (int i = 0; i < map.Width; i++) { for (int j = 0; j < map.Height; j++) { map.SetCell(i, j, output_cells[i, j]); } } }
public static VirtualCell Copy(VirtualCell input_cell) { VirtualCell copied_cell = new VirtualCell(input_cell.location); foreach (CellInstance c in input_cell.instances) { copied_cell.AddCellInstance(CellInstance.Copy(c)); } copied_cell.connectedCells = input_cell.connectedCells; // They have the same connected cells TODO: maybe instead copy them alltogether? copied_cell.distance_from_root = input_cell.distance_from_root; return(copied_cell); }
override public void CreateObject(VirtualMap map, MetricLocation l, VirtualCell.CellType cell_type, VirtualMap.DirectionType orientation) { GameObject go = null; if (alreadyCreated && currentIndex < spawnedSpriteGos.Count) { go = spawnedSpriteGos[currentIndex]; currentIndex++; } else { go = (GameObject)GameObject.Instantiate(behaviour.spritePrefab, new Vector3(l.x * behaviour.tileSize, 0, l.y * behaviour.tileSize), Quaternion.identity); spawnedSpriteGos.Add(go); } Sprite sprite = behaviour.GetPrefab(cell_type); go.GetComponent <SpriteRenderer>().sprite = sprite; go.name = cell_type.ToString(); go.GetComponent <BoxCollider2D>().size = new Vector2(behaviour.tileSize, behaviour.tileSize); AddToMapGameObject(cell_type, go); // Debug.Log ("Cell at " + l.x+"-"+l.y + " has orientation " + orientation); go.transform.localEulerAngles = new Vector3(90, 0, 0); switch (orientation) { case VirtualMap.DirectionType.West: go.transform.localEulerAngles = new Vector3(90, 0, 0); break; case VirtualMap.DirectionType.North: go.transform.localEulerAngles = new Vector3(90, 90, 0); break; case VirtualMap.DirectionType.East: go.transform.localEulerAngles = new Vector3(90, 180, 0); break; case VirtualMap.DirectionType.South: go.transform.localEulerAngles = new Vector3(90, 270, 0); break; } // Move walls up a bit if (VirtualCell.IsFloor(cell_type)) { // Already good } else { go.transform.localPosition += Vector3.up * 0.01f; } if (cell_type == VirtualCell.CellType.DoorHorizontalBottom) { go.transform.localPosition += Vector3.forward * behaviour.tileSize * 0.25f; } }
protected void ConvertTileIntersections(VirtualMap map, VirtualCell conversion_cell) { if (conversion_cell.IsEmpty()) { // Empty passages should be filled with floors conversion_cell.Type = VirtualCell.CellType.CorridorFloor; } else { // 'None' cells will remain as such, since they will be converted to rocks later } }
// Directional walls/columns public void ConvertDirectionalColumn(VirtualMap map, VirtualCell conversion_cell, bool mayBeDirectional) { if (!mayBeDirectional) { return; } if (conversion_cell.IsCorridorColumn()) { ConvertDirectionalCorridorColumn(map, conversion_cell); } else if (conversion_cell.IsRoomColumn()) { ConvertDirectionalRoomColumn(map, conversion_cell); } }
// Various protected void ConvertWallOrientation(VirtualMap map, VirtualCell conversion_cell) { // Fix orientation of walls so that they follow the floors orientation conversion_cell.Orientation = VirtualMap.DirectionType.North; CellLocation neigh_loc = map.GetNeighbourCellLocation(conversion_cell.location, VirtualMap.DirectionType.North); if (!map.LocationIsOutsideBounds(neigh_loc)) { VirtualCell neigh_cell = map.GetCell(neigh_loc); if (neigh_cell.IsNone()) { conversion_cell.Orientation = VirtualMap.DirectionType.East; } } }
// Wall protected bool ConvertWall(VirtualMap map, VirtualCell conversion_cell) { if (behaviour.useDirectionalFloors) { if (conversion_cell.IsCorridorWall()) { conversion_cell.Type = VirtualCell.CellType.CorridorWallI; } else { conversion_cell.Type = VirtualCell.CellType.RoomWallI; } ConvertWallOrientation(map, conversion_cell); } return(ConvertPerimeterWall(map, conversion_cell)); // Returns whether it is a perimeter or not }
/***************** * Building *****************/ override public void BuildMaps(VirtualMap[] maps) { // We build what we have defined in the virtual maps for (int storey = 0; storey < maps.Length; storey++) { VirtualMap map = maps[storey]; for (int i = 0; i < map.Width; i++) { for (int j = 0; j < map.Height; j++) { CellLocation loc = new CellLocation(i, j); VirtualCell cell = map.GetCell(loc); BuildObjectsOfCell(map, cell, storey); } } } }
override public void CreateObject(VirtualMap map, MetricLocation l, VirtualCell.CellType cell_type, VirtualMap.DirectionType orientation) { Texture2D tile_texture = null; tile_texture = behaviour.GetPrefab(cell_type); GameObject go = (GameObject)GameObject.Instantiate(behaviour.tilePrefab, new Vector3(l.x * behaviour.tileSize, 0, l.y * behaviour.tileSize), Quaternion.identity); var tempMaterial = new Material(go.transform.GetComponent <Renderer>().sharedMaterial); tempMaterial.SetTexture("_MainTex", tile_texture); tempMaterial.name = cell_type.ToString() + "_Material"; go.transform.GetComponent <Renderer>().sharedMaterial = tempMaterial; if (createdMaterialsList == null) { createdMaterialsList = new List <Material>(); } createdMaterialsList.Add(tempMaterial); go.name = cell_type.ToString(); AddToMapGameObject(cell_type, go); go.transform.localEulerAngles = new Vector3(0, 0, 0); switch (orientation) { case VirtualMap.DirectionType.West: go.transform.localEulerAngles = new Vector3(0, 0, 0); break; case VirtualMap.DirectionType.North: go.transform.localEulerAngles = new Vector3(0, 90, 0); break; case VirtualMap.DirectionType.East: go.transform.localEulerAngles = new Vector3(0, 180, 0); break; case VirtualMap.DirectionType.South: go.transform.localEulerAngles = new Vector3(0, 270, 0); break; } // Move walls up a bit if (VirtualCell.IsFloor(cell_type)) { // Already good } else { go.transform.localPosition += Vector3.up * 0.01f; } }
protected bool CheckWallRendering(VirtualMap map, VirtualCell conversion_cell) { // Check wheter we need to show a wall or not for this type of map if (conversion_cell.Type == VirtualCell.CellType.EmptyPassage) { return(false); } if (behaviour.usePerimeter && conversion_cell.Type == VirtualCell.CellType.PerimeterWall) { return(true); } //Debug.Log("Check rendering of wall " + conversion_cell.location); if (map.IsPassageRemovable(conversion_cell.location)) { //Debug.Log("NO RENDER"); // Do not render this wall! conversion_cell.Type = VirtualCell.CellType.EmptyPassage; return(false); } else { // This wall must be rendered! return(true); } /* * // We check the neighbours. A rendered wall needs at least one floor nearby. * CellLocation[] floor_neighs = map.GetAllNeighbours(conversion_cell.starting_location); * int countFloorNeighs = 0; * for(int n_i=0; n_i<floor_neighs.Length; n_i++){ * CellLocation other_l = floor_neighs[n_i]; * if (!map.LocationIsOutsideBounds(other_l) && map.GetCell(other_l).IsFloor()){ * countFloorNeighs++; * } * } * if (countFloorNeighs > 0){ * // This wall must be rendered! * return true; * } else { * // Do not render this wall! * conversion_cell.Type = VirtualCell.CellType.EmptyPassage; * return false; * }*/ }
// A dead end cell has one and only one direction free for walking (i.e. there is no wall there -> empty) public bool IsDeadEnd(CellLocation l, bool alsoConsiderDoors = false) { int emptyCount = 0; CellLocation[] locs = GetAllNeighbours(l); foreach (CellLocation n_l in locs) { VirtualCell.CellType type = this.GetCell(n_l.x, n_l.y).Type; if (type == VirtualCell.CellType.EmptyPassage || (alsoConsiderDoors && VirtualCell.IsDoor(type))) { emptyCount++; //Debug.Log("For loc " + l + " neigh " + n_l + " is empty!"); } } return(emptyCount == 1); }
private void ComputeCellDistanceRecursive(VirtualCell input_cell, List <CellLocation> unvisited_locations, int current_distance) { //Debug.Log("Check cell " + input_cell.location + " dist " + current_distance); input_cell.visited = true; current_distance += 1; foreach (CellLocation nl in input_cell.connectedCells) { VirtualCell nc = this.GetCell(nl); //Debug.Log("NEIGH LOC" + nl); int last_distance = nc.distance_from_root; nc.distance_from_root = (current_distance <= last_distance) ? current_distance : last_distance; //Debug.Log("SET DIST " + nc.distance_from_root); if (!nc.visited) { ComputeCellDistanceRecursive(nc, unvisited_locations, current_distance); } } }
protected void ConvertFloor(VirtualMap map, VirtualCell conversion_cell, bool mayBeDirectional = true) { CellLocation loc = conversion_cell.location; if (generator.mapDimensionsType == MapDimensionsType.THREE_DEE) { // 3D case if (GeneratorValues.multiStorey) { // Add ladders and avoid placing floors or ceilings for multi-storey if (map.start == loc && map.storey_number > 0) { // No floor, just a ceiling ConvertCeiling(map, conversion_cell); conversion_cell.Type = VirtualCell.CellType.None; } else if (map.end == loc && map.storey_number < GeneratorValues.numberOfStoreys - 1) { // Ladder up on top of a floor, no ceiling ConvertDirectionalFloor(map, conversion_cell, mayBeDirectional); conversion_cell.AddCellInstance(VirtualCell.CellType.Ladder, conversion_cell.Orientation); } else { ConvertDirectionalFloor(map, conversion_cell, mayBeDirectional); ConvertCeiling(map, conversion_cell); } } else { ConvertDirectionalFloor(map, conversion_cell, mayBeDirectional); ConvertCeiling(map, conversion_cell); } } else { // 2D case // We just check for directionality, if needed ConvertDirectionalFloor(map, conversion_cell, mayBeDirectional); } }
void DrawConnections(VirtualCell input_cell, List <CellLocation> unvisited_locations, PhysicalMap physicalMap, VirtualMap virtualMap, int max_distance) { unvisited_locations.Remove(input_cell.location); Vector3 input_pos = physicalMap.GetRealWorldPosition(input_cell.location, virtualMap.storey_number); //Debug.Log("Has connected cells: " + start_cell.connectedCells.Count); foreach (CellLocation connected_cell_location in input_cell.connectedCells) { //Debug.Log(connected_cell_location); Vector3 end_pos = physicalMap.GetRealWorldPosition(connected_cell_location, virtualMap.storey_number); //Debug.Log(input_cell.distance_from_root * 1f / virtualMap.GetMaximumDistance()); Color col = Color.Lerp(Color.red, Color.green, input_cell.distance_from_root * 1f / max_distance); Handles.color = col; Handles.DrawLine(input_pos, end_pos); if (unvisited_locations.Contains(connected_cell_location)) { DrawConnections(virtualMap.GetCell(connected_cell_location), unvisited_locations, physicalMap, virtualMap, max_distance); } } }
protected bool ConvertPerimeterColumn(VirtualMap map, VirtualCell conversion_cell) { if (!behaviour.usePerimeter) { return(false); } if (behaviour.internalPerimeter) { // Internal perimeter: we check that we have nothing towards the outside // TODO: } else { // External perimeter: we place a perimeter around the whole map if (map.LocationIsInPerimeter(conversion_cell.location)) { conversion_cell.Type = VirtualCell.CellType.PerimeterColumn; return(true); } } return(false); }
public void ConvertDoor(VirtualMap map, VirtualCell conversion_cell) { if (conversion_cell.IsDoor()) { if (!behaviour.drawDoors) { conversion_cell.Type = VirtualCell.CellType.EmptyPassage; } else { CellLocation prev_loc = map.GetNeighbourCellLocation(conversion_cell.location, conversion_cell.Orientation); CellLocation next_loc = map.GetNeighbourCellLocation(conversion_cell.location, map.GetDirectionOpposite(conversion_cell.Orientation)); // Debug.Log (prev_loc); // Debug.Log (next_loc); // Debug.Log (map.GetCell(prev_loc).IsRoomFloor()); // Debug.Log (map.GetCell(next_loc).IsRoomFloor()); if (map.GetCell(prev_loc).IsRoomFloor() && map.GetCell(next_loc).IsRoomFloor()) { conversion_cell.Type = VirtualCell.CellType.RoomDoor; } } } }
override public void CreateObject(VirtualMap map, MetricLocation l, VirtualCell.CellType cell_type, VirtualMap.DirectionType orientation) { GameObject prefab = behaviour.GetPrefab(cell_type); DaedalusDebugUtils.Assert(prefab != null, "No variation was chosen for " + cell_type); GameObject go = (GameObject)GameObject.Instantiate(prefab, new Vector3(l.x * behaviour.tileSize, 0, l.y * behaviour.tileSize), Quaternion.identity); go.name = cell_type.ToString(); if (orientation == VirtualMap.DirectionType.None) { orientation = VirtualMap.DirectionType.North; } switch (orientation) { case VirtualMap.DirectionType.West: go.transform.localEulerAngles = new Vector3(90, 0, 0); break; case VirtualMap.DirectionType.North: go.transform.localEulerAngles = new Vector3(90, 90, 0); break; case VirtualMap.DirectionType.East: go.transform.localEulerAngles = new Vector3(90, 180, 0); break; case VirtualMap.DirectionType.South: go.transform.localEulerAngles = new Vector3(90, 270, 0); break; } AddToMapGameObject(cell_type, go, cell_type == VirtualCell.CellType.Door, l.storey); // Move walls up a bit if (VirtualCell.IsFloor(cell_type)) { // Already good } else { go.transform.localPosition += Vector3.up * 0.01f; } }
void OnSceneGUI() { if (showDebugCoordinates || showDebugConnections) { PhysicalMap physicalMap = this.targetInstance.GetPhysicalMap(); VirtualMap[] virtualMaps = this.targetInstance.GetVirtualMaps(); if (this.targetInstance.HasGeneratedDungeon()) { if (physicalMap != null && virtualMaps.Length > 0) { GUIStyle guiStyle = new GUIStyle(); if (showDebugCoordinates) { for (int i = 0; i < virtualMaps.Length; i++) { foreach (VirtualCell c in virtualMaps[i].GetAllCells()) { Vector3 p = physicalMap.GetRealWorldPosition(c.location, i); if (c.location.x % 2 == 1 && c.location.y % 2 == 1) { guiStyle.normal.textColor = Color.yellow; int actual_x = (c.location.x - 1) / 2; int actual_y = (c.location.y - 1) / 2; Handles.Label(p, c.location.x + "," + c.location.y + "\n(" + actual_x + "," + actual_y + ")", guiStyle); } else { guiStyle.normal.textColor = Color.white; Handles.Label(p, c.location.x + "," + c.location.y, guiStyle); } } } } if (showDebugConnections) { for (int i = 0; i < virtualMaps.Length; i++) { VirtualMap virtualMap = virtualMaps[i]; List <CellLocation> unvisited_locations = new List <CellLocation>(virtualMap.WalkableLocations); //Debug.Log("Starting from " + start_location); int max_distance = virtualMap.GetMaximumDistance(); int stop_iter = 0; while (unvisited_locations.Count > 0) { CellLocation start_location = unvisited_locations[0]; // We start from a walkable cell (doesn't matter which one) VirtualCell start_cell = virtualMap.GetCell(start_location); DrawConnections(start_cell, unvisited_locations, physicalMap, virtualMap, max_distance); stop_iter++; if (stop_iter == 100) { DaedalusDebugUtils.Assert(false, "Looping in show debug connectsion!"); break; // ERROR HERE! } } } } // TEST path check //VirtualMap test_virtualMap = virtualMaps[0]; //List<CellLocation> test_unvisited_locations = new List<CellLocation>(test_virtualMap.WalkableLocations); //test_virtualMap.ExistsPathBetweenLocations(test_unvisited_locations[0], test_unvisited_locations[test_unvisited_locations.Count - 1]); } } } }
public bool GetIsDynamicCell(VirtualCell.CellType cell_type) { return(VirtualCell.IsDynamic(cell_type)); }