Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="viewIndex"></param>
        /// <param name="renderView"></param>
        /// <param name="lightCount"></param>
        /// <returns>The number of lights accepted in <see cref="CurrentLights"/>.</returns>
        public virtual int AddView(int viewIndex, RenderView renderView, int lightCount)
        {
            LightRanges[viewIndex] = new LightRange(Lights.Count, Lights.Count + lightCount);
            LightCurrentCount      = Math.Max(LightCurrentCount, ComputeLightCount(lightCount));

            return(Math.Min(LightCurrentCount, lightCount));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="viewIndex"></param>
        /// <param name="renderView"></param>
        /// <param name="lightCount"></param>
        /// <returns>The number of lights accepted in <see cref="CurrentLights"/>.</returns>
        public virtual int AddView(int viewIndex, RenderView renderView, int lightCount)
        {
            LightRanges[viewIndex] = new LightRange(Lights.Count, Lights.Count + lightCount);
            LightCurrentCount = Math.Max(LightCurrentCount, ComputeLightCount(lightCount));

            return Math.Min(LightCurrentCount, lightCount);
        }
        public virtual void SetViews(FastList<RenderView> views)
        {
            Array.Resize(ref LightRanges, views.Count);

            // Reset ranges
            for (var i = 0; i < views.Count; ++i)
                LightRanges[i] = new LightRange(0, 0);
        }
Ejemplo n.º 4
0
        public static (LightMap FloorLight, LightMap CeilingLight) Trace(
            MapData map,
            LightRange lightRange,
            IEnumerable <LightDefinition> lights)
        {
            var board = map.GetBoard();

            return(Trace(map.Dimensions, p => board[p].HasTile, lightRange, lights));
        }
Ejemplo n.º 5
0
        public virtual void SetViews(FastList <RenderView> views)
        {
            Array.Resize(ref LightRanges, views.Count);

            // Reset ranges
            for (var i = 0; i < views.Count; ++i)
            {
                LightRanges[i] = new LightRange(0, 0);
            }
        }
Ejemplo n.º 6
0
        public static (LightMap FloorLight, LightMap CeilingLight) Trace(
            Size dimensions,
            Func <Position, bool> isPositionObscured,
            LightRange lightRange,
            IEnumerable <LightDefinition> lights)
        {
            var floorLight   = new LightMap(lightRange, dimensions).Blackout();
            var ceilingLight = new LightMap(lightRange, dimensions).Blackout();

            foreach (var light in lights)
            {
                // Check a big square around the light. This is very brute force but it doesn't appear to cause any
                // problems.
                for (int y = 0; y < light.LengthAffected; y++)
                {
                    for (int x = 0; x < light.LengthAffected; x++)
                    {
                        var delta = new PositionDelta(x, y) - light.Radius;

                        var location = light.Center + delta;

                        if (!dimensions.Contains(location))
                        {
                            continue;
                        }

                        // check for line of sight
                        var obscured =
                            DrawingUtil.BresenhamLine(
                                start: light.Center,
                                end: location)
                            .Any(isPositionObscured);

                        if (!obscured)
                        {
                            var(floorIncrement, ceilingIncrement) = light.GetBrightness(location);

                            floorLight.Lighten(location, floorIncrement);
                            ceilingLight.Lighten(location, ceilingIncrement);
                        }
                    }
                }
            }

            return(floorLight, ceilingLight);
        }
Ejemplo n.º 7
0
    public static IEnumerable <(Position Location, TreasureType Type)> RandomlyPlaceTreasure(
        ConnectedArea area,
        IEnumerable <Position> edge,
        LightMap floorLighting,
        LightRange lightRange,
        Random random)
    {
        var maxScore = 3 * lightRange.DarkLevels;
        var cutOff   = (int)(0.5 * maxScore);

        var scoredLocations = edge
                              .Select(p => new { Location = p, Score = area.CountAdjacentWalls(p) * -floorLighting[p] })
                              .OrderBy(scoredLocation => scoredLocation.Score)
                              .Where(scoredLocation => scoredLocation.Score >= cutOff)
                              .OrderBy(sl => random.Next())
                              .ToArray();

        var numberToTake = scoredLocations.Length / 2;

        return(scoredLocations.Take(numberToTake).Select(sl => (sl.Location, TreasureType.Medium)));
    }
Ejemplo n.º 8
0
        public void ShowFloorVsCeilingLighting()
        {
            void SaveImage(IFastImage image, string description) =>
            image.Save(Path.Combine(_dirInfo.FullName, $"{description}.png"));

            var random = new Random(Seed);
            var board  =
                new CellBoard(new(128, 128))
                .Fill(random, probabilityAlive: 0.5)
                .MakeBorderAlive(thickness: 3)
                .GenerateStandardCave();

            var(largestComponent, dimensions) =
                ConnectedAreaAnalyzer
                .FindForegroundAreas(board.Dimensions, p => board[p] == CellType.Dead)
                .OrderByDescending(component => component.Area)
                .First()
                .TrimExcess(border: 1);

            var interior = largestComponent.DetermineInteriorEdgeDistance(Neighborhood.VonNeumann);

            // Place some lights
            var lightRange = new LightRange(DarkLevels: 15, LightLevels: 5);
            var lights     = CaveThingPlacement.RandomlyPlaceLights(
                interior.Where(pair => pair.Value == 2).Select(pair => pair.Key).ToList(),
                random,
                lightRange,
                percentAreaToCover: 0.05,
                varyHeight: true)
                             .ToArray();

            var(floorLighting, ceilingLight) =
                LightTracer.Trace(dimensions, p => !largestComponent.Contains(p), lightRange, lights);

            using var floorImg   = LightMapVisualizer.Render(floorLighting, lights, largestComponent, scale: 5);
            using var ceilingImg = LightMapVisualizer.Render(ceilingLight, lights, largestComponent, scale: 5);

            SaveImage(floorImg, "Floor");
            SaveImage(ceilingImg, "Ceiling");
        }
Ejemplo n.º 9
0
    public static IEnumerable <LightDefinition> RandomlyPlaceLights(
        IReadOnlyList <Position> validPositions,
        Random random,
        LightRange lightRange,
        double percentAreaToCover,
        bool varyHeight = false)
    {
        var numLights = (int)(validPositions.Count * percentAreaToCover);

        var positions = new List <Position>();

        return(Enumerable
               .Range(0, numLights)
               .Select(_ =>
        {
            while (true)
            {
                var posIndex = random.Next(0, validPositions.Count);
                var position = validPositions[posIndex];

                var positionIsInvalid =
                    positions.Any(p => p.Touches(position));

                if (positionIsInvalid)
                {
                    continue;
                }

                positions.Add(position);

                return new LightDefinition(
                    position,
                    Brightness: lightRange.DarkLevels,
                    Radius: 10,
                    Height: varyHeight ? random.Next(2) == 0 ? LightHeight.Ceiling : LightHeight.Floor : LightHeight.Middle);
            }
        }));
    }
Ejemplo n.º 10
0
    public static MapData Create(int seed, string texturePrefix, TextureQueue textureQueue)
    {
        var random = new Random(seed);

        var caveBoard =
            new CellBoard(new Size(128, 128))
            .Fill(random, probabilityAlive: 0.5)
            .MakeBorderAlive(thickness: 3)
            .GenerateStandardCave();

        var(caveArea, size) =
            ConnectedAreaAnalyzer
            .FindForegroundAreas(caveBoard.Dimensions, p => caveBoard[p] == CellType.Dead)
            .OrderByDescending(a => a.Area)
            .First()
            .TrimExcess(border: 1);

        var interior = caveArea.DetermineInteriorEdgeDistance(Neighborhood.VonNeumann);

        var alternateFloor =
            new CellBoard(new Size(size.Width + 1, size.Height + 1))
            .Fill(random, probabilityAlive: 0.5)
            .RunGenerations(6);
        var alternateCeiling =
            new CellBoard(new Size(size.Width + 1, size.Height + 1))
            .Fill(random, probabilityAlive: 0.5)
            .RunGenerations(6);

        var lightRange = new LightRange(DarkLevels: 15, LightLevels: 5);
        var lights     = CaveThingPlacement.RandomlyPlaceLights(
            interior.Where(pair => pair.Value == 2).Select(pair => pair.Key).ToList(),
            random,
            lightRange,
            percentAreaToCover: 0.05,
            varyHeight: true)
                         .ToArray();

        var(floorLighting, ceilingLighting) =
            LightTracer.Trace(size, p => !caveArea.Contains(p), lightRange, lights);

        var(planeMap, sectors, tiles) =
            CreateGeometry(
                size,
                caveArea,
                alternateFloor,
                alternateCeiling,
                floorLighting,
                ceilingLighting,
                textureQueue,
                texturePrefix);

        var playerPosition = caveArea.First();

        var things =
            lights.Select(light => new Thing(
                              Type: light.Height == LightHeight.Ceiling ? "CeilingCrystal" : "FloorCrystal",
                              X: light.Center.X + 0.5,
                              Y: light.Center.Y + 0.5,
                              Z: 0,
                              Angle: 0,
                              Ambush: false,
                              Skill1: true,
                              Skill2: true,
                              Skill3: true,
                              Skill4: true)).ToList();

        things.Add(new Thing(
                       Type: Actor.Player1Start.ClassName,
                       X: playerPosition.X + 0.5,
                       Y: playerPosition.Y + 0.5,
                       Z: 0,
                       Angle: 0,
                       Ambush: false,
                       Skill1: true,
                       Skill2: true,
                       Skill3: true,
                       Skill4: true));


        return(new MapData(
                   NameSpace: "Wolf3D",
                   TileSize: 64,
                   Name: "Procedural Cave",
                   Width: size.Width,
                   Height: size.Height,
                   Tiles: tiles,
                   Sectors: sectors,
                   Zones: ImmutableArray.Create(new Zone()),
                   Planes: ImmutableArray.Create(new Plane(Depth: 64)),
                   PlaneMaps: ImmutableArray.Create(planeMap),
                   Things: things.ToImmutableArray(),
                   Triggers: ImmutableArray <Trigger> .Empty));
    }