예제 #1
0
 public RandomDungeonTileData(RandomDungeonTileData copy)
 {
     tileType = copy.tileType;
     scope    = copy.scope;
     room     = copy.room;
     trap     = copy.trap;
     chest    = copy.chest;
     distanceFromPrimaryPath = copy.distanceFromPrimaryPath;
 }
예제 #2
0
        public RandomDungeon(int dungeonWidth, int dungeonHeight)
        {
            width  = dungeonWidth;
            height = dungeonHeight;
            mTiles = new RandomDungeonTileData[width, height];

            for (int x = 0; x < width; ++x)
            {
                for (int y = 0; y < height; ++y)
                {
                    mTiles[x, y]          = new RandomDungeonTileData();
                    mTiles[x, y].tileType = RandomDungeonTileData.EMPTY_TILE;
                    mTiles[x, y].scope    = 0;
                }
            }
        }
예제 #3
0
        private int NeighborTrap(int x, int y)
        {
            for (int adjustedX = -1; adjustedX <= 1; ++adjustedX)
            {
                for (int adjustedY = -1; adjustedY <= 1; ++adjustedY)
                {
                    int        mapX = x + adjustedX;
                    int        mapY = y + adjustedY;
                    Vector2Int v    = new Vector2Int(mapX, mapY);

                    RandomDungeonTileData td = null;
                    if (mRoomScratch.TryGetValue(v, out td))
                    {
                        if (td.trap != -1)
                        {
                            return(td.trap);
                        }
                    }
                }
            }

            return(-1);
        }
예제 #4
0
        public void EvaluateDungeon(RandomDungeon dungeon)
        {
            int[] orthogonalOffsets = new int[] { 0, 1, 1, 0, 0, -1, -1, 0 };

            for (int x = 0; x < dungeon.width; ++x)
            {
                for (int y = 0; y < dungeon.height; ++y)
                {
                    // Only evaluate walkable tiles
                    if (dungeon.TileType(x, y) != RandomDungeonTileData.WALKABLE_TILE && dungeon.TileType(x, y) != RandomDungeonTileData.EXIT_TILE)
                    {
                        continue;
                    }

                    RandomDungeonTileData data = dungeon.Data(x, y);

                    // If the room isn't already part of the set, add it
                    RandomDungeonNetworkNode node = null;
                    if (!mNodeMap.TryGetValue(data.room, out node))
                    {
                        node        = new RandomDungeonNetworkNode();
                        node.roomId = data.room;
                        node.distanceFromPrimaryPath = data.distanceFromPrimaryPath;

                        mNodeMap.Add(data.room, node);
                    }

                    // Distance from primary path should be the closest tile that we can get into for this room.
                    node.distanceFromPrimaryPath = Mathf.Min(data.distanceFromPrimaryPath, node.distanceFromPrimaryPath);

                    // Evaluate connections (orthogonally, only considering walkable / exit tiles)
                    for (int i = 0; i < orthogonalOffsets.Length; i += 2)
                    {
                        int neighborX = x + orthogonalOffsets[i];
                        int neighborY = y + orthogonalOffsets[i + 1];

                        if (dungeon.IsPositionInBounds(neighborX, neighborY))
                        {
                            RandomDungeonTileData neighborData = dungeon.Data(neighborX, neighborY);
                            bool isWalkable = (neighborData.tileType == RandomDungeonTileData.WALKABLE_TILE || neighborData.tileType == RandomDungeonTileData.EXIT_TILE);

                            if (isWalkable && neighborData.room != node.roomId && !node.ConnectionExists(neighborData.room))
                            {
                                node.AddConnection(neighborData.room);
                            }
                        }
                    }

                    // Keep track of all walkable tiles in this room so we know where we can spawn stuff.
                    // todo bdsowers - change the name of this
                    // By design it only keeps track of tiles that aren't next to a wall, but that
                    // isn't conveyed in the name.
                    // todo bdsowers - move a 'num surrounding walls' into map generation, as that can
                    // be useful for more than just this.
                    bool hasUnwalkableNeighbor = false;
                    for (int offsetX = -1; offsetX <= 1; ++offsetX)
                    {
                        for (int offsetY = -1; offsetY <= 1; ++offsetY)
                        {
                            int testX = x + offsetX;
                            int testY = y + offsetY;
                            if (!dungeon.IsPositionInBounds(testX, testY))
                            {
                                hasUnwalkableNeighbor = true;
                                continue;
                            }

                            char tileType = dungeon.TileType(testX, testY);
                            if (tileType != RandomDungeonTileData.WALKABLE_TILE &&
                                tileType != RandomDungeonTileData.EXIT_TILE)
                            {
                                hasUnwalkableNeighbor = true;
                                continue;
                            }
                        }
                    }

                    if (!hasUnwalkableNeighbor)
                    {
                        node.RegisterEmptyPosition(x, y);
                    }
                }
            }
        }
