Exemplo n.º 1
0
    public override void GetLevel(ref Level level)
    {
        Random.InitState((int)System.DateTime.Now.Ticks);

        List <Room> rooms = new List <Room>();

        rooms.Add(Room.RandSized(smallestRoomSize, largestRoomSize));
        while (rooms.Count < numRooms)
        {
            Room fromRoom = rooms[Random.Range(0, rooms.Count)];
            Room newRoom  = Room.RandSized(smallestRoomSize, largestRoomSize);
            newRoom.lowerCorner  = fromRoom.lowerCorner;
            newRoom.lowerCorner += new IntVector2(Random.Range(-largestRoomSize / 2, (largestRoomSize + 1) / 2), Random.Range(-largestRoomSize / 2, (largestRoomSize + 1) / 2));
            rooms.Add(newRoom);
        }

        bool changed = true;
        int  iters   = 0;

        while (changed)
        {
            changed = false;
            for (int i = 0; i < rooms.Count; i++)
            {
                for (int j = 0; j < rooms.Count; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    if (rooms[i].Overlaps(rooms[j]))
                    {
                        Room       modified = rooms[i];
                        IntVector2 dir      = new IntVector2(
                            (int)Mathf.Sign(rooms[i].lowerCorner.x - rooms[j].lowerCorner.x),
                            (int)Mathf.Sign(rooms[i].lowerCorner.y - rooms[j].lowerCorner.y));
                        int moveStyle = Mathf.FloorToInt(Random.value * 3);
                        if (moveStyle == 0)
                        {
                            dir.x = 0;
                        }
                        if (moveStyle == 1)
                        {
                            dir.y = 0;
                        }
                        modified.lowerCorner += dir;
                        rooms[i]              = modified;
                        changed = true;
                    }
                }
            }
            iters++;
            if (iters > 100)
            {
                break;
            }
        }

        // Put rooms into map
        Dictionary <IntVector2, Tile> tiles = new Dictionary <IntVector2, Tile>();

        foreach (Room room in rooms)
        {
            for (int y = -1; y <= room.size.y + 1; y++)
            {
                for (int x = -1; x <= room.size.x + 1; x++)
                {
                    IntVector2 tilePos = new IntVector2(room.lowerCorner.x + x, room.lowerCorner.y + y);
                    Tile       tile    = new Tile();
                    tile.floor = floor;
                    if (x <= -1 || x >= room.size.x + 1 || y <= -1 || y >= room.size.y + 1)
                    {
                        tile.occupant = wallBase;
                    }
                    tiles[tilePos] = tile;
                }
            }
        }

        // Remove connection
        List <IntVector2> tileKeys = new List <IntVector2>(tiles.Keys);

        foreach (IntVector2 pos in tileKeys)
        {
            Tile tile = tiles[pos];
            if (tile.floor != null && tile.occupant != null)
            {
                if (((OnlyFloorAt(ref tiles, pos + IntVector2.left) && OnlyFloorAt(ref tiles, pos + IntVector2.right)) ||
                     (OnlyFloorAt(ref tiles, pos + IntVector2.up) && OnlyFloorAt(ref tiles, pos + IntVector2.down))))
                {
                    tile.occupant = null;
                    tiles[pos]    = tile;
                }
            }
        }

        // Add an extra two layer of walls
        for (int i = 0; i < 2; i++)
        {
            Dictionary <IntVector2, Tile> tilesCopy = new Dictionary <IntVector2, Tile>();
            IntVector2[] dirs = { IntVector2.up, IntVector2.right, IntVector2.down, IntVector2.left };
            foreach (KeyValuePair <IntVector2, Tile> pair in tiles)
            {
                tilesCopy[pair.Key] = pair.Value;
                foreach (IntVector2 dir in dirs)
                {
                    if (!tiles.ContainsKey(pair.Key + dir))
                    {
                        Tile t = new Tile();
                        t.floor    = floor;
                        t.occupant = wallBase;
                        tilesCopy[pair.Key + dir] = t;
                    }
                }
            }
            tiles = tilesCopy;
        }

        // Get the size of the map
        IntVector2 bottomLeft = new IntVector2(int.MaxValue, int.MaxValue);
        IntVector2 topRight   = new IntVector2(int.MinValue, int.MinValue);

        foreach (KeyValuePair <IntVector2, Tile> pair in tiles)
        {
            IntVector2 pos = pair.Key;
            bottomLeft.x = Mathf.Min(bottomLeft.x, pos.x);
            bottomLeft.y = Mathf.Min(bottomLeft.y, pos.y);
            topRight.x   = Mathf.Max(topRight.x, pos.x);
            topRight.y   = Mathf.Max(topRight.y, pos.y);
        }
        IntVector2 size = topRight - bottomLeft + IntVector2.one;

        // Add enemies
        tileKeys = new List <IntVector2>(tiles.Keys);
        foreach (IntVector2 pos in tileKeys)
        {
            Tile tile = tiles[pos];
            if (tile.occupant == null && Random.value < enemySpawnRate)
            {
                float spawnIndex = (pos.y - bottomLeft.y) / (float)size.y;
                spawnIndex   += Random.Range(-.20f, .20f);
                spawnIndex    = Mathf.Clamp(spawnIndex, 0, .999f);
                tile.occupant = enemies[Mathf.FloorToInt(spawnIndex * enemies.Count)];
                tiles[pos]    = tile;
            }
        }

        // Add weapons
        tileKeys = new List <IntVector2>(tiles.Keys);
        foreach (IntVector2 pos in tileKeys)
        {
            Tile tile = tiles[pos];
            if (tile.occupant == null && Random.value < weaponSpawnRate)
            {
                float spawnIndex = (pos.y - bottomLeft.y) / (float)size.y;
                spawnIndex += Random.Range(-.20f, .20f);
                spawnIndex  = Mathf.Clamp(spawnIndex, 0, .999f);
                tile.AddCollectable(weapons[Mathf.FloorToInt(spawnIndex * weapons.Count)]);
                tiles[pos] = tile;
            }
        }

        // Convert the map to an array
        level.Resize(size);
        for (int y = 0; y < size.y; y++)
        {
            for (int x = 0; x < size.x; x++)
            {
                IntVector2 realCoord = new IntVector2(x, y) + bottomLeft;
                if (tiles.ContainsKey(realCoord))
                {
                    level.tiles[x, y] = tiles[realCoord];
                }
            }
        }

        level.spawnPositions = new List <IntVector2>();
        int remainingSpawnPositions = 40;

        for (int y = 0; y < size.y; y++)
        {
            for (int x = 0; x < size.x; x++)
            {
                IntVector2 pos = new IntVector2(x, y);
                if (level.tiles[x, y].floor != null && level.tiles[x, y].occupant == null)
                {
                    level.spawnPositions.Add(pos);
                    remainingSpawnPositions -= 1;
                }
                if (remainingSpawnPositions <= 0)
                {
                    break;
                }
            }
            if (remainingSpawnPositions <= 0)
            {
                break;
            }
        }
    }