// 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); } }