예제 #5
0
 public void SetData(int x, int y, RandomDungeonTileData data)
 {
     mTiles[x, y] = data;
 }
예제 #6
0
        /// <summary>
        /// Actually performs room placement in the scratchpad.
        /// </summary>
        /// <param name="roomData"></param>
        /// <param name="mapExit"></param>
        /// <param name="roomExit"></param>
        /// <param name="scope"></param>
        /// <param name="primaryPath"></param>
        private void PlaceRoom(RoomData roomData, Vector2Int mapExit, Vector2Int roomExit, int scope, bool primaryPath)
        {
            int maxDistance = 0;

            roomData.placeCount++;

            for (int x = 0; x < roomData.width; ++x)
            {
                for (int y = 0; y < roomData.height; ++y)
                {
                    int        mapX     = mapExit.x - roomExit.x + x;
                    int        mapY     = mapExit.y - roomExit.y + y;
                    Vector2Int mapPos   = new Vector2Int(mapX, mapY);
                    char       roomTile = roomData.Tile(x, y);

                    // Empty tiles shouldn't be represented in the dictionary
                    if (roomTile == RandomDungeonTileData.EMPTY_TILE)
                    {
                        continue;
                    }

                    // Create a new tile or edit a tile that already exists.
                    // This ensures we don't generate unnecessary garbage.
                    RandomDungeonTileData td = null;
                    if (!mRoomScratch.ContainsKey(mapPos))
                    {
                        td = new RandomDungeonTileData();
                        mRoomScratch.Add(mapPos, td);

                        float distance    = Vector2Int.Distance(roomExit, new Vector2Int(x, y));
                        int   distanceInt = Mathf.CeilToInt(distance);
                        maxDistance = Mathf.Max(maxDistance, distanceInt);

                        td.tileId = mCurrentTileId + distanceInt;

                        td.position = mapPos;
                    }
                    else
                    {
                        td = mRoomScratch[mapPos];
                        td.Clear();
                    }

                    td.tileType = roomTile;
                    td.scope    = scope;
                    td.room     = mCurrentRoomId;

                    if (primaryPath)
                    {
                        td.distanceFromPrimaryPath = 0;
                    }
                    else
                    {
                        // todo bdsowers - this is not perfect
                        // maybe it doesn't need to be perfect, we'll see
                        int mapExitDistance = mRoomScratch[mapExit].distanceFromPrimaryPath;
                        td.distanceFromPrimaryPath = mapExitDistance + 1;
                        maxDistanceFromPrimaryPath = Mathf.Max(maxDistanceFromPrimaryPath, td.distanceFromPrimaryPath);
                    }

                    // Trap
                    // Register it in the map proper as a walkable tile
                    // give a block of trap tiles the same identifier - they form one large trap
                    if (roomTile == RandomDungeonTileData.TRAP_TILE)
                    {
                        int neighborTrap = NeighborTrap(mapX, mapY);
                        int trapId       = neighborTrap;
                        if (trapId == -1)
                        {
                            trapId = mCurrentTrapId;
                            mCurrentTrapId++;
                        }

                        td.tileType = RandomDungeonTileData.WALKABLE_TILE;
                        td.trap     = trapId;
                    }
                    else if (roomTile == RandomDungeonTileData.POSSIBLE_CHEST_TILE)
                    {
                        td.tileType = RandomDungeonTileData.WALKABLE_TILE;
                        td.chest    = 1;
                    }
                    else if (roomTile == RandomDungeonTileData.GUARANTEED_CHEST_TILE)
                    {
                        td.tileType = RandomDungeonTileData.WALKABLE_TILE;
                        td.chest    = 2;
                    }

                    // Add the new exit to the list of available exits
                    if (roomTile == RandomDungeonTileData.EXIT_TILE)
                    {
                        mAvailableExits.Add(mapPos);
                    }
                }
            }

            ++mCurrentRoomId;
            mCurrentTileId += maxDistance + 1;
        }