public override void Deserialize(IntVector3 position, SerializedObject serializedObject) { this.Type = (WallType) serializedObject.Properties[0]; this.rotation = (Rotation) serializedObject.Properties[1]; SpawnWall(this.Type, position, this.rotation); }
private void DrawChunkBounds(IntVector3 relPos) { var cubeSize = new Vector3(Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE); var chunkCenter = new Vector3((topLeftCorner.x + relPos.x) * Chunk.CHUNK_SIZE - Chunk.HALF_CHUNK_SIZE, (topLeftCorner.y + relPos.y) * Chunk.CHUNK_SIZE - Chunk.HALF_CHUNK_SIZE, (topLeftCorner.z + relPos.z) * Chunk.CHUNK_SIZE - Chunk.HALF_CHUNK_SIZE); Gizmos.DrawWireCube(chunkCenter, cubeSize); }
public Chunk(IntVector3 position) { var indexedSize = (int) Mathf.Pow(CHUNK_SIZE, 3); var chunkPos = ClampAbsPosition(position); this.cells = new CellDefinition[indexedSize]; this.dirtyCells = new List<CellDefinition>(128); this.Bounds = new CubeBounds(chunkPos, CHUNK_SIZE); }
public static IntVector3 ClampAbsPosition(IntVector3 absPos) { var clampedPos = new IntVector3(); clampedPos.x = (int)Mathf.Floor(absPos.x / Chunk.CHUNK_SIZE) * CHUNK_SIZE; clampedPos.y = (int)Mathf.Floor(absPos.y / Chunk.CHUNK_SIZE) * CHUNK_SIZE; clampedPos.z = (int)Mathf.Floor(absPos.z / Chunk.CHUNK_SIZE) * CHUNK_SIZE; return clampedPos; }
public static void IntXYZ(IntVector3 from, IntVector3 to, int step, Action<int, int, int> callback) { for (int x = from.x; x <= to.x; x += step) { for (int y = from.y; y <= to.y; y += step) { for (int z = from.z; z <= to.z; z += step) { callback(x, y, z); } } } }
public CellDefinition CreateCellAt(IntVector3 position) { var targetChunk = activeRegion.GetChunkAt(position); if (targetChunk == null) { Logger.Warn("CreateCellAt", "Could not create cell at {0}, position out of bounds.", position); return null; } return targetChunk.CreateCell(position); }
private void SpawnDoor(IntVector3 position, Rotation rotation) { if (this.goReference == null) { PreloadPrefabs(); this.goReference = doorPrefab.Spawn(); this.goReference.transform.position = position.ToVector3(); SetRotation(rotation); } }
public IntVector3 ConvertRelToAbsPosition(IntVector3 relPos) { var absolutePos = new IntVector3(); absolutePos = this.Bounds.Position.ToIntVector3(); absolutePos.x += relPos.x; absolutePos.y += relPos.y; absolutePos.z += relPos.z; return absolutePos; }
public CellDefinition CreateCell(IntVector3 position) { var index = ConvertAbsPositionToIndex(position); if (cells[index] != null) { Logger.Warn("CreateCell", "Cell at {0} already exists.", position); return cells[index]; } cells[index] = new CellDefinition(position, this); return cells[index]; }
private void SpawnFloor(IntVector3 position) { /* Spawn floor object and initialize if it does not exist yet */ if (this.goReference == null) { PreloadPrefabs(); this.goReference = floorPrefab.Spawn(); this.goReference.transform.position = position.ToVector3(); this.goReference.transform.eulerAngles = floorPrefab.transform.eulerAngles; } /* TODO: Add texture update logic */ }
public void ReloadChunks(IntVector3 centerChunk) { var regionManager = RegionManager.Instance; topLeftCorner = centerChunk - 1; LoopHelper.IntXYZ(topLeftCorner, centerChunk + 1, 1, (x, y, z) => { var position = new IntVector3(x, y, z); var relativePosition = position - topLeftCorner; var index = GetChunkIndexFromPosition(relativePosition); Logger.Info("ReloadChunks", "Loading chunk at {0}.", position); this.activeChunks[index] = regionManager.GetChunkAt(position); this.activeChunks[index].SetActive(); }); }
public Chunk GetChunkAt(IntVector3 position) { if (!this.Bounds.Contains(position)) { Logger.Warn("GetChunkAt", "Cannot get chunk at {0}, does not belong inside this region.", position); return null; } var indexedPos = ConvertPositionToIndex(position); /* Initialize chunk if it does not exist yet */ if (this.chunks[indexedPos] == null) { this.chunks[indexedPos] = new Chunk(Chunk.ClampAbsPosition(position)); } return this.chunks[indexedPos]; }
private void OnDrawGizmos() { if (!DebugMode) { return; } Gizmos.color = Color.yellow; LoopHelper.IntXYZ(IntVector3.zero, new IntVector3(2), 1, (x, y, z) => { var relativePosition = new IntVector3(x, y, z); this.DrawChunkBounds(relativePosition); }); /* Render center chunk in green */ Gizmos.color = Color.green; this.DrawChunkBounds(IntVector3.one); }
public override void Update(IntVector3 position) { var neighborCells = new bool[4]; var cellCounter = 0; foreach (IntVector2 offset in CellRange.Values2DCardinal()) { var absPos2D = offset + position.ToIntVector2(); var absPos = new IntVector3(absPos2D.x, position.y, absPos2D.z); var cell = RegionManager.Instance.GetCellAt(absPos); neighborCells[cellCounter] = cell.wall != null; cellCounter++; } var rotation = (neighborCells[0] && neighborCells[2] ? Rotation.EAST : Rotation.NORTH); SpawnDoor(position, rotation); }
public void ApplyToGrid() { var upperBounds = new IntVector2(cells.GetLength(0) - 1, cells.GetLength(1) - 1); var topLeftCorner = new IntVector3(64, 64, 64); LoopHelper.IntXZ(IntVector2.zero, upperBounds, 1, (x, z) => { var absPosition = topLeftCorner + new IntVector3(x, 0, upperBounds.z - z); var cell = RegionManager.Instance.GetCellAt(absPosition); /* If cell was empty and we don't want anything there, return */ if (this.cells[x, z] == CellType.EMPTY && cell == null) { return; } /* Otherwise, create a new cell if we need to add something here */ if (cell == null) { cell = RegionManager.Instance.CreateCellAt(absPosition); } switch (this.cells[x, z]) { case CellType.WALL: cell.CreateWall(); break; case CellType.FLOOR: cell.CreateFloor(); break; case CellType.DOOR: cell.CreateObject(new DoorObject()); break; /* This is a special case! If something was here previously, * we need to destroy the whole cell. */ case CellType.EMPTY: cell.Destroy(); break; } }); }
private CellDefinition GetClosestWalkableCell(IntVector3 position) { var regionManager = RegionManager.Instance; var centerCell = regionManager.GetCellAt(position); /* If our target is a floor tile, return it */ if (centerCell.floor != null) { return centerCell; } /* If not, search in a 9x9 grid around the target to find a walkable cell */ foreach (var offset in CellRange.Values2D(false)) { var absPosGrid = offset + position.ToIntVector2(); var cell = regionManager.GetCellAt(absPosGrid.ToIntVector3(position.y)); if (cell != null && cell.floor != null) { return cell; } } return null; }
private int Distance(IntVector3 start, IntVector3 end) { return Mathf.Abs(end.x - start.x) + Mathf.Abs(end.y - start.y) + Mathf.Abs(end.z - start.z); }
public CubeBounds(IntVector3 position, float width, float height, float length) : this(position.x, position.y, position.z, width, height, length) { }
public CubeBounds(IntVector3 position, float size) : this(position, size, size, size) { }
public override void Deserialize(IntVector3 position, SerializedObject serializedObject) { SpawnFloor(position); }
public override void Update(IntVector3 position) { SpawnFloor(position); }
/** * Prepares all UI to show the room editing dialog. * This should be the central entry point for all other scripts referencing the room builder. * * @param center - Center point of the editable region */ public void ShowBuildDialog(IntVector3 center) { this.cells = new CellType[AreaSize, AreaSize]; this.temporaryCells = null; }
public bool Contains(IntVector3 position) { return Contains(position.x, position.y, position.z); }
private void SpawnWall(WallType type, IntVector3 position, Rotation rotation) { var prefabs = registry.WallObjectHelper.Prefabs; if (!prefabs.ContainsKey(type)) { Logger.Warn("Could not load prefab for type {0}.", type); return; } var prefab = prefabs[type].Spawn(); prefab.transform.position = position.ToVector3(); this.goReference = prefab; this.Type = type; SetRotation(rotation); Logger.Info("Spawned wall {0} at {1} {2}.", type, position, this.goReference.transform.eulerAngles); }
private int GetChunkIndexFromPosition(IntVector3 relativePosition) { return relativePosition.x + (relativePosition.y * 3) + (relativePosition.z * 9); }
public override void Update(IntVector3 position) { var neighborCells = new short[9]; var validMasks = new Dictionary<WallType, CellMask>(5); /* Properties used to refine valid tile masks */ var containsEmptySpaces = false; var containsOtherWalls = false; var wallCount = 0; var cellCounter = -1; /* Grab surrounding block information */ foreach (IntVector2 offset in CellRange.Values2D()) { var absPos2D = offset + position.ToIntVector2(); var absPos = new IntVector3(absPos2D.x, position.y, absPos2D.z); CellDefinition cell; cellCounter++; cell = RegionManager.Instance.GetCellAt(absPos); containsEmptySpaces = containsEmptySpaces || CellDefinition.IsEmpty(cell); if (cell == null) { neighborCells[cellCounter] = GameRegistry.EmptyObjectId; continue; } if (cell.wall != null) { if (!absPos.Equals(position)) { containsOtherWalls = containsOtherWalls || cell.wall != null; } wallCount++; neighborCells[cellCounter] = registry.GetObjectId<WallObject>(); } else if (cell.floor != null) { neighborCells[cellCounter] = registry.GetObjectId<FloorObject>(); } else if (cell.containedObject.Is<DoorObject>()) { neighborCells[cellCounter] = registry.GetObjectId<DoorObject>(); } else { neighborCells[cellCounter] = GameRegistry.EmptyObjectId; } } if (containsOtherWalls) { /* Default walls */ AddValidMask(WallType.INNER_DEFAULT, validMasks); AddValidMask(WallType.INNER_END, validMasks); if (wallCount >= 3) { AddValidMask(WallType.INNER_EDGE_INNER, validMasks); AddValidMask(WallType.INNER_EDGE_T, validMasks); } if (wallCount >= 4) { AddValidMask(WallType.INNER_EDGE_CROSS, validMasks); } if (containsEmptySpaces) { AddValidMask(WallType.OUTER_DEFAULT, validMasks); if (wallCount >= 3) { AddValidMask(WallType.OUTER_EDGE_OUTER, validMasks); AddValidMask(WallType.OUTER_EDGE_INNER, validMasks); AddValidMask(WallType.OUTER_EDGE_T_INNER, validMasks); AddValidMask(WallType.OUTER_EDGE_T_OUTER, validMasks); } } } var calculatedType = WallType.OUTER_DEFAULT; var calculatedRotation = Rotation.NORTH; var foundMatch = false; foreach (var wallType in validMasks.Keys) { if (validMasks[wallType].Match(neighborCells, out calculatedRotation)) { calculatedType = wallType; foundMatch = true; break; } } if (!foundMatch) { Logger.Warn("Could not find matching type for wall at {0}", position); } /* Spawn the new wall object and set transform */ if (this.Type != calculatedType) { SpawnWall(calculatedType, position, calculatedRotation); } else if (this.rotation != calculatedRotation) { SetRotation(calculatedRotation); } }
public static CellDefinition Deserialize(IntVector3 position, Chunk parentChunk, SerializedCellDefinition serializedCell) { var cell = new CellDefinition(position, parentChunk); if (serializedCell.wall != null) { cell.wall = new WallObject(); cell.wall.Deserialize(position, serializedCell.wall); } if (serializedCell.floor != null) { cell.floor = new FloorObject(); cell.floor.Deserialize(position, serializedCell.floor); } if (serializedCell.containedObject != null) { var type = GameRegistry.Instance.GetObjectType(serializedCell.containedObject.Id); cell.containedObject = (BaseObject) Activator.CreateInstance(type); cell.containedObject.Deserialize(position, serializedCell.containedObject); } parentChunk.SetCellAt(position, cell); return cell; }
public IEnumerator FindPath(IntVector3 start, IntVector3 end, Action<bool> callback) { currentNode = null; this.endNode = null; this.start = start; this.end = end; this.openNodes.Clear(); this.closedNodes.Clear(); this.finalNodes.Clear(); /* Create start node and add to open list */ var startNode = new PathNode() { Position = start, G = 0, F = Manhattan(start, end) }; this.openNodes.Add(startNode); while (this.openNodes.Count > 0) { /* Sort open nodes by lowest f(G, H) = G + H */ this.openNodes = this.openNodes.OrderBy( node => node.F ).ToList(); currentNode = this.openNodes.PopAt(0); this.closedNodes.Add(currentNode); if (currentNode.Position.Equals(end)) { this.endNode = currentNode; break; } while (!ContinueSteps && PerformSteps) { yield return null; } ContinueSteps = false; /* Visit all neighbors of our current node */ foreach(var offset in CellRange.Values2D(false)) { var absPos = currentNode.Position + offset.ToIntVector3(0); /* Continue if we already visited that neighbor */ var isClosedNode = this.closedNodes.Find( node => node.Position.Equals(absPos) ) != null; var isWalkable = CellDefinition.IsWalkable(regionManager.GetCellAt(absPos)); if (isClosedNode || !isWalkable) { continue; } var tentativeG = currentNode.G + Distance(currentNode.Position, absPos); var openNeighbor = this.openNodes.Find( node => node.Position.Equals(absPos) ); if (openNeighbor == null || tentativeG < openNeighbor.G) { if (openNeighbor == null) { openNeighbor = new PathNode(); this.openNodes.Add(openNeighbor); } openNeighbor.ParentNode = currentNode; openNeighbor.Position = absPos; openNeighbor.G = tentativeG; openNeighbor.F = openNeighbor.G + Manhattan(absPos, end); } } } callback(this.endNode != null); }
public CellDefinition(IntVector3 position, Chunk parentChunk) { this.Position = position; this.ParentChunk = parentChunk; }
private int Manhattan(IntVector3 start, IntVector3 end) { return Mathf.Abs(start.x - end.x) + Mathf.Abs(start.y - end.y) + Mathf.Abs(start.z - end.z); }