Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/story_entities/world.cc @ 6048

Last change on this file since 6048 was 6034, checked in by bensch, 18 years ago

orxonox/trunk: merged the spaceshipcontroll branche back to the trunk
merged with command
svn merge branche/spaceshipcontroll trunk -r5978:HEAD
confilcs:
space_ship.cc: favor of controll, but Draw from trunk
rest: space_ship.h and sound_engine. in favor of the spaceshipcontroll branche

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