topical media & game development
game-xna-intro-XnaPong-PongGame.cs / cs
// 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
{
<summary>
This is the main type for your game
</summary>
public class PongGame : Microsoft.Xna.Framework.Game
{
#region Constants
<summary>
Rectangles for our graphics, tested with the unit tests below.
</summary>
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);
<summary>
Ball speed multiplicator, this is how much screen space the ball will
travel each second.
</summary>
const float BallSpeedMultiplicator = 0.5f;
<summary>
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.
</summary>
const float ComputerPaddleSpeed = 0.5f;//25f;
<summary>
Game modes
</summary>
enum GameMode
{
Menu,
Game,
GameOver,
} // enum GameMode
#endregion
#region Variables
GraphicsDeviceManager graphics;
ContentManager content;
Texture2D backgroundTexture, menuTexture, gameTexture;
AudioEngine audioEngine;
WaveBank waveBank;
SoundBank soundBank;
<summary>
Resolution of our game.
</summary>
int width, height;
<summary>
Current paddle positions, 0 means top, 1 means bottom.
</summary>
float leftPaddlePosition = 0.5f,
rightPaddlePosition = 0.5f;
<summary>
Current ball position, again from 0 to 1, 0 is left and top,
1 is bottom and right.
</summary>
Vector2 ballPosition = new Vector2(0.5f, 0.5f);
<summary>
Ball speed vector, randomized for every new ball.
Will be set to Zero if we are in menu or game is over.
</summary>
Vector2 ballSpeedVector = new Vector2(0, 0);//1);
<summary>
Life for left and right players. If one player has 0 lives left,
the other one wins.
</summary>
int leftPlayerLives = 3,
rightPlayerLives = 3;
<summary>
Are we playing a multiplayer game? If this is false, the computer
controls the left paddle.
</summary>
bool multiplayer = false;
<summary>
Game mode we are currently in. Very simple game flow.
</summary>
GameMode
gameMode = GameMode.Menu;
<summary>
Currently selected menu item.
</summary>
int currentMenuItem = 0;
#endregion
#region Constructor
<summary>
Create pong game
</summary>
public PongGame()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
} // PongGame()
<summary>
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.
</summary>
protected override void Initialize()
{
// Remember resolution
width = graphics.GraphicsDevice.Viewport.Width;
height = graphics.GraphicsDevice.Viewport.Height;
base.Initialize();
} // Initialize()
<summary>
Load all graphics content (just our background texture).
Use this method to make sure a device reset event is handled correctly.
</summary>
<param name="loadAllContent">Load everything?
</param>
protected override void LoadGraphicsContent(bool loadAllContent)
{
if (loadAllContent)
{
// Create sprite batch
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
// Load all our content
backgroundTexture = content.Load<Texture2D>("SpaceBackground");
menuTexture = content.Load<Texture2D>("PongMenu");
gameTexture = content.Load<Texture2D>("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)
<summary>
Unload graphic content if the device gets lost.
</summary>
<param name="unloadAllContent">Unload everything?
</param>
protected override void UnloadGraphicsContent(bool unloadAllContent)
{
if (unloadAllContent == true)
content.Unload();
base.UnloadGraphicsContent(unloadAllContent);
} // UnloadGraphicsContent(loadAllContent)
#endregion
#region Start and stop ball
<summary>
Start new ball at the beginning of each game and when a ball is lost.
</summary>
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()
<summary>
Stop ball for menu and when game is over.
</summary>
public void StopBall()
{
ballSpeedVector = new Vector2(0, 0);
} // StopBall
#endregion
#region Update
<summary>
Game pad and keyboard states for full 2 player support.
</summary>
GamePadState
gamePad,
gamePad2;
KeyboardState keyboard;
<summary>
Remember up, down, start and back buttons for the menu.
</summary>
bool remUpPressed = false,
remDownPressed = false,
remSpaceOrStartPressed = false,
remEscOrBackPressed = false;
<summary>
Store up/down states and include thumbstick to control paddles.
</summary>
bool
gamePadUp = false,
gamePadDown = false,
gamePad2Up = false,
gamePad2Down = false;
<summary>
Allows the game to run logic such as updating the world,
checking for collisions, gathering input and playing audio.
</summary>
<param name="
gameTime">Provides a snapshot of timing values.
</param>
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<SpriteToRender> sprites = new List<SpriteToRender>();
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
<summary>
This is called when the game should draw itself.
</summary>
<param name="
gameTime">Provides a snapshot of timing values.
</param>
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
<summary>
Test delegate helper
</summary>
delegate void TestDelegate();
#endregion
#region TestPongGame class
<summary>
Helper class to test the PongGame
</summary>
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
(C) Æliens
20/2/2008
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.