SafeAreaGame.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // SafeAreaGame.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using Microsoft.Xna.Framework;
  11. using Microsoft.Xna.Framework.Graphics;
  12. using Microsoft.Xna.Framework.Input;
  13. #endregion
  14. namespace SafeArea
  15. {
  16. /// <summary>
  17. /// Sample showing how to handle television safe areas in an XNA Framework game.
  18. /// </summary>
  19. public class SafeAreaGame : Microsoft.Xna.Framework.Game
  20. {
  21. #region Fields
  22. const int ScreenWidth = 1280;
  23. const int ScreenHeight = 720;
  24. GraphicsDeviceManager graphics;
  25. SafeAreaOverlay safeAreaOverlay;
  26. AlignedSpriteBatch spriteBatch;
  27. SpriteFont font;
  28. Texture2D catTexture;
  29. Texture2D backgroundTexture;
  30. Vector2 catPosition;
  31. Vector2 catVelocity;
  32. Vector2 cameraPosition;
  33. KeyboardState currentKeyboardState;
  34. GamePadState currentGamePadState;
  35. KeyboardState previousKeyboardState;
  36. GamePadState previousGamePadState;
  37. #endregion
  38. #region Initialization
  39. public SafeAreaGame()
  40. {
  41. Content.RootDirectory = "Content";
  42. graphics = new GraphicsDeviceManager(this);
  43. graphics.PreferredBackBufferWidth = ScreenWidth;
  44. graphics.PreferredBackBufferHeight = ScreenHeight;
  45. // In debug Xbox builds, we add a SafeAreaOverlay so we can easily
  46. // check whether our important graphics are positioned inside the
  47. // title safe area. But we don't bother with this on other platforms
  48. // (where the entire screen is safe) or in release mode builds
  49. // (because we don't want it to show up in the finished game).
  50. #if XBOX && DEBUG
  51. safeAreaOverlay = new SafeAreaOverlay(this);
  52. Components.Add(safeAreaOverlay);
  53. #else
  54. safeAreaOverlay = null;
  55. #endif
  56. }
  57. /// <summary>
  58. /// Load your graphics content.
  59. /// </summary>
  60. protected override void LoadContent()
  61. {
  62. spriteBatch = new AlignedSpriteBatch(GraphicsDevice);
  63. font = Content.Load<SpriteFont>("Font");
  64. catTexture = Content.Load<Texture2D>("Cat");
  65. backgroundTexture = Content.Load<Texture2D>("Background");
  66. }
  67. #endregion
  68. #region Update and Draw
  69. /// <summary>
  70. /// Allows the game to run logic.
  71. /// </summary>
  72. protected override void Update(GameTime gameTime)
  73. {
  74. HandleInput();
  75. UpdateCat();
  76. UpdateCamera();
  77. base.Update(gameTime);
  78. }
  79. /// <summary>
  80. /// Moves the cat sprite around the screen.
  81. /// </summary>
  82. void UpdateCat()
  83. {
  84. const float speedOfCat = 0.75f;
  85. const float catFriction = 0.9f;
  86. // Apply gamepad input.
  87. Vector2 flipY = new Vector2(1, -1);
  88. catVelocity += currentGamePadState.ThumbSticks.Left * flipY * speedOfCat;
  89. // Apply keyboard input.
  90. if (currentKeyboardState.IsKeyDown(Keys.Left))
  91. catVelocity.X -= speedOfCat;
  92. if (currentKeyboardState.IsKeyDown(Keys.Right))
  93. catVelocity.X += speedOfCat;
  94. if (currentKeyboardState.IsKeyDown(Keys.Up))
  95. catVelocity.Y -= speedOfCat;
  96. if (currentKeyboardState.IsKeyDown(Keys.Down))
  97. catVelocity.Y += speedOfCat;
  98. // Apply velocity and friction.
  99. catPosition += catVelocity;
  100. catVelocity *= catFriction;
  101. }
  102. /// <summary>
  103. /// Updates the camera position, scrolling the
  104. /// screen if the cat gets too close to the edge.
  105. /// </summary>
  106. void UpdateCamera()
  107. {
  108. // How far away from the camera should we allow the cat
  109. // to move before we scroll the camera to follow it?
  110. Vector2 maxScroll = new Vector2(ScreenWidth, ScreenHeight) / 2;
  111. // Apply a safe area to prevent the cat getting too close to the edge
  112. // of the screen. Note that this is even more restrictive than the 80%
  113. // safe area used for the overlays, because we want to start scrolling
  114. // even before the cat gets right up to the edge of the legal area.
  115. const float catSafeArea = 0.7f;
  116. maxScroll *= catSafeArea;
  117. // Adjust for the size of the cat sprite, so we will start
  118. // scrolling based on the edge rather than center of the cat.
  119. maxScroll -= new Vector2(catTexture.Width, catTexture.Height) / 2;
  120. // Make sure the camera stays within the desired distance of the cat.
  121. Vector2 min = catPosition - maxScroll;
  122. Vector2 max = catPosition + maxScroll;
  123. cameraPosition.X = MathHelper.Clamp(cameraPosition.X, min.X, max.X);
  124. cameraPosition.Y = MathHelper.Clamp(cameraPosition.Y, min.Y, max.Y);
  125. }
  126. /// <summary>
  127. /// This is called when the game should draw itself.
  128. /// </summary>
  129. protected override void Draw(GameTime gameTime)
  130. {
  131. GraphicsDevice.Clear(Color.Black);
  132. // Work out how far to scroll based on the current camera position.
  133. Vector2 screenCenter = new Vector2(ScreenWidth, ScreenHeight) / 2;
  134. Vector2 scrollOffset = screenCenter - cameraPosition;
  135. // Draw the background, cat, and text overlays.
  136. spriteBatch.Begin();
  137. DrawBackground(scrollOffset);
  138. DrawCat(scrollOffset);
  139. DrawOverlays();
  140. spriteBatch.End();
  141. base.Draw(gameTime);
  142. }
  143. /// <summary>
  144. /// Draws the repeating background texture.
  145. /// </summary>
  146. void DrawBackground(Vector2 scrollOffset)
  147. {
  148. // Work out the position of the top left visible tile.
  149. int tileX = (int)scrollOffset.X % backgroundTexture.Width;
  150. int tileY = (int)scrollOffset.Y % backgroundTexture.Height;
  151. if (tileX > 0)
  152. tileX -= backgroundTexture.Width;
  153. if (tileY > 0)
  154. tileY -= backgroundTexture.Height;
  155. // Draw however many repeating tiles are needed to cover the screen.
  156. for (int x = tileX; x < ScreenWidth; x += backgroundTexture.Width)
  157. {
  158. for (int y = tileY; y < ScreenHeight; y += backgroundTexture.Height)
  159. {
  160. spriteBatch.Draw(backgroundTexture, new Vector2(x, y), Color.White);
  161. }
  162. }
  163. }
  164. /// <summary>
  165. /// Draws the cat sprite.
  166. /// </summary>
  167. void DrawCat(Vector2 scrollOffset)
  168. {
  169. Vector2 catCenter = new Vector2(catTexture.Width, catTexture.Height) / 2;
  170. Vector2 position = catPosition - catCenter + scrollOffset;
  171. spriteBatch.Draw(catTexture, position, Color.White);
  172. }
  173. /// <summary>
  174. /// Draws text overlays on top of the game graphics.
  175. /// </summary>
  176. void DrawOverlays()
  177. {
  178. Rectangle safeArea = GraphicsDevice.Viewport.TitleSafeArea;
  179. // Draw labels in the four corners of the screen,
  180. // aligned to the edges of the safe area.
  181. spriteBatch.DrawString(font, "Top Left",
  182. new Vector2(safeArea.Left, safeArea.Top),
  183. Color.White, Alignment.TopLeft);
  184. spriteBatch.DrawString(font, "Top Right",
  185. new Vector2(safeArea.Right, safeArea.Top),
  186. Color.White, Alignment.TopRight);
  187. spriteBatch.DrawString(font, "Bottom Left",
  188. new Vector2(safeArea.Left, safeArea.Bottom),
  189. Color.White, Alignment.BottomLeft);
  190. spriteBatch.DrawString(font, "Bottom Right",
  191. new Vector2(safeArea.Right, safeArea.Bottom),
  192. Color.White, Alignment.BottomRight);
  193. // Draw a prompt saying how to toggle the safe area overlay.
  194. if (safeAreaOverlay != null)
  195. {
  196. spriteBatch.DrawString(font, "Press A to toggle the safe area overlay",
  197. new Vector2(safeArea.Center.X, safeArea.Top),
  198. Color.White, Alignment.TopCenter);
  199. }
  200. }
  201. #endregion
  202. #region Handle Input
  203. /// <summary>
  204. /// Handles input for quitting the game and toggling the safe area overlay.
  205. /// </summary>
  206. private void HandleInput()
  207. {
  208. previousKeyboardState = currentKeyboardState;
  209. previousGamePadState = currentGamePadState;
  210. currentKeyboardState = Keyboard.GetState();
  211. currentGamePadState = GamePad.GetState(PlayerIndex.One);
  212. // Check for exit.
  213. if (currentKeyboardState.IsKeyDown(Keys.Escape) ||
  214. currentGamePadState.IsButtonDown(Buttons.Back))
  215. {
  216. Exit();
  217. }
  218. // Check for showing or hiding the safe area overlay.
  219. if (safeAreaOverlay != null)
  220. {
  221. if ((currentKeyboardState.IsKeyDown(Keys.A) &&
  222. previousKeyboardState.IsKeyUp(Keys.A)) ||
  223. (currentGamePadState.IsButtonDown(Buttons.A) &&
  224. previousGamePadState.IsButtonUp(Buttons.A)))
  225. {
  226. safeAreaOverlay.Visible = !safeAreaOverlay.Visible;
  227. }
  228. }
  229. }
  230. #endregion
  231. }
  232. #region Entry Point
  233. /// <summary>
  234. /// The main entry point for the application.
  235. /// </summary>
  236. static class Program
  237. {
  238. static void Main()
  239. {
  240. using (SafeAreaGame game = new SafeAreaGame())
  241. {
  242. game.Run();
  243. }
  244. }
  245. }
  246. #endregion
  247. }