#region File Description
//-----------------------------------------------------------------------------
// SpacewarGame.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion
namespace Spacewar
{
///
/// This is the main type for your game
///
partial class SpacewarGame : Microsoft.Xna.Framework.Game
{
// these are the size of the offscreen drawing surface
// in general, no one wants to change these as there
// are all kinds of UI calculations and positions based
// on these dimensions.
const int FixedDrawingWidth = 1280;
const int FixedDrawingHeight = 720;
// these are the size of the output window, ignored
// on Xbox 360
private int preferredWindowWidth = 1280;
private int preferredWindowHeight = 720;
private static ContentManager contentManager;
///
/// The game settings from settings.xml
///
private static Settings settings = new Settings();
private static Camera camera;
///
/// Information about the players such as score, health etc
///
private static Player[] players;
///
/// The current game state
///
private static GameState gameState = GameState.Started;
///
/// Which game board are we playing on
///
private static int gameLevel;
///
/// Stores game paused state
///
private bool paused;
private GraphicsDeviceManager graphics;
private bool enableDrawScaling;
private RenderTarget2D drawBuffer;
private SpriteBatch spriteBatch;
private static Screen currentScreen;
private static PlatformID currentPlatform;
private static KeyboardState keyState;
private bool justWentFullScreen;
#region Properties
public static GameState GameState
{
get
{
return gameState;
}
}
public static int GameLevel
{
get
{
return gameLevel;
}
set
{
gameLevel = value;
}
}
public static Camera Camera
{
get
{
return camera;
}
}
public static Settings Settings
{
get
{
return settings;
}
}
public static Player[] Players
{
get
{
return players;
}
}
public static ContentManager ContentManager
{
get
{
return contentManager;
}
}
public static PlatformID CurrentPlatform
{
get
{
return currentPlatform;
}
}
public static KeyboardState KeyState
{
get
{
return keyState;
}
}
#endregion
public SpacewarGame()
{
#if XBOX360
// we might as well use the xbox in all its glory
preferredWindowWidth = FixedDrawingWidth;
preferredWindowHeight = FixedDrawingHeight;
enableDrawScaling = false;
#else
enableDrawScaling = true;
#endif
this.graphics = new Microsoft.Xna.Framework.GraphicsDeviceManager(this);
this.graphics.PreferredBackBufferWidth = preferredWindowWidth;
this.graphics.PreferredBackBufferHeight = preferredWindowHeight;
// Game should run as fast as possible.
IsFixedTimeStep = false;
}
protected override void Initialize()
{
// game initialization code here
//Uncomment this line to force a save of the default settings file. Useful when you had added things to settings.cs
//NOTE in VS this will go in DEBUG or RELEASE - need to copy up to main project
//Settings.Save("settings.xml");
settings = Settings.Load("settings.xml");
currentPlatform = System.Environment.OSVersion.Platform;
//Initialise the sound
Sound.Initialize();
Window.Title = Settings.WindowTitle;
base.Initialize();
}
protected override void BeginRun()
{
Sound.PlayCue(Sounds.TitleMusic);
//Kick off the game by loading the logo splash screen
ChangeState(GameState.LogoSplash);
float fieldOfView = (float)Math.PI / 4;
float aspectRatio = (float)FixedDrawingWidth / (float)FixedDrawingHeight;
float nearPlane = 10f;
float farPlane = 700f;
camera = new Camera(fieldOfView, aspectRatio, nearPlane, farPlane);
camera.ViewPosition = new Vector3(0, 0, 500);
base.BeginRun();
}
protected override void Update(GameTime gameTime)
{
TimeSpan elapsedTime = gameTime.ElapsedGameTime;
TimeSpan time = gameTime.TotalGameTime;
// The time since Update was called last
float elapsed = (float)elapsedTime.TotalSeconds;
GameState changeState = GameState.None;
keyState = Keyboard.GetState();
XInputHelper.Update(this, keyState);
if ((keyState.IsKeyDown(Keys.RightAlt) || keyState.IsKeyDown(Keys.LeftAlt)) && keyState.IsKeyDown(Keys.Enter) && !justWentFullScreen)
{
ToggleFullScreen();
justWentFullScreen = true;
}
if (keyState.IsKeyUp(Keys.Enter))
{
justWentFullScreen = false;
}
if (XInputHelper.GamePads[PlayerIndex.One].BackPressed ||
XInputHelper.GamePads[PlayerIndex.Two].BackPressed)
{
if (gameState == GameState.PlayEvolved || gameState == GameState.PlayRetro)
{
paused = !paused;
}
if (gameState == GameState.LogoSplash)
{
this.Exit();
}
}
//Reload settings file?
if (XInputHelper.GamePads[PlayerIndex.One].YPressed)
{
//settings = Settings.Load("settings.xml");
//GC.Collect();
}
if (!paused)
{
//Update everything
changeState = currentScreen.Update(time, elapsedTime);
// Update the AudioEngine - MUST call this every frame!!
Sound.Update();
//If either player presses start then reset the game
if (XInputHelper.GamePads[PlayerIndex.One].StartPressed ||
XInputHelper.GamePads[PlayerIndex.Two].StartPressed)
{
changeState = GameState.LogoSplash;
}
if (changeState != GameState.None)
{
ChangeState(changeState);
}
}
base.Update(gameTime);
}
protected override bool BeginDraw()
{
if (!base.BeginDraw())
return false;
BeginDrawScaling();
return true;
}
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(ClearOptions.DepthBuffer,
Color.CornflowerBlue, 1.0f, 0);
base.Draw(gameTime);
currentScreen.Render();
}
protected override void EndDraw()
{
EndDrawScaling();
base.EndDraw();
}
internal void ChangeState(GameState NextState)
{
//Logo spash can come from ANY state since its the place you go when you restart
if (NextState == GameState.LogoSplash)
{
if (currentScreen != null)
currentScreen.Shutdown();
currentScreen = new TitleScreen(this);
gameState = GameState.LogoSplash;
}
else if (gameState == GameState.LogoSplash && NextState == GameState.ShipSelection)
{
Sound.PlayCue(Sounds.MenuAdvance);
//This is really where the game starts so setup the player information
players = new Player[2] { new Player(), new Player() };
//Start at level 1
gameLevel = 1;
currentScreen.Shutdown();
currentScreen = new SelectionScreen(this);
gameState = GameState.ShipSelection;
}
else if (gameState == GameState.PlayEvolved && NextState == GameState.ShipUpgrade)
{
currentScreen.Shutdown();
currentScreen = new ShipUpgradeScreen(this);
gameState = GameState.ShipUpgrade;
}
else if ((gameState == GameState.ShipSelection || GameState == GameState.ShipUpgrade) && NextState == GameState.PlayEvolved)
{
Sound.PlayCue(Sounds.MenuAdvance);
currentScreen.Shutdown();
currentScreen = new EvolvedScreen(this);
gameState = GameState.PlayEvolved;
}
else if (gameState == GameState.LogoSplash && NextState == GameState.PlayRetro)
{
//Game starts here for retro
players = new Player[2] { new Player(), new Player() };
currentScreen.Shutdown();
currentScreen = new RetroScreen(this);
gameState = GameState.PlayRetro;
}
else if (gameState == GameState.PlayEvolved && NextState == GameState.Victory)
{
currentScreen.Shutdown();
currentScreen = new VictoryScreen(this);
gameState = GameState.Victory;
}
else
{
//This is a BAD thing and should never happen
// What does this map to on XBox 360?
//Debug.Assert(false, String.Format("Invalid State transition {0} to {1}", gameState.ToString(), NextState.ToString()));
}
}
protected override void LoadContent()
{
base.LoadContent();
contentManager = new ContentManager(Services);
if (currentScreen != null)
currentScreen.OnCreateDevice();
Font.Init(this);
if (enableDrawScaling)
{
PresentationParameters pp = graphics.GraphicsDevice.PresentationParameters;
drawBuffer = new RenderTarget2D(graphics.GraphicsDevice,
FixedDrawingWidth, FixedDrawingHeight,
true, SurfaceFormat.Color,
DepthFormat.Depth24Stencil8, pp.MultiSampleCount,
RenderTargetUsage.DiscardContents);
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
}
}
protected override void UnloadContent()
{
base.UnloadContent();
if (drawBuffer != null)
{
drawBuffer.Dispose();
drawBuffer = null;
}
if (spriteBatch != null)
{
spriteBatch.Dispose();
spriteBatch = null;
}
Font.Dispose();
if (contentManager != null)
{
contentManager.Dispose();
contentManager = null;
}
}
private void ToggleFullScreen()
{
PresentationParameters presentation = graphics.GraphicsDevice.PresentationParameters;
if (presentation.IsFullScreen)
{ // going windowed
graphics.PreferredBackBufferWidth = preferredWindowWidth;
graphics.PreferredBackBufferHeight = preferredWindowHeight;
}
else
{
// going fullscreen, use desktop resolution to minimize display mode changes
// this also has the nice effect of working around some displays that lie about
// supporting 1280x720
GraphicsAdapter adapter = graphics.GraphicsDevice.Adapter;
graphics.PreferredBackBufferWidth = adapter.CurrentDisplayMode.Width;
graphics.PreferredBackBufferHeight = adapter.CurrentDisplayMode.Height;
}
graphics.ToggleFullScreen();
}
private void BeginDrawScaling()
{
if (enableDrawScaling && drawBuffer != null)
{
graphics.GraphicsDevice.SetRenderTarget(drawBuffer);
}
}
private void EndDrawScaling()
{
// copy our offscreen surface to the backbuffer with appropriate
// letterbox bars
if (!enableDrawScaling || drawBuffer == null)
return;
graphics.GraphicsDevice.SetRenderTarget(null);
PresentationParameters presentation = graphics.GraphicsDevice.PresentationParameters;
float outputAspect = (float)presentation.BackBufferWidth / (float)presentation.BackBufferHeight;
float preferredAspect = (float)FixedDrawingWidth / (float)FixedDrawingHeight;
Rectangle dst;
if (outputAspect <= preferredAspect)
{
// output is taller than it is wider, bars on top/bottom
int presentHeight = (int)((presentation.BackBufferWidth / preferredAspect) + 0.5f);
int barHeight = (presentation.BackBufferHeight - presentHeight) / 2;
dst = new Rectangle(0, barHeight, presentation.BackBufferWidth, presentHeight);
}
else
{
// output is wider than it is tall, bars left/right
int presentWidth = (int)((presentation.BackBufferHeight * preferredAspect) + 0.5f);
int barWidth = (presentation.BackBufferWidth - presentWidth) / 2;
dst = new Rectangle(barWidth, 0, presentWidth, presentation.BackBufferHeight);
}
// clear to get black bars
graphics.GraphicsDevice.Clear(ClearOptions.Target, Color.Black, 1.0f, 0);
// draw a quad to get the draw buffer to the back buffer
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque);
spriteBatch.Draw(drawBuffer, dst, Color.White);
spriteBatch.End();
}
}
}