 |
//-----------------------------------------------------------------------------
// File: App.cs
//
// Desc: Sample code for Introduction to 3D Game Engine Design
//
// This sample shows the basic application software that sets up the
// base application and the process flow. The application uses a version
// of the CD3DApplication base class provided with the Microsoft
// DirectX 9 SDK to perform the standard initialization of DirectX.
//
// Note: This code uses the D3D Framework helper library.
//
// Copyright (c) 2002 Lynn T. Harrison. All rights reserved.
//-----------------------------------------------------------------------------
using System;
using System.Drawing;
using System.Collections;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.Directlnput;
using GameEngine;
using GameAI;
namespace SampleGame
{
/// <summary>
/// Summary description for GameEngine.
/// </summary>
class CGameApplication : GraphicsSample
{
#region // Game State enumeration
/// <summary>
/// Each member of this enumeration is one possible state for the
/// application
/// </summary>
///
/// <remarks>
/// DevSplash -Display the developer splash screen
/// </remarks>
/// <remarks>
/// GameSplash -Display the game splash screen
/// </remarks>
/// <remarks>
/// OptionsMain -Display and process the primary options screen
/// </remarks>
/// <remarks>
/// GamePlay -State to actually play the game
/// </remarks>
/// <remarks>
/// AfterActionReview - Display the results of the game
/// </remarks>
public enum GameState
{
/// <summary>
/// Display the developer splash screen
/// </summary>
DevSplash,
/// <summary>
/// Display the game splash screen
/// </summary>
GameSplash,
/// <summary>
/// Display and process the primary options screen
/// </summary>
OptionsMain,
/// <summary>
/// State to actually play the game
/// </summary>
GamePlay,
/// <summary>
/// Display the results of the game
/// </summary>
AfterActionReview,
}
#endregion
#region // Application member variables
/// <summary>
/// Current state of the application
/// </summary>
private GameState m_State;
private static CGameEngine m_Engine = new CGameEngine();
private GraphicsFont m_pFont = null;
private GameEngine.Console m_Console;
private ArrayList m_opponents = null;
private OptionScreen m_OptionScreen = null;
private bool m_bShowStatistics = false;
private bool m_bScreenCapture = false;
private bool m_bUsingJoystick = true;
private bool m_bUsingKeyboard = false;
private bool m_bUsingMouse = false;
private Ownship m_ownship = null;
private Cloth m_flag = null;
private Jukebox music = null;
#endregion
public static CGameEngine Engine { get { return m_Engine; } }
/// <summary>
/// Application constructor. Sets attributes for the app.
/// </summary>
public CGameApplication()
{
// Initialize the game state for the developer splash screen.
m_State = GameState.DevSplash;
m_pFont = new GraphicsFont( "Aerial", System.Drawing.FontStyle.Bold );
windowed = false;
m_opponents = new ArrayList();
}
/// <summary>
/// Called during initial app startup, this function performs all the
/// permanent initialization.
/// </summary>
protected override void OneTimeSceneInitialization()
{
// Initialize the font's internal textures.
m_pFont.InitializeDeviceObjects( device );
// Nothing much to do yet - will be used in later chapters.
m_Engine.Initialize( this, device );
CGameEngine.Inputs.MapKeyboardAction(Key.Escape,
new ButtonAction (Terminate), true);
CGameEngine.Inputs.MapKeyboardAction(Key.A,
new ButtonAction(MoveCameraXM), false);
CGameEngine.Inputs.MapKeyboardAction (Key.W,
new ButtonAction(MoveCameraZP), false);
CGameEngine.Inputs.MapKeyboardAction(Key.S,
new ButtonAction(MoveCameraXP), false);
CGameEngine.Inputs.MapKeyboardAction (Key.Z,
new ButtonAction(MoveCameraZM), false);
CGameEngine.Inputs.MapKeyboardAction(Key.P,
new ButtonAction(ScreenCapture), true);
CGameEngine.Inputs.MapMouseAxisAction(0,
new AxisAction(PointCamera));
CGameEngine.Inputs.MapMouseAxisAction(1,
new AxisAction(PitchCamera));
m_Console = new GameEngine.Console( m_pFont, "console.jpg" );
GameEngine.Console.AddCommand( "QUIT", "Terminate the game",
new CommandFunction(TerminateCommand));
GameEngine.Console.AddCommand( "STATISTICS",
"Toggle statistics display",
new CommandFunction(ToggleStatistics));
m_OptionScreen = new OptionScreen( "Options1.jpg");
m_OptionScreen.AddButton( 328, 150, "PlayOff.jpg", "PlayOn.jpg",
"PlayHover.jpg", new ButtonFunction(Play) );
m_OptionScreen.AddButton(328, 300, "QuitOff.jpg", "QuitOn.jpg",
"QuitHover.jpg", new ButtonFunction(Terminate) );
m_Engine.SetOptionScreen( m_OptionScreen );
music = new Jukebox();
music.AddSong("nadine.mp3");
music.AddSong("ComeOn.mp3");
music.AddSong("Rock.mp3");
music.Volume = 0.75f;
music.Play();
}
/// <summary>
/// Called once per frame, the call is the entry point for all game
/// processing. This function calls the appropriate part of the
/// game engine based on the
/// engine based on the current state.
/// </summary>
protected override void FrameMove()
{
try
{
SelectControls select_form = null;
// get any player inputs
m_Engine.GetPlayerInputs();
// Clear the viewport.
device.Clear( ClearFlags.Target | ClearFlags.ZBuffer,
0×00000000, 1.0f, 0 );
device.BeginScene();
// Determine what needs to be rendered based on the current game state,
switch ( m_State )
{
case GameState.DevSplash:
if ( m_Engine.ShowSplash("devsplash.jpg", 8,
new BackgroundTask(LoadOptions)) )
{
m_State = GameState.GameSplash;
}
break;
case GameState.GameSplash:
if ( m_Engine.ShowSplash("gamesplash.jpg", 8, null) )
{
m_State = GameState.OptionsMain;
select_form = new SelectControls();
select_form.ShowDialog(this);
m_bUsingJoystick = select_form.UseJoystick.Checked;
m_bUsingKeyboard = select_form.UseKeyboard.Checked;
m_bUsingMouse = select_form.UseMouse.Checked;
if ( m_bUsingJoystick )
GameEngine.Console.AddLine("Using Joystick");
if ( m_bUsingKeyboard )
GameEngine.Console.AddLine("Using Keyboard");
if ( m_bUsingMouse )
GameEngine.Console.AddLine("Using Mouse");
m_ownship = (Ownship)Engine.GetObject("car1");
m_ownship.UseJoystick = m_bUsingJoystick;
m_ownship.UseKeyboard = m_bUsingKeyboard;
m_ownship.UseMouse = m_bUsingMouse;
}
break;
case GameState.OptionsMain:
m_Engine.DoOptions();
break;
case GameState.GamePlay:
m_Engine.GetPlayerInputs();
m_Engine.DoAI( elapsedTime );
m_Engine.DoDynamics( elapsedTime );
m_Engine.DoNetworking( elapsedTime );
m_Engine.Render();
break;
case GameState.AfterActionReview:
m_Engine.DoAfterActionReview();
break;
}
GameEngine.Console.Render();
if ( m_ownship != null && m_State == GameState.GamePlay )
{
m_pFont.DrawText( 200, 560, Color.FromArgb(255,0,0,0),
m_ownship.MPH.ToString() );
m_pFont.DrawText( 200, 580, Color. FromArgb(255, 0,0,0),
m_ownship.ForwardVelocity.ToString() );
m_pFont.DrawText( 200, 600, Color.FromArgb(255,0,0,0),
m_ownship.SidewaysVelocity.ToString() );
}
// Output statistics.
if ( m_bShowStatistics )
{
m_pFont.DrawText( 2, 560, Color.FromArgb(255,255,255,0),
frameStats );
m_pFont.DrawText( 2, 580, Color.FromArgb(255,255,255,0),
deviceStats );
}
if ( m_bScreenCapture )
{
SurfaceLoader.Save("capture.bmp",ImageFileFormat.Bmp,
device.GetBackBuffer(0,0,BackBufferType.Mono));
m_bScreenCapture = false;
GameEngine.Console.AddLine("snapshot taken");
}
}
catch (DirectXException d3de)
{
System.Diagnostics.Debug.WriteLine(
"Error in Sample Game Application FrameMove" );
System.Diagnostics.Debug.WriteLine(d3de.ErrorString);
}
catch ( Exception e )
{
System.Diagnostics.Debug.WriteLine(
"Error in Sample Game Application FrameMove");
System.Diagnostics.Debug.WriteLine(e.Message);
}
finally
{
device.EndScene();
}
}
/// <summary>
/// The main entry point for the application
/// </summary>
[STAThread]
static void Main(string[] args)
{
try
{
CGameApplication d3dApp = new CGameApplication();
if (d3dApp.CreateGraphicsSample())
d3dApp.Run();
}
catch (DirectXException d3de)
{
System.Diagnostics.Debug.WriteLine(
"Error in Sample Game Application" );
System.Diagnostics.Debug.WriteLine(d3de.ErrorString);
}
catch ( Exception e )
{
System.Diagnostics.Debug.WriteLine(
"Error in Sample Game Application" );
System.Diagnostics.Debug.WriteLine(e.Message);
}
}
// Action functions
/// <summary>
/// Action to start playing
/// </summary>
public void Play()
{
m_State = GameState.GamePlay;
GameEngine.Console.Reset();
}
/// <summary>
/// Action to terminate the application
/// </summary>
public void Terminate()
{
m_bTerminate = true;
}
/// <summary>
/// Screen capture
/// </summary>
public void ScreenCapture()
{
m_bScreenCapture = true;
}
/// <summary>
/// Version of terminate for use by the console
/// </summary>
/// <param name="sData"></param>
public void TerminateCommand( string sData )
{
Terminate();
}
/// <summary>
/// Toggle the display of statistics information.
/// </summary>
/// <param name="sData"></param>
public void ToggleStatistics( string sData )
{
m_bShowStatistics = !m_bShowStatistics;
}
/// <summary>
/// Action to transition to the next game state based on a mapper action
/// </summary>
public void NextState()
{
if ( m_State < GameState.AfterActionReview )
{
m_State++;
}
else
{
m_State = GameState.OptionsMain;
}
}
public void PointCamera( int count )
{
m_Engine.MoveCamera(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, count);
}
public void PitchCamera( int count )
{
m_Engine.MoveCamera(0.0f, 0.0f, 0.0f, count * 0.1f, 0.0f, 0.0f);
}
public void MoveCameraXP()
{
m_Engine.MoveCamera(0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
}
public void MoveCameraXM()
{
m_Engine.MoveCamera(−0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
}
public void MoveCameraY()
{
m_Engine.MoveCamera(0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f);
}
public void MoveCameraZP()
{
m_Engine.MoveCamera(0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f);
}
public void MoveCameraZM()
{
m_Engine.MoveCamera(0.0f, 0.0f, −0.5f, 0.0f, 0.0f, 0.0f);
}
/// <summary>
///
/// </summary>
protected override void RestoreDeviceObjects(System.Object sender,
System.EventArgs e)
{
// Set the transform matrices (view and world are updated per frame).
Matrix matProj;
float fAspect = device.PresentationParameters.BackBufferWidth /
(float)device.PresentationParameters.BackBufferHeight;
matProj = Matrix.PerspectiveFovLH( (float)Math.PI/4, fAspect,
1.0f, 100.0f );
device.Transform.Projection = matProj;
// Set up the default texture states.
device.TextureState[0].ColorOperation = TextureOperation.Modulate;
device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
device.TextureState[0].AlphaOperation = TextureOperation.SelectArg1;
device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
device.SamplerState[0].MinFilter = TextureFilter.Linear;
device.SamplerState[0].MagFilter = TextureFilter.Linear;
device.SamplerState[0].MipFilter = TextureFilter.Linear;
device.SamplerState[0].AddressU = TextureAddress.Clamp;
device.SamplerState[0].AddressV = TextureAddress.Clamp;
device.RenderState.DitherEnable = true;
}
/// <summary>
/// Called when the app is exiting, or the device is being changed, this
/// function deletes any device-dependent objects.
/// </summary>
protected override void DeleteDeviceObjects(System.Object sender,
System.EventArgs e)
{
m_Engine.Dispose();
}
public void LoadOptions()
{
try
{
System.Random rand = new System.Random();
// Loading of options will happen here.
m_Engine.SetTerrain(200, 200, "heightmap.jpg", "sand1.jpg", 10.0f, 0.45f);
for ( int i=0; i<300; i++ )
{
float north = (float) (rand.NextDouble() * 1900.0);
float east = (float) (rand.NextDouble() * 1900.0);
BillBoard.Add( east, north, 0.0f, "cactus"+i, "cactus.dds",
1.0f, 1.0f);
}
for ( int i=0; i<300; i++ )
{
float north = (float) (rand.NextDouble() * 1900.0);
float east = (float) (rand.NextDouble() * 1900.0);
BillBoard.Add( east, north, 0.0f, "tree"+i, "palmtree.dds",
6.5f, 10. 0f);
}
GameEngine.Console.AddLine("all trees loaded");
m_Engine.AddObject(new ParticleGenerator("Spray1", 2000, 2000,
Color.Yellow, "Particle.bmp",
new ParticleUpdate(Gravity)));
double j = 0.0;
double center_x = 1000.0;
double center_z = 1000.0;
double radius = 700.0;
double width = 20.0;
m_flag = new Cloth ("flag", "flag.jpg", 2, 2, 0.1, 1.0f);
m_flag.Height = 0.6f;
m_flag.North = 2.0f;
m_flag.East = 0.1f;
Cloth.EastWind = −3.0f;
for ( double i=0.0; i<360.0; i += 1.5 )
{
float north = (float) (center_z +
Math.Cos(i/180.0*Math.PI) * radius);
float east = (float) (center_x +
Math.Sin(i/180.0*Math.PI) * radius );
BillBoard.Add( east, north, 0.0f, "redpost"+
(int) (i*2), "redpost.dds",0.25f, 1.0f);
j += 5.0;
if ( j > 360.0 ) j −= 360.0;
}
j = 0.0;
for ( double i=0.5; i<360.0; i += 1.5 )
{
float north = (float) (center_z +
Math.Cos(i/180.0*Math.PI) * (radius+width) );
float east = (float) (center_x +
Math.Sin(i/180.0*Math.PI) * (radius+width) );
BillBoard.Add(east, north, 0.0f, "bluepost"+
(int)(i*2), "bluepost.dds",0.25f, 1.0f);
j += 5.0;
if ( j >= 360.0 ) j −= 360.0;
}
m_ownship = new Ownship(this, "car1", "SprintRacer.x",
new Vector3(0.0f, 0.8f, 0.0f),
new Attitude(0.0f, (float)Math.PI, 0.0f));
m_ownship.AddChild(m_flag);
SoundEffect.Volume = 0.25f;
m_Engine.AddObject( m_ownship );
m_own ship.North = 298.0f;
m_ownship.East = 1000.0f;
m_Engine.Cam.Attach(m_ownship, new Vector3(0.0f, 0.85f,−4.5f));
m_Engine.Cam.LookAt(m_ownship);
m_ownship.Heading = (float)Math.PI * 1.5f;
m_ownship.SetLOD( 10, 3000.0f );
GameEngine.GameLights headlights =
GameEngine.GameLights.AddSpotLight(
new Vector3(0.0f, 0.0f, 0.0f),
new Vector3(1.0f, 0.0f, 1.0f), Color.White, "headlight");
headlights.EffectiveRange = 200.0f;
headlights.Attenuation0 = 1.0f;
headlights.Attenuation1 = 0.0f;
headlights.InnerConeAngle = 1.0f;
headlights.OuterConeAngle = 1.5f;
headlights.PositionOff set = new Vector3(0.0f, 2.0f, 1.0f);
headlights.DirectionOffset = new Vector3(0.0f, 0.00f, 1.0f);
m_ownship.AddChild(headlights);
headlights.Enabled = false;
CGameEngine.FogColor = Color.Beige;
CGameEngine.FogDensity = 0.5f;
CGameEngine.FogEnable = true;
CGameEngine.FogStart = 100.0f;
CGameEngine.FogEnd = 900.0f;
CGameEngine.FogTableMode = FogMode.Linear;
}
catch ( Exception e )
{
GameEngine.Console.AddLine("Exception");
GameEngine.Console.AddLine(e.Message);
}
}
public void Gravity ( ref Particle Obj, float DeltaT )
{
Obj.m_Position += Obj.m_Velocity * DeltaT;
Obj.m_Velocity.Y += −9.8f * DeltaT;
if ( Obj.m_Position.Y < 0.0f ) Obj.m_bActive = false;
}
public void OwnshipUpdate( Object3D Obj, float DeltaT )
{
}
public void OpponentUpdate( Object3D Obj, float DeltaT )
{
Obj.Height = CGameEngine.Ground.HeightOfTerrain(Obj.Position) +
((Model)Obj).Offset.Y;
}
}
}
 |