public override void Update(GameTime gameTime, GameEngine.TeeEngine engine) { // Get the Hero player for interaction purposes. Hero player = (Hero)engine.GetEntity("Player"); Vector2 prevPos = Pos; AttackTarget = player; // Check if this Bat has died. if (HP <= 0) { this.Opacity -= 0.02f; this.Drawables.ResetState(CurrentDrawableState, gameTime); if (this.Opacity < 0) { if (!_goldGiven) SpawnCoins(engine); engine.RemoveEntity(this); } } else { // ATTACKING LOGIC. if (Stance == AttackStance.Attacking) { this.Pos.X -= (float)(Math.Cos(_attackAngle) * _attackSpeed); this.Pos.Y -= (float)(Math.Sin(_attackAngle) * _attackSpeed); this._attackHeight.Y += 30.0f / ATTACK_COUNTER_LIMIT; this.Drawables.SetGroupProperty("Body", "Offset", _attackHeight); onAttack(engine, gameTime); } // ATTACK PREPERATION LOGIC. else if (Stance == AttackStance.Preparing) { _attackHeight.Y -= 2; if (_attackHeight.Y < -40) { _attackHeight.Y = -40; _attackAngle = Math.Atan2( this.Pos.Y - player.Pos.Y, this.Pos.X - player.Pos.X ); Stance = AttackStance.Attacking; _attackCounter = 0; } Drawables.SetGroupProperty("Body", "Offset", _attackHeight); } // NON-ATTACKING LOGIC. PATROL AND APPROACH. else if (Stance == AttackStance.NotAttacking) { double distance = Vector2.Distance(player.Pos, this.Pos); if (distance < AggroDistance && player.HP > 0) { // Move towards the player for an attack move. double angle = Math.Atan2( player.Pos.Y - this.Pos.Y, player.Pos.X - this.Pos.X ); // Approach Function. double moveValue; if (distance < AttackDistance) { Stance = AttackStance.Preparing; moveValue = 0; } else moveValue = _moveSpeed; Pos.X += (float)(Math.Cos(angle) * moveValue); Pos.Y += (float)(Math.Sin(angle) * moveValue); } else { // Perform a standard patrol action. Pos.X += (float)(Math.Cos(gameTime.TotalGameTime.TotalSeconds - _randomModifier * 90) * 2); } } else if (Stance == AttackStance.Retreating) { double distance = Vector2.Distance(player.Pos, this.Pos); if (distance < AggroDistance * 1.10) { if (_attackHeight.Y < -10) { _attackHeight.Y += 0.4f; if (_attackHeight.Y > -10) _attackHeight.Y = -10; Drawables.SetGroupProperty("Body", "Offset", _attackHeight); } double angle = Math.Atan2( player.Pos.Y - this.Pos.Y, player.Pos.X - this.Pos.X ); Pos.X += (float)(Math.Cos(angle) * -(_moveSpeed * 0.8f)); Pos.Y += (float)(Math.Sin(angle) * -(_moveSpeed * 0.8f)); } else { Stance = AttackStance.NotAttacking; if (_attackHeight.Y < -10) _attackHeight.Y = -10; Drawables.SetGroupProperty("Body", "Offset", _attackHeight); } } // Determine the animation based on the change in position. if (Math.Abs(prevPos.X - Pos.X) > Math.Abs(prevPos.Y - Pos.Y)) { if (prevPos.X < Pos.X) this.CurrentDrawableState = Prefix + "Right"; if (prevPos.X > Pos.X) this.CurrentDrawableState = Prefix + "Left"; } else { if (prevPos.Y < Pos.Y) this.CurrentDrawableState = Prefix + "Down"; if (prevPos.Y > Pos.Y) this.CurrentDrawableState = Prefix + "Up"; } } base.Update(gameTime, engine); }