Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/objectmanager/src/story_entities/world.cc @ 6134

Last change on this file since 6134 was 6134, checked in by bensch, 19 years ago

om: disected the old worldEntity list out.
removed GarbageCollector
minor updates

File size: 21.8 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13   co-programmer: Christian Meyer
14   co-programmer: Benjamin Grauer
15*/
16
17#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD
18
19#include "world.h"
20
21#include "shell_command.h"
22
23#include "state.h"
24
25#include "p_node.h"
26#include "pilot_node.h"
27#include "world_entity.h"
28#include "player.h"
29#include "camera.h"
30#include "environment.h"
31#include "skysphere.h"
32#include "skybox.h"
33#include "satellite.h"
34#include "test_entity.h"
35#include "terrain.h"
36#include "light.h"
37#include "load_param.h"
38#include "shell.h"
39
40#include "fast_factory.h"
41#include "animation_player.h"
42#include "particle_engine.h"
43#include "graphics_engine.h"
44#include "physics_engine.h"
45#include "fields.h"
46
47#include "md2Model.h"
48
49#include "glmenu_imagescreen.h"
50#include "list.h"
51#include "game_loader.h"
52
53#include "animation3d.h"
54
55#include "substring.h"
56
57#include "factory.h"
58
59#include "weapons/projectile.h"
60#include "event_handler.h"
61#include "sound_engine.h"
62#include "ogg_player.h"
63
64#include "class_list.h"
65
66#include "cd_engine.h"
67#include "npcs/npc_test1.h"
68#include "shader.h"
69
70#include "playable.h"
71#include "network_manager.h"
72#include "playable.h"
73
74
75SHELL_COMMAND(speed, World, setSpeed);
76SHELL_COMMAND(togglePNodeVisibility, World, togglePNodeVisibility);
77SHELL_COMMAND(toggleBVVisibility, World, toggleBVVisibility);
78
79using namespace std;
80
81//! This creates a Factory to fabricate a World
82CREATE_FACTORY(World, CL_WORLD);
83
84World::World(const TiXmlElement* root)
85{
86  this->constuctorInit("", -1);
87  this->path = NULL;
88
89  this->loadParams(root);
90}
91
92/**
93  *  create a new World
94
95    This creates a new empty world!
96*/
97World::World (const char* name)
98{
99  this->path = NULL;
100  this->constuctorInit(name, -1);
101}
102
103/**
104 *  creates a new World...
105 * @param worldID with this ID
106*/
107World::World (int worldID)
108{
109  this->path = NULL;
110  this->constuctorInit(NULL, worldID);
111}
112
113/**
114 *  remove the World from memory
115
116    delete everything explicitly, that isn't contained in the parenting tree!
117    things contained in the tree are deleted automaticaly
118 */
119World::~World ()
120{
121  delete this->shell;
122  PRINTF(3)("World::~World() - deleting current world\n");
123
124  delete this->localPlayer;
125
126  // delete all the initialized Engines.
127  FastFactory::flushAll(true);
128  delete LightManager::getInstance();
129  delete ParticleEngine::getInstance();
130  delete AnimationPlayer::getInstance();
131  delete PhysicsEngine::getInstance();
132
133  // external engines initialized by the orxonox-class get deleted
134  SoundEngine::getInstance()->flushAllBuffers();
135  SoundEngine::getInstance()->flushAllSources();
136
137  if (State::getObjectManager() == &this->objectManager)
138    State::setObjectManager(NULL);
139  // erease everything that is left.
140  delete PNode::getNullParent();
141
142  //secondary cleanup of PNodes;
143  const std::list<BaseObject*>* nodeList = ClassList::getList(CL_PARENT_NODE);
144  if (nodeList != NULL)
145    while (!nodeList->empty())
146      delete nodeList->front();
147
148  Shader::suspendShader();
149
150  // unload the resources !!
151  ResourceManager::getInstance()->unloadAllByPriority(RP_LEVEL);
152
153  delete[] this->path;
154}
155
156/**
157 * initializes the world.
158 * @param name the name of the world
159 * @param worldID the ID of this world
160 *
161 * set all stuff here that is world generic and does not use to much memory
162 * because the real init() function StoryEntity::init() will be called
163 * shortly before start of the game.
164 * since all worlds are initiated/referenced before they will be started.
165 * NO LEVEL LOADING HERE - NEVER!
166*/
167void World::constuctorInit(const char* name, int worldID)
168{
169  this->setClassID(CL_WORLD, "World");
170
171  this->setName(name);
172  this->debugWorldNr = worldID;
173  this->gameTime = 0.0f;
174  this->setSpeed(1.0);
175  this->music = NULL;
176  this->shell = NULL;
177  this->localPlayer = NULL;
178  this->localCamera = NULL;
179
180  this->showPNodes = false;
181  this->showBV = false;
182}
183
184/**
185 * loads the parameters of a World from an XML-element
186 * @param root the XML-element to load from
187 */
188void World::loadParams(const TiXmlElement* root)
189{
190  PRINTF(4)("Creating a World\n");
191
192  LoadParam(root, "identifier", this, World, setStoryID)
193    .describe("Sets the StoryID of this world");
194
195  LoadParam(root, "nextid", this, World, setNextStoryID)
196    .describe("Sets the ID of the next world");
197
198  LoadParam(root, "path", this, World, setPath)
199    .describe("The Filename of this World (relative from the data-dir)");
200}
201
202/**
203 * this is executed just before load
204 *
205 * since the load function sometimes needs data, that has been initialized
206 * before the load and after the proceeding storyentity has finished
207*/
208ErrorMessage World::preLoad()
209{
210  State::setObjectManager(&this->objectManager);
211  this->cycle = 0;
212
213  /* init the world interface */
214  this->shell = new Shell();
215
216  LightManager::getInstance();
217  PNode::getNullParent();
218
219  AnimationPlayer::getInstance(); // initializes the animationPlayer
220  ParticleEngine::getInstance();
221  PhysicsEngine::getInstance();
222
223  this->localCamera = new Camera();
224  this->localCamera->setName ("World-Camera");
225
226  State::setCamera(this->localCamera, this->localCamera->getTarget());
227
228  GraphicsEngine::getInstance()->displayFPS(true);
229}
230
231
232/**
233 *  loads the World by initializing all resources, and set their default values.
234*/
235ErrorMessage World::load()
236{
237  PRINTF(3)("> Loading world: '%s'\n", getPath());
238  TiXmlElement* element;
239  GameLoader* loader = GameLoader::getInstance();
240
241  if( getPath() == NULL)
242    {
243      PRINTF(1)("World has no path specified for loading");
244      this->loadDebugWorld(this->getStoryID());
245      return (ErrorMessage){213,"Path not specified","World::load()"};
246    }
247
248  TiXmlDocument* XMLDoc = new TiXmlDocument( getPath());
249  // load the campaign document
250  if( !XMLDoc->LoadFile())
251  {
252    // report an error
253    PRINTF(1)("loading XML File: %s @ %s:l%d:c%d\n", XMLDoc->ErrorDesc(), this->getPath(), XMLDoc->ErrorRow(), XMLDoc->ErrorCol());
254    delete XMLDoc;
255    return (ErrorMessage){213,"XML File parsing error","World::load()"};
256  }
257
258  // check basic validity
259  TiXmlElement* root = XMLDoc->RootElement();
260  assert( root != NULL);
261
262  if( root == NULL || root->Value() == NULL || strcmp( root->Value(), "WorldDataFile"))
263    {
264      // report an error
265      PRINTF(1)("Specified XML File is not an orxonox world data file (WorldDataFile element missing)\n");
266      delete XMLDoc;
267      return (ErrorMessage){213,"Path not a WorldDataFile","World::load()"};
268    }
269
270  // load the parameters
271  // name
272  const char* string = grabParameter( root, "name");
273  if( string == NULL)
274    {
275      PRINTF(2)("World is missing a proper 'name'\n");
276      this->setName("Unknown");
277    }
278  else
279    {
280      this->setName(string);
281    }
282
283  ////////////////
284  // LOADSCREEN //
285  ////////////////
286  element = root->FirstChildElement("LoadScreen");
287  if (element == NULL)
288    {
289      PRINTF(2)("no LoadScreen specified, loading default\n");
290
291      glmis->setBackgroundImage("pictures/load_screen.jpg");
292      this->glmis->setMaximum(8);
293      this->glmis->draw();
294    }
295  else
296    {
297      this->glmis->loadParams(element);
298      this->glmis->draw();
299    }
300  this->glmis->draw();
301
302  ////////////////////////
303  // find WorldEntities //
304  ////////////////////////
305
306  element = root->FirstChildElement("WorldEntities");
307
308  if( element == NULL)
309    {
310      PRINTF(1)("World is missing 'WorldEntities'\n");
311    }
312  else
313    {
314      element = element->FirstChildElement();
315      // load Players/Objects/Whatever
316      PRINTF(4)("Loading WorldEntities\n");
317      while( element != NULL)
318        {
319          BaseObject* created = Factory::fabricate(element);
320          if( created != NULL )
321          {
322            if(created->isA(CL_WORLD_ENTITY))
323              this->spawn(dynamic_cast<WorldEntity*>(created));
324            printf("Created a %s: %s\n", created->getClassName(), created->getName());
325          }
326
327          // if we load a 'Player' we use it as localPlayer
328
329
330          //todo do this more elegant
331          if( element->Value() != NULL && !strcmp( element->Value(), "SkyBox"))
332            sky = dynamic_cast<SkyBox*>(created);
333          if( element->Value() != NULL && !strcmp( element->Value(), "Terrain"))
334          {
335            terrain = dynamic_cast<Terrain*>(created);
336            CDEngine::getInstance()->setTerrain(terrain);
337          }
338          element = element->NextSiblingElement();
339          glmis->step(); //! @todo temporary
340        }
341      PRINTF(4)("Done loading WorldEntities\n");
342    }
343
344    //////////////////////////////
345    // LOADING ADDITIONAL STUFF //
346    //////////////////////////////
347
348    LoadParamXML(root, "LightManager", LightManager::getInstance(), LightManager, loadParams);
349
350   LoadParamXML(root, "ParticleEngine", ParticleEngine::getInstance(), ParticleEngine, loadParams);
351//   LoadParamXML(root, "PhysicsEngine", PhysicsEngine::getInstance(), PhysicsEngine, loadParams);
352
353  // free the XML data
354
355  delete XMLDoc;
356  /* GENERIC LOADING PROCESS FINISHED */
357
358
359  // Create a Player
360  this->localPlayer = new Player();
361
362  Playable* playable;
363  const list<BaseObject*>* playableList = ClassList::getList(CL_PLAYABLE);
364  if (playableList != NULL)
365  {
366    playable = dynamic_cast<Playable*>(playableList->front());
367    this->localPlayer->setControllable(playable);
368  }
369
370  // bind camera
371  playable->addChild (this->localCamera);
372
373//   //localCamera->setParent(TrackNode::getInstance());
374//  tn->addChild(this->localCamera);
375  localCamera->setClipRegion(1, 10000.0);
376  localCamera->lookAt(playable);
377//  this->localPlayer->setParentMode(PNODE_ALL);
378  if (sky != NULL)
379  {
380    this->sky->setParent(this->localCamera);
381    this->sky->setParentMode(PNODE_MOVEMENT);
382  }
383
384  // initialize debug coord system
385  objectList = glGenLists(1);
386  glNewList (objectList, GL_COMPILE);
387
388  glEndList();
389
390  SoundEngine::getInstance()->setListener(this->localCamera);
391
392
393
394  ////////////
395  // STATIC //
396  ////////////
397
398
399//   TestEntity* testEntity = new TestEntity();
400//   testEntity->setRelCoor(Vector(570, 10, -15));
401//   testEntity->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
402//   this->spawn(testEntity);
403
404  for(int i = 0; i < 100; i++)
405  {
406    WorldEntity* tmp = new NPCTest1();
407    char npcChar[10];
408    sprintf (npcChar, "NPC_%d", i);
409        tmp->setName(npcChar);
410    tmp->setAbsCoor(((float)rand()/RAND_MAX) * 5000, 50/*+ (float)rand()/RAND_MAX*20*/, ((float)rand()/RAND_MAX -.5) *30);
411    this->spawn(tmp);
412  }
413
414  this->music = NULL;
415  //(OggPlayer*)ResourceManager::getInstance()->load("sound/00-luke_grey_-_hypermode.ogg", OGG, RP_LEVEL);
416  //music->playback();
417}
418
419
420
421/**
422 * creates a debug world: only for experimental stuff
423*/
424void World::loadDebugWorld(int worldID)
425{
426  /*monitor progress*/
427  this->glmis->step();
428  // stuff beyond this point remains to be loaded properly
429
430  // LIGHT initialisation
431  LightManager::getInstance()->setAmbientColor(.1,.1,.1);
432//  LightManager::getInstance()->addLight();
433  LightManager::getInstance()->debug();
434
435  switch(this->debugWorldNr)
436    {
437      /*
438        this loads the hard-coded debug world. this only for simplicity and will be
439        removed by a reald world-loader, which interprets a world-file.
440        if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
441        make whatever you want...
442      */
443    case DEBUG_WORLD_0:
444      {
445        LightManager::getInstance()->getLight()->setAbsCoor(-5.0, 10.0, -40.0);
446        /*monitor progress*/
447        this->glmis->step();
448
449        // bind camera
450        this->localCamera = new Camera();
451        this->localCamera->setName ("camera");
452        /*monitor progress*/
453        this->glmis->step();
454
455
456        // Create SkySphere
457        this->sky = new Skysphere("pictures/sky-replace.jpg");
458        this->sky->setName("SkySphere");
459        this->spawn(this->sky);
460        this->localCamera->addChild(this->sky);
461        this->sky->setParentMode(PNODE_MOVEMENT);
462        /*monitor progress*/
463        this->glmis->step();
464
465
466        terrain = new Terrain("worlds/newGround.obj");
467        terrain->setRelCoor(Vector(0,-10,0));
468        this->spawn(terrain);
469        /*monitor progress*/
470        this->glmis->step();
471
472        this->glmis->step();
473        break;
474      }
475    case DEBUG_WORLD_1:
476      {
477
478        break;
479      }
480    case DEBUG_WORLD_2:
481      {
482
483        break;
484      }
485    default:
486      break;
487    }
488}
489
490/**
491 *  initializes a new World shortly before start
492 *
493 * this is the function, that will be loaded shortly before the world is
494 * started
495*/
496ErrorMessage World::init()
497{
498  this->bPause = false;
499
500  /* update the object position before game start - so there are no wrong coordinates used in the first processing */
501  PNode::getNullParent()->updateNode (0.001f);
502  PNode::getNullParent()->updateNode (0.001f);
503
504}
505
506
507/**
508 *  starts the World
509*/
510ErrorMessage World::start()
511{
512  PRINTF(3)("World::start() - starting current World: nr %i\n", this->debugWorldNr);
513  this->bQuitOrxonox = false;
514  this->bQuitCurrentGame = false;
515  this->mainLoop();
516}
517
518/**
519 *  stops the world.
520
521   This happens, when the player decides to end the Level.
522*/
523ErrorMessage World::stop()
524{
525  PRINTF(3)("World::stop() - got stop signal\n");
526  this->bQuitCurrentGame = true;
527}
528
529/**
530 *  pauses the Game
531*/
532ErrorMessage World::pause()
533{
534  this->isPaused = true;
535}
536
537/**
538 *  ends the pause Phase
539*/
540ErrorMessage World::resume()
541{
542  this->isPaused = false;
543}
544
545/**
546 *  destroys the World
547*/
548ErrorMessage World::destroy()
549{
550
551}
552
553/**
554 *  shows the loading screen
555*/
556void World::displayLoadScreen ()
557{
558  PRINTF(3)("World::displayLoadScreen - start\n");
559
560  //GLMenuImageScreen*
561  this->glmis = new GLMenuImageScreen();
562  this->glmis->setMaximum(8);
563
564  PRINTF(3)("World::displayLoadScreen - end\n");
565}
566
567/**
568 *  removes the loadscreen, and changes over to the game
569
570   @todo take out the delay
571*/
572void World::releaseLoadScreen ()
573{
574  PRINTF(3)("World::releaseLoadScreen - start\n");
575  this->glmis->setValue(this->glmis->getMaximum());
576  PRINTF(3)("World::releaseLoadScreen - end\n");
577  delete this->glmis;
578}
579
580
581/**
582 *  this returns the current game time
583 * @returns elapsed game time
584*/
585double World::getGameTime()
586{
587  return this->gameTime;
588}
589
590/**
591  \brief main loop of the world: executing all world relevant function
592
593  in this loop we synchronize (if networked), handle input events, give the heart-beat to
594  all other member-entities of the world (tick to player, enemies etc.), checking for
595  collisions drawing everything to the screen.
596*/
597void World::mainLoop()
598{
599  this->lastFrame = SDL_GetTicks ();
600  PRINTF(3)("World::mainLoop() - Entering main loop\n");
601
602  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* @todo implement pause */
603    {
604      ++this->cycle;
605      // Network
606      this->synchronize ();
607      // Process input
608      this->handleInput ();
609      if( this->bQuitCurrentGame || this->bQuitOrxonox)
610          break;
611      // Process time
612      this->tick ();
613      // Process collision
614      this->collide ();
615      // Update the state
616      this->update ();
617      // Draw
618      this->display ();
619    }
620
621  PRINTF(3)("World::mainLoop() - Exiting the main loop\n");
622}
623
624
625/**
626 *  synchronize local data with remote data
627*/
628void World::synchronize ()
629{
630  // Get remote input
631  // Update synchronizables
632/*  NetworkManager::getInstance()->synchronize();*/
633}
634
635
636/**
637 *  run all input processing
638
639   the command node is the central input event dispatcher. the node uses the even-queue from
640   sdl and has its own event-passing-queue.
641*/
642void World::handleInput ()
643{
644  EventHandler::getInstance()->process();
645
646  // remoteinput
647}
648
649void World::tick(std::list<WorldEntity*> entityList, float dt)
650{
651  std::list<WorldEntity*>::iterator entity;
652  for (entity = entityList.begin(); entity != entityList.end(); entity++)
653    (*entity)->tick(dt);
654
655}
656
657/**
658 *  advance the timeline
659
660   this calculates the time used to process one frame (with all input handling, drawing, etc)
661   the time is mesured in ms and passed to all world-entities and other classes that need
662   a heart-beat.
663*/
664void World::tick ()
665{
666  Uint32 currentFrame = SDL_GetTicks();
667  if(!this->bPause)
668    {
669      this->dt = currentFrame - this->lastFrame;
670
671      if( this->dt > 10)
672        {
673          float fps = 1000/dt;
674
675          // temporary, only for showing how fast the text-engine is
676          char tmpChar[20];
677          sprintf(tmpChar, "fps: %4.0f", fps);
678        }
679      else
680        {
681          /* the frame-rate is limited to 100 frames per second, all other things are for
682             nothing.
683          */
684          PRINTF(3)("fps = 1000 - frame rate is adjusted\n");
685          SDL_Delay(10-dt);
686          this->dt = 10;
687        }
688
689      this->dtS = (float)this->dt / 1000.0 * this->speed;
690      this->gameTime += this->dtS;
691
692      this->tick(this->objectManager.getObjectList(OM_DEAD_TICK), this->dtS);
693      this->tick(this->objectManager.getObjectList(OM_COMMON), this->dtS);
694      this->tick(this->objectManager.getObjectList(OM_GROUP_00), this->dtS);
695      this->tick(this->objectManager.getObjectList(OM_GROUP_01), this->dtS);
696      this->tick(this->objectManager.getObjectList(OM_GROUP_01_PROJ), this->dtS);
697
698//       tIterator<WorldEntity>* iterator = this->entities->getIterator();
699//       WorldEntity* entity = iterator->firstElement();
700//       while( entity != NULL)
701//         {
702//           entity->tick (this->dtS);
703//           entity = iterator->nextElement();
704//         }
705//       delete iterator;
706
707      /* update tick the rest */
708      this->localCamera->tick(this->dtS);
709      // tick the engines
710      AnimationPlayer::getInstance()->tick(this->dtS);
711//      if (this->cycle > 5)
712        PhysicsEngine::getInstance()->tick(this->dtS);
713
714      ParticleEngine::getInstance()->tick(this->dtS);
715
716
717      /** actualy the Graphics Engine should tick the world not the other way around...
718         but since we like the things not too complicated we got it this way around
719         until there is need or time to do it the other way around.
720         @todo: GraphicsEngine ticks world: separation of processes and data...
721
722        bensch: in my opinion the GraphicsEngine could draw the world, but not tick it,
723         beceause graphics have nothing(or at least not much) to do with Motion.
724      */
725      GraphicsEngine::getInstance()->tick(this->dtS);
726    }
727  this->lastFrame = currentFrame;
728}
729
730
731/**
732 *  this function gives the world a consistant state
733
734   after ticking (updating the world state) this will give a constistant
735   state to the whole system.
736*/
737void World::update()
738{
739  GraphicsEngine::getInstance()->update(this->dtS);
740  PNode::getNullParent()->updateNode (this->dtS);
741
742  SoundEngine::getInstance()->update();
743  //music->update();
744}
745
746
747void World::collide()
748{
749  CDEngine::getInstance()->checkCollisions(this->objectManager.getObjectList(OM_GROUP_00), this->objectManager.getObjectList(OM_GROUP_01_PROJ));
750  CDEngine::getInstance()->checkCollisions(this->objectManager.getObjectList(OM_GROUP_01), this->objectManager.getObjectList(OM_COMMON));
751}
752
753/**
754 *  render the current frame
755
756   clear all buffers and draw the world
757*/
758void World::display ()
759{
760  // clear buffer
761  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
762  // set camera
763  this->localCamera->apply ();
764  // draw world
765  this->draw();
766  // draw HUD
767  /** @todo draw HUD */
768  // flip buffers
769  GraphicsEngine::swapBuffers();
770  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
771  //SDL_Flip (screen);
772}
773
774
775/**
776 *  runs through all entities calling their draw() methods
777 */
778void World::draw ()
779{
780  GraphicsEngine* engine = GraphicsEngine::getInstance();
781  engine->draw(State::getObjectManager()->getObjectList(OM_ENVIRON_NOTICK));
782  engine->draw(State::getObjectManager()->getObjectList(OM_ENVIRON));
783  engine->draw(State::getObjectManager()->getObjectList(OM_COMMON));
784  engine->draw(State::getObjectManager()->getObjectList(OM_GROUP_00));
785  engine->draw(State::getObjectManager()->getObjectList(OM_GROUP_01));
786  engine->draw(State::getObjectManager()->getObjectList(OM_GROUP_01_PROJ));
787
788//   {
789//     if( entity->isVisible() ) entity->draw();
790  //FIXME
791//     if( unlikely( this->showBV)) entity->drawBVTree(3, 226);  // to draw the bounding boxes of the objects at level 2 for debug purp
792//     entity = iterator->nextElement();
793//   }
794
795  glCallList (objectList);
796
797  ParticleEngine::getInstance()->draw();
798
799  if (unlikely(this->showPNodes))
800    PNode::getNullParent()->debugDraw(0);
801
802  engine->draw();
803  //TextEngine::getInstance()->draw();
804}
805
806/**
807 *  add and spawn a new entity to this world
808 * @param entity to be added
809*/
810void World::spawn(WorldEntity* entity)
811{
812//   this->entities->add (entity);
813  entity->postSpawn ();
814}
815
816
817/**
818 *  add and spawn a new entity to this world
819 * @param entity to be added
820 * @param absCoor At what coordinates to add this entity.
821 * @param absDir In which direction should it look.
822*/
823void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
824{
825//   this->entities->add (entity);
826
827  entity->setAbsCoor (*absCoor);
828  entity->setAbsDir (*absDir);
829
830  entity->postSpawn ();
831}
832
833
834/**
835 *  add and spawn a new entity to this world
836 * @param entity to be added
837 * @param entity to be added to (PNode)
838 * @param At what relative  coordinates to add this entity.
839 * @param In which relative direction should it look.
840*/
841void World::spawn(WorldEntity* entity, PNode* parentNode,
842                  Vector* relCoor, Quaternion* relDir)
843{
844  if( parentNode != NULL)
845    {
846      parentNode->addChild (entity);
847
848      entity->setRelCoor (*relCoor);
849      entity->setRelDir (*relDir);
850
851//       this->entities->add (entity);
852
853      entity->postSpawn ();
854    }
855}
856
857void World::setPath( const char* name)
858{
859  if (this->path)
860    delete this->path;
861  if (ResourceManager::isFile(name))
862  {
863    this->path = new char[strlen(name)+1];
864    strcpy(this->path, name);
865  }
866  else
867    {
868      this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];
869      sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);
870    }
871}
872
873const char* World::getPath( void)
874{
875  return path;
876}
Note: See TracBrowser for help on using the repository browser.