2
0

Menu.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Collections.Generic;
  5. using Microsoft.Xna.Framework;
  6. using Microsoft.Xna.Framework.Audio;
  7. using Microsoft.Xna.Framework.Content;
  8. using Microsoft.Xna.Framework.GamerServices;
  9. using Microsoft.Xna.Framework.Graphics;
  10. using Microsoft.Xna.Framework.Input;
  11. using Microsoft.Xna.Framework.Media;
  12. using Microsoft.Xna.Framework.Net;
  13. using Microsoft.Xna.Framework.Storage;
  14. namespace XNAPacMan {
  15. /// <summary>
  16. /// This is a game component that implements IUpdateable.
  17. /// </summary>
  18. /// Optionally takes a GameLoop argument, when the menu must be able to
  19. /// resume the current GameLoop. Otherwise, the reference would be lost
  20. /// and the gameLoop garbage collected.
  21. public class Menu : Microsoft.Xna.Framework.DrawableGameComponent {
  22. public Menu(Game game, GameLoop gameLoop)
  23. : base(game) {
  24. gameLoop_ = gameLoop;
  25. gameStart_ = (gameLoop == null);
  26. }
  27. /// <summary>
  28. /// Allows the game component to perform any initialization it needs to before starting
  29. /// to run. This is where it can query for any required services and load content.
  30. /// </summary>
  31. public override void Initialize() {
  32. spriteBatch_ = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
  33. graphics_ = (GraphicsDeviceManager)Game.Services.GetService(typeof(GraphicsDeviceManager));
  34. soundBank_ = (SoundBank)Game.Services.GetService(typeof(SoundBank));
  35. selection_ = 0;
  36. if (gameLoop_ == null) {
  37. items_ = new string[] { "New Game", "High Scores", "Quit" };
  38. }
  39. else {
  40. items_ = new string[] { "Resume", "Quit Game" };
  41. }
  42. menuItem_ = Game.Content.Load<SpriteFont>("MenuItem");
  43. title_ = Game.Content.Load<Texture2D>("sprites/Title");
  44. selectionArrow_ = Game.Content.Load<Texture2D>("sprites/Selection");
  45. oldState_ = Keyboard.GetState();
  46. base.Initialize();
  47. }
  48. /// <summary>
  49. /// Allows the game component to update itself.
  50. /// </summary>
  51. /// <param name="gameTime">Provides a snapshot of timing values.</param>
  52. public override void Update(GameTime gameTime) {
  53. base.Update(gameTime);
  54. // Wonder why we test for this condition? Just replace gameStart_ by true and
  55. // try running the game. The answer should be instantaneous.
  56. if (gameStart_) {
  57. soundBank_.PlayCue("NewLevel");
  58. gameStart_ = false;
  59. }
  60. KeyboardState newState = Keyboard.GetState();
  61. // Get keys pressed now that weren't pressed before
  62. var newPressedKeys = from k in newState.GetPressedKeys()
  63. where !(oldState_.GetPressedKeys().Contains(k))
  64. select k;
  65. // Scroll through menu items
  66. if (newPressedKeys.Contains(Keys.Down)) {
  67. selection_++;
  68. selection_ %= items_.Length;
  69. soundBank_.PlayCue("PacMAnEat1");
  70. }
  71. else if (newPressedKeys.Contains(Keys.Up)) {
  72. selection_--;
  73. selection_ = (selection_ < 0? items_.Length -1 : selection_);
  74. soundBank_.PlayCue("PacManEat2");
  75. }
  76. else if (newPressedKeys.Contains(Keys.Enter)) {
  77. menuAction();
  78. }
  79. // Update keyboard state for next update
  80. oldState_ = newState;
  81. }
  82. /// <summary>
  83. /// This is called when the game should draw itself.
  84. /// </summary>
  85. /// <param name="gameTime">Provides a snapshot of timing values.</param>
  86. public override void Draw(GameTime gameTime) {
  87. base.Draw(gameTime);
  88. // The menu is a main component, so it is responsible for initializing the sprite batch each frame
  89. spriteBatch_.Begin();
  90. // Draw title
  91. spriteBatch_.Draw(title_, new Vector2((graphics_.PreferredBackBufferWidth / 2) - (title_.Width / 2), 75), Color.White);
  92. // Draw items
  93. Vector2 itemPosition;
  94. itemPosition.X = (graphics_.PreferredBackBufferWidth / 2) - 100;
  95. for (int i = 0; i < items_.Length; i++) {
  96. itemPosition.Y = (graphics_.PreferredBackBufferHeight / 2) - 60 + (60 * i);
  97. if (i == selection_) {
  98. spriteBatch_.Draw(selectionArrow_, new Vector2(itemPosition.X - 50, itemPosition.Y), Color.White);
  99. }
  100. spriteBatch_.DrawString(menuItem_, items_[i], itemPosition, Color.Yellow);
  101. }
  102. spriteBatch_.End();
  103. }
  104. void menuAction() {
  105. Game.Components.Remove(this);
  106. switch (items_[selection_]) {
  107. case ("Resume"):
  108. Game.Components.Add(gameLoop_);
  109. break;
  110. case ("New Game") :
  111. Game.Components.Add(new GameLoop(Game));
  112. break;
  113. case ("High Scores"):
  114. Game.Components.Add(new HighScores(Game));
  115. break;
  116. case ("Quit"):
  117. Game.Exit();
  118. break;
  119. case ("Quit Game"):
  120. Game.Components.Add(new Menu(Game, null));
  121. SaveHighScore(gameLoop_.Score);
  122. break;
  123. default:
  124. throw new ArgumentException("\"" + items_[selection_] + "\" is not a valid case");
  125. }
  126. }
  127. /// <summary>
  128. /// Keep a history of the best 10 scores
  129. /// </summary>
  130. /// <param name="highScore">New score to save, might make it inside the list, might not.</param>
  131. public static void SaveHighScore(int highScore) {
  132. const string fileName = "highscores.txt";
  133. if (!File.Exists(fileName)) {
  134. File.WriteAllLines(fileName, new string[] { highScore.ToString() });
  135. }
  136. else {
  137. List<string> contents = File.ReadAllLines(fileName).ToList<string>();
  138. contents.Add(highScore.ToString());
  139. if (contents.Count >= 10) {
  140. contents.Sort((a, b) => Convert.ToInt32(a).CompareTo(Convert.ToInt32(b)));
  141. while (contents.Count > 10) {
  142. contents.RemoveAt(0);
  143. }
  144. }
  145. File.WriteAllLines(fileName, contents.ToArray());
  146. }
  147. }
  148. GameLoop gameLoop_;
  149. SoundBank soundBank_;
  150. GraphicsDeviceManager graphics_;
  151. SpriteBatch spriteBatch_;
  152. SpriteFont menuItem_;
  153. string[] items_;
  154. int selection_;
  155. bool gameStart_;
  156. Texture2D title_;
  157. Texture2D selectionArrow_;
  158. KeyboardState oldState_;
  159. }
  160. }