topical media & game development
game-xna-intro-XnaGraphicEngineChapter6-Game-BaseGame.cs / cs
// Project: XnaGraphicEngineVs2005, File: BaseGame.cs
// Namespace: XnaGraphicEngine.Game, Class: BaseGame
// Path: C:\code\XnaBook\XnaGraphicEngine\Game, Author: Abi
// Code lines: 728, Size of file: 21,72 KB
// Creation date: 26.11.2006 12:22
// Last modified: 27.11.2006 07:11
// Generated with Commenter by abi.exDream.com
#region Using directives
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Text;
using XnaGraphicEngine.Graphics;
using XnaGraphicEngine.Helpers;
#endregion
namespace XnaGraphicEngine.Game
{
<summary>
Base game class for all the basic game support.
Connects all our helper classes together and makes our live easier!
</summary>
public class BaseGame : Microsoft.Xna.Framework.Game
{
#region Constants
<summary>
Background color
</summary>
protected static readonly
Color BackgroundColor =
Color.Black;
<summary>
Field of view and near and far plane distances for the
ProjectionMatrix creation.
</summary>
private const float FieldOfView = (float)Math.PI / 2,
NearPlane = 1.0f,
FarPlane = 500.0f;
#endregion
#region Variables
<summary>
Graphics
</summary>
protected GraphicsDeviceManager graphics;
<summary>
Content
</summary>
protected static ContentManager content;
<summary>
Remember graphics device and allow the useage wherever needed via
the Device property.
</summary>
private static GraphicsDevice device;
<summary>
Resolution of our game.
</summary>
protected static int width, height;
<summary>
Aspect ratio of our current resolution
</summary>
private static float aspectRatio = 1.0f;
<summary>
Render delegate for rendering methods, also used for many other
methods.
</summary>
public delegate void RenderDelegate();
<summary>
Matrices for shaders. Used in a similar way than in Rocket Commander,
but since we don't have a fixed function pipeline here we just use
these values in the shader. Make sure to set all matrices before
calling a shader. Inside a shader you have to update the shader
parameter too, just setting the WorldMatrix alone does not work.
</summary>
private static Matrix worldMatrix,
viewMatrix,
projectionMatrix;
<summary>
Line manager 2D
</summary>
private static LineManager2D lineManager2D = null;
<summary>
Line manager 3D
</summary>
private static LineManager3D lineManager3D = null;
<summary>
Texture font to render text on the screen.
</summary>
private static TextureFont font;
#endregion
#region Properties
#region Calc rectangle helpers
<summary>
XToRes helper method to convert 1024x640 to the current
screen resolution. Used to position UI elements.
</summary>
<param name="xIn1024px">X in 1024px width resolution
</param>
<returns>Int
</returns>
public static int XToRes(int xIn1024px)
{
return (int)Math.Round(xIn1024px * BaseGame.Width / 1024.0f);
} // XToRes(xIn1024px)
<summary>
YToRes helper method to convert 1024x640 to the current
screen resolution. Used to position UI elements.
</summary>
<param name="yIn640px">Y in 640px height
</param>
<returns>Int
</returns>
public static int YToRes(int yIn640px)
{
return (int)Math.Round(yIn640px * BaseGame.Height / 640.0f);
} // YToRes(yIn768px)
<summary>
YTo res 768
</summary>
<param name="yIn768px">Y in 768px
</param>
<returns>Int
</returns>
public static int YToRes768(int yIn768px)
{
return (int)Math.Round(yIn768px * BaseGame.Height / 768.0f);
} // YToRes768(yIn768px)
<summary>
XTo res 1600
</summary>
<param name="xIn1600px">X in 1600px
</param>
<returns>Int
</returns>
public static int XToRes1600(int xIn1600px)
{
return (int)Math.Round(xIn1600px * BaseGame.Width / 1600.0f);
} // XToRes1600(xIn1600px)
<summary>
YTo res 1200
</summary>
<param name="yIn768px">Y in 1200px
</param>
<returns>Int
</returns>
public static int YToRes1200(int yIn1200px)
{
return (int)Math.Round(yIn1200px * BaseGame.Height / 1200.0f);
} // YToRes1200(yIn1200px)
<summary>
XTo res 1400
</summary>
<param name="xIn1400px">X in 1400px
</param>
<returns>Int
</returns>
public static int XToRes1400(int xIn1400px)
{
return (int)Math.Round(xIn1400px * BaseGame.Width / 1400.0f);
} // XToRes1400(xIn1400px)
<summary>
YTo res 1200
</summary>
<param name="yIn1050px">Y in 1050px
</param>
<returns>Int
</returns>
public static int YToRes1050(int yIn1050px)
{
return (int)Math.Round(yIn1050px * BaseGame.Height / 1050.0f);
} // YToRes1050(yIn1050px)
<summary>
Calc rectangle, helper method to convert from our images (1024)
to the current resolution. Everything will stay in the 16/9
format of the textures.
</summary>
<param name="x">X
</param>
<param name="y">Y
</param>
<param name="width">Width
</param>
<param name="height">Height
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangle(
int relX, int relY, int relWidth, int relHeight)
{
float widthFactor = width / 1024.0f;
float heightFactor = height / 640.0f;
return new Rectangle(
(int)Math.Round(relX * widthFactor),
(int)Math.Round(relY * heightFactor),
(int)Math.Round(relWidth * widthFactor),
(int)Math.Round(relHeight * heightFactor));
} // CalcRectangle(x, y, width)
<summary>
Calc rectangle with bounce effect, same as CalcRectangle, but sizes
the resulting rect up and down depending on the bounceEffect value.
</summary>
<param name="relX">Rel x
</param>
<param name="relY">Rel y
</param>
<param name="relWidth">Rel width
</param>
<param name="relHeight">Rel height
</param>
<param name="bounceEffect">Bounce effect
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangleWithBounce(
int relX, int relY, int relWidth, int relHeight, float bounceEffect)
{
float widthFactor = width / 1024.0f;
float heightFactor = height / 640.0f;
float middleX = (relX + relWidth / 2) * widthFactor;
float middleY = (relY + relHeight / 2) * heightFactor;
float retWidth = relWidth * widthFactor * bounceEffect;
float retHeight = relHeight * heightFactor * bounceEffect;
return new Rectangle(
(int)Math.Round(middleX - retWidth / 2),
(int)Math.Round(middleY - retHeight / 2),
(int)Math.Round(retWidth),
(int)Math.Round(retHeight));
} // CalcRectangleWithBounce(relX, relY, relWidth)
<summary>
Calc rectangle, same method as CalcRectangle, but keep the 4 to 3
ratio for the image. The Rect will take same screen space in
16:9 and 4:3 modes. E.g.
Buttons should be displayed this way.
Should be used for 1024px width graphics.
</summary>
<param name="relX">Rel x
</param>
<param name="relY">Rel y
</param>
<param name="relWidth">Rel width
</param>
<param name="relHeight">Rel height
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangleKeep4To3(
int relX, int relY, int relWidth, int relHeight)
{
float widthFactor = width / 1024.0f;
float heightFactor = height / 768.0f;
return new Rectangle(
(int)Math.Round(relX * widthFactor),
(int)Math.Round(relY * heightFactor),
(int)Math.Round(relWidth * widthFactor),
(int)Math.Round(relHeight * heightFactor));
} // CalcRectangleKeep4To3(relX, relY, relWidth)
<summary>
Calc rectangle, same method as CalcRectangle, but keep the 4 to 3
ratio for the image. The Rect will take same screen space in
16:9 and 4:3 modes. E.g.
Buttons should be displayed this way.
Should be used for 1024px width graphics.
</summary>
<param name="gfxRect">Gfx rectangle
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangleKeep4To3(
Rectangle gfxRect)
{
float widthFactor = width / 1024.0f;
float heightFactor = height / 768.0f;
return new Rectangle(
(int)Math.Round(gfxRect.X * widthFactor),
(int)Math.Round(gfxRect.Y * heightFactor),
(int)Math.Round(gfxRect.Width * widthFactor),
(int)Math.Round(gfxRect.Height * heightFactor));
} // CalcRectangleKeep4To3(gfxRect)
<summary>
Calc rectangle for 1600px width graphics.
</summary>
<param name="relX">Rel x
</param>
<param name="relY">Rel y
</param>
<param name="relWidth">Rel width
</param>
<param name="relHeight">Rel height
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangle1600(
int relX, int relY, int relWidth, int relHeight)
{
float widthFactor = width / 1600.0f;
// keep height factor: float heightFactor = height / 1200.0f;
float heightFactor = (height / 1200.0f);// / (aspectRatio / (16 / 9));
return new Rectangle(
(int)Math.Round(relX * widthFactor),
(int)Math.Round(relY * heightFactor),
(int)Math.Round(relWidth * widthFactor),
(int)Math.Round(relHeight * heightFactor));
} // CalcRectangle1600(relX, relY, relWidth)
<summary>
Calc rectangle 2000px, just a helper to scale stuff down
</summary>
<param name="relX">Rel x
</param>
<param name="relY">Rel y
</param>
<param name="relWidth">Rel width
</param>
<param name="relHeight">Rel height
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangle2000(
int relX, int relY, int relWidth, int relHeight)
{
float widthFactor = width / 2000.0f;
float heightFactor = (height / 1500.0f);
return new Rectangle(
(int)Math.Round(relX * widthFactor),
(int)Math.Round(relY * heightFactor),
(int)Math.Round(relWidth * widthFactor),
(int)Math.Round(relHeight * heightFactor));
} // CalcRectangle2000(relX, relY, relWidth)
/*unused
<summary>
Calc rectangle for 1920px width graphics.
</summary>
<param name="relX">Rel x
</param>
<param name="relY">Rel y
</param>
<param name="relWidth">Rel width
</param>
<param name="relHeight">Rel height
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangle1920(
int relX, int relY, int relWidth, int relHeight)
{
float widthFactor = width / 1920.0f;
// keep height factor: float heightFactor = height / 1200.0f;
float heightFactor = (height / 1200.0f);// / (aspectRatio / (16 / 9));
return new Rectangle(
(int)Math.Round(relX * widthFactor),
(int)Math.Round(relY * heightFactor),
(int)Math.Round(relWidth * widthFactor),
(int)Math.Round(relHeight * heightFactor));
} // CalcRectangle1920(relX, relY, relWidth)
<summary>
Calc rectangle keep 4 to 3 align bottom
</summary>
<param name="relX">Rel x
</param>
<param name="relY">Rel y
</param>
<param name="relWidth">Rel width
</param>
<param name="relHeight">Rel height
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangleKeep4To3AlignBottom(
int relX, int relY, int relWidth, int relHeight)
{
float widthFactor = width / 1024.0f;
float heightFactor16To9 = height / 640.0f;
float heightFactor4To3 = height / 768.0f;
return new Rectangle(
(int)(relX * widthFactor),
(int)(relY * heightFactor16To9) -
(int)Math.Round(relHeight * heightFactor4To3),
(int)Math.Round(relWidth * widthFactor),
(int)Math.Round(relHeight * heightFactor4To3));
} // CalcRectangleKeep4To3AlignBottom(relX, relY, relWidth)
<summary>
Calc rectangle keep 4 to 3 align bottom right
</summary>
<param name="relX">Rel x
</param>
<param name="relY">Rel y
</param>
<param name="relWidth">Rel width
</param>
<param name="relHeight">Rel height
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangleKeep4To3AlignBottomRight(
int relX, int relY, int relWidth, int relHeight)
{
float widthFactor = width / 1024.0f;
float heightFactor16To9 = height / 640.0f;
float heightFactor4To3 = height / 768.0f;
return new Rectangle(
(int)(relX * widthFactor) -
(int)Math.Round(relWidth * widthFactor),
(int)(relY * heightFactor16To9) -
(int)Math.Round(relHeight * heightFactor4To3),
(int)Math.Round(relWidth * widthFactor),
(int)Math.Round(relHeight * heightFactor4To3));
} // CalcRectangleKeep4To3AlignBottomRight(relX, relY, relWidth)
<summary>
Calc rectangle centered with given height.
This one uses relX and relY points as the center for our rect.
The relHeight is then calculated and we align everything
with help of gfxRect (determinating the width).
Very useful for buttons, logos and other centered UI textures.
</summary>
<param name="relX">Rel x
</param>
<param name="relY">Rel y
</param>
<param name="relHeight">Rel height
</param>
<param name="gfxRect">Gfx rectangle
</param>
<returns>Rectangle
</returns>
public static Rectangle CalcRectangleCenteredWithGivenHeight(
int relX, int relY, int relHeight, Rectangle gfxRect)
{
float widthFactor = width / 1024.0f;
float heightFactor = height / 640.0f;
int rectHeight = (int)Math.Round(relHeight * heightFactor);
// Keep aspect ratio
int rectWidth = (int)Math.Round(
gfxRect.Width * rectHeight / (float)gfxRect.Height);
return new Rectangle(
Math.
Max(0, (int)Math.Round(relX * widthFactor) - rectWidth / 2),
Math.
Max(0, (int)Math.Round(relY * heightFactor) - rectHeight / 2),
rectWidth, rectHeight);
} // CalcRectangleCenteredWithGivenHeight(relX, relY, relHeight)
#endregion
<summary>
Graphics device access for the whole the engine.
</summary>
<returns>Graphics device
</returns>
public static GraphicsDevice Device
{
get
{
return device;
} // get
} // Device
<summary>
Content manager access for the whole the engine.
</summary>
<returns>Content manager
</returns>
public static ContentManager Content
{
get
{
return content;
} // get
} // Content
<summary>
Width of our backbuffer we render into.
</summary>
<returns>Int
</returns>
public static int Width
{
get
{
return width;
} // get
} // Width
<summary>
Height of our backbuffer we render into.
</summary>
<returns>Int
</returns>
public static int Height
{
get
{
return height;
} // get
} // Height
<summary>
Resolution rectangle
</summary>
<returns>Rectangle
</returns>
public static Rectangle ResolutionRect
{
get
{
return new Rectangle(0, 0, width, height);
} // get
} // ResolutionRect
<summary>
Alpha blending
</summary>
<returns>Bool
</returns>
public static bool AlphaBlending
{
set
{
if (value)
{
device.RenderState.AlphaBlendEnable = true;
device.RenderState.SourceBlend = Blend.SourceAlpha;
device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
} // if (value)
else
device.RenderState.AlphaBlendEnable = false;
} // set
} // AlphaBlending
<summary>
World matrix
</summary>
<returns>Matrix
</returns>
public static Matrix WorldMatrix
{
get
{
return worldMatrix;
} // get
set
{
worldMatrix = value;
// Update worldViewProj here?
} // set
} // WorldMatrix
<summary>
View matrix
</summary>
<returns>Matrix
</returns>
public static Matrix ViewMatrix
{
get
{
return viewMatrix;
} // get
set
{
// Set view matrix, usually only done in ChaseCamera.Update!
viewMatrix = value;
// Update camera pos and rotation, used all over the game!
invViewMatrix = Matrix.Invert(ViewMatrix);
CameraPos = invViewMatrix.Translation;
cameraRotation = Vector3.TransformNormal(
new Vector3(0, 0, 1), invViewMatrix);
} // set
} // ViewMatrix
<summary>
Projection matrix
</summary>
<returns>Matrix
</returns>
public static Matrix ProjectionMatrix
{
get
{
return projectionMatrix;
} // get
set
{
projectionMatrix = value;
// Update worldViewProj here?
} // set
} // ProjectionMatrix
<summary>
Camera pos, updated each loop in Update()!
Public to allow easy access from everywhere, will be called a lot each
frame, for example Model.Render uses this for distance checks.
</summary>
public static Vector3 CameraPos;
<summary>
Camera rotation, used to compare objects for visibility.
</summary>
private static Vector3 cameraRotation = new Vector3(0, 0, 1);
<summary>
Camera rotation
</summary>
<returns>Vector 3
</returns>
public static Vector3 CameraRotation
{
get
{
return cameraRotation;
} // get
} // CameraRotation
<summary>
Remember inverse view matrix.
</summary>
private static Matrix invViewMatrix;
<summary>
Inverse view matrix
</summary>
<returns>Matrix
</returns>
public static Matrix InverseViewMatrix
{
get
{
return invViewMatrix;//Matrix.Invert(ViewMatrix);
} // get
} // InverseViewMatrix
<summary>
View projection matrix
</summary>
<returns>Matrix
</returns>
public static Matrix ViewProjectionMatrix
{
get
{
return ViewMatrix * ProjectionMatrix;
} // get
} // ViewProjectionMatrix
<summary>
World view projection matrix
</summary>
<returns>Matrix
</returns>
public static Matrix WorldViewProjectionMatrix
{
get
{
return WorldMatrix * ViewMatrix * ProjectionMatrix;
} // get
} // WorldViewProjectionMatrix
public static Vector3 LightDirection
{
get
{
// Note: Not really used here yet, only for the Model.Render method!
// Note2: Because we have no valid tangent data, the model will
// not look right yet, read Chapter 7 on how to fix that.
return new Vector3(0, 0, 1);
} // get
} // LightDirection
<summary>
Move factor per second
</summary>
public static float MoveFactorPerSecond
{
get
{
// Not really implemented here. This is just a quick hack.
// See later chapters for the full implementation!
return 1.0f / FpsCounter.Fps;
} // get
} // MoveFactorPerSecond
#endregion
#region Constructor
<summary>
Create base game
</summary>
public BaseGame()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
if !XBOX360
this.Components.Add(new ScreenshotCapturer(this));
endif
} // BaseGame()
<summary>
Initialize
</summary>
protected override void Initialize()
{
// Remember device
device = graphics.GraphicsDevice;
// Remember resolution
width = graphics.GraphicsDevice.Viewport.Width;
height = graphics.GraphicsDevice.Viewport.Height;
// Create matrices for our shaders, this makes it much easier to manage
// all the required matrices and we have to do this ourselfs since there
// is no fixed function support and theirfore no Device.Transform class.
WorldMatrix = Matrix.Identity;
aspectRatio = (float)width / (float)height;
ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(
FieldOfView, aspectRatio, NearPlane, FarPlane);
// ViewMatrix is updated in camera class
ViewMatrix = Matrix.CreateLookAt(
new Vector3(0, 0, 15), Vector3.Zero, Vector3.Up);
// Init global manager classes, which will be used all over the place ^^
lineManager2D = new LineManager2D();
lineManager3D = new LineManager3D();
// Create font
font = new TextureFont();
base.Initialize();
} // Initialize()
<summary>
Graphic content container, just holds a link to every resource we
create.
</summary>
static List<IGraphicContent> graphicContent =
new List<IGraphicContent>();
<summary>
Register a IGraphicContent object to our internal graphicContent
container in case we need to recreate the graphic content later.
</summary>
<param name="obj">Graphic object
<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)
{
// Remember device
device = graphics.GraphicsDevice;
// Recreate all content files
foreach (IGraphicContent contentItem in
// Create a new temporary list to prevent direct modification
new List<IGraphicContent>(graphicContent))
contentItem.Load();
} // 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)
{
// Dispose everything, but start with the stuff we create.
foreach (IGraphicContent contentItem in graphicContent)
contentItem.Dispose();
SpriteHelper.Dispose();
// Make sure there is nothing left
content.Unload();
} // if
base.UnloadGraphicsContent(unloadAllContent);
} // UnloadGraphicsContent(loadAllContent)
#endregion
#region Update
<summary>
Update
</summary>
<param name="
gameTime">Game time
</param>
protected override void Update(GameTime
gameTime)
{
//unused:
Sound.Update();
Input.Update();
if (Input.KeyboardEscapeJustPressed ||
Input.GamePadBackJustPressed)
this.Exit();
base.Update(gameTime);
} // Update(gameTime)
#endregion
#region Draw
<summary>
Draw
</summary>
<param name="
gameTime">Game time
</param>
protected override void Draw(GameTime
gameTime)
{
// Draw all sprites and fonts
SpriteHelper.DrawSprites(width, height);
font.WriteAll();
lineManager2D.Render();
lineManager3D.Render();
base.Draw(gameTime);
// Allow clearing background next frame
clearedYet = false;
} // Draw(gameTime)
#endregion
#region ClearBackground
private bool clearedYet = false;
<summary>
Clear background, will only be executed once per frame, so
it is save to call it multiple times.
</summary>
public void ClearBackground()
{
if (clearedYet == false)
graphics.GraphicsDevice.Clear(BackgroundColor);
clearedYet = true;
} // ClearBackground()
#endregion
#region Line helper methods
<summary>
Draw line
</summary>
<param name="startPoint">Start point
</param>
<param name="endPoint">End point
</param>
<param name="color">
Color</param>
public static void DrawLine(Point startPoint, Point endPoint,
Color color)
{
lineManager2D.AddLine(startPoint, endPoint, color);
} // DrawLine(startPoint, endPoint, color)
<summary>
Draw line
</summary>
<param name="startPoint">Start point
</param>
<param name="endPoint">End point
</param>
public static void DrawLine(Point startPoint, Point endPoint)
{
lineManager2D.AddLine(startPoint, endPoint,
Color.White);
} // DrawLine(startPoint, endPoint)
<summary>
Draw line
</summary>
<param name="startPos">Start position
</param>
<param name="endPos">End position
</param>
<param name="color">
Color</param>
public static void DrawLine(Vector3 startPos, Vector3 endPos,
Color color)
{
lineManager3D.AddLine(startPos, endPos, color);
} // DrawLine(startPos, endPos, color)
<summary>
Draw line
</summary>
<param name="startPos">Start position
</param>
<param name="endPos">End position
</param>
<param name="startColor">Start color
</param>
<param name="endColor">End color
</param>
public static void DrawLine(Vector3 startPos, Vector3 endPos,
Color startColor,
Color endColor)
{
lineManager3D.AddLine(startPos, startColor, endPos, endColor);
} // DrawLine(startPos, endPos, startColor)
<summary>
Draw line
</summary>
<param name="startPos">Start position
</param>
<param name="endPos">End position
</param>
public static void DrawLine(Vector3 startPos, Vector3 endPos)
{
lineManager3D.AddLine(startPos, endPos,
Color.White);
} // DrawLine(startPos, endPos)
<summary>
Flush line manager 2D. Renders all lines and allows more lines
to be rendered. Used to render lines into textures and stuff.
</summary>
public static void FlushLineManager2D()
{
lineManager2D.Render();
} // FlushLineManager2D()
<summary>
Flush line manager 3D. Renders all lines and allows more lines
to be rendered.
</summary>
public static void FlushLineManager3D()
{
lineManager3D.Render();
} // FlushLineManager3D()
#endregion
} // class BaseGame
} // namespace XnaGraphicEngine.Game
(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.
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2780434-1";
urchinTracker();
</script>