#region File Description //----------------------------------------------------------------------------- // SafeAreaGame.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; #endregion namespace SafeArea { /// /// Sample showing how to handle television safe areas in an XNA Framework game. /// public class SafeAreaGame : Microsoft.Xna.Framework.Game { #region Fields const int ScreenWidth = 1280; const int ScreenHeight = 720; GraphicsDeviceManager graphics; SafeAreaOverlay safeAreaOverlay; AlignedSpriteBatch spriteBatch; SpriteFont font; Texture2D catTexture; Texture2D backgroundTexture; Vector2 catPosition; Vector2 catVelocity; Vector2 cameraPosition; KeyboardState currentKeyboardState; GamePadState currentGamePadState; KeyboardState previousKeyboardState; GamePadState previousGamePadState; #endregion #region Initialization public SafeAreaGame() { Content.RootDirectory = "Content"; graphics = new GraphicsDeviceManager(this); graphics.PreferredBackBufferWidth = ScreenWidth; graphics.PreferredBackBufferHeight = ScreenHeight; // In debug Xbox builds, we add a SafeAreaOverlay so we can easily // check whether our important graphics are positioned inside the // title safe area. But we don't bother with this on other platforms // (where the entire screen is safe) or in release mode builds // (because we don't want it to show up in the finished game). #if XBOX && DEBUG safeAreaOverlay = new SafeAreaOverlay(this); Components.Add(safeAreaOverlay); #else safeAreaOverlay = null; #endif } /// /// Load your graphics content. /// protected override void LoadContent() { spriteBatch = new AlignedSpriteBatch(GraphicsDevice); font = Content.Load("Font"); catTexture = Content.Load("Cat"); backgroundTexture = Content.Load("Background"); } #endregion #region Update and Draw /// /// Allows the game to run logic. /// protected override void Update(GameTime gameTime) { HandleInput(); UpdateCat(); UpdateCamera(); base.Update(gameTime); } /// /// Moves the cat sprite around the screen. /// void UpdateCat() { const float speedOfCat = 0.75f; const float catFriction = 0.9f; // Apply gamepad input. Vector2 flipY = new Vector2(1, -1); catVelocity += currentGamePadState.ThumbSticks.Left * flipY * speedOfCat; // Apply keyboard input. if (currentKeyboardState.IsKeyDown(Keys.Left)) catVelocity.X -= speedOfCat; if (currentKeyboardState.IsKeyDown(Keys.Right)) catVelocity.X += speedOfCat; if (currentKeyboardState.IsKeyDown(Keys.Up)) catVelocity.Y -= speedOfCat; if (currentKeyboardState.IsKeyDown(Keys.Down)) catVelocity.Y += speedOfCat; // Apply velocity and friction. catPosition += catVelocity; catVelocity *= catFriction; } /// /// Updates the camera position, scrolling the /// screen if the cat gets too close to the edge. /// void UpdateCamera() { // How far away from the camera should we allow the cat // to move before we scroll the camera to follow it? Vector2 maxScroll = new Vector2(ScreenWidth, ScreenHeight) / 2; // Apply a safe area to prevent the cat getting too close to the edge // of the screen. Note that this is even more restrictive than the 80% // safe area used for the overlays, because we want to start scrolling // even before the cat gets right up to the edge of the legal area. const float catSafeArea = 0.7f; maxScroll *= catSafeArea; // Adjust for the size of the cat sprite, so we will start // scrolling based on the edge rather than center of the cat. maxScroll -= new Vector2(catTexture.Width, catTexture.Height) / 2; // Make sure the camera stays within the desired distance of the cat. Vector2 min = catPosition - maxScroll; Vector2 max = catPosition + maxScroll; cameraPosition.X = MathHelper.Clamp(cameraPosition.X, min.X, max.X); cameraPosition.Y = MathHelper.Clamp(cameraPosition.Y, min.Y, max.Y); } /// /// This is called when the game should draw itself. /// protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.Black); // Work out how far to scroll based on the current camera position. Vector2 screenCenter = new Vector2(ScreenWidth, ScreenHeight) / 2; Vector2 scrollOffset = screenCenter - cameraPosition; // Draw the background, cat, and text overlays. spriteBatch.Begin(); DrawBackground(scrollOffset); DrawCat(scrollOffset); DrawOverlays(); spriteBatch.End(); base.Draw(gameTime); } /// /// Draws the repeating background texture. /// void DrawBackground(Vector2 scrollOffset) { // Work out the position of the top left visible tile. int tileX = (int)scrollOffset.X % backgroundTexture.Width; int tileY = (int)scrollOffset.Y % backgroundTexture.Height; if (tileX > 0) tileX -= backgroundTexture.Width; if (tileY > 0) tileY -= backgroundTexture.Height; // Draw however many repeating tiles are needed to cover the screen. for (int x = tileX; x < ScreenWidth; x += backgroundTexture.Width) { for (int y = tileY; y < ScreenHeight; y += backgroundTexture.Height) { spriteBatch.Draw(backgroundTexture, new Vector2(x, y), Color.White); } } } /// /// Draws the cat sprite. /// void DrawCat(Vector2 scrollOffset) { Vector2 catCenter = new Vector2(catTexture.Width, catTexture.Height) / 2; Vector2 position = catPosition - catCenter + scrollOffset; spriteBatch.Draw(catTexture, position, Color.White); } /// /// Draws text overlays on top of the game graphics. /// void DrawOverlays() { Rectangle safeArea = GraphicsDevice.Viewport.TitleSafeArea; // Draw labels in the four corners of the screen, // aligned to the edges of the safe area. spriteBatch.DrawString(font, "Top Left", new Vector2(safeArea.Left, safeArea.Top), Color.White, Alignment.TopLeft); spriteBatch.DrawString(font, "Top Right", new Vector2(safeArea.Right, safeArea.Top), Color.White, Alignment.TopRight); spriteBatch.DrawString(font, "Bottom Left", new Vector2(safeArea.Left, safeArea.Bottom), Color.White, Alignment.BottomLeft); spriteBatch.DrawString(font, "Bottom Right", new Vector2(safeArea.Right, safeArea.Bottom), Color.White, Alignment.BottomRight); // Draw a prompt saying how to toggle the safe area overlay. if (safeAreaOverlay != null) { spriteBatch.DrawString(font, "Press A to toggle the safe area overlay", new Vector2(safeArea.Center.X, safeArea.Top), Color.White, Alignment.TopCenter); } } #endregion #region Handle Input /// /// Handles input for quitting the game and toggling the safe area overlay. /// private void HandleInput() { previousKeyboardState = currentKeyboardState; previousGamePadState = currentGamePadState; currentKeyboardState = Keyboard.GetState(); currentGamePadState = GamePad.GetState(PlayerIndex.One); // Check for exit. if (currentKeyboardState.IsKeyDown(Keys.Escape) || currentGamePadState.IsButtonDown(Buttons.Back)) { Exit(); } // Check for showing or hiding the safe area overlay. if (safeAreaOverlay != null) { if ((currentKeyboardState.IsKeyDown(Keys.A) && previousKeyboardState.IsKeyUp(Keys.A)) || (currentGamePadState.IsButtonDown(Buttons.A) && previousGamePadState.IsButtonUp(Buttons.A))) { safeAreaOverlay.Visible = !safeAreaOverlay.Visible; } } } #endregion } #region Entry Point /// /// The main entry point for the application. /// static class Program { static void Main() { using (SafeAreaGame game = new SafeAreaGame()) { game.Run(); } } } #endregion }