PlayerShip.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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 AtomicEngine;
  7. namespace AtomicBlaster
  8. {
  9. class PlayerShip : Entity
  10. {
  11. private static PlayerShip instance;
  12. public static PlayerShip Instance
  13. {
  14. get
  15. {
  16. if (instance == null)
  17. instance = new PlayerShip();
  18. return instance;
  19. }
  20. }
  21. const int cooldownFrames = 6;
  22. int cooldowmRemaining = 0;
  23. int framesUntilRespawn = 0;
  24. public bool IsDead { get { return framesUntilRespawn > 0; } }
  25. static Random rand = new Random();
  26. private PlayerShip()
  27. {
  28. image = Art.Player;
  29. Position = GameRoot.ScreenSize / 2;
  30. Radius = 10;
  31. }
  32. public override void Update()
  33. {
  34. if (IsDead)
  35. {
  36. if (--framesUntilRespawn == 0)
  37. {
  38. if (PlayerStatus.Lives == 0)
  39. {
  40. PlayerStatus.Reset();
  41. Position = GameRoot.ScreenSize / 2;
  42. }
  43. GameRoot.Grid.ApplyDirectedForce(new Vector3(0, 0, 5000), new Vector3(Position.X, Position.Y, 0), 50);
  44. }
  45. return;
  46. }
  47. var aim = ShipInput.GetAimDirection();
  48. if (aim.LengthSquared > 0 && cooldowmRemaining <= 0)
  49. {
  50. cooldowmRemaining = cooldownFrames;
  51. float aimAngle = aim.ToAngle();
  52. Quaternion aimQuat = Quaternion.CreateFromYawPitchRoll(0, 0, aimAngle);
  53. float randomSpread = rand.NextFloat(-0.04f, 0.04f) + rand.NextFloat(-0.04f, 0.04f);
  54. Vector2 vel = MathUtil.FromPolar(aimAngle + randomSpread, 11f);
  55. Vector2 offset = Vector2.Transform(new Vector2(35, -8), aimQuat);
  56. EntityManager.Add(new Bullet(Position + offset, vel));
  57. offset = Vector2.Transform(new Vector2(35, 8), aimQuat);
  58. EntityManager.Add(new Bullet(Position + offset, vel));
  59. // Sound.Shot.Play(0.2f, rand.NextFloat(-0.2f, 0.2f), 0);
  60. }
  61. if (cooldowmRemaining > 0)
  62. cooldowmRemaining--;
  63. const float speed = 8;
  64. Velocity += speed * ShipInput.GetMovementDirection();
  65. Position += Velocity;
  66. Position = Vector2.Clamp(Position, Size / 2, GameRoot.ScreenSize - Size / 2);
  67. if (Velocity.LengthSquared > 0)
  68. Orientation = Velocity.ToAngle();
  69. MakeExhaustFire();
  70. Velocity = Vector2.Zero;
  71. }
  72. private void MakeExhaustFire()
  73. {
  74. if (Velocity.LengthSquared > 0.1f)
  75. {
  76. // set up some variables
  77. Orientation = Velocity.ToAngle();
  78. Quaternion rot = Quaternion.CreateFromYawPitchRoll(0f, 0f, Orientation);
  79. double t = GameRoot.ElapsedTime;
  80. // The primary velocity of the particles is 3 pixels/frame in the direction opposite to which the ship is travelling.
  81. Vector2 baseVel = Velocity.ScaleTo(-3);
  82. // Calculate the sideways velocity for the two side streams. The direction is perpendicular to the ship's velocity and the
  83. // magnitude varies sinusoidally.
  84. Vector2 perpVel = new Vector2(baseVel.Y, -baseVel.X) * (0.6f * (float)Math.Sin(t * 10));
  85. Color sideColor = new Color(200.0f/255.0f, 38.0f/255.0f, 9.0f/255.0f); // deep red
  86. Color midColor = new Color(255/255.0f, 187/255.0f, 30/255.0f); // orange-yellow
  87. Vector2 pos = Position + Vector2.Transform(new Vector2(-25, 0), rot); // position of the ship's exhaust pipe.
  88. const float alpha = 0.7f;
  89. // middle particle stream
  90. Vector2 velMid = baseVel + rand.NextVector2(0, 1);
  91. GameRoot.ParticleManager.CreateParticle(Art.LineParticle, pos, Color.White * alpha, 60f, new Vector2(0.5f, 1),
  92. new ParticleState(velMid, ParticleType.Enemy));
  93. GameRoot.ParticleManager.CreateParticle(Art.Glow, pos, midColor * alpha, 60f, new Vector2(0.5f, 1),
  94. new ParticleState(velMid, ParticleType.Enemy));
  95. // side particle streams
  96. Vector2 vel1 = baseVel + perpVel + rand.NextVector2(0, 0.3f);
  97. Vector2 vel2 = baseVel - perpVel + rand.NextVector2(0, 0.3f);
  98. GameRoot.ParticleManager.CreateParticle(Art.LineParticle, pos, Color.White * alpha, 60f, new Vector2(0.5f, 1),
  99. new ParticleState(vel1, ParticleType.Enemy));
  100. GameRoot.ParticleManager.CreateParticle(Art.LineParticle, pos, Color.White * alpha, 60f, new Vector2(0.5f, 1),
  101. new ParticleState(vel2, ParticleType.Enemy));
  102. GameRoot.ParticleManager.CreateParticle(Art.Glow, pos, sideColor * alpha, 60f, new Vector2(0.5f, 1),
  103. new ParticleState(vel1, ParticleType.Enemy));
  104. GameRoot.ParticleManager.CreateParticle(Art.Glow, pos, sideColor * alpha, 60f, new Vector2(0.5f, 1),
  105. new ParticleState(vel2, ParticleType.Enemy));
  106. }
  107. }
  108. public override void Draw(/*SpriteBatch spriteBatch*/)
  109. {
  110. if (!IsDead)
  111. base.Draw();
  112. }
  113. public void Kill()
  114. {
  115. PlayerStatus.RemoveLife();
  116. framesUntilRespawn = PlayerStatus.IsGameOver ? 300 : 120;
  117. Color explosionColor = new Color(0.8f, 0.8f, 0.4f); // yellow
  118. for (int i = 0; i < 1200; i++)
  119. {
  120. float speed = 18f * (1f - 1 / rand.NextFloat(1f, 10f));
  121. Color color = Color.Lerp(Color.White, explosionColor, rand.NextFloat(0, 1));
  122. var state = new ParticleState()
  123. {
  124. Velocity = rand.NextVector2(speed, speed),
  125. Type = ParticleType.None,
  126. LengthMultiplier = 1
  127. };
  128. GameRoot.ParticleManager.CreateParticle(Art.LineParticle, Position, color, 190, 1.5f, state);
  129. }
  130. }
  131. }
  132. }