/// <summary> /// Advance the current position some distance on the flight path. /// </summary> /// <param name="distance"></param> /// <param name="destination">position after the advance</param> /// <param name="cCfinalDirection">direction of the segment that the position is on after the advance</param> internal void Advance(CCPoint currentPosition, float distance, out CCPoint destination, out float CCfinalDirection) { int currentIndex = (int)AdvancementAsQuasiIndex; float relativeAdvancementToNextPoint = AdvancementAsQuasiIndex % 1; if (currentIndex == Path.Length - 1) // if you've already reached the end you're done { destination = EndPoint; CCfinalDirection = DirectionAt(currentIndex); return; } float absoluteAdvancementToNextPoint = relativeAdvancementToNextPoint * CCPoint.Distance(Path[currentIndex], Path[currentIndex + 1]); float directionToNextPointInRadians = Constants.CCDegreesToMathRadians(DirectionAt(currentIndex)); float absoluteXAdvancement = absoluteAdvancementToNextPoint * (float)Math.Cos(directionToNextPointInRadians); float absoluteYAdvancement = absoluteAdvancementToNextPoint * (float)Math.Sin(directionToNextPointInRadians); //CCPoint currentPosition = new CCPoint(Path[currentIndex].X + absoluteXAdvancement, Path[currentIndex].Y + absoluteYAdvancement); // try to advance from the current position to the next point on the Path float distanceToNextPoint = CCPoint.Distance(currentPosition, Path[currentIndex + 1]); while (distanceToNextPoint < distance) { currentIndex = currentIndex + 1; currentPosition = Path[currentIndex]; distance -= distanceToNextPoint; AdvancementAsQuasiIndex = currentIndex; if (currentIndex == Path.Length - 1) { break; } distanceToNextPoint = CCPoint.Distance(currentPosition, Path[currentIndex + 1]); } // if you can't go far enough just move towards the point if (distance > 0 && currentIndex != Path.Length - 1) { // update the direction directionToNextPointInRadians = Constants.CCDegreesToMathRadians(DirectionAt(currentIndex)); // calculate how far you can go // relative between the points float relativeAdvanche = distance / distanceToNextPoint; // in x direction float newX = currentPosition.X + distance * (float)Math.Cos(directionToNextPointInRadians); // in y direction float newY = currentPosition.Y + distance * (float)Math.Sin(directionToNextPointInRadians); AdvancementAsQuasiIndex = (float)currentIndex + relativeAdvanche; destination = new CCPoint(newX, newY); CCfinalDirection = Constants.RadiansToCCDegrees(directionToNextPointInRadians); } else { destination = Path[currentIndex]; CCfinalDirection = DirectionAt(currentIndex); } // }
/// <summary> /// Advance the life cycles of all clouds and possibly add a new cloud. /// Rotate the given angle by 45° before creating clouds. /// </summary> /// <param name="dt">how far to advance the lifecycle</param> /// <param name="currentPosition">the position at which to add a possible new cloud</param> /// <param name="decayOnly">if true, no new clouds are added (i.e. this just advances the cloud life cycles)</param> internal override void Advance(float dt, CCPoint currentPosition, float currentCCRotation, bool decayOnly = false) { // advance the lifecycle of each cloud foreach (var cloud in clouds) { cloud.LifeTime += dt; cloud.MatchLifeCycle(); } CCPoint pos; if (AddRing) // add a special ring cloud, only one { pos = CCPoint.RotateByAngle(RelativePosition, CCPoint.Zero, Constants.CCDegreesToMathRadians(currentCCRotation)); pos += currentPosition; AddRing = false; clouds.Add(new RingCloud(pos, 0, CCColor4B.White, DrawLow, 100f, 1f)); } // check if it is time for a new cloud float timePlusDt = TimeSinceLastCloud + dt; if (AutoAddClouds && timePlusDt > CloudDelay) { // reset the timer to 0 + overshoot TimeSinceLastCloud = timePlusDt % CloudDelay; // add a new cloud if (!decayOnly) { // calculate the total position based on the saved relative position, the currentPosition and the current CCrotation pos = CCPoint.RotateByAngle(RelativePosition, CCPoint.Zero, Constants.CCDegreesToMathRadians(currentCCRotation)); pos += currentPosition; // move the spawn of the cloud a little in a random direction for a nice little bonus effect // also make the cloud size a bit random var cloud = new Cloud(Constants.RandomPointNear(pos, ReferenceSize), currentCCRotation + 45f, CloudColor, DrawLow, ReferenceSize + (float)(new Random()).NextDouble() * ReferenceSize * 2, CloudLifeTime); //var cloud = new DamageCloud(Constants.RandomPointNear(pos, ReferenceSize), currentCCRotation+45f, CloudColor, ReferenceSize + (float)(new Random()).NextDouble() * ReferenceSize, CloudLifeTime); //cloud.FireColor = FireColor; clouds.Add(cloud); } } else { // let the timer run TimeSinceLastCloud = timePlusDt; } // remove all clouds that have gone beyond their lifecycle for (int i = 0; i < clouds.Count; i++) { if (clouds[i].LifeTime > clouds[i].TotalLifeTime) { clouds.RemoveAt(i--); } } }
internal void AddSquadron(Squadron squadron, CCPoint position, float CCdirection) { squadron.Leader.Position = position; squadron.Leader.RotateTo(CCdirection); // rotate all formation positions correctly around the leader and set everyone to their positions float angle = Constants.CCDegreesToMathRadians(CCdirection); foreach (var entry in squadron.AircraftsWithRelPositions) { var formationPoint = CCPoint.RotateByAngle(entry.Value, CCPoint.Zero, angle); entry.Key.Position = position + formationPoint; entry.Key.RotateTo(CCdirection); AddAircraft(entry.Key); } squadron.GenerateWayPoint(); Squadrons.Add(squadron); }
internal void ReactToHit(float damage, CCPoint collisionPos) { const float MAX_DISTANCE_FROM_COLLISION = 200f; float maxDistanceFromCollision = ((ContentSize.Width + ContentSize.Height) / 4) * GetTotalScale(); if (maxDistanceFromCollision > MAX_DISTANCE_FROM_COLLISION) { maxDistanceFromCollision = MAX_DISTANCE_FROM_COLLISION; } // generate a random point near the collisionPos // and show an effect there Random rng = new Random(); for (int tries = 0; tries < 5; tries++) { CCPoint randomPoint = Constants.RandomPointNear(collisionPos, maxDistanceFromCollision, rng); //CCPoint randomPoint = collisionPos; if (Collisions.CollidePositionPolygon(randomPoint, this) || tries == 4) // check whether the random point is inside the collision polygon { CCPoint relativePosition = randomPoint - PositionWorldspace; relativePosition = CCPoint.RotateByAngle(relativePosition, CCPoint.Zero, -Constants.CCDegreesToMathRadians(TotalRotation)); // react differently depending upon how damaged you now are float refSize = DamageToReferenceSize(damage); var damageTail = new DamageCloudTailNode(refSize, relativePosition); if (Aircraft.SelectedPower != PowerUp.PowerType.SHIELD) { if (Health / MaxHealth > 0.7f) { damageTail.AutoAddClouds = false; } if (Health / MaxHealth < 0.5f) { var planeColor = ((PlayLayer)Layer).CurrentPlaneColor; var baseFlameColor = new CCColor4B((byte)rng.Next(0, 256), 0, 0); var h = (new SKColor(planeColor.R, planeColor.G, planeColor.B)).Hue; damageTail.CloudColor = Constants.MoveHue(baseFlameColor, h); } damageTail.CloudLifeTime += (refSize - 8f) * 0.1f; } else { damageTail.AutoAddClouds = false; } DamageCloudTailNodes.Add(damageTail); break; } } // shake! if (Aircraft.ControlledByPlayer && Aircraft.SelectedPower != PowerUp.PowerType.SHIELD) { // the shake amount depends on the damage, but mostly on how the damage relates to the max health float baseRefSize = DamageToReferenceSize(damage, 10f); float specialBonus = 0f; float healthFactor = damage / MaxHealth; if (healthFactor > 1) { healthFactor = 1; } if (Health <= 0) { baseRefSize *= (1 + TotalParts.Count()) * 0.8f; specialBonus += (float)Math.Sqrt(TotalMaxHealth) * 3; } float shakeAmount = baseRefSize * 10 * healthFactor + specialBonus; ((PlayLayer)Layer).AddScreenShake(shakeAmount, shakeAmount); } }
private float AircraftVelocityBoost() { return MyPart.Aircraft.VelocityVector.Length * (float)Math.Cos(Constants.CCDegreesToMathRadians(Constants.AngleFromToDeg(MyPart.TotalRotation, MyPart.Aircraft.TotalRotation))); }