示例#1
0
        private Dictionary <Hex.OffsetCoordinates, Hex.OffsetCoordinates> PerformBFS(Hex.OffsetCoordinates startHexagon, int maxDistance = -1)
        {
            var bfsQueue = new Queue <Hex.OffsetCoordinates>();

            bfsQueue.Enqueue(startHexagon);
            var cameFromHexagons = new Dictionary <Hex.OffsetCoordinates, Hex.OffsetCoordinates>()
            {
                { startHexagon, new Hex.OffsetCoordinates(-1, -1) }
            };
            var stepsToHexagon = new Dictionary <Hex.OffsetCoordinates, int>()
            {
                { startHexagon, 0 }
            };

            while (bfsQueue.Count > 0)
            {
                var currentHexagon = bfsQueue.Dequeue();

                if (maxDistance >= 0 && stepsToHexagon[currentHexagon] >= maxDistance)
                {
                    continue;
                }

                foreach (var neighborHexagon in this.CombatMap.GetAllNeighbors(currentHexagon).Where(c => this.SpaceObjects[this.OffsetCoordinatesToIndex(c)] == null))
                {
                    if (!cameFromHexagons.ContainsKey(neighborHexagon))
                    {
                        bfsQueue.Enqueue(neighborHexagon);
                        cameFromHexagons.Add(neighborHexagon, currentHexagon);
                        stepsToHexagon.Add(neighborHexagon, stepsToHexagon[currentHexagon] + 1);
                    }
                }
            }
            return(cameFromHexagons);
        }
示例#2
0
        public List <PointF[]> GetAllHexagonCornersInRange(Hex.OffsetCoordinates centerHexagon, int range)
        {
            var allHexagonCorners = new List <PointF[]>();

            foreach (var hexagonCoordinates in this.GetAllHexagonsInRange(centerHexagon, range))
            {
                allHexagonCorners.Add(this.GetHexagonCorners(hexagonCoordinates));
            }
            return(allHexagonCorners);
        }
示例#3
0
        public void CreateMeteor()
        {
            var meteorCoordinates = new Hex.OffsetCoordinates();
            HexagonNeighborDirection movementDirection = 0;

            var rand          = new Random();
            var randomMapSide = rand.Next(4);

            switch (randomMapSide)
            {
            case 0:      // left
                meteorCoordinates = this.GetRandomVacantHexagon(0, 0, 0, this.MapHeight - 1);
                movementDirection = rand.Next(2) == 0
                        ? HexagonNeighborDirection.NorthEast
                        : HexagonNeighborDirection.SouthEast;
                break;

            case 1:     // top
                meteorCoordinates = this.GetRandomVacantHexagon(0, this.MapWidth - 1, 0, 0);
                movementDirection = rand.Next(2) == 0
                        ? HexagonNeighborDirection.SouthEast
                        : HexagonNeighborDirection.SouthWest;
                break;

            case 2:     // right
                meteorCoordinates = this.GetRandomVacantHexagon(this.MapWidth - 1, this.MapWidth - 1, 0, this.MapHeight - 1);
                movementDirection = rand.Next(2) == 0
                        ? HexagonNeighborDirection.NorthWest
                        : HexagonNeighborDirection.SouthWest;
                break;

            case 3:     // bottom
                meteorCoordinates = this.GetRandomVacantHexagon(0, this.MapWidth - 1, this.MapHeight - 1, this.MapHeight - 1);
                movementDirection = rand.Next(2) == 0
                        ? HexagonNeighborDirection.NorthEast
                        : HexagonNeighborDirection.NorthWest;
                break;
            }

            var meteorHealth = rand.Next(1, 150);
            var meteorDmg    = meteorHealth / 4;

            var meteor       = new Meteor(meteorCoordinates, meteorHealth, meteorDmg, movementDirection);
            var headingAngle = this.CombatMap.GetAngle(meteorCoordinates,
                                                       this.CombatMap.GetNeighborCoordinates(meteorCoordinates, (int)movementDirection));

            meteor.Rotate(headingAngle);
            this.AddObject(meteor);
        }
示例#4
0
        public List <Hex.OffsetCoordinates> GetHexagonPath(Hex.OffsetCoordinates startHexagon, Hex.OffsetCoordinates finishHexagon)
        {
            var stepOriginHexagons = this.PerformBFS(startHexagon);
            var currentHexagon     = finishHexagon;
            var path = new List <Hex.OffsetCoordinates>();

            while (!currentHexagon.Equals(startHexagon))
            {
                path.Add(currentHexagon);
                currentHexagon = stepOriginHexagons[currentHexagon];
            }

            path.Reverse();
            return(path);
        }
示例#5
0
        public List <Hex.OffsetCoordinates> GetAllNeighbors(Hex.OffsetCoordinates hexagon)
        {
            var neighbors = new List <Hex.OffsetCoordinates>();

            for (int i = 0; i < 6; i++)
            {
                var potentialNeighbor = this.HexGrid.ToOffsetCoordinates(Hex.CubeCoordinates.Neighbor(this.HexGrid.ToCubeCoordinates(hexagon), i));
                if (potentialNeighbor.Column >= 0 && potentialNeighbor.Column < this.FieldWidth &&
                    potentialNeighbor.Row >= 0 && potentialNeighbor.Row < this.FieldHeight)
                {
                    neighbors.Add(potentialNeighbor);
                }
            }

            return(neighbors);
        }
