public bool HandleMovementOrder(ControlGroup Group, ArcenPoint MoveOrderPoint, bool isQueuedCommand) { ArcenSparseLookup <GameEntity, ArcenPoint> entitiesToPlace; GameEntity coreUnit; int shieldCoverageRadiusOrEquivalent, paddingAroundEachUnit; ArcenRectangle firstUnitRect; UtilityFunctions_Formation.Helper_FindAndPlaceCoreUnit(Group, MoveOrderPoint, out entitiesToPlace, out coreUnit, out shieldCoverageRadiusOrEquivalent, out paddingAroundEachUnit, out firstUnitRect); List <GameEntity> foreZoneEntities, aftZoneEntities; UtilityFunctions_Formation.Helper_GetForeAndAftZoneEntities(entitiesToPlace, out foreZoneEntities, out aftZoneEntities); int occupiedRadius = coreUnit.TypeData.Radius + paddingAroundEachUnit; int degreeBufferOnEachEndOfEachArc = 15; int arcWidth = 180 - (degreeBufferOnEachEndOfEachArc * 2); int foreArcCenterAngle = 0; int aftArcCenterAngle = foreArcCenterAngle + 180; if (Reverse) { List <GameEntity> temp = foreZoneEntities; foreZoneEntities = aftZoneEntities; aftZoneEntities = temp; } occupiedRadius = Helper_PlaceRings(foreZoneEntities, entitiesToPlace, isQueuedCommand, paddingAroundEachUnit, MoveOrderPoint, occupiedRadius, NonSimAngleDegrees.Create(foreArcCenterAngle - (arcWidth / 2)), NonSimAngleDegrees.Create(arcWidth)); // resetting this for the aft arc occupiedRadius = coreUnit.TypeData.Radius + paddingAroundEachUnit; occupiedRadius = Helper_PlaceRings(aftZoneEntities, entitiesToPlace, isQueuedCommand, paddingAroundEachUnit, MoveOrderPoint, occupiedRadius, NonSimAngleDegrees.Create(aftArcCenterAngle - (arcWidth / 2)), NonSimAngleDegrees.Create(arcWidth)); UtilityFunctions_Formation.Helper_RotatePointsAccordingToAngleFromCoreUnit(MoveOrderPoint, isQueuedCommand, entitiesToPlace, coreUnit); UtilityFunctions_Formation.Helper_ActuallyIssueMoveOrders(isQueuedCommand, entitiesToPlace); return(true); }
public static void Helper_RotatePointsAccordingToAngleFromCoreUnit(ArcenPoint MoveOrderPoint, bool isQueuedCommand, ArcenSparseLookup <GameEntity, ArcenPoint> entitiesToPlace, GameEntity coreUnit) { // rotate points according to angle from first unit to target Vector2 originPoint = coreUnit.WorldLocation.ToVector2(); if (isQueuedCommand) { for (int i = 0; i < coreUnit.EntitySpecificOrders.QueuedOrders.Count; i++) { EntityOrder order = coreUnit.EntitySpecificOrders.QueuedOrders[i]; if (order.TypeData.Type != EntityOrderType.Move) { continue; } originPoint = order.RelatedPoint.ToVector2(); } } Vector2 moveOrderVectorPoint = MoveOrderPoint.ToVector2(); NonSimAngleDegrees angle = originPoint.GetAngleToDegrees(moveOrderVectorPoint); NonSimAngleDegrees baseAngle = NonSimAngleDegrees.Create(0); NonSimAngleDegrees rotationAngle = angle.Add(baseAngle); for (int i = 0; i < entitiesToPlace.GetPairCount(); i++) { ArcenSparseLookupPair <GameEntity, ArcenPoint> pair = entitiesToPlace.GetPairByIndex(i); Vector2 destinationPoint = pair.Value.ToVector2(); NonSimAngleDegrees subAngle = moveOrderVectorPoint.GetAngleToDegrees(destinationPoint); Vector2 movementVector = destinationPoint - moveOrderVectorPoint; float distance = movementVector.magnitude;//involves sqrt, is awful, but in interface code of this kind it's probably fine NonSimAngleDegrees finalAngle = rotationAngle.Add(subAngle); Vector2 rotatedPoint = moveOrderVectorPoint; rotatedPoint.x += (float)(distance * finalAngle.Cos()); rotatedPoint.y += (float)(distance * finalAngle.Sin()); entitiesToPlace[pair.Key] = rotatedPoint.ToArcenPoint(); } }
private static int Helper_PlaceRings(List <GameEntity> entitiesToPlaceWithinZone, ArcenSparseLookup <GameEntity, ArcenPoint> overallEntitySet, bool isQueuedCommand, int paddingAroundEachUnit, ArcenPoint Center, int CurrentOccupiedRadius, NonSimAngleDegrees StartingAngle, NonSimAngleDegrees ArcWidth) { NonSimAngleRadians arcWidthRadians = ArcWidth.ToRadians(); int unitIndex = 0; while (unitIndex < entitiesToPlaceWithinZone.Count) { GameEntity firstEntityOnRing = entitiesToPlaceWithinZone[unitIndex]; int firstUnitRadius = firstEntityOnRing.TypeData.Radius + paddingAroundEachUnit; int radiusOfNewRing = CurrentOccupiedRadius + firstUnitRadius; NonSimAngleRadians workingAngle = StartingAngle.ToRadians(); NonSimAngleRadians sumOfArcIncreases = NonSimAngleRadians.Create(0); int lastUnitRadius = 0; ArcenPoint firstPointFound = ArcenPoint.OutOfRange; for ( ; unitIndex < entitiesToPlaceWithinZone.Count; unitIndex++) { GameEntity entity = entitiesToPlaceWithinZone[unitIndex]; int thisUnitRadius = entity.TypeData.Radius + paddingAroundEachUnit; int distanceNeededFromPreviousPoint = 0; if (lastUnitRadius > 0) { distanceNeededFromPreviousPoint = lastUnitRadius + thisUnitRadius; } lastUnitRadius = thisUnitRadius; if (distanceNeededFromPreviousPoint > 0) { if (distanceNeededFromPreviousPoint > radiusOfNewRing) { break; } if (radiusOfNewRing <= 0) { break; } float unitDistanceNeeded = (float)distanceNeededFromPreviousPoint / (float)radiusOfNewRing; //translating this to "distance" on the unit circle //Given point A at angle M on a circle, increasing the angle by N results in another point at a distance of 2*sin(N/2) from point A //D=2*sin(N/2) //D/2=sin(N/2) //arcsin(D/2)=N/2 //2*arcsin(D/2)=N NonSimAngleRadians angleChangeNeeded = NonSimAngleRadians.Create(2 * Mathf.Asin(unitDistanceNeeded / 2)); sumOfArcIncreases = sumOfArcIncreases.Add(angleChangeNeeded); if (sumOfArcIncreases.Raw_GetIsGreaterThan(arcWidthRadians)) { break; // if this would bring us past the ending angle, stop and go to next "ring" in arc } workingAngle = workingAngle.Add(angleChangeNeeded); } Vector2 pointOnCircle = Center.ToVector2(); pointOnCircle.x += (float)(radiusOfNewRing * workingAngle.Cos()); pointOnCircle.y += (float)(radiusOfNewRing * workingAngle.Sin()); ArcenPoint pointOnCircleAsArcenPoint = pointOnCircle.ToArcenPoint(); if (firstPointFound == ArcenPoint.OutOfRange) { firstPointFound = pointOnCircleAsArcenPoint; } else if (firstPointFound.GetDistanceTo(pointOnCircleAsArcenPoint, false) < (firstUnitRadius + thisUnitRadius)) { break; // we've come full circle, and don't want to overlap } overallEntitySet[entity] = pointOnCircleAsArcenPoint; } CurrentOccupiedRadius = radiusOfNewRing + firstUnitRadius; } return(CurrentOccupiedRadius); }