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); }
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); }
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); }
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); }
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); }
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); }
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); }
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(); } }
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; }
public int GetDistance(Hex.OffsetCoordinates firstHexagon, Hex.OffsetCoordinates secondHexagon) { return(Hex.CubeCoordinates.Distance(this.HexGrid.ToCubeCoordinates(firstHexagon), this.HexGrid.ToCubeCoordinates(secondHexagon))); }
public bool CanMoveObjectTo(SpaceObject spaceObject, Hex.OffsetCoordinates destination) { return(this.PerformBFS(spaceObject.ObjectCoordinates, spaceObject.ActionsLeft).Keys.Contains(destination)); }
public double GetTargetHexagonAngle(Hex.OffsetCoordinates sourceOffsetCoordinates, Hex.OffsetCoordinates targetOffsetCoordinates) { return(this.CombatMap.GetAngle(sourceOffsetCoordinates, targetOffsetCoordinates)); }
public double GetAngle(Hex.OffsetCoordinates sourceOffsetCoordinates, Hex.OffsetCoordinates targetOffsetCoordinates) { return(this.GetAngle(this.HexGrid.ToCubeCoordinates(sourceOffsetCoordinates), this.HexGrid.ToCubeCoordinates(targetOffsetCoordinates))); }
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)); } }
public bool AreNeighbors(Hex.OffsetCoordinates firstHexagon, Hex.OffsetCoordinates secondHexagon) { return(this.AreNeighbors(this.HexGrid.ToCubeCoordinates(firstHexagon), this.HexGrid.ToCubeCoordinates(secondHexagon))); }
public Hex.OffsetCoordinates GetNeighborCoordinates(Hex.OffsetCoordinates hexagonOffsetCoordinates, int neighborDirection) { return(this.HexGrid.ToOffsetCoordinates( Hex.CubeCoordinates.Neighbor(this.HexGrid.ToCubeCoordinates(hexagonOffsetCoordinates), neighborDirection))); }
public Point HexToPixel(Hex.OffsetCoordinates objectCoordinates) { return(this.HexGrid.HexToPixel(this.HexGrid.ToCubeCoordinates(objectCoordinates)).ConvertToDrawingPoint()); }
private int OffsetCoordinatesToIndex(Hex.OffsetCoordinates offsetCoordinates) { return(this.OffsetCoordinatesToIndex(offsetCoordinates.Column, offsetCoordinates.Row)); }
public PointF[] GetHexagonCorners(Hex.OffsetCoordinates offsetCoordinates) { var coordinates = this.HexGrid.ToCubeCoordinates(offsetCoordinates); return(this.HexGrid.PolygonCorners(coordinates).Select(c => c.ConvertToDrawingPointF()).ToArray()); }