1 #include "Level.h"
2 #include "GameObjectManager.h"
3 #include "tinyxml.h"
4 #include "GameObject.h"
5 #include "GameObjectTemplate.h"
6
7 #include "PhysicsSubSystem.h"
8 #include "MeshSubSystem.h"
9 #include "RenderSubSystem.h"
10 #include "BehaviorSubSystem.h"
11 #include "AnimationSubSystem.h"
12 #include "SoundSubSystem.h"
13 #include "TriggerSubSystem.h"
14 #include "LifeSubSystem.h"
15
16 #include "Event.h"
17 #include "EventManager.h"
18 #include "CaelumFrameListener.h"
19
20 #include "MemLeakDetect.h"
21
22 using namespace Ogre;
23
24 Level::Level(const std::string& name,const std::string& desc,Ogre::Camera* camera,Ogre::SceneManager* sceneMgr,Ogre::Viewport* viewPort) : mSceneMgr(sceneMgr), mCamera(camera), mName(name), mDesc(desc), mObjectCount(0), mViewport(viewPort), mFadingTimer(0), fading(false), mPlayerHitpoints(100), mKeyDirection(Ogre::Vector3::ZERO)
25 {
26 mFader = new Fader("Overlays/FadeInOut", "Materials/OverlayMaterial");
27 mFader->startFadeIn(4.5);
28 }
29
30 Level::~Level()
31 {
32 if(hikariMgr)
33 {
34 acorn_count->hide();
35 //fps->hide();
36 lifebar->hide();
37 }
38
39 GameObjectManager::getInstance()->clearSubSystems();
40 GameObjectManager::getInstance()->clearGameObjects();
41 GameObjectManager::getInstance()->clearGameObjectTemplates();
42
43 delete physicsSubSystem;
44 physicsSubSystem =NULL;
45 delete renderSubSystem;
46 renderSubSystem =NULL;
47 delete meshSubSystem;
48 meshSubSystem=NULL;
49 delete behaviorSubSystem;
50 behaviorSubSystem=NULL;
51 delete animationSubSystem;
52 animationSubSystem=NULL;
53 delete triggerSubSystem;
54 triggerSubSystem=NULL;
55 delete soundSubSystem;
56 soundSubSystem = NULL;
57 delete lifeSubSystem;
58 lifeSubSystem = NULL;
59
60 if(mFader)
61 delete mFader;
62 mFader = NULL;
63 }
64
65 void Level::initialize()
66 {
67 Ogre::LogManager::getSingleton().logMessage("Level Init");
68
69 setupHikari();
70
71 // Set ambient light
72 mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
73
74 Light* l = mSceneMgr->createLight("MainLight");
75
76 //add a skybox
77 mSceneMgr->setSkyBox(true, "TreeSkyBox", 1000);
78
79 //setup the light
80 l->setType(Light::LT_DIRECTIONAL);
81 Vector3 dir(-0.3, -1, 0.2);
82 dir.normalise();
83 l->setDirection(dir);
84 l->setDiffuseColour(1.0, 1.0, 0.8);
85
86
87 initializeSubSystems();
88
89 loadTemplates();
90 loadInitialObjects();
91
92 EventManager::getInstance()->registerListener(this,EventType::SpawnPlayer);
93
94 Ogre::LogManager::getSingleton().logMessage("End Level Inits");
95
96 }
97
98 void Level::setupHikari()
99 {
100 using namespace Hikari;
101
102 hikariMgr = HikariManager::GetPointer();
103
104 if(!hikariMgr->getFlashControl("acorn_count"))
105 {
106 acorn_count = hikariMgr->createFlashOverlay("acorn_count", mViewport, 78, 54, Hikari::Position(TopRight));
107 acorn_count->load("acorn_count.swf");
108 acorn_count->setTransparent(true);
109 acorn_count->setDraggable(false);
110 }
111 else
112 {
113 acorn_count = hikariMgr->getFlashControl("acorn_count");
114 acorn_count->show();
115 }
116
117 if(!hikariMgr->getFlashControl("FPS2"))
118 {
119 fps = hikariMgr->createFlashOverlay("FPS2", mViewport, 130, 91, Hikari::Position(TopLeft));
120 fps->load("fps.swf");
121 fps->setTransparent(true);
122 fps->setDraggable(false);
123 fps->hide();
124 }
125 else
126 {
127 fps = hikariMgr->getFlashControl("FPS2");
128 fps->show();
129 }
130
131 if(!hikariMgr->getFlashControl("lifebar"))
132 {
133 lifebar = hikariMgr->createFlashOverlay("lifebar", mViewport, 125, 32, Hikari::Position(TopLeft));
134 lifebar->load("lifebar.swf");
135 lifebar->setTransparent(true);
136 lifebar->setDraggable(false);
137 }
138 else
139 {
140
141 lifebar = hikariMgr->getFlashControl("lifebar2");
142 lifebar->show();
143 }
144
145
146 mKeyDirection = Ogre::Vector3::ZERO;
147 }
148
149 void Level::initializeSubSystems()
150 {
151
152 physicsSubSystem = new PhysicsSubSystem(mName);
153 GameObjectManager::getInstance()->registerSubSystem(physicsSubSystem,"PhysicsComponent");
154
155 meshSubSystem = new MeshSubSystem;
156 GameObjectManager::getInstance()->registerSubSystem(meshSubSystem,"MeshComponent");
157
158 renderSubSystem = new RenderSubSystem;
159 GameObjectManager::getInstance()->registerSubSystem(renderSubSystem,"RenderComponent");
160
161 triggerSubSystem = new TriggerSubSystem(physicsSubSystem);
162 GameObjectManager::getInstance()->registerSubSystem(triggerSubSystem,"TriggerComponent");
163
164 behaviorSubSystem = new BehaviorSubSystem(triggerSubSystem);
165 GameObjectManager::getInstance()->registerSubSystem(behaviorSubSystem,"BehaviorComponent");
166
167 animationSubSystem = new AnimationSubSystem;
168 GameObjectManager::getInstance()->registerSubSystem(animationSubSystem,"AnimationComponent");
169
170 soundSubSystem = new SoundSubSystem;
171 GameObjectManager::getInstance()->registerSubSystem(soundSubSystem,"SoundComponent");
172
173 lifeSubSystem = new LifeSubSystem;
174 GameObjectManager::getInstance()->registerSubSystem(lifeSubSystem,"LifeComponent");
175 }
176
177
178
179 void Level::loadTemplates()
180 {
181 Ogre::String lvlstr("..\\levels\\");
182 lvlstr+=mName;
183 TiXmlDocument doc((lvlstr += ".xml").c_str());
184 if (!doc.LoadFile())
185 {
186 Ogre::LogManager::getSingleton().logMessage("unable to load level");
187 return;
188 }
189
190 TiXmlHandle hDoc(&doc);
191 TiXmlElement* firstElement;
192 TiXmlHandle hRoot(0);
193 TiXmlNode* pNode;
194 firstElement=hDoc.FirstChildElement().FirstChild().Element();
195 // should always have a valid root but handle gracefully if it does not
196 if (!firstElement) return;
197
198 if(strcmp(firstElement->Value(),"Templates") == 0)
199 {
200 TiXmlElement* templateEle = firstElement->FirstChildElement();
201 //for each game object template
202 for(templateEle; templateEle; templateEle=templateEle->NextSiblingElement())
203 {
204 GameObjectTemplate* goTemplate = GameObjectManager::getInstance()->createGameObjectTemplate(templateEle->Value());
205 pNode = templateEle->FirstChild();
206 for(pNode;pNode; pNode = pNode->NextSibling())
207 {
208 const std::string familyID = pNode->Value();
209 TiXmlElement* compNode = pNode->FirstChildElement();
210 const char *name=compNode->Attribute("name");
211 goTemplate->addComponentTemplate(familyID,std::string(name));
212 //now lets add the template to the proper subsystem
213 GameObjectManager::getInstance()->buildComponentTemplate(familyID,pNode);
214
215 }
216 }
217 }
218
219 }
220
221 void Level::loadInitialObjects()
222 {
223 Ogre::String lvlstr("..\\levels\\");
224 lvlstr+=mName;
225 TiXmlDocument doc((lvlstr += ".xml").c_str());
226 if (!doc.LoadFile())
227 {
228 Ogre::LogManager::getSingleton().logMessage("unable to load level");
229 return;
230 }
231
232 TiXmlHandle hDoc(&doc);
233 TiXmlElement* firstElement;
234 TiXmlHandle hRoot(0);
235 TiXmlNode* pNode;
236 firstElement=hDoc.FirstChildElement().FirstChild().Element();
237 // should always have a valid root but handle gracefully if it does not
238 if (!firstElement) return;
239
240 TiXmlElement* gameObjectElement = hDoc.FirstChildElement().Child(1).Element();
241
242 if(strcmp(gameObjectElement->Value(),"GameObjects") == 0)
243 {
244 TiXmlElement* goElement = gameObjectElement->FirstChildElement();
245 //for a given template name
246 for(goElement; goElement; goElement=goElement->NextSiblingElement())
247 {
248 std::string templateName(goElement->Value());
249 //for each object to be made from this template
250 TiXmlElement* dataElement = goElement->FirstChildElement();
251 for(dataElement; dataElement; dataElement=dataElement->NextSiblingElement())
252 {
253
254 const char *ename=dataElement->Attribute("name");
255 std::string goID(ename);
256
257 //make an new object with the new ID, if not specified, increment our counter
258 if(goID.length() == 0)
259 {
260 goID = Ogre::StringConverter::toString(mObjectCount++);
261 }
262
263 GameObject* go = GameObjectManager::getInstance()->createGameObject(templateName,goID);
264 //adjust the position and rotation with an event
265
266 PositionChange posData;
267 dataElement->QueryFloatAttribute("posX", &posData.posX);
268 dataElement->QueryFloatAttribute("posY", &posData.posY);
269 dataElement->QueryFloatAttribute("posZ", &posData.posZ);
270 dataElement->QueryFloatAttribute("rotX", &posData.rotX);
271 dataElement->QueryFloatAttribute("rotY", &posData.rotY);
272 dataElement->QueryFloatAttribute("rotZ", &posData.rotZ);
273 dataElement->QueryFloatAttribute("rotW", &posData.rotW);
274
275 Event* event = new Event(goID,EventType::Position,&posData);
276 EventManager::getInstance()->sendEvent(event);
277
278 }
279 }
280 }
281
282 }
283
284
285
286
287 void Level::preFrameTick(const Ogre::FrameEvent &evt)
288 {
289
290 // Will fade if told so, otherwise does nothing
291 mFader->fade(evt.timeSinceLastFrame);
292 if(mFadingTimer>0 && fading)
293 {
294 mFadingTimer-= evt.timeSinceLastFrame;
295 }
296 else if(fading)//player died, lets fade out and reposition
297 {
298 fading = false;
299 respawnPlayer();
300 }
301
302
303 InputManager* mInputManager = InputManager::getSingletonPtr();
304
305 Ogre::Real angle = 0.0f;
306
307 //mouse angle used for player orientation
308 const Real MOUSE_SENSITIVITY = 1.0f;
309
310 int mouseX = mInputManager->getMouse()->getMouseState().X.abs;
311 int halfWindowWidth = mInputManager->getMouse()->getMouseState().width >> 1;
312 int halfWindowHeight = mInputManager->getMouse()->getMouseState().height >> 1;
313
314 {
315 Real inc = Real(halfWindowWidth - mouseX) / halfWindowWidth;
316 inc = (inc < -1.0f) ? -1.0f : inc;
317 inc = (inc > 1.0f) ? 1.0f : inc;
318 angle = 3.4f * inc * MOUSE_SENSITIVITY;
319 }
320
321
322 if(fading)
323 {
324 mKeyDirection = Ogre::Vector3::ZERO;
325 }
326 {
327 #ifdef _DEBUG
328 OgreProfile("Physics");
329 #endif
330 physicsSubSystem->translate(mKeyDirection,angle);
331 physicsSubSystem->update(evt.timeSinceLastFrame);
332
333 }
334 behaviorSubSystem->update(evt.timeSinceLastFrame);
335 {
336 #ifdef _DEBUG
337 OgreProfile("Animation");
338 #endif
339 animationSubSystem->update(evt.timeSinceLastFrame);
340 }
341 {
342 #ifdef _DEBUG
343 OgreProfile("Triggers");
344 #endif
345 triggerSubSystem->update(evt.timeSinceLastFrame);
346 }
347
348 soundSubSystem->update(evt.timeSinceLastFrame);
349
350 {
351 #ifdef _DEBUG
352 OgreProfile("Hikari");
353 #endif
354 hikariMgr->update();
355
356 const RenderTarget::FrameStats& stats =Ogre::Root::getSingletonPtr()->getAutoCreatedWindow()->getStatistics();
357 //fps->callFunction("setFPS", Hikari::Args((int)stats.lastFPS));
358 //Ogre::LogManager::getSingleton().logMessage(Ogre::StringConverter::toString(stats.lastFPS));
359
360 lifebar->callFunction("setLife",Hikari::Args((float)mPlayerHitpoints/100));
361 acorn_count->callFunction("setAcornCount", Hikari::Args((int)GameObjectManager::getInstance()->getAcornCount()));
362 }
363
364 }
365
366 void Level::postFrameTick(const Ogre::FrameEvent& evt)
367 {
368 GameObjectManager::getInstance()->removeQueuedObjects();
369 }
370
371
372 void Level::mouseMoved( const OIS::MouseEvent &evt )
373 {
374 //send an event to the player so it can update its camera
375 PositionChange posData;
376 posData.rotX =-0.15f * evt.state.X.rel;
377 posData.rotY = -0.05f * evt.state.Y.rel;
378 posData.rotZ -0.005f * evt.state.Z.rel;
379 Event* event = new Event("Player",EventType::Mouse,&posData);
380 EventManager::getInstance()->sendEvent(event);
381
382
383 }
384
385 void Level::mousePressed( const OIS::MouseEvent &e, OIS::MouseButtonID id )
386 {
387 }
388
389 void Level::mouseReleased( const OIS::MouseEvent &e, OIS::MouseButtonID id )
390 {
391
392 }
393 void Level::keyPressed(const OIS::KeyEvent &evt)
394 {
395 // keep track of the player's intended direction
396 if (evt.key == OIS::KC_W) mKeyDirection.z = -1;
397 else if (evt.key == OIS::KC_A) mKeyDirection.x = -1;
398 else if (evt.key == OIS::KC_S) mKeyDirection.z = 1;
399 else if (evt.key == OIS::KC_D) mKeyDirection.x = 1;
400 else if (evt.key == OIS::KC_SPACE) mKeyDirection.y = 1;
401
402 #ifdef _DEBUG
403 if(evt.key == OIS::KC_N)
404 {
405 GameObjectManager::getInstance()->clearGameObjects();
406 }
407
408 if(evt.key == OIS::KC_M)
409 {
410 physicsSubSystem->loadPhysicsSystem();
411 loadInitialObjects();
412 }
413 #endif
414
415 }
416
417 void Level::keyReleased(const OIS::KeyEvent &evt)
418 {
419
420 // keep track of the player's intended direction
421 if (evt.key == OIS::KC_W && mKeyDirection.z == -1) mKeyDirection.z = 0;
422 else if (evt.key == OIS::KC_A && mKeyDirection.x == -1) mKeyDirection.x = 0;
423 else if (evt.key == OIS::KC_S && mKeyDirection.z == 1) mKeyDirection.z = 0;
424 else if (evt.key == OIS::KC_D && mKeyDirection.x == 1) mKeyDirection.x = 0;
425 else if (evt.key == OIS::KC_SPACE) mKeyDirection.y = 0;
426
427 }
428
429 void Level::handleEvent(Event *event)
430 {
431 switch(event->getType())
432 {
433 case SpawnPlayer:
434 {
435 if(!fading)
436 {
437 mFader->startFadeOut(3.0f);
438
439 mFadingTimer = 3.0f;
440 fading = true;
441 mKeyDirection = Ogre::Vector3::ZERO;
442 }
443
444 }
445 break;
446 }
447 }
448
449 void Level::respawnPlayer()
450 {
451 mPlayerHitpoints = 100;
452 GameObjectManager::getInstance()->clearGameObjects();
453 GameObjectManager::getInstance()->setAcornCount(0);
454 //level reloads
455 //once we're done reloading we fade back in
456 physicsSubSystem->loadPhysicsSystem();
457 loadInitialObjects();
458 // PositionChange* posData = reinterpret_cast<PositionChange*>(event->getEventData());
459 // Event* event = new Event("Player",EventType::Position,posData);
460 // EventManager::getInstance()->sendEvent(event);
461 mFader->startFadeIn(1.5f);
462
463
464 }