Exemple #1
0
 private void OnTriggerEnter2D(Collider2D collision)
 {
     if (_player != null && collision.tag == "Sheep")
     {
         Sheep sheep = collision.GetComponent <Sheep>();
         sheep.Hit(_player);
     }
 }
Exemple #2
0
        public void SetStartScreenActive(bool active)
        {
            _startScreen.gameObject.SetActive(active);

            if (active)
            {
                if (_startScreenSheep == null)
                {
                    _startScreenSheep = Instantiate(_sheepPrefab, new Vector3(0, -2.5f, 0), Quaternion.identity);
                    _startScreenSheep.transform.localScale = new Vector3(2f, 2f, 2f);
                }
            }
            else
            {
                if (_startScreenSheep != null)
                {
                    Destroy(_startScreenSheep);
                    _startScreenSheep = null;
                }
            }
        }
Exemple #3
0
        public void RegisterDeadSheep(Sheep deadSheep, Player fromPlayer)
        {
            Debug.Assert(!deadSheep.IsAlive);

            KilledSheep += 1;

            SoundPlayer.Instance.Play(Sound.SheepHit, deadSheep.AudioSource);

            if (Master.Instance.CurrentDifficulty == Difficulty.Easy)
            {
                WakeUpSheep(fromPlayer);
            }

            int sheepAlive = 0;

            foreach (Sheep sheep in _sheep)
            {
                if (sheep.IsAlive)
                {
                    sheepAlive += 1;
                }
            }

            if (sheepAlive > 0)
            {
                Coin    coin    = Instantiate(_coinPrefab, deadSheep.transform.position, Quaternion.identity);
                Vector2 coinVec = (coin.transform.position - fromPlayer.transform.position).normalized;

                coin.Rigidbody.AddForce(coinVec * Random.Range(3f, 10f), ForceMode2D.Impulse);
            }

            if (sheepAlive == 0)
            {
                _levelTime.Stop();
                _levelDone = true;
                MainWindow.Instance.RunTimelineLevelWon();
            }
        }
