/// <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--);
                }
            }
        }
Exemplo n.º 2
0
        private void WasteCurrentWreck()
        {
            GUILayer.AddScreenShake(50f, 50f);
            var         mAircraft    = MiddleAircraft;
            float       startP       = GetWreckPercentile(mAircraft);
            var         percentLabel = GetPercentLabel(mAircraft);
            const float DURATION     = 1.5f;

            AddAction(new CCSequence(new CCEaseIn(new CCCallFiniteTimeFunc(DURATION, (progress, duration) => { SetWreckPercentile(mAircraft, startP * (1 - progress)); }), 4f),
                                     new CCCallFunc(() => { EndRepair(true); })));
            // let the aircraft visually crumble to pieces
            var totalParts  = mAircraft.TotalParts;
            var currentConf = new Dictionary <Part, Tuple <CCPoint, float, float> >();

            foreach (var part in totalParts)
            {
                currentConf[part] = new Tuple <CCPoint, float, float>(part.PositionWorldspace, part.MyRotation, part.GetTotalScale());
            }
            mAircraft.Body.Disassemble();
            mAircraft.Body = null;
            var rng = new Random();

            foreach (var part in totalParts)
            {
                AddChild(part, 99999);
                // place them so that the position is (visually) the same
                var config = currentConf[part];
                part.Position = config.Item1;
                part.Rotation = config.Item2;
                part.Scale    = config.Item3;
                // add an action to let it spin around a bit randomly
                part.AddAction(new CCSpawn(new CCEaseOut(new CCMoveTo(DURATION * 2, Constants.RandomPointNear(part.Position, 600f, rng)), 2f),
                                           new CCFadeOut(DURATION * 2)));
                part.AddAction(new CCRepeatForever(new CCRotateBy(1f, (rng.NextBoolean() ? -1 : 1) * (50f + (float)rng.NextDouble() * 100f))));
                part.AddAction(new CCSequence(new CCDelayTime(DURATION * 2 + 0.1f), new CCRemoveSelf()));
            }
        }
Exemplo n.º 3
0
        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);
            }
        }