Exemplo n.º 1
0
 // dirty, because only the center of the bounding box + all points of the box are used to check the angle;
 // this function is using CCDegrees
 internal static bool CollideArcBoundingBox(CCPoint posCircle, float radius, float angleArcCenter, float angleHalfArcWidth, CCRect box)
 {
     if (CollideBoundingBoxCircle(box, posCircle, radius))
     {
         // check whether the center of the box is inside the arc
         CCPoint vectorCirclePoint = box.Center - posCircle;
         float   anglePoint        = Constants.DxDyToCCDegrees(vectorCirclePoint.X, vectorCirclePoint.Y);
         float   angleDifference   = Constants.AbsAngleDifferenceDeg(angleArcCenter, anglePoint);
         if (angleDifference <= angleHalfArcWidth)
         {
             return(true);
         }
         // check whether a point of the box is inside the arc
         foreach (CCPoint point in Constants.CCRectPoints(box))
         {
             vectorCirclePoint = point - posCircle;
             anglePoint        = Constants.DxDyToCCDegrees(vectorCirclePoint.X, vectorCirclePoint.Y);
             angleDifference   = Constants.AbsAngleDifferenceDeg(angleArcCenter, anglePoint);
             if (angleDifference <= angleHalfArcWidth)
             {
                 return(true);
             }
         }
     }
     return(false);
 }
 /// <summary>
 /// called by the Aircraft owning the part owning this WeaponAbility each frame
 /// </summary>
 /// <param name="dt">time since the previous frame</param>
 internal void ExecuteOrders(float dt)
 {
     // cool down
     CooldownUntilNextShot -= dt;
     CooldownUntilNextTargetUpdate -= dt;
     if (CooldownUntilNextShot < 0) CooldownUntilNextShot = 0;
     // if you have a target check if it is still in range
     if (TargetPart != null)
     {
             CCPoint vectorMyPartTarget = TargetPart.PositionWorldspace - MyPart.PositionWorldspace;
             if (TargetPart.MyState == Part.State.DESTROYED || (TargetAircraft != null && TargetAircraft.MyState == Aircraft.State.SHOT_DOWN)
                 || CooldownUntilNextTargetUpdate <= 0
                 || CCPoint.Distance(MyPart.PositionWorldspace, TargetPart.PositionWorldspace) > AttentionRange
                 || Constants.AbsAngleDifferenceDeg(MyPart.TotalRotation - MyPart.RotationFromNull, Constants.DxDyToCCDegrees(vectorMyPartTarget.X, vectorMyPartTarget.Y)) > AttentionAngle)
                 TargetPart = null;
     }
     if (TargetPart == null && CooldownUntilNextTargetUpdate <= 0)     // if you currently do not aim at anything search for a target
     {
         CooldownUntilNextTargetUpdate = UpdateTargetDelay;
         // collect aircrafts that are near enough to have parts which could be targets
         // go through the parts of all of these planes and collect those that are in the attention angle
         PartsInRange(out List<Part> partsInRange, out List<float> anglesFromTo, out List<float> distances);
         // try to choose a part that is in reach
         // choose the part that is closest anglewise
         // but prioritize aircraft bodies:
         //  this means that you should only change target from a body to another part if the part you would choose instead (because it's closer)
         //  belongs to another plane
         float minAngle = float.PositiveInfinity;
         for (int i=0; i<partsInRange.Count(); i++)
         {
             if (distances[i] <= ShootingRange)  // first only try parts that are already in reach
             {
                 float absAngle = (float)Math.Abs(anglesFromTo[i]);
                 var part = partsInRange[i];
                 if (absAngle < minAngle) //&&
                     //(TargetPart == null || !(part.Parent == TargetPart.Parent && TargetPart == TargetAircraft.Body)))  // don't switch from a body to a different part of the same aircraft
                 {
                     TargetPart = part;
                     minAngle = absAngle;
                 }
             }
         }
         if (TargetPart == null) // if you found no target this way check the rest
         {
             minAngle = float.PositiveInfinity;
             for (int i = 0; i < partsInRange.Count(); i++)
             {
                 float absAngle = (float)Math.Abs(anglesFromTo[i]);
                 var part = partsInRange[i];
                 // now also try parts that are not already in reach
                 if (absAngle < minAngle) //&&
                     //(TargetPart == null || !(part.Parent == TargetPart.Parent && TargetPart == TargetAircraft.Body)))  // don't switch from a body to a different part of the same aircraft
                 {
                     TargetPart = part;
                     minAngle = absAngle;
                 }
             }
         }
     }
     // calculate the perfect point to aim for in order to hit the target
     if (TargetPart != null)
     {
         float angleToAimFor = AngleToAimFor();
         if (!(MyPart is WingJet))   // a dirty fix to make sure jet wings don't rotate since rotation screws up the flip state; for other weapons this effect can be neglected since it is only visual
         {
             float angleToTurnTo = angleToAimFor;
             float angleTurn = Constants.AngleFromToDeg(MyPart.NullRotation, angleToTurnTo);
             // make sure you don't rotate further than your MountPoint allows
             if (angleTurn > MyPart.MountPoint.MaxTurningAngle)
                 angleToTurnTo = MyPart.NullRotation + MyPart.MountPoint.MaxTurningAngle;
             else if (angleTurn < -MyPart.MountPoint.MaxTurningAngle)
                 angleToTurnTo = MyPart.NullRotation - MyPart.MountPoint.MaxTurningAngle;
             // make sure you don't rotate further than this weapons MaxTurningAngle allows
             if (MaxTurningAngle < MyPart.MountPoint.MaxTurningAngle)
             {
                 if (angleTurn > MaxTurningAngle)
                     angleToTurnTo = MyPart.NullRotation + MaxTurningAngle;
                 else if (angleTurn < -MaxTurningAngle)
                     angleToTurnTo = MyPart.NullRotation - MaxTurningAngle;
             }
             MyPart.RotateTowards(angleToTurnTo, TurningAnglePerSecond * dt);
         }
         // if you're now close enough to the perfect angle (and in range) start shooting
         if (CanShoot()
             && CCPoint.Distance(MyPart.PositionWorldspace, TargetPart.PositionWorldspace) <= ShootingRange
             && (Constants.AbsAngleDifferenceDeg(angleToAimFor, MyPart.MyRotation) <= ToleratedError || WouldHit()))
         {
             TryShoot();
         }
             
     }
     // and if you have no target try to get back to NullRotation
     else if (!(MyPart is WingJet))
     {
         MyPart.RotateTowards(MyPart.NullRotation, TurningAnglePerSecond * dt);
     }
 }