示例#6
0
        public List <Hex.OffsetCoordinates> GetAllHexagonsInRange(Hex.OffsetCoordinates centerHexagon, int range)
        {
            var allHexagons = new List <Hex.OffsetCoordinates>();

            //  TODO: implement spiral ring algorithm from redblobgames
            for (int x = 0; x < this.FieldWidth; x++)
            {
                for (int y = 0; y < this.FieldHeight; y++)
                {
                    var coordinates = new Hex.OffsetCoordinates(x, y);
                    var distance    = this.GetDistance(centerHexagon, coordinates);
                    if (distance <= range && distance > 0)
                    {
                        allHexagons.Add(coordinates);
                    }
                }
            }
            return(allHexagons);
        }
示例#7
0
        public double GetRelativeHexagonAngle(SpaceObject sourceSpaceObject, Hex.OffsetCoordinates targetOffsetCoordinates)
        {
            var angle = this.CombatMap.GetAngle(sourceSpaceObject.ObjectCoordinates, targetOffsetCoordinates);

            if (sourceSpaceObject.Owner == Player.SecondPlayer)
            {
                angle -= 180;
            }

            while (angle > 180)
            {
                angle -= 360;
            }

            while (angle < -180)
            {
                angle += 360;
            }

            return(angle);
        }
示例#8
0
        public CubeCoordinates ToCubeCoordinates(OffsetCoordinates h)
        {
            int q, r, s;

            switch (_orientation.name)
            {
            case OrientationName.FlatHexagons:

                q = h.Column;
                r = h.Row - ((h.Column + _offset.Value * (h.Column & 1)) / 2);
                s = -q - r;
                return(new CubeCoordinates(q, r, s));

            case OrientationName.PointyHexagons:
                q = h.Column - ((h.Row + _offset.Value * (h.Row & 1)) / 2);
                r = h.Row;
                s = -q - r;
                return(new CubeCoordinates(q, r, s));

            default:
                throw new NotImplementedException();
            }
        }
示例#9
0
        public void MoveObjectTo(SpaceObject spaceObject, Hex.OffsetCoordinates destination, bool onlyAnimate = false)
        {
            if (spaceObject is Ship)
            {
                SoundPlayed?.Invoke(this, new SoundEventArgs(Properties.Resources.spaceShipFly));
            }
            ObjectAnimated?.Invoke(this, new AnimationEventArgs(this.CaptureGameState(spaceObject), this.CombatMap.HexToPixel(spaceObject.ObjectCoordinates), this.CombatMap.HexToPixel(destination)));
            if (destination.Column < 0 || destination.Column >= this.MapWidth ||
                destination.Row < 0 || destination.Row >= this.MapHeight)
            {
                // moving object outside bounds = deleting object
                this.DeleteObject(spaceObject);
                return;
            }

            if (onlyAnimate)
            {
                return;
            }

            this.SpaceObjects[this.OffsetCoordinatesToIndex(spaceObject.ObjectCoordinates)] = null;
            this.SpaceObjects[this.OffsetCoordinatesToIndex(destination)] = spaceObject;
            spaceObject.ObjectCoordinates = destination;
        }
示例#10
0
 public int GetDistance(Hex.OffsetCoordinates firstHexagon, Hex.OffsetCoordinates secondHexagon)
 {
     return(Hex.CubeCoordinates.Distance(this.HexGrid.ToCubeCoordinates(firstHexagon), this.HexGrid.ToCubeCoordinates(secondHexagon)));
 }
示例#11
0
 public bool CanMoveObjectTo(SpaceObject spaceObject, Hex.OffsetCoordinates destination)
 {
     return(this.PerformBFS(spaceObject.ObjectCoordinates, spaceObject.ActionsLeft).Keys.Contains(destination));
 }
示例#12
0
 public double GetTargetHexagonAngle(Hex.OffsetCoordinates sourceOffsetCoordinates, Hex.OffsetCoordinates targetOffsetCoordinates)
 {
     return(this.CombatMap.GetAngle(sourceOffsetCoordinates, targetOffsetCoordinates));
 }
示例#13
0
 public double GetAngle(Hex.OffsetCoordinates sourceOffsetCoordinates, Hex.OffsetCoordinates targetOffsetCoordinates)
 {
     return(this.GetAngle(this.HexGrid.ToCubeCoordinates(sourceOffsetCoordinates), this.HexGrid.ToCubeCoordinates(targetOffsetCoordinates)));
 }
