PlayerShip.cs 6.5 KB

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