Enemy.cs 5.4 KB

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