www.pudn.com > IntroductionTo3DGameEngineDesign.rar > GameEngine.cs
//-----------------------------------------------------------------------------
// File: GameEngine.cs
//
// Desc: GameEngine code for Chapter 1 of Introduction to 3D Game Engine Design.
//
// This File contains the GameEngine class definition for Chapter 1. You
// will notice that at this point it consists of only a few stub methods
// That provide no functionality yet.
//
// Copyright (c) 2002 Lynn T. Harrison All rights reserved.
//-----------------------------------------------------------------------------
using System;
using System.Threading;
using System.Diagnostics;
using System.Drawing;
using System.Collections;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;
using Microsoft.DirectX.Direct3D;
namespace GameEngine
{
///
/// Summary description for GameEngine.
/// This is the definition of the 3D game engine developed as part of the bok
/// Introduction to 3D Game Engine Design.
///
#region delegates
public delegate void BackgroundTask();
#endregion
public class CGameEngine : IDisposable
{
#region Attributes
// A local reference to the DirectX device
private static Microsoft.DirectX.Direct3D.Device m_pd3dDevice;
private System.Windows.Forms.Form m_WinForm;
private SplashScreen m_SplashScreen = null;
private OptionScreen m_OptionScreen = null;
private SkyBox m_Skybox = null;
private Camera m_Camera = null;
public static GameInput m_GameInput = null;
private static Terrain m_Terrain = null;
private static Quad m_QuadTree = null;
private ArrayList m_Objects = null;
private ArrayList m_Cameras = null;
public float fTimeLeft = 0.0f;
Thread m_threadTask = null;
#endregion
#region Properties
public Camera Cam { get { return m_Camera; } }
public ArrayList Objects { get { return m_Objects; } }
public static Terrain Ground { get { return m_Terrain; } }
public static Quad QuadTree { get { return m_QuadTree; } }
public static Microsoft.DirectX.Direct3D.Device Device3D { get { return m_pd3dDevice; } }
public static GameInput Inputs { get { return m_GameInput; } }
public static Color FogColor { set { m_pd3dDevice.RenderState.FogColor = value; } }
public static FogMode FogTableMode { set { m_pd3dDevice.RenderState.FogTableMode = value; } }
public static FogMode FogVertexMode { set { m_pd3dDevice.RenderState.FogVertexMode = value; } }
public static float FogDensity { set { m_pd3dDevice.RenderState.FogDensity = value; } }
public static float FogStart { set { m_pd3dDevice.RenderState.FogStart = value; } }
public static float FogEnd { set { m_pd3dDevice.RenderState.FogEnd = value; } }
public static bool FogEnable { set { m_pd3dDevice.RenderState.FogEnable = value; } }
#endregion
int frame = 0;
public void Dispose()
{
Debug.WriteLine("disposing of game engine objects");
m_GameInput.Dispose();
Debug.WriteLine("disposing of terrain");
if ( m_Terrain != null ) m_Terrain.Dispose();
Debug.WriteLine("disposing of skybox");
m_Skybox.Dispose();
Debug.WriteLine("disposing of quadtree");
m_QuadTree.Dispose();
Debug.WriteLine("disposing of splashscreen");
if ( m_SplashScreen != null )
{
m_SplashScreen.Dispose();
}
Debug.WriteLine("disposing of optionscreen");
if ( m_OptionScreen != null )
{
m_OptionScreen.Dispose();
}
Debug.WriteLine("number of objects="+m_Objects.Count);
for ( int i=0; i < m_Objects.Count; i++ )
{
try
{
Object3D obj = (Object3D)m_Objects[i];
Debug.WriteLine("calling dispose for " + obj.Name);
obj.Dispose( );
}
catch
{
}
}
for ( int i=0; i < BillBoard.Objects.Count; i++ )
{
Object3D obj = (Object3D)BillBoard.Objects[i];
obj.Dispose();
}
}
public void RestoreSurfaces()
{
if ( m_SplashScreen != null )
{
m_SplashScreen.Restore();
}
if ( m_OptionScreen != null )
{
m_OptionScreen.Restore();
}
}
public void SetOptionScreen( OptionScreen Screen )
{
m_OptionScreen = Screen;
}
///
/// Initial setup of the Game Engine
///
///
public void Initialize ( System.Windows.Forms.Form form, Microsoft.DirectX.Direct3D.Device pd3dDevice )
{
// capture a reference to the window handle
m_WinForm = form;
// For now just capture a reference to the DirectX device for future use
m_pd3dDevice = pd3dDevice;
m_GameInput = new GameInput( m_WinForm );
m_Skybox = new SkyBox(@"..\..\Resources\Dunes_Front.tga",
@"..\..\Resources\Dunes_Right.tga",
@"..\..\Resources\Dunes_Back.tga",
@"..\..\Resources\Dunes_Left.tga",
@"..\..\Resources\Dunes_Top.tga",
@"..\..\Resources\Dunes_Bottom.tga" );
m_Camera = new Camera();
m_Cameras = new ArrayList();
m_Cameras.Add(m_Camera);
m_Objects = new ArrayList();
m_pd3dDevice.RenderState.Ambient = System.Drawing.Color.Gray;
// Set light #0 to be a simple, faint grey directional light so
// the walls and floor are slightly different shades of grey
m_pd3dDevice.RenderState.Lighting = true; // was true
GameLights.InitializeLights();
// SetDefaultStates( );
}
///
/// Display a Splash Screen based on a suppplied bitmap filename
///
///
public bool ShowSplash ( string sFileName, int nSeconds, BackgroundTask task )
{
bool bDone = false;
if ( m_SplashScreen == null )
{
m_SplashScreen = new SplashScreen( sFileName, nSeconds);
if ( task != null )
{
m_threadTask = new Thread(new ThreadStart(task) );
m_threadTask.Name = "Game_backgroundTask";
m_threadTask.Start();
}
}
bDone = m_SplashScreen.Render();
fTimeLeft = m_SplashScreen.fTimeLeft;
if ( bDone )
{
m_SplashScreen.Dispose();
m_SplashScreen = null;
}
return bDone;
}
///
/// Display the Options screen
///
public void DoOptions ( )
{
if ( m_OptionScreen != null )
{
m_OptionScreen.SetMousePosition(m_GameInput.GetMousePoint().X, m_GameInput.GetMousePoint().Y, m_GameInput.IsMouseButtonDown(0) );
m_OptionScreen.Render();
}
}
///
/// Display the latest game frame
///
public void Render ( )
{
m_Camera.Render();
m_QuadTree.Cull( m_Camera );
GameLights.CheckCulling( m_Camera );
// test code
Model ownship = (Model)GetObject("car1");
if ( ownship != null && ownship.IsCulled )
{
Console.AddLine("ownship culled at " + ownship.North + " " + ownship.East + " H " + ownship.Heading );
}
GameLights.DeactivateLights();
if ( m_Skybox != null )
{
m_Skybox.Render( m_Camera );
}
GameLights.SetupLights();
if ( m_Terrain != null )
{
m_Terrain.Render( m_Camera );
}
BillBoard.RenderAll( m_Camera );
foreach ( Object3D obj in m_Objects )
{
if ( !obj.IsCulled )
{
obj.Render( m_Camera );
}
}
}
void SetDefaultStates( )
{
//
// Set the recomended defaults by nVidia
//
m_pd3dDevice.RenderState.MultiSampleAntiAlias = true;
m_pd3dDevice.RenderState.MultiSampleMask = -1;
m_pd3dDevice.RenderState.ColorWriteEnable = ColorWriteEnable.Alpha | ColorWriteEnable.Blue |
ColorWriteEnable.Green | ColorWriteEnable.Red;
m_pd3dDevice.RenderState.AlphaBlendEnable = true;
m_pd3dDevice.RenderState.SourceBlend = Blend.One;
m_pd3dDevice.RenderState.DestinationBlend = Blend.Zero;
m_pd3dDevice.RenderState.BlendOperation = BlendOperation.Add;
m_pd3dDevice.RenderState.AlphaTestEnable = true; // was false
m_pd3dDevice.RenderState.AlphaFunction = Compare.Always;
// m_pd3dDevice.RenderState.AlphaReference = 0;
m_pd3dDevice.RenderState.Lighting = false; // was true
m_pd3dDevice.RenderState.Ambient = Color.FromArgb(128,255,255,255);
m_pd3dDevice.RenderState.SpecularEnable = false;
m_pd3dDevice.RenderState.LocalViewer = true;
m_pd3dDevice.RenderState.NormalizeNormals = false;
m_pd3dDevice.RenderState.ColorVertex = true;
m_pd3dDevice.RenderState.AmbientMaterialSource = ColorSource.Material;
m_pd3dDevice.RenderState.DiffuseMaterialSource = ColorSource.Color1;
m_pd3dDevice.RenderState.EmissiveMaterialSource = ColorSource.Material;
m_pd3dDevice.RenderState.SpecularMaterialSource = ColorSource.Color2;
m_pd3dDevice.RenderState.Clipping = true;
// m_pd3dDevice.RenderState.ClipPlaneEnable = 0;
m_pd3dDevice.RenderState.CullMode = Cull.CounterClockwise;
m_pd3dDevice.RenderState.FillMode = FillMode.Solid;
m_pd3dDevice.RenderState.ShadeMode = ShadeMode.Gouraud;
m_pd3dDevice.RenderState.TextureFactor = 0;
// m_pd3dDevice.RenderState.VertexBlend = VertexBlendFlags.Disable;
m_pd3dDevice.RenderState.DitherEnable = false;
m_pd3dDevice.RenderState.LastPixel = true;
m_pd3dDevice.RenderState.FogEnable = false;
m_pd3dDevice.RenderState.FogColor = Color.FromArgb(0x00ff0000);
m_pd3dDevice.RenderState.FogTableMode = Microsoft.DirectX.Direct3D.FogMode.None;
m_pd3dDevice.RenderState.FogVertexMode = Microsoft.DirectX.Direct3D.FogMode.None;
m_pd3dDevice.RenderState.RangeFogEnable = false;
m_pd3dDevice.RenderState.FogDensity = 0;
m_pd3dDevice.RenderState.FogStart = 0;
m_pd3dDevice.RenderState.StencilEnable = false;
m_pd3dDevice.RenderState.StencilFail = StencilOperation.Keep;
m_pd3dDevice.RenderState.StencilFunction = Compare.Always;
m_pd3dDevice.RenderState.StencilMask = -1;
m_pd3dDevice.RenderState.StencilPass = StencilOperation.Keep;
// m_pd3dDevice.RenderState.StencilReference = 0;
m_pd3dDevice.RenderState.StencilWriteMask = -1;
// m_pd3dDevice.RenderState.StencilZFail = StencilOperation.Keep;
m_pd3dDevice.RenderState.Wrap0 = 0;
m_pd3dDevice.RenderState.Wrap1 = 0;
m_pd3dDevice.RenderState.Wrap2 = 0;
m_pd3dDevice.RenderState.Wrap3 = 0;
m_pd3dDevice.RenderState.Wrap4 = 0;
m_pd3dDevice.RenderState.Wrap5 = 0;
m_pd3dDevice.RenderState.Wrap6 = 0;
m_pd3dDevice.RenderState.Wrap7 = 0;
// m_pd3dDevice.RenderState.ZEnable = ZB.True;
// m_pd3dDevice.RenderState.ZWriteEnable = true;
// m_pd3dDevice.RenderState.ZBias = 0;
// m_pd3dDevice.RenderState.ZFunction = Compare.LessEqual;
for( int i=0; i<4; i++ )
{
// m_pd3dDevice.SetTexture(i, null);
// m_pd3dDevice.SetTextureStageState(i, TextureStageState.TexCoordIndex, i);
// m_pd3dDevice.SetTextureStageState(i, TextureStageState.ColorArg0, (int)TextureArgument.TextureColor);
// m_pd3dDevice.SetTextureStageState(i, TextureStageState.ColorArg1, (int)TextureArgument.Diffuse);
// m_pd3dDevice.SetTextureStageState(i, TextureStageState.AlphaArg0, (int)TextureArgument.TextureColor);
// m_pd3dDevice.SetTextureStageState(i, TextureStageState.AlphaArg1, (int)TextureArgument.Diffuse);
// m_pd3dDevice.SetTextureStageState(i, TextureStageState.ColorOp, (int)TextureOp.Modulate);
// m_pd3dDevice.SetTextureStageState(i, TextureStageState.AlphaOp, (int)TextureOp.Modulate);
// m_pd3dDevice.SetTextureStageState(i, TextureStageState.TextureTransformFlags D3DTSS_MINFILTER, D3DTEXF_LINEAR );
// m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_MAGFILTER, D3DTEXF_LINEAR );
/* m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_MIPFILTER, D3DTEXF_NONE );
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_BUMPENVMAT00, 0);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_BUMPENVMAT01, 0);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_BUMPENVMAT10, 0);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_BUMPENVMAT11, 0);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_ADDRESSW, D3DTADDRESS_WRAP);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_BORDERCOLOR, 0);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_MIPMAPLODBIAS, 0);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_MAXMIPLEVEL, 0);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_MAXANISOTROPY, 1);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_BUMPENVLSCALE, 0);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_BUMPENVLOFFSET, 0);
m_pd3dDevice.SetTextureStageState(i, TextureStageStateD3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
*/
}
// m_pd3dDevice.SetTextureStageState(0, TextureStageState.ColorOperation, (int)TextureOperation.Modulate);
// Bad bad nVidia bad! hehe...
// m_pd3dDevice.RenderState D3DRS_CULLMODE, D3DCULL_CW );
// Don't do alpha as a default
m_pd3dDevice.RenderState.AlphaBlendEnable = true;
m_pd3dDevice.RenderState.SourceBlend = Blend.One;
m_pd3dDevice.RenderState.DestinationBlend = Blend.Zero;
// Set the ambient light
// ENG_SetAmbientLight( zcolor(128,128,128,255) );
}
///
/// Display the After Action Review Screen
///
public void DoAfterActionReview ( )
{
// The implementation for this will be done in a later Chapter
}
///
/// Process mouse, keyboard and if appropriate, joystick inputs
///
public void GetPlayerInputs ( )
{
m_GameInput.Poll();
}
///
/// Process any automated player artificial intelligence
///
///
public void DoAI ( float DeltaT )
{
// The implementation for this will be done in a later Chapter
}
///
/// Process any moving object dynamics
///
///
public void DoDynamics ( float DeltaT )
{
try
{
frame++;
if ( frame > 30 )
{
bool los = m_Terrain.InLineOfSight(new Vector3(0.0f, 1.0f, 0.0f ), m_Camera.EyeVector);
frame=0;
// Console.AddLine("los = " + los);
}
if ( m_Objects.Count > 0 )
{
foreach ( Object3D obj in m_Objects )
{
obj.Update( DeltaT );
}
}
}
catch (DirectXException d3de)
{
Console.AddLine("Unable to update an object " + m_Objects);
Console.AddLine(d3de.ErrorString);
}
catch ( Exception e )
{
Console.AddLine("Unable to update an object " + m_Objects);
Console.AddLine(e.Message);
}
}
///
/// Process any multiplayer state sharing if applicable
///
///
public void DoNetworking ( float DeltaT )
{
// The implementation for this will be done in a later Chapter
}
public void MoveCamera( float x, float y, float z, float pitch, float roll, float heading )
{
m_Camera.AdjustHeading( heading );
m_Camera.AdjustPitch( pitch );
// m_Camera.AdjustRoll( roll );
m_Camera.MoveCamera(x, y, z );
}
public void SetTerrain(int xSize, int ySize, string sName, string sTexture, float fSpacing, float fElevFactor)
{
Rectangle bounds = new Rectangle(0,0,(int)(xSize*fSpacing+0.9),(int)(ySize*fSpacing+0.9));
m_QuadTree = new Quad(bounds, 0, 7, null);
m_Terrain = new Terrain(xSize, ySize, sName, sTexture, fSpacing, fElevFactor);
}
public void AddObject( Object3D obj )
{
Debug.WriteLine("adding " + obj.Name + " to engine object list");
m_QuadTree.AddObject(obj);
m_Objects.Add(obj);
}
public Object3D GetObject ( string name )
{
Object3D obj = null;
foreach ( Object3D o in m_Objects )
{
if ( o.Name == name )
{
obj = o;
}
}
if ( obj == null )
{
foreach ( Object3D o in BillBoard.Objects )
{
if ( o.Name == name )
{
obj = o;
}
}
}
return obj;
}
public bool SetCamera ( string name )
{
bool success = false;
foreach ( Camera c in m_Cameras )
{
if ( c.Name == name )
{
m_Camera = c;
success = true;
}
}
return success;
}
public void AddCamera( Camera cam )
{
m_Cameras.Add(cam);
}
public void RemoveCamera ( string name )
{
Camera cam = null;
foreach ( Camera c in m_Cameras )
{
if ( c.Name == name )
{
cam = c;
break;
}
}
if ( cam != null ) m_Cameras.Remove(cam);
}
}
}