SimEngine.cpp

Go to the documentation of this file.
00001 /*
00002 SagaEngine library
00003 Copyright (c) 2002-2006 Skalden Studio AS
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to distribute the library under the terms of the 
00010 Q Public License version 1.0. Be sure to read and understand the license
00011 before using the library. It should be included here, or you may read it
00012 at http://www.trolltech.com/products/qt/licenses/licensing/qpl
00013 
00014 The original version of this library can be located at:
00015 http://www.sagaengine.com/
00016 
00017 Rune Myrland
00018 rune@skalden.com
00019 */
00020 
00021 #include "InitListeners.hpp"
00022 #include "SimEngine.hpp"
00023 #include "SimListeners.hpp"
00024 #include "./action/ActionManager.hpp"
00025 #include "./physics/PhysicsManager.hpp"
00026 #include "./react/CollisionManager.hpp"
00027 #include "./script/ScriptManager.hpp"
00028 #include "./schema/SimSchema.hpp"
00029 #include "./pos/Pos.hpp"
00030 #include "./area/Area.hpp"
00031 #include "./area/AreaManager.hpp"
00032 #include "./signal/SignalManager.hpp"
00033 #include "./spawn/SpawnManager.hpp"
00034 #include "util/vecmath/Point3.hpp"
00035 #include "util/system/RealClock.hpp"
00036 #include "util/error/Log.hpp"
00037 #include "util/math/Trig.hpp"
00038 #include "util/math/CoorT.hpp"
00039 #include "util/vecmath/Vector3.hpp"
00040 #include "comp/schema/CompSchema.hpp"
00041 #include "comp/Composite.hpp"
00042 #include <cstdio>
00043 #include <cmath>
00044 
00045 
00046 namespace se_core {
00047 
00048     SimEngine
00049     ::SimEngine()
00050             : previousPerform_(0), multiplePerformsPerStepEnabled_(false)
00051             , multiplePerformsDisabledOnce_(false)
00052             , lostPerformAdjustment_(0) {
00053         LogDetail("Creating SimEngine");
00054     }
00055 
00056 
00057     SimEngine
00058     ::~SimEngine() {
00059         resetAll();
00060         LogDetail("Destroying SimEngine");
00061     }
00062 
00063 
00064     void SimEngine
00065     ::setMultiplePerformsPerStepEnabled(bool state) {
00066         multiplePerformsPerStepEnabled_ = state;
00067     }
00068 
00069 
00070     void SimEngine
00071     ::setLevel(const char* name) {
00072         nextLevel_.copy(name);
00073     }
00074 
00075 
00076     void SimEngine
00077     ::go() {
00078         //LogWarning("Capacity: " << CompSchema::voidList.capacity() << " (go 1)");
00079         SimSchema::initListeners().castStartGameEvent();
00080 
00081         while(true) {
00082             // Any in-game events caused the game to end?
00083             if(SimSchema::simEngine.isGameOver()) {
00084                 // Will cause renderloop to end
00085                 break;
00086             }
00087 
00088             // Translate game clock to SagaEngine format
00089             long when = SimSchema::realClock->millis();
00090 
00091             // Perform next AI steps if any is waiting
00092             SimSchema::simEngine.step(when);
00093 
00094             // Tell registered render modules to render
00095             SimSchema::engineListeners().castRenderEvent(SimSchema::realClock->millis());
00096         }
00097         CompSchema::activeRoot().setActive(false, true);
00098         level_.reset();
00099         SimSchema::initListeners().castCleanupLevelEvent();
00100         SimSchema::initListeners().castStopGameEvent();
00101         //LogWarning("Capacity: " << CompSchema::voidList.capacity() << " (go 2)");
00102     }
00103 
00104 
00105     bool SimEngine
00106     ::step(long when) {
00107         // Check if ready to perform the next
00108         if(when < (previousPerform_ + 1) << TIMESTEP_INTERVAL_SHIFT) {
00109             return false;
00110         }
00111 
00112         // If multiple performs are disabled, adjust game clock
00113         // to catch up.
00114         long p = when >> TIMESTEP_INTERVAL_SHIFT;
00115         if(!multiplePerformsPerStepEnabled_ || multiplePerformsDisabledOnce_) {
00116             // Used to avoid jumps in the game clocks when
00117             // multiple steps are turned off.
00118             if(previousPerform_ != 0)
00119                 lostPerformAdjustment_ += p - previousPerform_ - 1;
00120             previousPerform_ = p - 1;
00121             multiplePerformsDisabledOnce_ = false;
00122         }
00123 
00124         // w is the game clock ('when') adjusted for lost performs.
00125         long w = (p - lostPerformAdjustment_) << TIMESTEP_INTERVAL_SHIFT;
00126 
00127         // Cast PreSimTick event
00128         SimSchema::engineListeners().castPreSimTickEvent(w);
00129 
00130         // Perform actions in actionQueue until up to date...
00131         int performCount = 0;
00132         while(p > previousPerform_) {
00134             if(previousPerform_ == 0) {
00135                 // This is the first AI perform()
00136                 previousPerform_ = p;
00137             }
00138             else {
00139                 // Increase perform() counter
00140                 ++previousPerform_;
00141             }
00142 
00143             // Perform AI actions.
00144             perform(SimEngine::when());
00145             ++performCount;
00146             if(performCount > 64) {
00147                 multiplePerformsDisabledOnce_ = true;
00148                 break;
00149             }
00150         }
00151 
00152         // Cast event telling listeners that the AI actions are performed,
00153         // and that the AI now is up to date with the game clock.
00154         //e.init(*this, EngineEvent::TYPE_POST_TICK, w);
00155         SimSchema::engineListeners().castPostSimTickEvent(w);
00156 
00157         return true;
00158     }
00159 
00160 
00161     void SimEngine
00162     ::perform(long when) {
00163         // Performs all destructions that resulted from the actions.
00164         // It is necessary to do this as a separate step, because an
00165         // object destroyed in this initiative may have a counteraction
00166         // scheduled that by game rules are performed simultaneously,
00167         // but by the game code performed slightly later than the destroying
00168         // actions.
00169         SimSchema::spawnManager().performDestructions();
00170 
00171         // Updates didTrack
00172         ScriptManager::singleton().step(when);
00173 
00174         // Schedules and performs the scheduled actions in all action channels
00175         ActionManager::singleton().step(when);
00176 
00177         // Move things and check for collisions
00178         PhysicsManager::singleton().step(when);
00179 
00180         // Move things and check for collisions
00181         CollisionManager::singleton().step(when);
00182 
00183         // Move things and check for collisions
00184         SignalManager::singleton().step(when);
00185 
00186         if(!nextLevel_.equals(level_)) {
00187             LogWarning("New level is " << nextLevel_);
00188             CompSchema::activeRoot().setActive(false, true);
00189             if(!level_.isEmpty()) {
00190                 SimSchema::initListeners().castCleanupLevelEvent();
00191             }
00192             level_.copy(nextLevel_.get());
00193             CompSchema::activeRoot().setActive(true, true);
00194             SimSchema::initListeners().castInitLevelEvent();
00195 
00196             // Don't have AI and physics catch up because
00197             // of skipped frames during level loading
00198             multiplePerformsDisabledOnce_ = true;
00199         }
00200     }
00201 
00202 
00203     bool SimEngine
00204 	::init() {
00205         if(!SimSchema::initListeners().castPriorityInitEngineEvent())
00206             return false;
00207         if(!SimSchema::initListeners().castInitEngineEvent())
00208             return false;
00209         // Platform module must create a clock
00210         //Assert(SimSchema::realClock);
00211         return true;
00212     }
00213 
00214 
00215     void SimEngine
00216 	::cleanup() {
00217         SimSchema::initListeners().castCleanupEngineEvent();
00218         SimSchema::initListeners().castPriorityCleanupEngineEvent();
00219         resetAll();
00220     }
00221 
00222 
00223     void SimEngine
00224     ::initGame() {
00225         LogWarning("Capacity: " << CompSchema::voidList.capacity() << " (initGame)");
00226         // Reset in game engine variable that remembers the
00227         // 'when' of the previous step
00228         resetTimer();
00229         SimSchema::realClock->reset();
00230         // Begin game with game over flag not set
00231         setGameOver(false);
00232         SimSchema::initListeners().castInitGameEvent();
00233         CompSchema::activeRoot().init(false);
00234         CollisionManager::singleton().resetGodMode();
00235     }
00236 
00237 
00238     void SimEngine
00239     ::setGameOver(bool state) {
00240         LogDetail(__FUNCTION__ << ": " << state);
00241         //static int c = 0; if(++c > 10) LogFatal("!");
00242         isGameOver_ = state;
00243     }
00244 
00245 
00246     void SimEngine
00247     ::cleanupGame() {
00248         CompSchema::activeRoot().cleanup(false);
00249         for(int i = 0; i < CHANNEL_COUNT; ++i) {
00250             SimSchema::actionQueue[i].reset();
00251         }
00252         SimSchema::areaManager.resetThings();
00253         SimSchema::spawnManager().reset();
00254         SimSchema::initListeners().castCleanupGameEvent();
00255         SimSchema::areaManager.resetAll();
00256         SimSchema::spawnManager().resetAll();
00257         PhysicsManager::singleton().cleanup();
00258 
00259 
00260         lostPerformAdjustment_ = 0;
00261         previousPerform_ = 0;
00262         isGameOver_ = false;
00263         LogWarning("Capacity: " << CompSchema::voidList.capacity() << " (cleanupGame)");
00264     }
00265 
00266 
00267     void SimEngine
00268     ::resetAll() {
00269         //SimSchema::thingManager.reset();
00270         SimSchema::areaManager.resetAll();
00271         SimSchema::spawnManager().reset();
00272     }
00273 
00274 }

Home Page | SagaEngine trunk (updated nightly) reference generated Sun Dec 2 20:06:12 2007 by Doxygen version 1.3.9.1.

SourceForge.net Logo