// Project: XnaPong, File: PongGame.cs // Namespace: XnaPong, Class: PongGame // Path: C:\code\XnaBook\XnaPong, Author: Abi // Code lines: 16, Size of file: 298 Bytes // Creation date: 18.11.2006 03:56 // Last modified: 19.11.2006 13:21 // Generated with Commenter by abi.exDream.com #region Using directives using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; #endregion namespace XnaPong { /// /// This is the main type for your game /// public class PongGame : Microsoft.Xna.Framework.Game { #region Constants /// /// Rectangles for our graphics, tested with the unit tests below. /// static readonly Rectangle XnaPongLogoRect = new Rectangle(0, 0, 512, 110), MenuSingleplayerRect = new Rectangle(0, 110, 512, 38), MenuMultiplayerRect = new Rectangle(0, 148, 512, 38), MenuExitRect = new Rectangle(0, 185, 512, 38), GameLivesRect = new Rectangle(0, 222, 100, 34), GameRedWonRect = new Rectangle(151, 222, 155, 34), GameBlueWonRect = new Rectangle(338, 222, 165, 34), GameRedPaddleRect = new Rectangle(23, 0, 22, 92), GameBluePaddleRect = new Rectangle(0, 0, 22, 92), GameBallRect = new Rectangle(1, 94, 33, 33), GameSmallBallRect = new Rectangle(37, 108, 19, 19); /// /// Ball speed multiplicator, this is how much screen space the ball will /// travel each second. /// const float BallSpeedMultiplicator = 0.5f; /// /// Computer paddle speed. If the ball moves faster up or down than this, /// the computer paddle can't keep up and finally we will win. /// const float ComputerPaddleSpeed = 0.5f;//25f; /// /// Game modes /// enum GameMode { Menu, Game, GameOver, } // enum GameMode #endregion #region Variables GraphicsDeviceManager graphics; ContentManager content; Texture2D backgroundTexture, menuTexture, gameTexture; AudioEngine audioEngine; WaveBank waveBank; SoundBank soundBank; /// /// Resolution of our game. /// int width, height; /// /// Current paddle positions, 0 means top, 1 means bottom. /// float leftPaddlePosition = 0.5f, rightPaddlePosition = 0.5f; /// /// Current ball position, again from 0 to 1, 0 is left and top, /// 1 is bottom and right. /// Vector2 ballPosition = new Vector2(0.5f, 0.5f); /// /// Ball speed vector, randomized for every new ball. /// Will be set to Zero if we are in menu or game is over. /// Vector2 ballSpeedVector = new Vector2(0, 0);//1); /// /// Life for left and right players. If one player has 0 lives left, /// the other one wins. /// int leftPlayerLives = 3, rightPlayerLives = 3; /// /// Are we playing a multiplayer game? If this is false, the computer /// controls the left paddle. /// bool multiplayer = false; /// /// Game mode we are currently in. Very simple game flow. /// GameMode gameMode = GameMode.Menu; /// /// Currently selected menu item. /// int currentMenuItem = 0; #endregion #region Constructor /// /// Create pong game /// public PongGame() { graphics = new GraphicsDeviceManager(this); content = new ContentManager(Services); } // PongGame() /// /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// protected override void Initialize() { // Remember resolution width = graphics.GraphicsDevice.Viewport.Width; height = graphics.GraphicsDevice.Viewport.Height; base.Initialize(); } // Initialize() /// /// Load all graphics content (just our background texture). /// Use this method to make sure a device reset event is handled correctly. /// /// Load everything? protected override void LoadGraphicsContent(bool loadAllContent) { if (loadAllContent) { // Create sprite batch spriteBatch = new SpriteBatch(graphics.GraphicsDevice); // Load all our content backgroundTexture = content.Load("SpaceBackground"); menuTexture = content.Load("PongMenu"); gameTexture = content.Load("PongGame"); audioEngine = new AudioEngine("PongSound.xgs"); waveBank = new WaveBank(audioEngine, "Wave Bank.xwb"); if (waveBank != null) soundBank = new SoundBank(audioEngine, "Sound Bank.xsb"); } // if base.LoadGraphicsContent(loadAllContent); } // LoadGraphicsContent(loadAllContent) /// /// Unload graphic content if the device gets lost. /// /// Unload everything? protected override void UnloadGraphicsContent(bool unloadAllContent) { if (unloadAllContent == true) content.Unload(); base.UnloadGraphicsContent(unloadAllContent); } // UnloadGraphicsContent(loadAllContent) #endregion #region Start and stop ball /// /// Start new ball at the beginning of each game and when a ball is lost. /// public void StartNewBall() { ballPosition = new Vector2(0.5f, 0.5f); Random rnd = new Random((int)DateTime.Now.Ticks); int direction = rnd.Next(4); ballSpeedVector = direction == 0 ? new Vector2(1, 0.8f) : direction == 1 ? new Vector2(1, -0.8f) : direction == 2 ? new Vector2(-1, 0.8f) : new Vector2(-1, -0.8f); } // StartNewBall() /// /// Stop ball for menu and when game is over. /// public void StopBall() { ballSpeedVector = new Vector2(0, 0); } // StopBall #endregion #region Update /// /// Game pad and keyboard states for full 2 player support. /// GamePadState gamePad, gamePad2; KeyboardState keyboard; /// /// Remember up, down, start and back buttons for the menu. /// bool remUpPressed = false, remDownPressed = false, remSpaceOrStartPressed = false, remEscOrBackPressed = false; /// /// Store up/down states and include thumbstick to control paddles. /// bool gamePadUp = false, gamePadDown = false, gamePad2Up = false, gamePad2Down = false; /// /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input and playing audio. /// /// Provides a snapshot of timing values. protected override void Update(GameTime gameTime) { // Remember last keyboard and gamepad states for the menu remUpPressed = gamePad.DPad.Up == ButtonState.Pressed || gamePad.ThumbSticks.Left.Y > 0.5f || keyboard.IsKeyDown(Keys.Up); remDownPressed = gamePad.DPad.Down == ButtonState.Pressed || gamePad.ThumbSticks.Left.Y < -0.5f || keyboard.IsKeyDown(Keys.Down); remSpaceOrStartPressed = gamePad.Buttons.Start == ButtonState.Pressed || gamePad.Buttons.A == ButtonState.Pressed || keyboard.IsKeyDown(Keys.LeftControl) || keyboard.IsKeyDown(Keys.RightControl) || keyboard.IsKeyDown(Keys.Space) || keyboard.IsKeyDown(Keys.Enter); remEscOrBackPressed = gamePad.Buttons.Back == ButtonState.Pressed || keyboard.IsKeyDown(Keys.Escape); // Get current gamepad and keyboard states gamePad = GamePad.GetState(PlayerIndex.One); gamePad2 = GamePad.GetState(PlayerIndex.Two); keyboard = Keyboard.GetState(); gamePadUp = gamePad.DPad.Up == ButtonState.Pressed || gamePad.ThumbSticks.Left.Y > 0.5f; gamePadDown = gamePad.DPad.Down == ButtonState.Pressed || gamePad.ThumbSticks.Left.Y < -0.5f; gamePad2Up = gamePad2.DPad.Up == ButtonState.Pressed || gamePad2.ThumbSticks.Left.Y > 0.5f; gamePad2Down = gamePad2.DPad.Down == ButtonState.Pressed || gamePad2.ThumbSticks.Left.Y < -0.5f; // Move half way across the screen each second float moveFactorPerSecond = 0.5f * (float)gameTime.ElapsedRealTime.TotalMilliseconds / 1000.0f; // Move up and down if we press the cursor or gamepad keys. if (gamePadUp || keyboard.IsKeyDown(Keys.Up)) rightPaddlePosition -= moveFactorPerSecond; if (gamePadDown || keyboard.IsKeyDown(Keys.Down)) rightPaddlePosition += moveFactorPerSecond; // Second player is either controlled by player 2 or by the computer if (multiplayer) { // Move up and down if we press the cursor or gamepad keys. if (gamePad2Up || keyboard.IsKeyDown(Keys.W)) leftPaddlePosition -= moveFactorPerSecond; if (gamePad2Down || keyboard.IsKeyDown(Keys.S) || keyboard.IsKeyDown(Keys.O)) leftPaddlePosition += moveFactorPerSecond; } // if else { // Just let the computer follow the ball position float computerChange = ComputerPaddleSpeed * moveFactorPerSecond; if (leftPaddlePosition > ballPosition.Y + computerChange) leftPaddlePosition -= computerChange; else if (leftPaddlePosition < ballPosition.Y - computerChange) leftPaddlePosition += computerChange; } // else // Make sure paddles stay between 0 and 1 if (leftPaddlePosition < 0) leftPaddlePosition = 0; if (leftPaddlePosition > 1) leftPaddlePosition = 1; if (rightPaddlePosition < 0) rightPaddlePosition = 0; if (rightPaddlePosition > 1) rightPaddlePosition = 1; // Ball is stopped and we are in the game? Then start it again. if (ballSpeedVector.LengthSquared() == 0 && gameMode == GameMode.Game) StartNewBall(); // Check top and bottom screen border if (ballPosition.Y < 0 || ballPosition.Y > 1) { ballSpeedVector.Y = -ballSpeedVector.Y; soundBank.PlayCue("PongBallHit"); } // if // Check for collisions with the paddles // Construct bounding boxes to use the intersection helper method. Vector2 ballSize = new Vector2( GameBallRect.Width / 1024.0f, GameBallRect.Height / 768.0f); BoundingBox ballBox = new BoundingBox( new Vector3(ballPosition.X-ballSize.X/2, ballPosition.Y-ballSize.Y/2, 0), new Vector3(ballPosition.X+ballSize.X/2, ballPosition.Y+ballSize.Y/2, 0)); Vector2 paddleSize = new Vector2( GameRedPaddleRect.Width / 1024.0f, GameRedPaddleRect.Height / 768.0f); BoundingBox leftPaddleBox = new BoundingBox( new Vector3(-paddleSize.X/2, leftPaddlePosition-paddleSize.Y/2, 0), new Vector3(+paddleSize.X/2, leftPaddlePosition+paddleSize.Y/2, 0)); BoundingBox rightPaddleBox = new BoundingBox( new Vector3(1-paddleSize.X/2, rightPaddlePosition-paddleSize.Y/2, 0), new Vector3(1+paddleSize.X/2, rightPaddlePosition+paddleSize.Y/2, 0)); // Ball hit left paddle? if (ballBox.Intersects(leftPaddleBox)) { // Bounce of the paddle (always make positive) ballSpeedVector.X = Math.Abs(ballSpeedVector.X); // Increase speed a little ballSpeedVector *= 1.05f; // Did we hit the edges of the paddle? if (ballBox.Intersects(new BoundingBox( new Vector3(leftPaddleBox.Min.X-0.01f, leftPaddleBox.Min.Y-0.01f, 0), new Vector3(leftPaddleBox.Min.X+0.01f, leftPaddleBox.Min.Y+0.01f, 0)))) // Bounce of at a more difficult angle for the other player ballSpeedVector.Y = -2; else if (ballBox.Intersects(new BoundingBox( new Vector3(leftPaddleBox.Min.X-0.01f, leftPaddleBox.Max.Y-0.01f, 0), new Vector3(leftPaddleBox.Min.X+0.01f, leftPaddleBox.Max.Y+0.01f, 0)))) // Bounce of at a more difficult angle for the other player ballSpeedVector.Y = +2; // Play sound soundBank.PlayCue("PongBallHit"); } // if // Ball hit right paddle? if (ballBox.Intersects(rightPaddleBox)) { // Bounce of the paddle (always make negative) ballSpeedVector.X = -Math.Abs(ballSpeedVector.X); // Increase speed a little ballSpeedVector *= 1.05f; // Did we hit the edges of the paddle? if (ballBox.Intersects(new BoundingBox( new Vector3(rightPaddleBox.Min.X-0.01f, rightPaddleBox.Min.Y-0.01f, 0), new Vector3(rightPaddleBox.Min.X+0.01f, rightPaddleBox.Min.Y+0.01f, 0)))) // Bounce of at a more difficult angle for the other player ballSpeedVector.Y = -2; else if (ballBox.Intersects(new BoundingBox( new Vector3(rightPaddleBox.Min.X-0.01f, rightPaddleBox.Max.Y-0.01f, 0), new Vector3(rightPaddleBox.Min.X+0.01f, rightPaddleBox.Max.Y+0.01f, 0)))) // Bounce of at a more difficult angle for the other player ballSpeedVector.Y = +2; // Play sound soundBank.PlayCue("PongBallHit"); } // if // Update ball position and bounce off the borders ballPosition += ballSpeedVector * moveFactorPerSecond * BallSpeedMultiplicator; // Ball lost? if (ballPosition.X < -0.065f) { // Play sound soundBank.PlayCue("PongBallLost"); // Reduce number of lives leftPlayerLives--; // Start new ball StartNewBall(); } // if else if (ballPosition.X > 1.065f) { // Play sound soundBank.PlayCue("PongBallLost"); // Reduce number of lives rightPlayerLives--; // Start new ball StartNewBall(); } // if // If either player has no more lives, the other one has won! if (gameMode == GameMode.Game && (leftPlayerLives == 0 || rightPlayerLives == 0)) { gameMode = GameMode.GameOver; StopBall(); } // if base.Update(gameTime); } // Update(gameTime) #endregion #region Sprite handling class SpriteToRender { public Texture2D texture; public Rectangle rect; public Rectangle? sourceRect; public Color color; public SpriteToRender(Texture2D setTexture, Rectangle setRect, Rectangle? setSourceRect, Color setColor) { texture = setTexture; rect = setRect; sourceRect = setSourceRect; color = setColor; } // SpriteToRender(setTexture, setRect, setColor) } // SpriteToRender List sprites = new List(); SpriteBatch spriteBatch = null; public void RenderSprite(Texture2D texture, Rectangle rect, Rectangle? sourceRect, Color color) { sprites.Add(new SpriteToRender(texture, rect, sourceRect, color)); } // RenderSprite(texture, rect, sourceRect, color) public void RenderSprite(Texture2D texture, Rectangle rect, Rectangle? sourceRect) { RenderSprite(texture, rect, sourceRect, Color.White); } // RenderSprite(texture, rect, sourceRect) public void RenderSprite(Texture2D texture, int x, int y, Rectangle? sourceRect, Color color) { RenderSprite(texture, new Rectangle(x, y, sourceRect.Value.Width, sourceRect.Value.Height), sourceRect, color); } // RenderSprite(texture, rect, sourceRect) public void RenderSprite(Texture2D texture, int x, int y, Rectangle? sourceRect) { RenderSprite(texture, new Rectangle(x, y, sourceRect.Value.Width, sourceRect.Value.Height), sourceRect, Color.White); } // RenderSprite(texture, rect, sourceRect) public void RenderSprite(Texture2D texture, Rectangle rect, Color color) { RenderSprite(texture, rect, null, color); } // RenderSprite(texture, rect, color) public void RenderSprite(Texture2D texture, Rectangle rect) { RenderSprite(texture, rect, null, Color.White); } // RenderSprite(texture, rect) public void RenderSprite(Texture2D texture) { RenderSprite(texture, new Rectangle(0, 0, 1024, 768), null, Color.White); } // RenderSprite(texture) public void DrawSprites() { // No need to render if we got no sprites this frame if (sprites.Count == 0) return; // Start rendering sprites spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.None); // Render all sprites foreach (SpriteToRender sprite in sprites) spriteBatch.Draw(sprite.texture, // Rescale to fit resolution new Rectangle( sprite.rect.X * width / 1024, sprite.rect.Y * height / 768, sprite.rect.Width * width / 1024, sprite.rect.Height * height / 768), sprite.sourceRect, sprite.color); // We are done, draw everything on screen with help of the end method. spriteBatch.End(); // Kill list of remembered sprites sprites.Clear(); } // DrawSprites() #endregion #region Render ball and paddles public void RenderBall() { RenderSprite(gameTexture, (int)((0.05f+0.9f*ballPosition.X)*1024)-GameBallRect.Width/2, (int)((0.02f+0.96f*ballPosition.Y)*768)-GameBallRect.Height/2, GameBallRect); } // RenderBall() public void RenderPaddles() { RenderSprite(gameTexture, (int)(0.05f*1024)-GameRedPaddleRect.Width/2, (int)((0.06f+0.88f*leftPaddlePosition)*768)-GameRedPaddleRect.Height/2, GameRedPaddleRect); RenderSprite(gameTexture, (int)(0.95f*1024)-GameBluePaddleRect.Width/2, (int)((0.06f+0.88f*rightPaddlePosition)*768)-GameBluePaddleRect.Height/2, GameBluePaddleRect); } // RenderPaddle(leftPaddle) public void ShowLives() { // Support for both Windows monitors and TV screens on the Xbox 360! int xPos = 2; int yPos = 2; #if XBOX360 xPos += Window.ClientBounds.Width / 24; yPos += Window.ClientBounds.Height / 24; #endif // Left players lives RenderSprite(menuTexture, xPos, yPos, GameLivesRect); for (int num = 0; num < leftPlayerLives; num++) RenderSprite(gameTexture, xPos + GameLivesRect.Width + GameSmallBallRect.Width * num - 2, yPos + 7, GameSmallBallRect); // Right players lives int rightX = 1024-GameLivesRect.Width-GameSmallBallRect.Width*3-xPos-2; RenderSprite(menuTexture, rightX, yPos, GameLivesRect); for (int num = 0; num < rightPlayerLives; num++) RenderSprite(gameTexture, rightX + GameLivesRect.Width + GameSmallBallRect.Width * num - 2, yPos + 7, GameSmallBallRect); } // ShowLives() #endregion #region Draw /// /// This is called when the game should draw itself. /// /// Provides a snapshot of timing values. protected override void Draw(GameTime gameTime) { // Clear background graphics.GraphicsDevice.Clear(Color.Black); // Draw background texture in a seperate pass, else it gets messed up with // our other sprites, the ordering does not really work great. spriteBatch.Begin(); spriteBatch.Draw(backgroundTexture, new Rectangle(0, 0, width, height), Color.LightGray); spriteBatch.End(); // Show screen depending on our current screen mode if (gameMode == GameMode.Menu) { // Show menu RenderSprite(menuTexture, 512-XnaPongLogoRect.Width/2, 150, XnaPongLogoRect); RenderSprite(menuTexture, 512-MenuSingleplayerRect.Width/2, 300, MenuSingleplayerRect, currentMenuItem == 0 ? Color.Orange : Color.White); RenderSprite(menuTexture, 512-MenuMultiplayerRect.Width/2, 350, MenuMultiplayerRect, currentMenuItem == 1 ? Color.Orange : Color.White); RenderSprite(menuTexture, 512-MenuExitRect.Width/2, 400, MenuExitRect, currentMenuItem == 2 ? Color.Orange : Color.White); // Note: Usually input should be handled in Update, but I really think // it is better to have to closely together with the UI code here! if ((keyboard.IsKeyDown(Keys.Down) || gamePadDown) && remDownPressed == false) { currentMenuItem = (currentMenuItem + 1)%3; soundBank.PlayCue("PongBallHit"); } // else if else if ((keyboard.IsKeyDown(Keys.Up) || gamePadUp) && remUpPressed == false) { currentMenuItem = (currentMenuItem + 2)%3; soundBank.PlayCue("PongBallHit"); } // else if else if ((keyboard.IsKeyDown(Keys.Space) || keyboard.IsKeyDown(Keys.LeftControl) || keyboard.IsKeyDown(Keys.RightControl) || keyboard.IsKeyDown(Keys.Enter) || gamePad.Buttons.A == ButtonState.Pressed || gamePad.Buttons.Start == ButtonState.Pressed || // Back or Escape exits our game on Xbox 360 and Windows keyboard.IsKeyDown(Keys.Escape) || gamePad.Buttons.Back == ButtonState.Pressed) && remSpaceOrStartPressed == false && remEscOrBackPressed == false) { // Quit app. if (currentMenuItem == 2 || keyboard.IsKeyDown(Keys.Escape) || gamePad.Buttons.Back == ButtonState.Pressed) { this.Exit(); } // if else { // Start game gameMode = GameMode.Game; leftPlayerLives = 3; rightPlayerLives = 3; leftPaddlePosition = 0.5f; rightPaddlePosition = 0.5f; StartNewBall(); // Set multiplayer if it was selected in menu. // Otherwise the computer controls the left paddle multiplayer = currentMenuItem == 1; } // else } // else if } // if else { // Show lives ShowLives(); // Ball in center RenderBall(); // Render both paddles RenderPaddles(); // If game is over, show winner if (gameMode == GameMode.GameOver) { if (leftPlayerLives == 0) RenderSprite(menuTexture, 512-GameBlueWonRect.Width/2, 300, GameBlueWonRect); else RenderSprite(menuTexture, 512-GameRedWonRect.Width/2, 300, GameRedWonRect); // A, Space or Enter returns us to the main menu. // Esc and Back do return the the menu too, see below. // Make sure the keys are released again when we enter the main menu. if ((gamePad.Buttons.A == ButtonState.Pressed || keyboard.IsKeyDown(Keys.Space) || keyboard.IsKeyDown(Keys.Enter)) && remSpaceOrStartPressed == false) gameMode = GameMode.Menu; } // if // Back and Escape always quits to the main menu if ((gamePad.Buttons.Back == ButtonState.Pressed || keyboard.IsKeyDown(Keys.Escape)) && remEscOrBackPressed == false) { gameMode = GameMode.Menu; StopBall(); } // if } // else // Draw everything on screen. DrawSprites(); base.Draw(gameTime); } // Draw(gameTime) #endregion #region Start game public static void StartGame() { using (PongGame game = new PongGame()) { game.Run(); } // using } // StartGame() #endregion #region Unit tests #if DEBUG #region Test delegate /// /// Test delegate helper /// delegate void TestDelegate(); #endregion #region TestPongGame class /// /// Helper class to test the PongGame /// class TestPongGame : PongGame { TestDelegate testLoop; public TestPongGame(TestDelegate setTestLoop) { testLoop = setTestLoop; } // TestPongGame(setTestLoop) protected override void Draw(GameTime gameTime) { base.Draw(gameTime); testLoop(); } // Draw(gameTime) } // class TestPongGame #endregion #region StartTest static TestPongGame testGame; static void StartTest(TestDelegate testLoop) { testGame = new TestPongGame(testLoop); testGame.Run(); testGame.Dispose(); } // RunTest(testLoop) #endregion #region TestSounds public static void TestSounds() { StartTest( delegate { if (testGame.keyboard.IsKeyDown(Keys.Space)) testGame.soundBank.PlayCue("PongBallHit"); if (testGame.keyboard.IsKeyDown(Keys.LeftControl)) testGame.soundBank.PlayCue("PongBallLost"); }); } // TestSounds() #endregion #region TestMenuSprites public static void TestMenuSprites() { StartTest( delegate { testGame.RenderSprite(testGame.menuTexture, new Rectangle(512-XnaPongLogoRect.Width/2, 150, XnaPongLogoRect.Width, XnaPongLogoRect.Height), XnaPongLogoRect); testGame.RenderSprite(testGame.menuTexture, new Rectangle(512-MenuSingleplayerRect.Width/2, 300, MenuSingleplayerRect.Width, MenuSingleplayerRect.Height), MenuSingleplayerRect); testGame.RenderSprite(testGame.menuTexture, new Rectangle(512-MenuMultiplayerRect.Width/2, 350, MenuMultiplayerRect.Width, MenuMultiplayerRect.Height), MenuMultiplayerRect, Color.Orange); testGame.RenderSprite(testGame.menuTexture, new Rectangle(512-MenuExitRect.Width/2, 400, MenuExitRect.Width, MenuExitRect.Height), MenuExitRect); }); } // TestMenuSprites() #endregion #region TestGameSprites public static void TestGameSprites() { StartTest( delegate { // Show lives testGame.ShowLives(); // Ball in center testGame.RenderBall(); // Render both paddles testGame.RenderPaddles(); }); } // TestGameSprites() #endregion #region TestSingleplayerGame public static void TestSingleplayerGame() { StartTest( delegate { // Make sure we are in the game and in singleplayer mode testGame.gameMode = GameMode.Game; testGame.multiplayer = false; // Show lives testGame.ShowLives(); // Ball in center testGame.RenderBall(); // Render both paddles testGame.RenderPaddles(); }); } // TestSingleplayerGame() #endregion #region TestBallCollisions public static void TestBallCollisions() { StartTest( delegate { // Make sure we are in the game and in singleplayer mode testGame.gameMode = GameMode.Game; testGame.multiplayer = false; testGame.Window.Title = "Xna Pong - Press 1-5 to start collision tests"; // Start specific collision scene based on the user input. if (testGame.keyboard.IsKeyDown(Keys.D1)) { // First test, just collide with screen border testGame.ballPosition = new Vector2(0.6f, 0.9f); testGame.ballSpeedVector = new Vector2(1, 1); } // if else if (testGame.keyboard.IsKeyDown(Keys.D2)) { // Second test, straight on collision with right paddle testGame.ballPosition = new Vector2(0.9f, 0.6f); testGame.ballSpeedVector = new Vector2(1, 1); testGame.rightPaddlePosition = 0.7f; } // if else if (testGame.keyboard.IsKeyDown(Keys.D3)) { // Thrid test, straight on collision with left paddle testGame.ballPosition = new Vector2(0.1f, 0.4f); testGame.ballSpeedVector = new Vector2(-1, -0.5f); testGame.leftPaddlePosition = 0.35f; } // if else if (testGame.keyboard.IsKeyDown(Keys.D4)) { // Advanced test to check if we hit the edge of the right paddle testGame.ballPosition = new Vector2(0.9f, 0.4f); testGame.ballSpeedVector = new Vector2(1, -0.5f); testGame.rightPaddlePosition = 0.29f; } // if else if (testGame.keyboard.IsKeyDown(Keys.D5)) { // Advanced test to check if we hit the edge of the right paddle testGame.ballPosition = new Vector2(0.9f, 0.4f); testGame.ballSpeedVector = new Vector2(1, -0.5f); testGame.rightPaddlePosition = 0.42f; } // if // Show lives testGame.ShowLives(); // Ball in center testGame.RenderBall(); // Render both paddles testGame.RenderPaddles(); }); } // TestBallCollisions() #endregion #endif #endregion } // class PongGame } // namespace XnaPong