Exemple #4
0
        public void Generate(int seed, int level, int playerCount, Difficulty difficulty)
        {
            Debug.Log($"Generating: Seed [{seed}], Level [{level}], Difficulty [{difficulty}]");


            Random.InitState(seed);


            // Reset GameObjects
            foreach (Player player in _players)
            {
                DestroyImmediate(player.gameObject);
            }
            _players.Clear();

            foreach (Sheep sheep in _sheep)
            {
                DestroyImmediate(sheep.gameObject);
            }
            _sheep.Clear();

            foreach (Haystack haystack in _haystacks)
            {
                DestroyImmediate(haystack.gameObject);
            }
            _haystacks.Clear();


            // Reset Status
            KilledSheep = 0;
            Coins       = 0;


            // Reset Tilemaps
            _baseTilemap.ClearAllTiles();
            _wallTilemap.ClearAllTiles();


            // Initialize Level Params
            int width  = 10;
            int height = 10;

            if (difficulty == Difficulty.Easy)
            {
                width  += level;
                height += level;
            }
            else if (difficulty == Difficulty.Normal)
            {
                width  += 2 * level;
                height += 2 * level;
            }
            else
            {
                width  += 3 * level;
                height += 3 * level;
            }


            Map map = new Map(width, height);


            // Create Initial Patch of Grass
            {
                int initialWidth  = Random.Range(10, 10 + level + 1);
                int initialHeight = Random.Range(10, 10 + level + 1);
                int initialX      = (width - initialWidth) / 2;
                int initialY      = (height - initialHeight) / 2;

                PlaceTileSquare(map, initialX, initialY, initialWidth, initialHeight, TileType.Open);
            }


            // Create Additional Patches of Grass on the outer side of existing Grass Patches
            {
                int patchCount    = level + 1;
                int placedPatches = 0;
                int iteration     = 0;

                while (placedPatches < patchCount && iteration < 1000)
                {
                    iteration += 1;

                    int approachDirection = Random.Range(0, 4);

                    bool apply = false;
                    int  x     = 0;
                    int  y     = 0;

                    if (approachDirection == 0)
                    {
                        // From South
                        x = Random.Range(0, map.Width);

                        for (y = 0; y < map.Height; ++y)
                        {
                            if (map.IsTileSurroundedBy(x, y, TileType.Open))
                            {
                                apply = true;
                                break;
                            }
                        }
                    }
                    else if (approachDirection == 1)
                    {
                        // From East
                        y = Random.Range(0, map.Height);

                        for (x = map.Width - 1; x >= 0; --x)
                        {
                            if (map.IsTileSurroundedBy(x, y, TileType.Open))
                            {
                                apply = true;
                                break;
                            }
                        }
                    }
                    else if (approachDirection == 2)
                    {
                        // From North
                        x = Random.Range(0, map.Width);

                        for (y = map.Height - 1; y >= 0; --y)
                        {
                            if (map.IsTileSurroundedBy(x, y, TileType.Open))
                            {
                                apply = true;
                                break;
                            }
                        }
                    }
                    else if (approachDirection == 3)
                    {
                        // From West
                        y = Random.Range(0, map.Height);

                        for (x = 0; x < map.Width; ++x)
                        {
                            if (map.IsTileSurroundedBy(x, y, TileType.Open))
                            {
                                apply = true;
                                break;
                            }
                        }
                    }


                    if (apply)
                    {
                        int patchWidth  = Random.Range(10 - level, 10 + level + 1);
                        int patchHeight = Random.Range(10 - level, 10 + level + 1);

                        if (patchWidth < 3)
                        {
                            patchWidth = 3;
                        }

                        if (patchHeight < 3)
                        {
                            patchHeight = 3;
                        }

                        for (int patchY = y - patchHeight / 2; patchY <= y + patchHeight / 2; ++patchY)
                        {
                            for (int patchX = x - patchWidth / 2; patchX <= x + patchWidth / 2; ++patchX)
                            {
                                if (!map.IsValid(patchX, patchY) ||
                                    map.GetTile(patchX, patchY) != TileType.Outside)
                                {
                                    continue;
                                }

                                map.SetTile(patchX, patchY, TileType.Open);
                            }
                        }

                        placedPatches += 1;

                        Debug.Log("Placed Patch of Grass");
                    }
                }
            }

            // Add outside border
            map.AddBorder(_borderSize, TileType.Outside);


            // Cleanup: Remove small Patches of Outside Grass
            //{
            //    int outsideCount;
            //    const int removeCriteria = 3;

            //    for (int y = 0; y < map.Height; ++y)
            //    {
            //        outsideCount = _borderSize;
            //        for (int x = 0; x < map.Width; ++x)
            //        {
            //            if (map.GetTile(x, y) == TileType.Grass)
            //            {
            //                if (outsideCount > 0 && outsideCount <= removeCriteria)
            //                {
            //                    int removeX = x - 1;
            //                    while (map.GetTile(removeX, y) == TileType.Outside)
            //                    {
            //                        map.SetTile(removeX, x, TileType.Grass);
            //                        removeX -= 1;
            //                    }
            //                }

            //                outsideCount = 0;
            //            }
            //            else
            //            {
            //                Debug.Assert(map.GetTile(x, y) == TileType.Outside);
            //                outsideCount += 1;
            //            }
            //        }
            //    }

            //    for (int x = 0; x < map.Width; ++x)
            //    {
            //        outsideCount = _borderSize;
            //        for (int y = 0; y < map.Height; ++y)
            //        {
            //            if (map.GetTile(x, y) == TileType.Grass)
            //            {
            //                if (outsideCount > 0 && outsideCount <= removeCriteria)
            //                {
            //                    int removeY = y - 1;
            //                    while (map.GetTile(x, removeY) == TileType.Outside)
            //                    {
            //                        map.SetTile(x, removeY, TileType.Grass);
            //                        removeY -= 1;
            //                    }
            //                }

            //                outsideCount = 0;
            //            }
            //            else
            //            {
            //                Debug.Assert(map.GetTile(x, y) == TileType.Outside);
            //                outsideCount += 1;
            //            }
            //        }
            //    }
            //}



            // Add Player / Players
            Vector2Int center    = new Vector2Int(map.Width / 2, map.Width / 2);
            int        minSpawnX = center.x - 4;
            int        maxSpawnX = center.x + 4;
            int        minSpawnY = center.y - 4;
            int        maxSpawnY = center.y + 4;

            {
                if (playerCount <= 1)
                {
                    map.SetTile(center.x, center.y, TileType.StartTile);
                }
                else if (playerCount == 2)
                {
                    map.SetTile(center.x - 2, center.y, TileType.StartTile);
                    map.SetTile(center.x + 2, center.y, TileType.StartTile);
                }
                else
                {
                    int   restPlayers;
                    float radius;

                    if (playerCount <= 3)
                    {
                        radius      = 1;
                        restPlayers = playerCount;
                    }
                    else
                    {
                        map.SetTile(center.x, center.y, TileType.StartTile);
                        radius      = 2;
                        restPlayers = playerCount - 1;
                    }

                    float angle        = 360f / restPlayers;
                    float currentAngle = Random.Range(0, 360);

                    for (int i = 0; i < restPlayers; ++i)
                    {
                        Vector2 v = Quaternion.Euler(0, 0, currentAngle) * Vector2.up;
                        v *= radius;

                        int shiftx;

                        if (Mathf.Abs(v.x) <= 0.5f)
                        {
                            shiftx = 0;
                        }
                        else
                        {
                            shiftx = v.x > 0 ? Mathf.CeilToInt(v.x) : Mathf.FloorToInt(v.x);
                        }

                        int shifty;

                        if (Mathf.Abs(v.y) <= 0.5f)
                        {
                            shifty = 0;
                        }
                        else
                        {
                            shifty = v.y > 0 ? Mathf.CeilToInt(v.y) : Mathf.FloorToInt(v.y);
                        }

                        int x = center.x + shiftx;
                        int y = center.y + shifty;

                        map.SetTile(x, y, TileType.StartTile);

                        minSpawnX = Mathf.Min(minSpawnX, x);
                        maxSpawnX = Mathf.Max(maxSpawnX, x);

                        minSpawnY = Mathf.Min(minSpawnY, y);
                        maxSpawnY = Mathf.Max(maxSpawnY, y);

                        currentAngle += angle;
                    }
                }

                //// Ensure that players are inside of a grass patch.

                //for (int x = minSpawnX; x <= maxSpawnX; ++x)
                //{
                //    for (int y = minSpawnY; y <= maxSpawnY; ++y)
                //    {
                //        if (map.GetTile(x, y) != TileType.StartTile)
                //        {
                //            map.SetTile(x, y, TileType.Grass);
                //        }
                //    }
                //}
            }


            // Add Sheep
            {
                int sheepCount;

                if (difficulty == Difficulty.Easy)
                {
                    sheepCount = level + 1;
                }
                else if (difficulty == Difficulty.Normal)
                {
                    sheepCount = Mathf.FloorToInt(level * 1.5f) + 1;
                }
                else
                {
                    sheepCount = level * 2 + 1;
                }

                int addedSheeps = 0;
                int failCount   = 0;

                while (addedSheeps < sheepCount && failCount < 1000)
                {
                    failCount += 1;

                    int x = Random.Range(0, map.Width);
                    int y = Random.Range(0, map.Height);

                    if (x >= minSpawnX && x <= maxSpawnX &&
                        y >= minSpawnY && y <= maxSpawnY)
                    {
                        continue;
                    }

                    if (map.GetTile(x, y) != TileType.Open)
                    {
                        continue;
                    }

                    map.SetTile(x, y, TileType.SheepTile);
                    addedSheeps += 1;
                    failCount    = 0;
                }
            }


            // Add fences
            List <Vector2Int> nearFencePositions = new List <Vector2Int>();

            {
                List <Tuple <Vector2Int, TileType> > fencePositions = new List <Tuple <Vector2Int, TileType> >();

                for (int y = 0; y < map.Height; ++y)
                {
                    for (int x = 0; x < map.Width; ++x)
                    {
                        if (map.GetTile(x, y) == TileType.Outside)
                        {
                            bool grassN  = false;
                            bool grassNE = false;
                            bool grassE  = false;
                            bool grassSE = false;
                            bool grassS  = false;
                            bool grassSW = false;
                            bool grassW  = false;
                            bool grassNW = false;

                            if (map.IsValid(x, y + 1) &&
                                map.GetTile(x, y + 1) != TileType.Outside)
                            {
                                // North Grass
                                grassN = true;
                                nearFencePositions.Add(new Vector2Int(x, y + 1));
                            }

                            if (map.IsValid(x + 1, y + 1) &&
                                map.GetTile(x + 1, y + 1) != TileType.Outside)
                            {
                                // NorthEast Grass
                                grassNE = true;
                                nearFencePositions.Add(new Vector2Int(x + 1, y + 1));
                            }

                            if (map.IsValid(x + 1, y) &&
                                map.GetTile(x + 1, y) != TileType.Outside)
                            {
                                // East Grass
                                grassE = true;
                                nearFencePositions.Add(new Vector2Int(x + 1, y));
                            }

                            if (map.IsValid(x + 1, y - 1) &&
                                map.GetTile(x + 1, y - 1) != TileType.Outside)
                            {
                                // SouthEast Grass
                                grassSE = true;
                                nearFencePositions.Add(new Vector2Int(x + 1, y - 1));
                            }

                            if (map.IsValid(x, y - 1) &&
                                map.GetTile(x, y - 1) != TileType.Outside)
                            {
                                // South Grass
                                grassS = true;
                                nearFencePositions.Add(new Vector2Int(x, y - 1));
                            }

                            if (map.IsValid(x - 1, y - 1) &&
                                map.GetTile(x - 1, y - 1) != TileType.Outside)
                            {
                                // SouthWest Grass
                                grassSW = true;
                                nearFencePositions.Add(new Vector2Int(x - 1, y - 1));
                            }

                            if (map.IsValid(x - 1, y) &&
                                map.GetTile(x - 1, y) != TileType.Outside)
                            {
                                // West Grass
                                grassW = true;
                                nearFencePositions.Add(new Vector2Int(x - 1, y));
                            }

                            if (map.IsValid(x - 1, y + 1) &&
                                map.GetTile(x - 1, y + 1) != TileType.Outside)
                            {
                                // NorthWest Grass
                                grassNW = true;
                                nearFencePositions.Add(new Vector2Int(x - 1, y + 1));
                            }

                            if (grassN && grassE)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceNE));
                            }
                            else if (grassE && grassS)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceSE));
                            }
                            else if (grassS && grassW)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceSW));
                            }
                            else if (grassW && grassN)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceNW));
                            }
                            else if (grassN)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceS));
                            }
                            else if (grassE)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceW));
                            }
                            else if (grassS)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceN));
                            }
                            else if (grassW)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceE));
                            }
                            else if (grassNE)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceSW));
                            }
                            else if (grassSE)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceNW));
                            }
                            else if (grassSW)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceNE));
                            }
                            else if (grassNW)
                            {
                                fencePositions.Add(Tuple.Create(new Vector2Int(x, y), TileType.FenceSE));
                            }
                        }
                    }
                }

                foreach (var entry in fencePositions)
                {
                    map.SetTile(entry.Item1.x, entry.Item1.y, entry.Item2);
                }
            }

            // Add Pitchfork
            {
                for (int i = 0; i < 1000; ++i)
                {
                    int x = Random.Range(0, map.Width);
                    int y = Random.Range(0, map.Height);

                    if (x >= minSpawnX && x <= maxSpawnX &&
                        y >= minSpawnY && y <= maxSpawnY)
                    {
                        continue;
                    }

                    if (map.GetTile(x, y) == TileType.Open)
                    {
                        map.SetTile(x, y, TileType.Haystack);
                        break;
                    }
                }
            }

            // Add Blocked Tiles near Fences
            {
                int blockNearFences;

                if (difficulty == Difficulty.Easy)
                {
                    blockNearFences = level + Random.Range(2, 3);
                }
                else if (difficulty == Difficulty.Normal)
                {
                    blockNearFences = level + Random.Range(2, 4);
                }
                else
                {
                    blockNearFences = level + Random.Range(2, 5);
                }

                List <Vector2Int> addedPositions = new List <Vector2Int>();

                int addedBlockNearFences = 0;
                for (int i = 0; i < 1000 && addedBlockNearFences < blockNearFences; i++)
                {
                    Vector2Int position = nearFencePositions[Random.Range(0, nearFencePositions.Count)];
                    if (map.GetTile(position.x, position.y) != TileType.Open)
                    {
                        continue;
                    }

                    bool tooNear = false;

                    foreach (Vector2Int addedPosition in addedPositions)
                    {
                        if ((addedPosition - position).magnitude < 10)
                        {
                            if (Random.value < 0.8f)
                            {
                                tooNear = true;
                                break;
                            }
                        }
                    }

                    if (tooNear)
                    {
                        continue;
                    }

                    map.SetTile(position.x, position.y, TileType.Rock);
                    addedBlockNearFences += 1;
                    addedPositions.Add(position);
                }
            }


            // Add Blocked Tiles
            {
                int blocks;

                if (difficulty == Difficulty.Easy)
                {
                    blocks = level + Random.Range(2, 3);
                }
                else if (difficulty == Difficulty.Normal)
                {
                    blocks = level + Random.Range(2, 4);
                }
                else
                {
                    blocks = level + Random.Range(2, 5);
                }


                int addedBlocks = 0;
                for (int i = 0; i < 1000 && addedBlocks < blocks; i++)
                {
                    int x = Random.Range(0, map.Width);
                    int y = Random.Range(0, map.Height);

                    if (x >= minSpawnX && x <= maxSpawnX &&
                        y >= minSpawnY && y <= maxSpawnY)
                    {
                        continue;
                    }

                    if (map.GetTile(x, y) == TileType.Open)
                    {
                        map.SetTile(x, y, TileType.Rock);
                        addedBlocks += 1;
                    }
                    else if (map.GetTile(x, y) == TileType.Outside)
                    {
                        map.SetTile(x, y, TileType.Rock);
                    }
                }
            }


            Map = map;

            int remainingPitchForks = Master.Instance.CurrentPitchForkCount;

            // Generate Real TileMap
            {
                List <Transform> playerTransforms = new List <Transform>();

                List <Vector2Int> setBlockedTiles = new List <Vector2Int>();

                for (int y = 0; y < map.Height; ++y)
                {
                    for (int x = 0; x < map.Width; ++x)
                    {
                        switch (map.GetTile(x, y))
                        {
                        case TileType.Outside:
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _outsideTiles[Random.Range(0, _outsideTiles.Length)]);
                            break;

                        case TileType.Open:
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            break;

                        case TileType.FenceN:
                            map.SetTile(x, y, TileType.Blocked);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            _wallTilemap.SetTile(new Vector3Int(x, y, 0), _fenceN);
                            break;

                        case TileType.FenceNE:
                            map.SetTile(x, y, TileType.Blocked);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            _wallTilemap.SetTile(new Vector3Int(x, y, 0), _fenceNE);
                            break;

                        case TileType.FenceNW:
                            map.SetTile(x, y, TileType.Blocked);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            _wallTilemap.SetTile(new Vector3Int(x, y, 0), _fenceNW);
                            break;

                        case TileType.FenceS:
                            map.SetTile(x, y, TileType.Blocked);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            _wallTilemap.SetTile(new Vector3Int(x, y, 0), _fenceS);
                            break;

                        case TileType.FenceSE:
                            map.SetTile(x, y, TileType.Blocked);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            _wallTilemap.SetTile(new Vector3Int(x, y, 0), _fenceSE);
                            break;

                        case TileType.FenceSW:
                            map.SetTile(x, y, TileType.Blocked);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            _wallTilemap.SetTile(new Vector3Int(x, y, 0), _fenceSW);
                            break;

                        case TileType.FenceE:
                            map.SetTile(x, y, TileType.Blocked);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            _wallTilemap.SetTile(new Vector3Int(x, y, 0), _fenceE);
                            break;

                        case TileType.FenceW:
                            map.SetTile(x, y, TileType.Blocked);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            _wallTilemap.SetTile(new Vector3Int(x, y, 0), _fenceW);
                            break;

                        case TileType.Rock:
                            map.SetTile(x, y, TileType.Blocked);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);
                            _wallTilemap.SetTile(new Vector3Int(x, y, 0), _rockTiles[Random.Range(0, _rockTiles.Length)]);
                            break;

                        case TileType.Haystack:
                            map.SetTile(x, y, TileType.Open);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);

                            Haystack haystack = Instantiate(_haystackPrefab, new Vector3(x + 0.5f, y + 0.5f, 0), Quaternion.identity);
                            _haystacks.Add(haystack);
                            break;

                        case TileType.StartTile:
                            map.SetTile(x, y, TileType.Open);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);

                            Player player = Instantiate(_playerPrefab, new Vector3(x + 0.5f, y + 0.5f, 0), Quaternion.identity);
                            _players.Add(player);
                            playerTransforms.Add(player.transform);

                            if (remainingPitchForks > 0)
                            {
                                player.PickupPitchfork();
                                remainingPitchForks -= 1;
                            }

                            break;

                        case TileType.SheepTile:
                            map.SetTile(x, y, TileType.Open);
                            _baseTilemap.SetTile(new Vector3Int(x, y, 0), _grassTiles[Random.Range(0, _grassTiles.Length)]);

                            Sheep sheep = Instantiate(_sheepPrefab, new Vector3(x + 0.5f, y + 0.5f, 0), Quaternion.identity);
                            _sheep.Add(sheep);

                            break;


                        default:
                            Debug.Assert(false, "Unknown Tile Type");
                            continue;
                        }
                    }
                }

                FollowCamera.Instance.FollowObjects = playerTransforms.ToArray();
            }

            _levelTime.Restart();
            _levelStarted = true;
        }