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.