Enemy.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //---------------------------------------------------------------------------------
  2. // Written by Michael Hoffman
  3. // Find the full tutorial at: http://gamedev.tutsplus.com/series/vector-shooter-xna/
  4. //----------------------------------------------------------------------------------
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using AtomicEngine;
  9. namespace AtomicBlaster
  10. {
  11. class Enemy : Entity
  12. {
  13. public static Random rand = new Random();
  14. private List<IEnumerator<int>> behaviours = new List<IEnumerator<int>>();
  15. private int timeUntilStart = 60;
  16. public bool IsActive { get { return timeUntilStart <= 0; } }
  17. public int PointValue { get; private set; }
  18. public Enemy(Texture2D image, Vector2 position)
  19. {
  20. this.image = image;
  21. Position = position;
  22. Radius = image.Width / 2f;
  23. color = Color.Transparent;
  24. PointValue = 1;
  25. }
  26. public static Enemy CreateSeeker(Vector2 position)
  27. {
  28. var enemy = new Enemy(Art.Seeker, position);
  29. enemy.AddBehaviour(enemy.FollowPlayer(0.9f));
  30. enemy.PointValue = 2;
  31. return enemy;
  32. }
  33. public static Enemy CreateWanderer(Vector2 position)
  34. {
  35. var enemy = new Enemy(Art.Wanderer, position);
  36. enemy.AddBehaviour(enemy.MoveRandomly());
  37. return enemy;
  38. }
  39. public override void Update()
  40. {
  41. if (timeUntilStart <= 0)
  42. ApplyBehaviours();
  43. else
  44. {
  45. timeUntilStart--;
  46. float mul = (1 - timeUntilStart / 60f);
  47. color = new Color(mul, mul, mul, mul);
  48. }
  49. Position += Velocity;
  50. Position = Vector2.Clamp(Position, Size / 2, GameRoot.ScreenSize - Size / 2);
  51. Velocity *= 0.8f;
  52. }
  53. public override void Draw(/*SpriteBatch spriteBatch*/)
  54. {
  55. if (timeUntilStart > 0)
  56. {
  57. // Draw an expanding, fading-out version of the sprite as part of the spawn-in effect.
  58. float factor = timeUntilStart / 60f; // decreases from 1 to 0 as the enemy spawns in
  59. CustomRenderer.Draw(image, Position, Color.White * factor, Orientation, Size / 2f, 2 - factor, 0);
  60. }
  61. base.Draw();
  62. }
  63. private void AddBehaviour(IEnumerable<int> behaviour)
  64. {
  65. behaviours.Add(behaviour.GetEnumerator());
  66. }
  67. private void ApplyBehaviours()
  68. {
  69. for (int i = 0; i < behaviours.Count; i++)
  70. {
  71. if (!behaviours[i].MoveNext())
  72. behaviours.RemoveAt(i--);
  73. }
  74. }
  75. public void HandleCollision(Enemy other)
  76. {
  77. var d = Position - other.Position;
  78. Velocity += 10 * d / (d.LengthSquared + 1);
  79. }
  80. public void WasShot()
  81. {
  82. IsExpired = true;
  83. PlayerStatus.AddPoints(PointValue);
  84. PlayerStatus.IncreaseMultiplier();
  85. float hue1 = rand.NextFloat(0, 6);
  86. float hue2 = (hue1 + rand.NextFloat(0, 2)) % 6f;
  87. Color color1 = ColorUtil.HSVToColor(hue1, 0.5f, 1);
  88. Color color2 = ColorUtil.HSVToColor(hue2, 0.5f, 1);
  89. for (int i = 0; i < 120; i++)
  90. {
  91. float speed = 18f * (1f - 1 / rand.NextFloat(1, 10));
  92. var state = new ParticleState()
  93. {
  94. Velocity = rand.NextVector2(speed, speed),
  95. Type = ParticleType.Enemy,
  96. LengthMultiplier = 1
  97. };
  98. Color color = Color.Lerp(color1, color2, rand.NextFloat(0, 1));
  99. GameRoot.ParticleManager.CreateParticle(Art.LineParticle, Position, color, 190, 1.5f, state);
  100. }
  101. //Sound.Explosion.Play(0.5f, rand.NextFloat(-0.2f, 0.2f), 0);
  102. }
  103. #region Behaviours
  104. IEnumerable<int> FollowPlayer(float acceleration)
  105. {
  106. while (true)
  107. {
  108. if (!PlayerShip.Instance.IsDead)
  109. Velocity += (PlayerShip.Instance.Position - Position).ScaleTo(acceleration);
  110. if (Velocity != Vector2.Zero)
  111. Orientation = Velocity.ToAngle();
  112. yield return 0;
  113. }
  114. }
  115. IEnumerable<int> MoveRandomly()
  116. {
  117. float direction = rand.NextFloat(0, MathHelper.TwoPi);
  118. while (true)
  119. {
  120. direction += rand.NextFloat(-0.1f, 0.1f);
  121. direction = MathHelper.WrapAngle(direction);
  122. for (int i = 0; i < 6; i++)
  123. {
  124. Velocity += MathUtil.FromPolar(direction, 0.4f);
  125. Orientation -= 0.05f;
  126. var bounds = GameRoot.ScreenBounds;
  127. bounds.Inflate(-image.Width / 2 - 1, -image.Height / 2 - 1);
  128. // if the enemy is outside the bounds, make it move away from the edge
  129. if (!bounds.Contains(Position))
  130. direction = (GameRoot.ScreenSize / 2 - Position).ToAngle() + rand.NextFloat(-MathHelper.PiOver2, MathHelper.PiOver2);
  131. yield return 0;
  132. }
  133. }
  134. }
  135. #endregion
  136. }
  137. }