/*
* Game Design Studio (Spring 2007)
* Optimization and Debugging example code
* April 2007
* by
* Priyesh Dixit
*
* Main focus of this sample code is to show:
* - Bad debugging
* - Good debugging
* - Great debugging
* - Multithreading
* - Using CLR
*/
#region Using Statements
using System;
using System.Collections.Generic;
using System.Threading;
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 Presentation
{
///
/// This is the main type for your game
///
public class MainGame : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
SpriteBatch spriteBatch;
public static int GAME_WINDOW_WIDTH = 1280;
public static int GAME_WINDOW_HEIGHT = 720;
public static int MAX_CREATURES_X = 25;
public static int MAX_CREATURES_Y = 20;
public enum GameModeType
{
TITLE,
GAME_SETUP,
GAME_RUNNING,
};
GameModeType gameMode = GameModeType.TITLE;
public enum GamePhaseType
{
PRINTS,
BREAKS,
PROFILE,
THREADS
};
GamePhaseType currentGamePhase = GamePhaseType.PRINTS;
//Menus
TitleScreen titleScreen = new TitleScreen();
GameSetup gameSetupScreen = new GameSetup();
string sortType = "";
bool inputReleased = true;
static int currentSortIndex = 0;
static bool FINISHED_SORTING = true;
Thread thread;
private class Creature
{
public int x, y;
public int value;
public Color color = Color.White;
public int index;
public Creature()
{
x = 0;
y = 0;
value = 0;
}
public Creature(int newX, int newY, int newValue)
{
x = newX;
y = newY;
value = newValue;
}
public Creature(Creature copyFrom)
{
x = copyFrom.x;
y = copyFrom.y;
value = copyFrom.value;
}
};
static List creatureList = new List();
Texture2D creatureTexture;
//~5% can't be seen on the TV
public const float SCREEN_CUTOFF_AVOIDANCE = 0.05f;
public MainGame()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
}
///
/// 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()
{
// TODO: Add your initialization logic here
graphics.PreferredBackBufferWidth = GAME_WINDOW_WIDTH;
graphics.PreferredBackBufferHeight = GAME_WINDOW_HEIGHT;
graphics.ApplyChanges();
//calculate max creatures
MAX_CREATURES_X = (GAME_WINDOW_WIDTH) / 32 - 2;
MAX_CREATURES_Y = (GAME_WINDOW_HEIGHT) / 32 - 2;
gameMode = GameModeType.TITLE;
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
TextWriter.initFont(graphics.GraphicsDevice, content);
base.Initialize();
}
///
/// Load your graphics content. If loadAllContent is true, you should
/// load content from both ResourceManagementMode pools. Otherwise, just
/// load ResourceManagementMode.Manual content.
///
/// Which type of content to load.
protected override void LoadGraphicsContent(bool loadAllContent)
{
if (loadAllContent)
{
// TODO: Load any ResourceManagementMode.Automatic content
if ((1.0f * GAME_WINDOW_WIDTH) / (1.0f * GAME_WINDOW_HEIGHT) > 1.5)
{
titleScreen.SetBackground(content.Load("_textures/TitleScreen_wide"));
}
else
{
titleScreen.SetBackground(content.Load("_textures/TitleScreen"));
}
creatureTexture = content.Load("_textures/fatmodabu");
}
// TODO: Load any ResourceManagementMode.Manual content
}
///
/// Unload your graphics content. If unloadAllContent is true, you should
/// unload content from both ResourceManagementMode pools. Otherwise, just
/// unload ResourceManagementMode.Manual content. Manual content will get
/// Disposed by the GraphicsDevice during a Reset.
///
/// Which type of content to unload.
protected override void UnloadGraphicsContent(bool unloadAllContent)
{
if (unloadAllContent == true)
{
content.Unload();
}
}
///
/// 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)
{
GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
KeyboardState keyboardState = Keyboard.GetState();
if (inputReleased == true)
{
if (gameMode == GameModeType.TITLE)
{
if (gamePadState.Buttons.Start == ButtonState.Pressed ||
keyboardState.IsKeyDown(Keys.Enter))
{
inputReleased = false;
gameMode = GameModeType.GAME_SETUP;
}
if (gamePadState.Buttons.Back == ButtonState.Pressed ||
keyboardState.IsKeyDown(Keys.Escape))
{
this.Exit();
}
}
else if (gameMode == GameModeType.GAME_SETUP)
{
if (gamePadState.Buttons.Start == ButtonState.Pressed ||
keyboardState.IsKeyDown(Keys.Enter))
{
inputReleased = false;
gameMode = GameModeType.GAME_RUNNING;
//Get game phase
GameMenuOption option = (GameMenuOption)gameSetupScreen.GetMenu().GetMenuElement("Phase:");
switch (option.GetActiveOption())
{
case "Prints":
currentGamePhase = GamePhaseType.PRINTS;
break;
case "Breaks":
currentGamePhase = GamePhaseType.BREAKS;
break;
case "Profile":
currentGamePhase = GamePhaseType.PROFILE;
break;
case "Threads":
currentGamePhase = GamePhaseType.THREADS;
break;
}
option = (GameMenuOption)gameSetupScreen.GetMenu().GetMenuElement("Sort:");
sortType = option.GetActiveOption();
//Get value of Population input
//GameMenuValueInput input = (GameMenuValueInput)gameSetupScreen.GetMenu().GetMenuElement("Population:");
InitializeCreatures(MAX_CREATURES_X*MAX_CREATURES_Y);
if (currentGamePhase == GamePhaseType.THREADS)
{
if (sortType == "Bubble")
{
thread = new Thread(new ThreadStart(AllInOneBubbleSort));
thread.Start();
}
else if (sortType == "Insertion")
{
thread = new Thread(new ThreadStart(AllInOneInsertionSort));
thread.Start();
}
}
}
if (gamePadState.Buttons.Back == ButtonState.Pressed ||
keyboardState.IsKeyDown(Keys.Escape))
{
this.Exit();
}
// Navigate menu
// Check for the keys and then do the appropriate action
bool menuUp = ((gamePadState.DPad.Up == ButtonState.Pressed) || (keyboardState.IsKeyDown(Keys.Up)));
bool menuDown = ((gamePadState.DPad.Down == ButtonState.Pressed) || (keyboardState.IsKeyDown(Keys.Down)));
bool menuLeft = ((gamePadState.DPad.Left == ButtonState.Pressed) || (keyboardState.IsKeyDown(Keys.Left)));
bool menuRight = ((gamePadState.DPad.Right == ButtonState.Pressed) || (keyboardState.IsKeyDown(Keys.Right)));
// Navigate up and down
if (menuUp || menuDown)
{
inputReleased = false;
// If they pressed Up then get the previous element
if (menuUp)
{
gameSetupScreen.GetMenu().PreviousMenuElement();
}
// Or if they pressed down, get the next one
else
{
gameSetupScreen.GetMenu().NextMenuElement();
}
}
// Change menu options or values
if (menuLeft || menuRight)
{
inputReleased = false;
GameMenuElement activeElement = gameSetupScreen.GetMenu().GetActiveMenuElement();
// OptionBox
if (activeElement.GetElementType() == MenuElementType.OPTION)
{
// Cast as option and change value
GameMenuOption option = (GameMenuOption)activeElement;
// If they pressed left, get previous option
if (menuLeft)
{
option.PreviousOption();
}
// Or if they pressed right, get next option
else
{
option.NextOption();
}
}
// ValueSlider
else if (activeElement.GetElementType() == MenuElementType.VALUE)
{
// Cast as ValueInput type and change value
GameMenuValueInput valueInput = (GameMenuValueInput)activeElement;
int activeIndex = gameSetupScreen.GetMenu().GetActiveIndex();
// If they pressed left, decrease the value
if (menuLeft)
{
valueInput.Decrement();
}
// Or if they pressed right, increase it
else
{
valueInput.Increment();
}
}
}
}
else
{
// Game running
if (gamePadState.Buttons.Back == ButtonState.Pressed ||
keyboardState.IsKeyDown(Keys.Escape))
{
inputReleased = false;
gameMode = GameModeType.GAME_SETUP;
}
if (currentGamePhase == GamePhaseType.BREAKS)
{
int x = 0;
}
//Else run the sorting algorithm
if (currentGamePhase != GamePhaseType.THREADS)
{
if (FINISHED_SORTING == false)
{
if (sortType == "Insertion")
{
if (currentGamePhase == GamePhaseType.PROFILE)
{
AllInOneInsertionSort();
}
else
{
InsertionSort();
}
}
else if (sortType == "Bubble")
{
if (currentGamePhase == GamePhaseType.PROFILE)
{
AllInOneBubbleSort();
}
else
{
bool swapped = BubbleSort();
if (!swapped)
{
FINISHED_SORTING = true;
}
}
}
}
}
}
}
else if (gamePadState.Buttons.Start == ButtonState.Released &&
gamePadState.Buttons.Back == ButtonState.Released &&
(keyboardState.IsKeyUp(Keys.Enter)) &&
(keyboardState.IsKeyUp(Keys.Escape)) &&
(gamePadState.DPad.Up == ButtonState.Released) && (keyboardState.IsKeyUp(Keys.Up)) &&
(gamePadState.DPad.Down == ButtonState.Released) && (keyboardState.IsKeyUp(Keys.Down)) &&
(gamePadState.DPad.Left == ButtonState.Released) && (keyboardState.IsKeyUp(Keys.Left)) &&
(gamePadState.DPad.Right == ButtonState.Released) && (keyboardState.IsKeyUp(Keys.Right)))
{
inputReleased = true;
}
base.Update(gameTime);
}
///
/// This is called when the game should draw itself.
///
/// Provides a snapshot of timing values.
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.Black);
if (gameMode == GameModeType.TITLE)
{
//draw title screen
titleScreen.Draw(spriteBatch);
}
else if (gameMode == GameModeType.GAME_SETUP)
{
//draw menu
gameSetupScreen.Draw(spriteBatch);
}
else
{
//game running
//draw the creatures
DrawCreatures();
}
base.Draw(gameTime);
}
private void AllInOneInsertionSort()
{
while (!FINISHED_SORTING)
{
InsertionSort();
}
}
private void InsertionSort()
{
if (currentSortIndex >= creatureList.Count)
{
//Done!
FINISHED_SORTING = true;
return;
}
//Does sorting algorithm
for (int i = currentSortIndex+1; i < creatureList.Count; i++)
{
//found something smaller!
if (creatureList[i].value < creatureList[currentSortIndex].value)
{
//swap them
Creature temp = new Creature(creatureList[currentSortIndex]);
creatureList[currentSortIndex] = new Creature(creatureList[i]);
creatureList[i] = new Creature(temp);
}
}
//Finished sorting this creature.. place in right place
creatureList[currentSortIndex].color = new Color(100, 0, 0, 255);
creatureList[currentSortIndex].x = (currentSortIndex % MAX_CREATURES_X) * 32 + 32;
creatureList[currentSortIndex].y = (int)((currentSortIndex) / MAX_CREATURES_X) * 32 + 32;
currentSortIndex++;
if (currentGamePhase == GamePhaseType.PRINTS)
{
System.Diagnostics.Debug.WriteLine("Done with " + currentSortIndex);
}
}
private void AllInOneBubbleSort()
{
// Bubble sort
bool swapped;
do
{
swapped = BubbleSort();
} while (swapped);
}
private bool BubbleSort()
{
bool swapped = false;
for (int i = 0; i < creatureList.Count - 1; i++)
{
//smaller than the one before it
if (creatureList[i].value > creatureList[i + 1].value)
{
//swap them
Creature temp = new Creature(creatureList[i + 1]);
creatureList[i + 1] = new Creature(creatureList[i]);
creatureList[i] = new Creature(temp);
creatureList[i].color = new Color(100, 100, 0, 255);
swapped = true;
}
}
if (currentGamePhase == GamePhaseType.PRINTS)
{
System.Diagnostics.Debug.WriteLine("swapped= " + swapped.ToString());
}
//test to see if some of them are already sorted
bool sorted = true;
for (int j = 0; j < creatureList.Count; j++)
{
sorted = true;
for (int i = j + 1; i < creatureList.Count; i++)
{
if (creatureList[i].value < creatureList[j].value)
{
sorted = false;
break;
}
}
if (sorted)
{
if (currentGamePhase == GamePhaseType.PRINTS)
{
System.Diagnostics.Debug.WriteLine("Creature#" + j + " already sorted");
}
creatureList[j].color = new Color(100, 0, 0, 255);
creatureList[j].x = (j % MAX_CREATURES_X) * 32 + 32;
creatureList[j].y = (int)((j) / MAX_CREATURES_X) * 32 + 32;
}
}
return swapped;
}
private void DrawCreatures()
{
for (int i = 0; i < creatureList.Count; i++)
{
spriteBatch.Begin();
spriteBatch.Draw(creatureTexture, new Vector2(creatureList[i].x, creatureList[i].y), creatureList[i].color);
spriteBatch.End();
TextWriter.Arial.Draw(creatureList[i].x, creatureList[i].y+15, ""+creatureList[i].value, RobLoach.Alignment.Left, Color.Green);
}
}
private void InitializeCreatures(int num)
{
Random rand = new Random();
creatureList.Clear();
for (int i = 0; i < num; i++)
{
creatureList.Add(new Creature());
creatureList[i].x = rand.Next(GAME_WINDOW_WIDTH);// - 2*(int)(0.05f * GAME_WINDOW_WIDTH)) + (int)(0.05f * GAME_WINDOW_WIDTH);
creatureList[i].y = rand.Next(GAME_WINDOW_HEIGHT);// - 2*(int)(0.05f * GAME_WINDOW_HEIGHT)) + (int)(0.05f * GAME_WINDOW_HEIGHT);
creatureList[i].value = rand.Next(100000) % 1000;
creatureList[i].index = i;
}
currentSortIndex = 0;
FINISHED_SORTING = false;
}
}
}