示例#14
0
        public Meteor(Hex.OffsetCoordinates meteorCoordinates, int health, int damage, HexagonNeighborDirection movementDirection) : base(Player.None, health, ObjectType.Meteor, 1)
        {
            this.MovementDirection = movementDirection;
            this.ObjectCoordinates = meteorCoordinates;
            this.CollisionDamage   = damage;

            int meteorRadius = 15; //TODO: make meteor size dependent on it's damage

            this.ObjectAppearance = new List <DrawableShape>
            {
                new Ellipse(new Point(-meteorRadius, -meteorRadius), Colors.DarkGray, new Size(2 * meteorRadius, 2 * meteorRadius)),
            };

            var    darkSpots     = new List <Ellipse>();
            Random rand          = new Random();
            int    minSpotRadius = meteorRadius / 7;
            int    maxSpotRadius = meteorRadius / 5;

            for (int i = 0; i < 20; i++)
            {
                var spotRadius = rand.Next(minSpotRadius, maxSpotRadius + 1);

                var r   = rand.Next(spotRadius, meteorRadius - spotRadius);
                var phi = 2 * Math.PI * rand.NextDouble();
                int x   = (int)(r * Math.Cos(phi)) - spotRadius;
                int y   = (int)(r * Math.Sin(phi)) - spotRadius;

                var spotCenter = new PointF(x + spotRadius, y + spotRadius);
                if (!darkSpots.Any(existingSpot => spotCenter.Distance(existingSpot.Origin + existingSpot.Size / 2) < spotRadius + existingSpot.Size.Width))
                {
                    darkSpots.Add(new Ellipse(new Point(x, y), Colors.DimGray, new Size(2 * spotRadius, 2 * spotRadius)));
                }
            }
            this.ObjectAppearance.AddRange(darkSpots);


            var flameSweepsOnMeteor = new Dictionary <Color, double> {
                { Colors.Orange, 2 * Math.PI / 3 }, { Colors.Red, Math.PI / 4 }
            };
            var flameSpanAngle = Math.PI / 4;

            foreach (var flameSweep in flameSweepsOnMeteor)
            {
                float flameBaseLengthHalf = meteorRadius * (float)Math.Sin(flameSweep.Value / 2);
                float flameHeight         = flameBaseLengthHalf / (float)Math.Tan(flameSpanAngle / 2);
                float flameTipOffset      = meteorRadius * (float)Math.Cos(flameSweep.Value / 2) + flameHeight;
                // arcSpanAngle = 180 - 2 * (90 - flameSpanAngle/2) = 180 - 180 + 2 * flameSpanAngle/2 = flameSpanAngle
                float arcRadius = flameHeight / (float)Math.Sin(flameSpanAngle);

                var pathComponents = new List <DrawableShape>
                {
                    new Arc(new Point(-meteorRadius, -meteorRadius),
                            new SizeF(2 * meteorRadius, 2 * meteorRadius),
                            180 - (float)(flameSweep.Value.ToDegrees() / 2),
                            (float)flameSweep.Value.ToDegrees()),
                    new Arc(new PointF(-flameTipOffset - arcRadius, -2 * arcRadius),
                            new SizeF(2 * arcRadius, 2 * arcRadius),
                            90 - (float)flameSpanAngle.ToDegrees(),
                            (float)flameSpanAngle.ToDegrees()),
                    new Arc(new PointF(-flameTipOffset - arcRadius, 0),
                            new SizeF(2 * arcRadius, 2 * arcRadius),
                            -90,
                            (float)flameSpanAngle.ToDegrees())
                };
                this.ObjectAppearance.Add(new Path(new Point(0, 0), flameSweep.Key, pathComponents));
            }
        }
示例#15
0
 public bool AreNeighbors(Hex.OffsetCoordinates firstHexagon, Hex.OffsetCoordinates secondHexagon)
 {
     return(this.AreNeighbors(this.HexGrid.ToCubeCoordinates(firstHexagon), this.HexGrid.ToCubeCoordinates(secondHexagon)));
 }
示例#16
0
 public Hex.OffsetCoordinates GetNeighborCoordinates(Hex.OffsetCoordinates hexagonOffsetCoordinates, int neighborDirection)
 {
     return(this.HexGrid.ToOffsetCoordinates(
                Hex.CubeCoordinates.Neighbor(this.HexGrid.ToCubeCoordinates(hexagonOffsetCoordinates), neighborDirection)));
 }
示例#17
0
 public Point HexToPixel(Hex.OffsetCoordinates objectCoordinates)
 {
     return(this.HexGrid.HexToPixel(this.HexGrid.ToCubeCoordinates(objectCoordinates)).ConvertToDrawingPoint());
 }
示例#18
0
 private int OffsetCoordinatesToIndex(Hex.OffsetCoordinates offsetCoordinates)
 {
     return(this.OffsetCoordinatesToIndex(offsetCoordinates.Column, offsetCoordinates.Row));
 }
示例#19
0
        public PointF[] GetHexagonCorners(Hex.OffsetCoordinates offsetCoordinates)
        {
            var coordinates = this.HexGrid.ToCubeCoordinates(offsetCoordinates);

            return(this.HexGrid.PolygonCorners(coordinates).Select(c => c.ConvertToDrawingPointF()).ToArray());
        }