Beispiel #1
0
 public ChunkGenerator(LevelConfig config, LevelObjectsPool pool, int length, int width)
 {
     levelConfig      = config;
     levelObjectsPool = pool;
     this.length      = Mathf.Max(length, LevelGraph.MinLength);
     this.width       = Mathf.Max(width, LevelGraph.MinWidth);
 }
Beispiel #2
0
        /// <summary>
        /// Generate chunk cells by graph nodes
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="levelConfig"></param>
        /// <param name="pool"></param>
        /// <param name="chunkPosition"></param>
        /// <returns></returns>
        private static List <LevelObject> GenerateCells(LevelGraph graph, LevelConfig levelConfig, LevelObjectsPool pool,
                                                        Vector3 chunkPosition)
        {
            const int cellsPerNode   = LevelGraph.CellsPerNode;
            var       chunkLength    = graph.length * cellsPerNode;
            var       chunkWidth     = graph.width;
            var       obstaclePlaces = new List <Vector2Int>();

            // Fill grid by wall and floor random configs
            var cells = new Grid <CellConfig>(chunkWidth, chunkLength);

            for (var l = 0; l < graph.length; l++)
            {
                for (var x = 0; x < graph.width; x++)
                {
                    var node = graph.nodes.Get(x, l);
                    var end  = l * cellsPerNode + cellsPerNode;
                    if (node.passable)
                    {
                        var y           = l * cellsPerNode;
                        var coordinates = new Vector2Int(x, y);
                        // Store passable coordinate for placing some obstacle
                        obstaclePlaces.Add(coordinates);
                        for (; y < end; y++)
                        {
                            cells.Set(x, y, GetRandom(levelConfig.floors));
                        }
                    }
                    else
                    {
                        var y = l * cellsPerNode;
                        cells.Set(x, y, levelConfig.walls[Random.Range(0, levelConfig.walls.Length)]);
                        y++;
                        if (graph.nodes.TryGet(x, l + 1, out var nextNode) && !nextNode.passable)
                        {
                            for (; y < end; y++)
                            {
                                cells.Set(x, y, GetRandom(levelConfig.walls));
                            }
                        }
                        else
                        {
                            for (; y < end; y++)
                            {
                                cells.Set(x, y, GetRandom(levelConfig.floors));
                            }
                        }
                    }
                }
            }

            // Try to place random obstacle config in previously founded coordinates
            foreach (var coordinates in obstaclePlaces)
            {
                var chance          = Random.value;
                var obstacleConfigs = Shuffle <CellConfig> .ToQueue(levelConfig.obstacles);

                while (obstacleConfigs.Count > 0)
                {
                    var config = obstacleConfigs.Dequeue();
                    // Check if obstacle placement restrictions passed
                    if (!config.CheckPlacement(chance, coordinates, cells))
                    {
                        continue;
                    }
                    cells.Set(coordinates, config);
                    break;
                }
            }

            // Setup instances
            var gameObjects = new List <LevelObject>(cells.items.Length);

            gameObjects.AddRange(cells.items.Select((t, i) =>
                                                    t.SetupInstance(pool.CreateFor(t.prefab),
                                                                    ToVector3(cells.GetIndexCoordinates(i)), chunkPosition)));
            return(gameObjects);
        }
Beispiel #3
0
        /// <summary>
        /// Generate chunk items by graph nodes
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="levelConfig"></param>
        /// <param name="pool"></param>
        /// <param name="chunkPosition"></param>
        /// <returns></returns>
        private static List <LevelObject> GenerateItems(LevelGraph graph, LevelConfig levelConfig, LevelObjectsPool pool,
                                                        Vector3 chunkPosition)
        {
            const int itemsCount       = 5;
            const int itemsCountOffset = 1;

            var levelObjects = new List <LevelObject>();
            var orderedItems = levelConfig.items.OrderBy(item => item.generateChance).ToArray();

            // Generate one items chain per graph row in random lane
            for (var y = 0; y < graph.length; y++)
            {
                var xShuffle = Shuffle <int> .ToQueue(Enumerable.Range(0, graph.width));

                while (xShuffle.Count > 0)
                {
                    var x    = xShuffle.Dequeue();
                    var node = graph.nodes.Get(x, y);
                    if (!node.passable)
                    {
                        continue;
                    }
                    var target = GetRandom(node.exits);

                    // Build smooth items "path" by Bezier curve
                    var offset = new Vector3(0, 0, 0.5f);
                    var a      = new Vector3(node.position.x, 0, node.position.y * LevelGraph.CellsPerNode) + offset;
                    var d      = new Vector3(target.x, 0, target.y * LevelGraph.CellsPerNode) + offset;
                    var middle = new Vector3(0, 0, d.z - a.z) * 0.5f;
                    var b      = a + middle;
                    var c      = d - middle;
                    var bezier = new Bezier(a, b, c, d);

                    // Place items on curve in some range
                    var from = Random.Range(0, itemsCountOffset + 1);
                    var to   = Random.Range(0, itemsCountOffset + 1) + itemsCount - itemsCountOffset;
                    for (var i = from; i < to; i++)
                    {
                        var chance          = Random.value;
                        var inChunkPosition = bezier.GetPoint(1f / itemsCount * i);
                        foreach (var itemConfig in orderedItems)
                        {
                            if (!itemConfig.CheckChance(chance))
                            {
                                continue;
                            }
                            levelObjects.Add(itemConfig.SetupInstance(pool.CreateFor(itemConfig),
                                                                      inChunkPosition, chunkPosition));
                            break;
                        }
                    }
                    break;
                }
            }
            return(levelObjects);
        }