PageRenderTime 53ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Breakout/BreakoutGame.cs

#
C# | 248 lines | 146 code | 32 blank | 70 comment | 12 complexity | 6991bc6e2c26cac271aef0a4e943b041 MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using Delta.Engine.Dynamic;
  4. using Delta.Utilities.Datatypes;
  5. using Delta.Rendering.Basics.Fonts;
  6. using Delta.InputSystem;
  7. using Delta.Engine;
  8. using Delta.Rendering.Basics.Materials;
  9. using Delta.Multimedia;
  10. using Delta.Utilities.Helpers;
  11. namespace Breakout
  12. {
  13. /// <summary>
  14. /// Breakout game
  15. /// </summary>
  16. public class BreakoutGame : DynamicModule
  17. {
  18. //TODO: known bug: the collision particle effect is blinking around, there is an issue with the effect system we have to fix soon!
  19. //TODO: better and more effects (explosions? ball collision)
  20. //TODO: add better trail and when adding trail, we still have to fix geometry and material rendering issues
  21. #region Constants
  22. /// <summary>
  23. /// Name of the command for 'Yes/No' decision of restart the game.
  24. /// </summary>
  25. private const string CommandYesNoClick = "YesNoClick";
  26. /// <summary>
  27. /// Name of the command for quitting the game.
  28. /// </summary>
  29. private const string CommandQuitGame = "Quit";
  30. #endregion
  31. #region Private
  32. /// <summary>
  33. /// The background of the game.
  34. /// </summary>
  35. private Material2D background;
  36. /// <summary>
  37. /// Block material
  38. /// </summary>
  39. private Material2DColored block;
  40. /// <summary>
  41. /// Material to visualize the player paddle.
  42. /// </summary>
  43. private Material2D paddle;
  44. /// <summary>
  45. /// Material to visualize the ball in the game.
  46. /// </summary>
  47. private Material2DColored ball;
  48. /// <summary>
  49. /// The collision sound between the ball and a player paddle.
  50. /// </summary>
  51. private Sound sound;
  52. private List<Point> lastBallPositions;
  53. private Board board;
  54. private int oldScore;
  55. private Rectangle scoreTextArea;
  56. private Rectangle gameOverTextArea;
  57. private Rectangle tryAgainTextArea;
  58. private Rectangle yesTextArea;
  59. private Rectangle noTextArea;
  60. #endregion
  61. #region Constructor
  62. /// <summary>
  63. /// Create breakout game
  64. /// </summary>
  65. public BreakoutGame()
  66. : base(typeof(BreakoutGame).Name, typeof(IGraphic))
  67. {
  68. // Load all needed content
  69. background = new Material2D("SpaceBackground");
  70. block = new Material2DColored("BreakoutBlock");
  71. paddle = new Material2D("Paddle");
  72. ball = new Material2DColored("Ball");
  73. sound = new Sound("DefaultSound");
  74. //disabled: music = new Music("DefaultMusic");
  75. lastBallPositions = new List<Point>();
  76. board = new Board();
  77. Settings.Extra.LimitFramerateNumber = 60;
  78. oldScore = MathHelper.InvalidIndex;
  79. scoreTextArea = Rectangle.FromCenter(0.5f, 0.6f, 0.25f, 0.05f);
  80. gameOverTextArea = Rectangle.FromCenter(0.5f, 0.25f, 0.15f, 0.05f);
  81. tryAgainTextArea = Rectangle.FromCenter(0.5f, 0.4f, 0.15f, 0.05f);
  82. yesTextArea = Rectangle.FromCenter(0.25f, 0.75f, 0.1f, 0.05f);
  83. noTextArea = Rectangle.FromCenter(0.75f, 0.75f, 0.1f, 0.05f);
  84. RegisterInputCommands();
  85. }
  86. #endregion
  87. #region RegisterInputCommands
  88. /// <summary>
  89. /// Register input commands
  90. /// </summary>
  91. private void RegisterInputCommands()
  92. {
  93. // Restart game
  94. Input.Commands[CommandYesNoClick].Add(this,
  95. delegate(CommandTrigger trigger)
  96. {
  97. // Check if the player wants to replay
  98. if (yesTextArea.Contains(trigger.Position))
  99. {
  100. sound.Play();
  101. board.StartGame();
  102. board.GameOver = false;
  103. }
  104. // or just quit the game now
  105. if (noTextArea.Contains(trigger.Position))
  106. {
  107. sound.Play();
  108. Application.Quit();
  109. }
  110. });
  111. // Quit game
  112. Input.Commands[CommandQuitGame].Add(this, delegate
  113. {
  114. Application.Quit();
  115. });
  116. }
  117. #endregion
  118. #region Run (override)
  119. /// <summary>
  120. /// Run
  121. /// </summary>
  122. public override void Run()
  123. {
  124. // Render background (resolution independent)
  125. background.Draw(Rectangle.One);
  126. Font textFont = Font.Default;
  127. if (board.GameOver)
  128. {
  129. #region Game over menu
  130. textFont.Draw("Game over", gameOverTextArea);
  131. textFont.Draw("Try again?", tryAgainTextArea);
  132. textFont.Draw("Score: " + board.Score, scoreTextArea);
  133. textFont.Draw("Yes", yesTextArea);
  134. textFont.Draw("No", noTextArea);
  135. #endregion
  136. }
  137. else
  138. {
  139. Rectangle drawArea = ScreenSpace.DrawArea;
  140. #region Ingame
  141. board.UpdateGame();
  142. // Use the score to detect if we had some collision
  143. if (oldScore != board.Score)
  144. {
  145. // Initialization?
  146. if (oldScore == MathHelper.InvalidIndex)
  147. {
  148. //disabled: music.Looping = true;
  149. //disabled: music.Play();
  150. }
  151. // If this was just a paddle collision (1 score), use less volume
  152. sound.Volume = (board.Score == oldScore + 1) ? 0.5f : 1.0f;
  153. sound.Play();
  154. oldScore = board.Score;
  155. }
  156. // Render all blocks with their color
  157. for (int x = 0; x < board.Level; x++)
  158. {
  159. for (int y = 0; y < board.Level; y++)
  160. {
  161. Brick brick = board.Bricks[x, y];
  162. if (brick.IsDead == false)
  163. {
  164. block.BlendColor = brick.Color;
  165. block.Draw(drawArea.GetInnerRectangle(brick.Bounds));
  166. } // if
  167. } // for
  168. } // for
  169. // Remaining Lives text rendering
  170. string livesString = "Lives: " + board.Lives;
  171. Size livesStringSize = textFont.Measure(livesString);
  172. textFont.Draw(livesString, new Rectangle(drawArea.BottomLeft +
  173. new Point(0.005f, -livesStringSize.Height), livesStringSize));
  174. // Scores Rendering
  175. string scoreString = "Score: " + board.Score;
  176. Size scoreStringSize = textFont.Measure(scoreString);
  177. textFont.Draw(scoreString, new Rectangle(drawArea.BottomRight -
  178. scoreStringSize - new Point(0.005f, 0.0f), scoreStringSize));
  179. // And finally the bonus for each hit in the middle
  180. textFont.Draw("Bonus: " + board.DestroyedBlocks,
  181. new Rectangle(0.0f, drawArea.Bottom - textFont.LineHeight, 1.0f,
  182. textFont.LineHeight));
  183. // Render the paddle itself
  184. Size ballSize = new Size(board.Ball.Radius, board.Ball.Radius);
  185. paddle.Draw(drawArea.GetInnerRectangle(
  186. new Rectangle(board.PlayerPaddle.Position -
  187. new Size(board.PlayerPaddle.Size.WidthHalf,
  188. -ballSize.Height * 0.5f),
  189. board.PlayerPaddle.Size)));
  190. // And finally draw the animated ball with trail
  191. //TODO: add better trail (maybe as effect)
  192. //if (lastBallPositions.Count > 10)
  193. //{
  194. // // Remove first if we have more than 10 ball trail positions
  195. // lastBallPositions.RemoveAt(0);
  196. //}
  197. //lastBallPositions.Add(board.Ball.Position);
  198. //// Draw all trails (0-9, in the first frames we will have less)
  199. //for (int num = 0; num < lastBallPositions.Count; num++)
  200. //{
  201. Rectangle ballRect = drawArea.GetInnerRectangle(
  202. //new Rectangle(lastBallPositions[num] - ballSize,
  203. new Rectangle(board.Ball.Position - ballSize, ballSize * 2));
  204. // Set size back to quadratic space for the correct aspect ratio
  205. //float trailAlpha = (num + 1) / 10.0f;
  206. ballRect.Size = ballSize * 2;// * trailAlpha;
  207. //ballRect.Position -= ballSize * 2 * trailAlpha / 2.0f;
  208. //ball.BlendColor = new Color(Color.White, trailAlpha);
  209. ball.Draw(ballRect);
  210. //}
  211. #endregion
  212. }
  213. }
  214. #endregion
  215. }
  216. }