Esempio n. 1
0
 public ProjectileEffect(ProjectileEffectData data)
 {
     _radius         = data.Radius;
     _damage         = data.Damage;
     _particleEffect = data.ParticleEffectName == null ?
                       null : new ParticleEffect(data.ParticleEffectName);
     _force       = data.Force;
     _statEffects = new StatEffect(data.FireEffect, data.CryoEffect, data.ShockEffect);
     Duration     = TimeSpan.FromSeconds(data.Duration);
 }
 public StatEffect ApplyResist(StatEffect resist)
 {
     return new StatEffect(Fire * (1 - resist.Fire / MaxEffect),
                           Cryo * (1 - resist.Cryo / MaxEffect),
                           Shock * (1 - resist.Shock / MaxEffect));
 }
 public ProjectileEffect(ProjectileEffectData data)
 {
     _radius = data.Radius;
     _damage = data.Damage;
     _particleEffect = data.ParticleEffectName == null ?
         null : new ParticleEffect(data.ParticleEffectName);
     _force = data.Force;
     _statEffects = new StatEffect(data.FireEffect, data.CryoEffect, data.ShockEffect);
     Duration = TimeSpan.FromSeconds(data.Duration);
 }
        public virtual void Update(GameTime gameTime, Rectangle levelBounds)
        {
            switch(_lifeState)
            {
                case LifeState.Living:
                case LifeState.Ghost:
                    {
                        if (Panicked)
                        {
                            _panicTimer -= gameTime.ElapsedGameTime;
                            if (_panicTimer <= TimeSpan.Zero)
                            {
                                _panicTimer = TimeSpan.FromSeconds(PANIC_DIRECTION_CHANGE_FREQUENCY);
                                XnaHelper.RandomizeVector(ref _moveDirection, -1, 1, -1, 1);
                                _lookDirection = _moveDirection;
                            }
                        }
                        lookThisWay(LookDirection);
                        if (MoveDirection.Length() > 0)
                            moveThisWay(MoveDirection, gameTime);

                        //handle burning
                        ApplyDamage(_statusEffects.Fire * (float)gameTime.ElapsedGameTime.TotalSeconds * FIRE_DPS);

                        break;
                    }
                case LifeState.Disabled:
                case LifeState.Frozen:
                    {
                        if (_statusEffects.Cryo <= 0)
                        {
                            _lifeState = LifeState.Living;
                            //still cold after defrosting
                            _statusEffects.Cryo = MAX_STAT_EFFECT / 2;
                        }
                        break;
                    }
                case LifeState.Shattered:
                    {
                        for (int y = 0; y < ICE_DIVISIONS; y++)
                            for (int x = 0; x < ICE_DIVISIONS; x++)
                            {
                                _fragments[x, y].Angle += _fragments[x, y].AngularVelocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                _fragments[x, y].Position += _fragments[x, y].Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                _fragments[x, y].Velocity += _fragments[x, y].Acceleration * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                _fragments[x, y].Acceleration = Vector2.Zero;
                                _fragments[x, y].Health -= FRAGMENT_MELT_RATE * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                _fragments[x, y].ScaleFactor = _fragments[x,y].Health / FRAGMENT_HEALTH * FRAGMENT_SCALE_FACTOR;
                                XnaHelper.ClampVector(ref _fragments[x, y].Velocity, FRAGMENT_MAX_VELOCITY, out _fragments[x, y].Velocity);
                                if (_fragments[x, y].BeingEaten)
                                {
                                    _fragments[x, y].Health -= FRAGMENT_EAT_RATE * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                }
                            }
                        return;
                    }
                case LifeState.BeingEaten:
                    {
                        _sprite.ScaleFactor -= BLACK_HOLE_EAT_SCALE_FACTOR * (float)gameTime.ElapsedGameTime.TotalSeconds;
                        if (_sprite.ScaleFactor <= 0)
                            _lifeState = LifeState.Destroyed;
                        break;
                    }
                case LifeState.Destroyed:
                default:
                    {
                        return;     //don't update anything
                    }
            }

            stayInBounds(levelBounds.Width, levelBounds.Height);
            _velocity += _acceleration * (float)gameTime.ElapsedGameTime.TotalSeconds;
            Position += _velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
            controlVelocity(_maxSpeed, gameTime.ElapsedGameTime);
            _sprite.Angle += _angularVelocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

            LookDirection = Vector2.Zero;
            MoveDirection = Vector2.Zero;
            _acceleration = Vector2.Zero;

            if (_movementParticleEffect != null)
                _movementParticleEffect.Update(gameTime);

            //burning visual effect
            _burningParticleEffect.Spawn(Position, 0.0f, gameTime.ElapsedGameTime, _velocity);
            _burningParticleEffect.IntensityFactor = _statusEffects.Fire / MAX_STAT_EFFECT;
            _burningParticleEffect.Update(gameTime);

            //cryo visual effect
            if (_statusEffects.Cryo > 0 && _lifeState != LifeState.Disabled)
            {
                _sprite.Shade = Color.Lerp(Color.White, Color.Blue, _statusEffects.Cryo / MAX_STAT_EFFECT);
            }

            _hitRect.X = (int)Position.X - _hitRect.Width / 2;
            _hitRect.Y = (int)Position.Y - _hitRect.Height / 2;

            //manage stat effects
            if (_statusEffects.Cryo >= MAX_STAT_EFFECT && _lifeState != LifeState.Frozen)
            {
                _lifeState = LifeState.Frozen;
                _iceIntegrity = maxHealth * ICE_INTEGRITY_FACTOR;
                _statusEffects.Fire = 0;    //stop burning if frozen
            }

            //decrement every stat effect based on status resist
            _statusEffects -= _statusResist * (float)gameTime.ElapsedGameTime.TotalSeconds;
            _statusEffects.Clamp(0, MAX_STAT_EFFECT);

            _sprite.Update(gameTime);
        }
        public void CheckAndApplyUnitCollision(PhysicalUnit other)
        {
            if (!Collides)
                return;     //don't check collision if unit shouldn't collide
            //special shattered collision detection
            if (_lifeState == LifeState.Shattered)
            {
                tempRec.Width = _hitRect.Width / ICE_DIVISIONS;
                tempRec.Height = _hitRect.Height / ICE_DIVISIONS;
                for (int i = 0; i < ICE_DIVISIONS ; i++)
                    for (int j = 0; j < ICE_DIVISIONS; j++)
                    {
                        tempRec.X = (int)(_fragments[i,j].Position.X - tempRec.Width / 2);
                        tempRec.Y = (int)(_fragments[i,j].Position.Y - tempRec.Height / 2);
                        if (tempRec.Intersects(other.HitRect))
                        {
                            Vector2 fVel = _fragments[i, j].Velocity;
                            float fMass = (float)Mass / (ICE_DIVISIONS * ICE_DIVISIONS);
                            temp = other.Velocity;
                            other._velocity = (other._velocity * (other.Mass - fMass) + 2 * fMass * fVel) /
                                                (fMass + other.Mass);
                            _fragments[i,j].Velocity = (fVel * (fMass - other.Mass) + 2 * other.Mass * temp) /
                                                (fMass + other.Mass);
                        }
                    }
                return; //ignore normal collision detection
            }

            //check if fire should be transferred
            float dist = XnaHelper.DistanceBetweenRects(HitRect, other.HitRect);
            if (dist < FIRE_SPREAD_DISTANCE)
            {
                if (_statusEffects.Fire > other._statusEffects.Fire)
                {
                    StatEffect transfer = new StatEffect() { Fire = FIRE_SPREAD_FACTOR * dist / FIRE_SPREAD_DISTANCE * _statusEffects.Fire };
                    other.ApplyStatus(transfer);
                    ApplyStatus(transfer * -FIRE_SPREAD_LOSS);
                }
            }

            if (XnaHelper.RectsCollide(HitRect, other.HitRect))
            {
                temp = other._velocity; //temp is a static reusable vector

                other._velocity = (other._velocity * (other.Mass - this.Mass) + 2 * this.Mass * this._velocity) /
                                    (this.Mass + other.Mass);
                this._velocity = (this._velocity * (this.Mass - other.Mass) + 2 * other.Mass * temp) /
                                    (this.Mass + other.Mass);
            }
        }
 public void ApplyStatus(StatEffect effects)
 {
     _statusEffects += effects;
 }
        /// <summary>
        /// Create a new physical sprite from data
        /// </summary>
        /// <param name="pd">data from which to construct unit</param>
        protected PhysicalUnit(PhysicalData pd)
        {
            _unitName = pd.Name;
            _sprite = new Sprite(_unitName);

            if (pd.MovementParticleEffectName != null)
                _movementParticleEffect = new ParticleEffect(pd.MovementParticleEffectName);
            _burningParticleEffect = new ParticleEffect("Burning");

            _mass = pd.Mass;
            _moveForce = pd.MoveForce;
            _maxSpeed = pd.MaxSpeed;
            _maxHealth = pd.Health;
            _health = _maxHealth;
            _decelerationFactor = pd.DecelerationFactor;

            _lifeState = LifeState.Dormant;     //not yet spawned
            _hitRect = new Rectangle(0, 0, (int)_sprite.Width, (int)_sprite.Height);

            Position = Vector2.Zero;
            MoveDirection = Vector2.Zero;
            LookDirection = Vector2.Zero;

            _statusEffects = new StatEffect(0, 0, 0);
            _statusResist = new StatEffect(pd.FireResist, pd.CryoResist, pd.ShockResist);

            _fragments = new IceFragment[ICE_DIVISIONS, ICE_DIVISIONS];
        }
        public virtual void Update(GameTime gameTime, Rectangle levelBounds)
        {
            switch(_lifeState)
            {
                case LifeState.Living:
                case LifeState.Ghost:
                    {
                        //handle burning
                        ApplyDamage(_statusEffects.Fire * (float)gameTime.ElapsedGameTime.TotalSeconds * FIRE_DPS);
                        break;
                    }
                case LifeState.Frozen:
                    {
                        if (_statusEffects.Cryo <= 0)
                        {
                            _lifeState = Health > 0 ? LifeState.Living : LifeState.Destroyed;
                            //still cold after defrosting
                            _statusEffects.Cryo = StatEffect.MaxEffect / 2;
                        }
                        break;
                    }
                case LifeState.Shattered:
                    {
                        bool allDestroyed = true;
                        for (int y = 0; y < c_shatterDivisions; y++)
                            for (int x = 0; x < c_shatterDivisions; x++)
                            {
                                allDestroyed = (_fragments[x, y].Health < 0) && allDestroyed;
                                _fragments[x, y].Angle += _fragments[x, y].AngularVelocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                _fragments[x, y].Position += _fragments[x, y].Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                _fragments[x, y].Velocity += _fragments[x, y].Acceleration * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                _fragments[x, y].Acceleration = Vector2.Zero;
                                if (_freezeShatter)
                                {
                                    _fragments[x, y].Health -= FRAGMENT_MELT_RATE * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                }
                                _fragments[x, y].ScaleFactor = _fragments[x, y].Health / FRAGMENT_HEALTH * FRAGMENT_SCALE_FACTOR;
                                XnaHelper.ClampVector(ref _fragments[x, y].Velocity, FRAGMENT_MAX_VELOCITY, out _fragments[x, y].Velocity);
                                if (_fragments[x, y].BeingEaten)
                                {
                                    _fragments[x, y].Health -= FRAGMENT_EAT_RATE * (float)gameTime.ElapsedGameTime.TotalSeconds;
                                }
                            }
                        if (allDestroyed) { _lifeState = LifeState.Destroyed; }
                        return;
                    }
                case LifeState.BeingEaten:
                    {
                        _sprite.ScaleFactor -= BLACK_HOLE_EAT_SCALE_FACTOR * (float)gameTime.ElapsedGameTime.TotalSeconds;
                        if (_sprite.ScaleFactor <= 0)
                            _lifeState = LifeState.Destroyed;
                        break;
                    }
                case LifeState.Destroyed:
                    {
                        return;
                    }
                default:
                    break;     //don't update anything
            }

            stayInBounds(levelBounds.Width, levelBounds.Height);
            _velocity += _acceleration * (float)gameTime.ElapsedGameTime.TotalSeconds;
            Position += _velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
            controlVelocity(_maxSpeed, gameTime.ElapsedGameTime);
            _sprite.Angle += _angularVelocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

            _acceleration = Vector2.Zero;

            //burning visual effect
            _burningParticleEffect.Spawn(Position, 0.0f, gameTime.ElapsedGameTime, _velocity);
            _burningParticleEffect.IntensityFactor = _statusEffects.Fire / StatEffect.MaxEffect;
            _burningParticleEffect.Update(gameTime);

            //cryo visual effect
            if (_statusEffects.Cryo > 0 && _lifeState != LifeState.Disabled)
            {
                _sprite.Shade = Color.Lerp(Color.White, Color.Blue, _statusEffects.Cryo / StatEffect.MaxEffect);
            }

            _hitRect.X = (int)Position.X - _hitRect.Width / 2;
            _hitRect.Y = (int)Position.Y - _hitRect.Height / 2;

            //manage stat effects
            if (_statusEffects.Cryo >= StatEffect.MaxEffect && _lifeState != LifeState.Frozen)
            {
                _lifeState = LifeState.Frozen;
                _iceIntegrity = MaxHealth * ICE_INTEGRITY_FACTOR;
                _statusEffects.Fire = 0;    //stop burning if frozen
            }

            //decrement every stat effect based on status resist
            _statusEffects -= _statusResist * (float)gameTime.ElapsedGameTime.TotalSeconds;
            _statusEffects.Clamp(0, StatEffect.MaxEffect);

            _sprite.Update(gameTime);
        }
 public void ApplyStatus(StatEffect effects)
 {
     _statusEffects += effects.ApplyResist(_statusResist);
 }
        /// <summary>
        /// Create a new physical sprite from data
        /// </summary>
        /// <param name="pd">data from which to construct unit</param>
        protected PhysicalBody(PhysicalData pd, Sprite.SpriteType spriteType)
        {
            _unitName = pd.Name;

            if (spriteType == Sprite.SpriteType.Unit)
            {
                _sprite = new UnitSprite(pd.Name, (PhysicalUnit)this);
            }
            else
            {
                _sprite = new Sprite(pd.Name, spriteType);
            }

            _burningParticleEffect = new ParticleEffect("Burning");

            _mass = pd.Mass;
            _gravitySensitivity = pd.GravitySensitivity;
            _moveForce = pd.MoveForce;
            _maxSpeed = pd.MaxSpeed;
            _maxHealth = pd.Health;
            _health = _maxHealth;
            _decelerationFactor = pd.DecelerationFactor;

            _lifeState = LifeState.Dormant;     //not yet spawned
            _hitRect = new Rectangle(0, 0, (int)_sprite.Width, (int)_sprite.Height);

            Position = Vector2.Zero;

            _statusEffects = new StatEffect(0, 0, 0);
            _statusResist = new StatEffect(pd.FireResist, pd.CryoResist, pd.ShockResist);

            _fragments = new IceFragment[c_shatterDivisions, c_shatterDivisions];
        }