/*
God.cpp
Written by Matthew Fisher
The God class glues the operating system, the graphics device, the application interface,
and the window manager together. It is essentially the first and the last code that is executed.
See God.h for a description of the class and member functions.
*/
//All source files include Main.h
#include "Main.h"
const int GraphicsDeviceType = GD_D3D;
//GraphicsDeviceType tells God what type of graphics device/API to use.
//possible choices are:
//GD_D3D -> DirectX API
//GD_OpenGL -> OpenGL API
//GD_Software -> Software rendering
//DirectX offers more functionality, but many people find it harder to understand and it's Windows only
//OpenGL is more widely supported but doesn't have nice things like N-Patching built in
//Software is written by me, by hand, and is slow and has very limited functionality
//you'll need #define USE_DIRECTX or #define USE_OPENGL (in Main.h) to use DirectX or OpenGL
const int ScreenWidth = 1280;
const int ScreenHeight = 800; //only one full screen mode is supported; this is the full screen width/height
const int WindowWidth = 720 + WindowBorderWidth;
const int WindowHeight = 640 + WindowBorderHeight; //the default windowed-mode window width and height. The window can be manually resized.
const bool FullScreenStart = false; //true to start in full screen mode. If you're debugging, windowed mode is usually better
const bool VSync = true; //true to wait for the monitor to finish the entire display (vertical retracing) before
//the front buffer is flipped. Setting this to false results in higher frame rate, but may
//induce flickering.
const bool CapturingScreen = false; //true if capturing of the screen to an AVI file is requested. press "C" to start capturing.
const int CaptureWidth = 800; //width and height of the captured video file images
const int CaptureHeight = 600;
const char AVIFileName[] = "C:\\test.avi"; //file name to save the captured images to
const float AvgFrameRate = 20.0f; //target frame rate to advance the scene at when capturing files
const int MilliSecondsPerFrame = int(1000.0f / AvgFrameRate); //milliseconds elapsed per frame in the target frame rate provided above
const int SleepBetweenFrames = 0; //time to sleep between frame, in milliseconds.
void God::Init(HINSTANCE hInstance, int nCmdShow)
{
#ifdef USE_VIDEO_TEXTURES
CoInitialize(NULL); //initalize COM objects. So far I use only one COM object, DirectX video textures.
//so this line is skipped if they are not used.
#endif
for(UINT i=0;i<256;i++)
{
key[i] = 0; //by default all keys are not pressed
}
//create a new GraphicsDevice object based upon the type of graphics device requested in GraphicsDeviceType
if(GraphicsDeviceType == GD_Software) GD = new SoftwareGraphicsDevice;
#ifdef USE_DIRECTX
else if(GraphicsDeviceType == GD_D3D) GD = new D3DGraphicsDevice;
#endif
#ifdef USE_OPENGL
else if(GraphicsDeviceType == GD_OpenGL) GD = new OpenGLGraphicsDevice;
#endif
else FatalMB("Invalid choice of graphics device type.");
CaptureStarted = false; //don't capture from the very beginning, wait for the user to give the signal
FullScreen = FullScreenStart; //start in the requested full screen mode
IgnoreReSize = true; //when we create a new window we want to ignore Win32's resize command
if(FullScreen)
WM.InitAll(hInstance, nCmdShow, FullScreen, ScreenWidth, ScreenHeight); //create a new full screen sized window
else
WM.InitAll(hInstance, nCmdShow, FullScreen, WindowWidth, WindowHeight); //create a new windowed window
if(CapturingScreen) Capture.OpenFile(AVIFileName,MilliSecondsPerFrame,CaptureWidth,CaptureHeight); //open the AVI if requested
GD->SetVSync(VSync); //set the GD vertical synchronization property
GD->Init3D(WM); //initalize the graphics device's 3D properties
if(FullScreen) ShowCursor(FALSE); //hide the cursor if we're in full screen
GD->SetScreenColor(RGBColor(0,0,0)); //default clear color is black
GD->SetWireframe(); //wireframe is on by default
T.Start(60.0f); //start at a guessed frame rate of 60 fps; this will be fixed in a few seconds to the "real" value
T.Pause(); //ignore the first few frames from causing an abnormally low FPS
App.Init(*GD, WM); //initalize this application's graphics objects
}
void God::RenderFrame()
{
GD->StartRender(WM); //have the Graphics device prepare a new frame
if(GD->GetSystemActive()) //if we are good to render (we wouldn't be if say we were in the middle of a window change)
{
T.Frame(); //update the FPS counter
App.Render(*GD, WM); //have the application render its objects through the graphics device
GD->DrawDouble("fps - > ", T.GetFramesPerSec(), 0, 0); //draw the FPS
if(SleepBetweenFrames) Sleep(SleepBetweenFrames);
} else {
T.Pause(); //if we aren't good to render, don't update the FPS counter
}
GD->FinishRender(WM, App); //put the rendered scene onto the screen
}
void God::CaptureFrame()
{
if(key[KEY_C]) CaptureStarted = true; //if the user requests it, begin capturing frames to the AVI file
if(CaptureStarted)
{
Capture.ScreenFrame(); //get the current frame and put it into the file
T.SetFPS(AvgFrameRate); //control the frame rate directly; otherwise we'd factor in the time it took to compress
//the scene, which would be bad.
}
}
void God::FullScreenMouseChange()
{
if(FullScreen)
{
ShowCursor(FALSE);
SetCursor(NULL); //hide the cursor if full screen
}
else
{
ShowCursor(TRUE);
SetCursor(LoadCursor(NULL, IDC_ARROW)); //show the cursor if windowed
}
}
void God::ResetGraphicsObjects()
{
T.Pause();
App.ReInit(*GD, WM); //reinialize all the scene objects
}
void God::HandleAltEnter()
{
T.Pause();
key[KEY_ALT_ENTER] = 0;
FullScreen = !FullScreen;
IgnoreReSize = true;
if(FullScreen)
WM.ResetWindow(FullScreen, SW_SHOW, ScreenWidth, ScreenHeight);
else
WM.ResetWindow(FullScreen, SW_SHOW, WindowWidth, WindowHeight); //toggle full screen mode
GD->ReSizeFullScreen(WM, App); //tell the graphics device what we did
ShowWindow(WM.GetHWND(),SW_SHOW);
SetForegroundWindow(WM.GetHWND());
SetFocus(WM.GetHWND()); //make sure our window is visible and has focus
FullScreenMouseChange(); //update the mouse
}
void God::HandleReSize()
{
T.Pause(); //avoid jerkiness in the frame timer
ReSizeDevice = false;
if(IgnoreReSize) IgnoreReSize = false; //if this is a new resize event to us,
else GD->ReSize(WM, App); //tell the graphics device to resize
}
void God::MessageLoop(HINSTANCE hInstance, int nCmdShow)
{
//the main Windows message loop
MSG msg;
BOOL bGotMsg;
PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE ); //get a new message
while( WM_QUIT != msg.message ) //while we don't have the quit message
{
bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ); //get a new message
if( bGotMsg ) //if we have a message
{
TranslateMessage( &msg ); //send it out
DispatchMessage( &msg );
}
else
{
//if we have no messages we decide it's a good time to render
RenderFrame(); //render a new frame
if(CapturingScreen) CaptureFrame(); //if we're capturing the screen, do so
if(key[KEY_ALT_ENTER]) HandleAltEnter(); //toggle full screen display if the user Alt+Enters
if(ReSizeDevice && !FullScreen) HandleReSize(); //if we're in a window and the user resizes it
if(GD->NeedToRestoreDevices()) //if we've lost devices,
{
T.Pause(); //pause the timer for a short bit,
ResetGraphicsObjects(); //reset the graphics objects,
GD->DevicesRestored(); //tell the GD everything's okay
}
}
}
}
void God::FreeMemory()
{
App.End(); //free application data
WM.FreeMemory(); //free the window
GD->FreeMemory(); //free the graphics API data
delete GD; //delete the graphics device
if(CapturingScreen) Capture.CloseFile(); //if we were capturing the screen, finalize the file
#ifdef USE_VIDEO_TEXTURES
CoUninitialize(); //frees COM objects, if we're using them
#endif
}
Top