/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* * Copyright (C) 2006-2010 - Frictional Games * * This file is part of HPL1 Engine. */ #include "hpl1/engine/game/Game.h" #include "hpl1/engine/game/ScriptFuncs.h" #include "hpl1/engine/game/Updater.h" #include "hpl1/engine/graphics/Graphics.h" #include "hpl1/engine/graphics/LowLevelGraphics.h" #include "hpl1/engine/graphics/Renderer3D.h" #include "hpl1/engine/input/Input.h" #include "hpl1/engine/input/Mouse.h" #include "hpl1/engine/resources/Resources.h" #include "hpl1/engine/system/LogicTimer.h" #include "hpl1/engine/system/String.h" #include "hpl1/engine/system/System.h" #include "hpl1/engine/gui/Gui.h" #include "hpl1/engine/game/low_level_game_setup.h" #include "hpl1/engine/system/low_level_system.h" #include "common/events.h" #include "hpl1/hpl1.h" namespace hpl { ////////////////////////////////////////////////////////////////////////// // FPS COUNTER ////////////////////////////////////////////////////////////////////////// cFPSCounter::cFPSCounter(LowLevelSystem *apLowLevelSystem) { mfFPS = 60; mlFramecounter = 0; mfFrametimestart = 0; mfFrametime = 0; mfUpdateRate = 1; mpLowLevelSystem = apLowLevelSystem; mfFrametimestart = ((float)GetApplicationTime()) / 1000.0f; } void cFPSCounter::AddFrame() { mlFramecounter++; mfFrametime = (((float)GetApplicationTime()) / 1000.0f) - mfFrametimestart; // update the timer if (mfFrametime >= mfUpdateRate) { mfFPS = ((float)mlFramecounter) / mfFrametime; mlFramecounter = 0; mfFrametimestart = ((float)GetApplicationTime()) / 1000.0f; } } ////////////////////////////////////////////////////////////////////////// // SETUP VAR CONTAINER ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cSetupVarContainer::cSetupVarContainer() { msBlank = ""; } //----------------------------------------------------------------------- void cSetupVarContainer::AddString(const tString &asName, const tString &asValue) { Common::StableMap::value_type val(asName, asValue); m_mapVars.insert(val); } void cSetupVarContainer::AddInt(const tString &asName, int alValue) { AddString(asName, cString::ToString(alValue)); } void cSetupVarContainer::AddFloat(const tString &asName, float afValue) { AddString(asName, cString::ToString(afValue)); } void cSetupVarContainer::AddBool(const tString &asName, bool abValue) { AddString(asName, abValue ? "true" : "false"); } //----------------------------------------------------------------------- const tString &cSetupVarContainer::GetString(const tString &asName) { Common::StableMap::iterator it = m_mapVars.find(asName); if (it == m_mapVars.end()) return msBlank; else return it->second; } float cSetupVarContainer::GetFloat(const tString &asName, float afDefault) { const tString &sVal = GetString(asName); if (sVal == "") return afDefault; else return cString::ToFloat(sVal.c_str(), afDefault); } int cSetupVarContainer::GetInt(const tString &asName, int alDefault) { const tString &sVal = GetString(asName); if (sVal == "") return alDefault; else return cString::ToInt(sVal.c_str(), alDefault); } bool cSetupVarContainer::GetBool(const tString &asName, bool abDefault) { const tString &sVal = GetString(asName); if (sVal == "") return abDefault; else return cString::ToBool(sVal.c_str(), abDefault); } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cGame::cGame(LowLevelGameSetup *apGameSetup, cSetupVarContainer &aVars) { GameInit(apGameSetup, aVars); } //----------------------------------------------------------------------- cGame::cGame(LowLevelGameSetup *apGameSetup, int alWidth, int alHeight, int alBpp, bool abFullscreen, unsigned int alUpdateRate, int alMultisampling) { cSetupVarContainer Vars; Vars.AddInt("ScreenWidth", alWidth); Vars.AddInt("ScreenHeight", alHeight); Vars.AddInt("ScreenBpp", alBpp); Vars.AddBool("Fullscreen", abFullscreen); Vars.AddInt("Multisampling", alMultisampling); Vars.AddInt("LogicUpdateRate", alUpdateRate); GameInit(apGameSetup, Vars); } //----------------------------------------------------------------------- void cGame::GameInit(LowLevelGameSetup *apGameSetup, cSetupVarContainer &aVars) { mpGameSetup = apGameSetup; Log("Creating Engine Modules\n"); Log("--------------------------------------------------------\n"); // Create the modules that game connects to and init them! Log(" Creating graphics module\n"); mpGraphics = mpGameSetup->createGraphics(); Log(" Creating system module\n"); mpSystem = mpGameSetup->createSystem(); Log(" Creating resource module\n"); mpResources = mpGameSetup->createResources(mpGraphics); Log(" Creating input module\n"); mpInput = mpGameSetup->createInput(mpGraphics); Log(" Creating sound module\n"); mpSound = mpGameSetup->createSound(); Log(" Creating physics module\n"); mpPhysics = mpGameSetup->createPhysics(); Log(" Creating ai module\n"); mpAI = mpGameSetup->createAi(); Log(" Creating gui module\n"); mpGui = hplNew(cGui, ()); Log(" Creating scene module\n"); mpScene = mpGameSetup->createScene(mpGraphics, mpResources, mpSound, mpPhysics, mpSystem, mpAI); Log("--------------------------------------------------------\n\n"); // Init the resources mpResources->Init(mpGraphics, mpSystem, mpSound, mpScene, mpGui); // Init the graphics mpGraphics->Init(aVars.GetInt("ScreenWidth", 800), aVars.GetInt("ScreenHeight", 600), aVars.GetInt("ScreenBpp", 32), aVars.GetBool("Fullscreen", false), aVars.GetInt("Multisampling", 0), aVars.GetString("WindowCaption"), mpResources); // Init Sound mpSound->Init(mpResources, aVars.GetBool("UseSoundHardware", true), aVars.GetBool("ForceGeneric", false), aVars.GetBool("UseEnvironmentalAudio", false), aVars.GetInt("MaxSoundChannels", 32), aVars.GetInt("StreamUpdateFreq", 10), aVars.GetBool("UseSoundThreading", true), aVars.GetBool("UseVoiceManagement", true), aVars.GetInt("MaxMonoChannelsHint", 0), aVars.GetInt("MaxStereoChannelsHint", 0), aVars.GetInt("StreamBufferSize", 4096), aVars.GetInt("StreamBufferCount", 8), aVars.GetBool("LowLevelSoundLogging", false), aVars.GetString("DeviceName")); // Init physics mpPhysics->Init(mpResources); // Init AI mpAI->Init(); // Init Gui mpGui->Init(mpResources, mpGraphics, mpSound, mpScene); Log("Initializing Game Module\n"); Log("--------------------------------------------------------\n"); // Create the updatehandler Log(" Adding engine updates\n"); mpUpdater = hplNew(cUpdater, (mpSystem->GetLowLevel())); // Add some loaded modules to the updater mpUpdater->AddGlobalUpdate(mpInput); mpUpdater->AddGlobalUpdate(mpPhysics); mpUpdater->AddGlobalUpdate(mpScene); mpUpdater->AddGlobalUpdate(mpSound); mpUpdater->AddGlobalUpdate(mpAI); mpUpdater->AddGlobalUpdate(mpGui); mpUpdater->AddGlobalUpdate(mpResources); // Setup the "default" updater container mpUpdater->AddContainer("Default"); mpUpdater->SetContainer("Default"); // Create the logic timer. mpLogicTimer = mpSystem->CreateLogicTimer(aVars.GetInt("LogicUpdateRate", 800)); // Init some standard script funcs Log(" Initializing script functions\n"); cScriptFuncs::Init(mpGraphics, mpResources, mpSystem, mpInput, mpScene, mpSound, this); // Since game is not done: mbGameIsDone = false; mfUpdateTime = 0; mfGameTime = 0; mbLimitFPS = true; mpFPSCounter = hplNew(cFPSCounter, (mpSystem->GetLowLevel())); Log("--------------------------------------------------------\n\n"); Log("User Initialization\n"); Log("--------------------------------------------------------\n"); } //----------------------------------------------------------------------- cGame::~cGame() { Log("--------------------------------------------------------\n\n"); hplDelete(mpLogicTimer); hplDelete(mpFPSCounter); hplDelete(mpUpdater); hplDelete(mpGui); hplDelete(mpScene); hplDelete(mpInput); hplDelete(mpSound); hplDelete(mpGraphics); hplDelete(mpResources); hplDelete(mpPhysics); hplDelete(mpAI); hplDelete(mpSystem); Log(" Deleting game setup provided by user\n"); hplDelete(mpGameSetup); Log("HPL Exit was successful!\n"); } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PUBLIC METHOD ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- int glClearUpdateCheck = 0; void cGame::Run() { double fNumOfTimes = 0; double fMediumTime = 0; mpUpdater->OnStart(); mpLogicTimer->Reset(); // Loop the game... fix the var... unsigned long lTempTime = GetApplicationTime(); mfFrameTime = 0; unsigned long lTempFrameTime = GetApplicationTime(); bool mbIsUpdated = true; while (!mbGameIsDone && !g_engine->shouldQuit()) { ////////////////////////// // Update logic. while (mpLogicTimer->WantUpdate() && !mbGameIsDone) { unsigned int lUpdateTime = GetApplicationTime(); mpUpdater->Update(GetStepSize()); unsigned int lDeltaTime = GetApplicationTime() - lUpdateTime; mfUpdateTime = (float)(lDeltaTime) / 1000.0f; mbIsUpdated = true; glClearUpdateCheck++; mfGameTime += GetStepSize(); } mpLogicTimer->EndUpdateLoop(); // If not making a single rendering is better to use gpu and // cpu at the same time and make query checks etc after logic update. // If any delete has occurred in the update this might crash. so skip it for now. /*if(mbRenderOnce==false) { mpGraphics->GetRenderer3D()->FetchOcclusionQueries(); mpUpdater->OnPostBufferSwap(); }*/ // Draw graphics! if (mbIsUpdated) mpScene->UpdateRenderList(mfFrameTime); if (mbLimitFPS == false || mbIsUpdated) { mbIsUpdated = false; // Get the the from the last frame. mfFrameTime = ((float)(GetApplicationTime() - lTempFrameTime)) / 1000; lTempFrameTime = GetApplicationTime(); // Draw this frame // unsigned long lFTime = GetApplicationTime(); mpUpdater->OnDraw(); mpScene->Render(mpUpdater, mfFrameTime); // Update fps counter. mpFPSCounter->AddFrame(); // Update the screen. mpGraphics->GetLowLevel()->SwapBuffers(); mpGraphics->GetRenderer3D()->FetchOcclusionQueries(); mpUpdater->OnPostBufferSwap(); fNumOfTimes++; } } Log("--------------------------------------------------------\n\n"); Log("Statistics\n"); Log("--------------------------------------------------------\n"); unsigned long lTime = GetApplicationTime() - lTempTime; fMediumTime = fNumOfTimes / (((double)lTime) / 1000); Log(" Medium framerate: %f\n", fMediumTime); Log("--------------------------------------------------------\n\n"); Log("User Exit\n"); Log("--------------------------------------------------------\n"); mpUpdater->OnExit(); } //----------------------------------------------------------------------- void cGame::Exit() { mbGameIsDone = true; } //----------------------------------------------------------------------- void cGame::ResetLogicTimer() { mpLogicTimer->Reset(); } void cGame::SetUpdatesPerSec(int alUpdatesPerSec) { mpLogicTimer->SetUpdatesPerSec(alUpdatesPerSec); } int cGame::GetUpdatesPerSec() { return mpLogicTimer->GetUpdatesPerSec(); } float cGame::GetStepSize() { return mpLogicTimer->GetStepSize(); } //----------------------------------------------------------------------- cScene *cGame::GetScene() { return mpScene; } //----------------------------------------------------------------------- cResources *cGame::GetResources() { return mpResources; } //----------------------------------------------------------------------- cGraphics *cGame::GetGraphics() { return mpGraphics; } //----------------------------------------------------------------------- cSystem *cGame::GetSystem() { return mpSystem; } //----------------------------------------------------------------------- cInput *cGame::GetInput() { return mpInput; } //----------------------------------------------------------------------- cSound *cGame::GetSound() { return mpSound; } //----------------------------------------------------------------------- cPhysics *cGame::GetPhysics() { return mpPhysics; } //----------------------------------------------------------------------- cAI *cGame::GetAI() { return mpAI; } //----------------------------------------------------------------------- cGui *cGame::GetGui() { return mpGui; } //----------------------------------------------------------------------- cUpdater *cGame::GetUpdater() { return mpUpdater; } float cGame::GetFPS() { return mpFPSCounter->mfFPS; } //----------------------------------------------------------------------- void cGame::SetFPSUpdateRate(float afSec) { mpFPSCounter->mfUpdateRate = afSec; } float cGame::GetFPSUpdateRate() { return mpFPSCounter->mfUpdateRate; } //----------------------------------------------------------------------- } // namespace hpl