Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/story_entities/world.cc @ 5968

Last change on this file since 5968 was 5968, checked in by patrick, 18 years ago

network: merged the trunk into the network with the command svn merge -r5824:HEAD ../trunk network, changes changed… bla bla..

File size: 21.6 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 "network_manager.h"
73#include "playable.h"
74
75
76SHELL_COMMAND(speed, World, setSpeed);
77SHELL_COMMAND(togglePNodeVisibility, World, togglePNodeVisibility);
78SHELL_COMMAND(toggleBVVisibility, World, toggleBVVisibility);
79
80using namespace std;
81
82//! This creates a Factory to fabricate a World
83CREATE_FACTORY(World, CL_WORLD);
84
85World::World(const TiXmlElement* root)
86{
87  this->constuctorInit("", -1);
88  this->path = NULL;
89
90  this->loadParams(root);
91}
92
93/**
94  *  create a new World
95
96    This creates a new empty world!
97*/
98World::World (const char* name)
99{
100  this->path = NULL;
101  this->constuctorInit(name, -1);
102}
103
104/**
105 *  creates a new World...
106 * @param worldID with this ID
107*/
108World::World (int worldID)
109{
110  this->path = NULL;
111  this->constuctorInit(NULL, worldID);
112}
113
114/**
115 *  remove the World from memory
116
117    delete everything explicitly, that isn't contained in the parenting tree!
118    things contained in the tree are deleted automaticaly
119 */
120World::~World ()
121{
122  delete this->shell;
123  PRINTF(3)("World::~World() - deleting current world\n");
124
125
126  // here everything that is alocated by the World is deleted
127  delete this->entities;
128  State::setWorldEntityList(NULL);
129
130  delete this->localPlayer;
131
132  // delete all the initialized Engines.
133  FastFactory::flushAll(true);
134  delete LightManager::getInstance();
135  delete ParticleEngine::getInstance();
136  delete AnimationPlayer::getInstance();
137  delete PhysicsEngine::getInstance();
138
139  // external engines initialized by the orxonox-class get deleted
140  SoundEngine::getInstance()->flushAllBuffers();
141  SoundEngine::getInstance()->flushAllSources();
142
143
144  // erease everything that is left.
145  delete NullParent::getInstance();
146
147  Shader::suspendShader();
148
149  // unload the resources !!
150  ResourceManager::getInstance()->unloadAllByPriority(RP_LEVEL);
151
152  delete[] this->path;
153}
154
155/**
156 * initializes the world.
157 * @param name the name of the world
158 * @param worldID the ID of this world
159 *
160 * set all stuff here that is world generic and does not use to much memory
161 * because the real init() function StoryEntity::init() will be called
162 * shortly before start of the game.
163 * since all worlds are initiated/referenced before they will be started.
164 * NO LEVEL LOADING HERE - NEVER!
165*/
166void World::constuctorInit(const char* name, int worldID)
167{
168  this->setClassID(CL_WORLD, "World");
169
170  this->setName(name);
171  this->debugWorldNr = worldID;
172  this->gameTime = 0.0f;
173  this->setSpeed(1.0);
174  this->music = NULL;
175  this->shell = NULL;
176  this->entities = 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::setWorldEntityList(this->entities = new tList<WorldEntity>());
211  this->cycle = 0;
212
213  /* init the world interface */
214  this->shell = new Shell();
215
216  LightManager::getInstance();
217  NullParent::getInstance ();
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  CDEngine::getInstance()->setEntityList( this->entities);
231}
232
233
234/**
235 *  loads the World by initializing all resources, and set their default values.
236*/
237ErrorMessage World::load()
238{
239  PRINTF(3)("> Loading world: '%s'\n", getPath());
240  TiXmlElement* element;
241  GameLoader* loader = GameLoader::getInstance();
242
243  if( getPath() == NULL)
244    {
245      PRINTF(1)("World has no path specified for loading");
246      this->loadDebugWorld(this->getStoryID());
247      return (ErrorMessage){213,"Path not specified","World::load()"};
248    }
249
250  TiXmlDocument* XMLDoc = new TiXmlDocument( getPath());
251  // load the campaign document
252  if( !XMLDoc->LoadFile())
253  {
254    // report an error
255    PRINTF(1)("loading XML File: %s @ %s:l%d:c%d\n", XMLDoc->ErrorDesc(), this->getPath(), XMLDoc->ErrorRow(), XMLDoc->ErrorCol());
256    delete XMLDoc;
257    return (ErrorMessage){213,"XML File parsing error","World::load()"};
258  }
259
260  // check basic validity
261  TiXmlElement* root = XMLDoc->RootElement();
262  assert( root != NULL);
263
264  if( root == NULL || root->Value() == NULL || strcmp( root->Value(), "WorldDataFile"))
265    {
266      // report an error
267      PRINTF(1)("Specified XML File is not an orxonox world data file (WorldDataFile element missing)\n");
268      delete XMLDoc;
269      return (ErrorMessage){213,"Path not a WorldDataFile","World::load()"};
270    }
271
272  // load the parameters
273  // name
274  const char* string = grabParameter( root, "name");
275  if( string == NULL)
276    {
277      PRINTF(2)("World is missing a proper 'name'\n");
278      this->setName("Unknown");
279    }
280  else
281    {
282      this->setName(string);
283    }
284
285  ////////////////
286  // LOADSCREEN //
287  ////////////////
288  element = root->FirstChildElement("LoadScreen");
289  if (element == NULL)
290    {
291      PRINTF(2)("no LoadScreen specified, loading default\n");
292
293      glmis->setBackgroundImage("pictures/load_screen.jpg");
294      this->glmis->setMaximum(8);
295      this->glmis->draw();
296    }
297  else
298    {
299      this->glmis->loadParams(element);
300      this->glmis->draw();
301    }
302  this->glmis->draw();
303
304  ////////////////////////
305  // find WorldEntities //
306  ////////////////////////
307
308  element = root->FirstChildElement("WorldEntities");
309
310  if( element == NULL)
311    {
312      PRINTF(1)("World is missing 'WorldEntities'\n");
313    }
314  else
315    {
316      element = element->FirstChildElement();
317      // load Players/Objects/Whatever
318      PRINTF(4)("Loading WorldEntities\n");
319      while( element != NULL)
320        {
321          BaseObject* created = (loader->fabricate(element));
322          if( created != NULL )
323          {
324            if(created->isA(CL_WORLD_ENTITY))
325              this->spawn(dynamic_cast<WorldEntity*>(created));
326            printf("Created a %s: %s\n", created->getClassName(), created->getName());
327            NetworkManager::getInstance()->connectSynchronizeable(*(Synchronizeable*)this->localPlayer);
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;//(OggPlayer*)ResourceManager::getInstance()->load("sound/00-luke_grey_-_hypermode.ogg", OGG, RP_LEVEL);
418  //music->playback();
419}
420
421
422
423/**
424 * creates a debug world: only for experimental stuff
425*/
426void World::loadDebugWorld(int worldID)
427{
428  /*monitor progress*/
429  this->glmis->step();
430  // stuff beyond this point remains to be loaded properly
431
432  // LIGHT initialisation
433  LightManager::getInstance()->setAmbientColor(.1,.1,.1);
434//  LightManager::getInstance()->addLight();
435  LightManager::getInstance()->debug();
436
437  switch(this->debugWorldNr)
438    {
439      /*
440        this loads the hard-coded debug world. this only for simplicity and will be
441        removed by a reald world-loader, which interprets a world-file.
442        if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
443        make whatever you want...
444      */
445    case DEBUG_WORLD_0:
446      {
447        LightManager::getInstance()->getLight()->setAbsCoor(-5.0, 10.0, -40.0);
448        /*monitor progress*/
449        this->glmis->step();
450
451        // bind camera
452        this->localCamera = new Camera();
453        this->localCamera->setName ("camera");
454        /*monitor progress*/
455        this->glmis->step();
456
457
458        // Create SkySphere
459        this->sky = new Skysphere("pictures/sky-replace.jpg");
460        this->sky->setName("SkySphere");
461        this->spawn(this->sky);
462        this->localCamera->addChild(this->sky);
463        this->sky->setParentMode(PNODE_MOVEMENT);
464        /*monitor progress*/
465        this->glmis->step();
466
467
468        terrain = new Terrain("worlds/newGround.obj");
469        terrain->setRelCoor(Vector(0,-10,0));
470        this->spawn(terrain);
471        /*monitor progress*/
472        this->glmis->step();
473
474        this->glmis->step();
475        break;
476      }
477    case DEBUG_WORLD_1:
478      {
479
480        break;
481      }
482    case DEBUG_WORLD_2:
483      {
484
485        break;
486      }
487    default:
488      break;
489    }
490}
491
492/**
493 *  initializes a new World shortly before start
494 *
495 * this is the function, that will be loaded shortly before the world is
496 * started
497*/
498ErrorMessage World::init()
499{
500  this->bPause = false;
501
502  /* update the object position before game start - so there are no wrong coordinates used in the first processing */
503  NullParent::getInstance()->updateNode (0.001f);
504  NullParent::getInstance()->updateNode (0.001f);
505
506}
507
508
509/**
510 *  starts the World
511*/
512ErrorMessage World::start()
513{
514  PRINTF(3)("World::start() - starting current World: nr %i\n", this->debugWorldNr);
515  this->bQuitOrxonox = false;
516  this->bQuitCurrentGame = false;
517  this->mainLoop();
518}
519
520/**
521 *  stops the world.
522
523   This happens, when the player decides to end the Level.
524*/
525ErrorMessage World::stop()
526{
527  PRINTF(3)("World::stop() - got stop signal\n");
528  this->bQuitCurrentGame = true;
529}
530
531/**
532 *  pauses the Game
533*/
534ErrorMessage World::pause()
535{
536  this->isPaused = true;
537}
538
539/**
540 *  ends the pause Phase
541*/
542ErrorMessage World::resume()
543{
544  this->isPaused = false;
545}
546
547/**
548 *  destroys the World
549*/
550ErrorMessage World::destroy()
551{
552
553}
554
555/**
556 *  shows the loading screen
557*/
558void World::displayLoadScreen ()
559{
560  PRINTF(3)("World::displayLoadScreen - start\n");
561
562  //GLMenuImageScreen*
563  this->glmis = new GLMenuImageScreen();
564  this->glmis->setMaximum(8);
565
566  PRINTF(3)("World::displayLoadScreen - end\n");
567}
568
569/**
570 *  removes the loadscreen, and changes over to the game
571
572   @todo take out the delay
573*/
574void World::releaseLoadScreen ()
575{
576  PRINTF(3)("World::releaseLoadScreen - start\n");
577  this->glmis->setValue(this->glmis->getMaximum());
578  PRINTF(3)("World::releaseLoadScreen - end\n");
579  delete this->glmis;
580}
581
582
583/**
584 *  gets the list of entities from the world
585 * @returns entity list
586*/
587tList<WorldEntity>* World::getEntities()
588{
589  return this->entities;
590}
591
592
593/**
594 *  this returns the current game time
595 * @returns elapsed game time
596*/
597double World::getGameTime()
598{
599  return this->gameTime;
600}
601
602
603/**
604 *  function to put your own debug stuff into it. it can display informations about
605   the current class/procedure
606*/
607void World::debug()
608{
609  PRINTF(0)("Printing out the List of alive WorldEntities:\n");
610  tIterator<WorldEntity>* iterator = this->entities->getIterator();
611  WorldEntity* entity = iterator->firstElement();
612  while( entity != NULL)
613  {
614    PRINTF(0)("%s::%s\n", entity->getClassName(), entity->getName());
615    entity = iterator->nextElement();
616  }
617  delete iterator;
618}
619
620
621/**
622  \brief main loop of the world: executing all world relevant function
623
624  in this loop we synchronize (if networked), handle input events, give the heart-beat to
625  all other member-entities of the world (tick to player, enemies etc.), checking for
626  collisions drawing everything to the screen.
627*/
628void World::mainLoop()
629{
630  this->lastFrame = SDL_GetTicks ();
631  PRINTF(3)("World::mainLoop() - Entering main loop\n");
632
633  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* @todo implement pause */
634    {
635      ++this->cycle;
636      PRINTF(4)("World::mainloop() - number of entities: %i\n", this->entities->getSize());
637      // Network
638      this->synchronize ();
639      // Process input
640      this->handleInput ();
641      if( this->bQuitCurrentGame || this->bQuitOrxonox)
642          break;
643      // Process time
644      this->tick ();
645      // Process collision
646      this->collide ();
647      // Update the state
648      this->update ();
649      // Draw
650      this->display ();
651    }
652
653  PRINTF(3)("World::mainLoop() - Exiting the main loop\n");
654}
655
656
657/**
658 *  synchronize local data with remote data
659*/
660void World::synchronize ()
661{
662  // Get remote input
663  // Update synchronizables
664  NetworkManager::getInstance()->synchronize();
665}
666
667
668/**
669 *  run all input processing
670
671   the command node is the central input event dispatcher. the node uses the even-queue from
672   sdl and has its own event-passing-queue.
673*/
674void World::handleInput ()
675{
676  EventHandler::getInstance()->process();
677
678  // remoteinput
679}
680
681
682/**
683 *  advance the timeline
684
685   this calculates the time used to process one frame (with all input handling, drawing, etc)
686   the time is mesured in ms and passed to all world-entities and other classes that need
687   a heart-beat.
688*/
689void World::tick ()
690{
691  Uint32 currentFrame = SDL_GetTicks();
692  if(!this->bPause)
693    {
694      this->dt = currentFrame - this->lastFrame;
695
696      if( this->dt > 10)
697        {
698          float fps = 1000/dt;
699
700          // temporary, only for showing how fast the text-engine is
701          char tmpChar[20];
702          sprintf(tmpChar, "fps: %4.0f", fps);
703        }
704      else
705        {
706          /* the frame-rate is limited to 100 frames per second, all other things are for
707             nothing.
708          */
709          PRINTF(3)("fps = 1000 - frame rate is adjusted\n");
710          SDL_Delay(10-dt);
711          this->dt = 10;
712        }
713
714      this->dtS = (float)this->dt / 1000.0 * this->speed;
715      this->gameTime += this->dtS;
716
717      tIterator<WorldEntity>* iterator = this->entities->getIterator();
718      WorldEntity* entity = iterator->firstElement();
719      while( entity != NULL)
720        {
721          entity->tick (this->dtS);
722          entity = iterator->nextElement();
723        }
724      delete iterator;
725
726      /* update tick the rest */
727      this->localCamera->tick(this->dtS);
728      // tick the engines
729      AnimationPlayer::getInstance()->tick(this->dtS);
730//      if (this->cycle > 5)
731        PhysicsEngine::getInstance()->tick(this->dtS);
732
733      ParticleEngine::getInstance()->tick(this->dtS);
734      GarbageCollector::getInstance()->tick(this->dtS);
735
736
737      /** actualy the Graphics Engine should tick the world not the other way around...
738         but since we like the things not too complicated we got it this way around
739         until there is need or time to do it the other way around.
740         @todo: GraphicsEngine ticks world: separation of processes and data...
741
742        bensch: in my opinion the GraphicsEngine could draw the world, but not tick it,
743         beceause graphics have nothing(or at least not much) to do with Motion.
744      */
745      GraphicsEngine::getInstance()->tick(this->dtS);
746    }
747  this->lastFrame = currentFrame;
748}
749
750
751/**
752 *  this function gives the world a consistant state
753
754   after ticking (updating the world state) this will give a constistant
755   state to the whole system.
756*/
757void World::update()
758{
759  GarbageCollector::getInstance()->update();
760  GraphicsEngine::getInstance()->update(this->dtS);
761  NullParent::getInstance()->updateNode (this->dtS);
762
763  SoundEngine::getInstance()->update();
764  //music->update();
765}
766
767
768void World::collide()
769{
770  CDEngine::getInstance()->checkCollisions();
771}
772
773/**
774 *  render the current frame
775
776   clear all buffers and draw the world
777*/
778void World::display ()
779{
780  // clear buffer
781  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
782  // set camera
783  this->localCamera->apply ();
784  // draw world
785  this->draw();
786  // draw HUD
787  /** @todo draw HUD */
788  // flip buffers
789  GraphicsEngine::swapBuffers();
790  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
791  //SDL_Flip (screen);
792}
793
794
795/**
796 *  runs through all entities calling their draw() methods
797 */
798void World::draw ()
799{
800  /* draw entities */
801  WorldEntity* entity;
802  glLoadIdentity();
803  tIterator<WorldEntity>* iterator = this->entities->getIterator();
804  entity = iterator->firstElement();
805  while( entity != NULL )
806  {
807    if( entity->isVisible() ) entity->draw();
808    if( unlikely( this->showBV)) entity->drawBVTree(3, 226);  // to draw the bounding boxes of the objects at level 2 for debug purp
809    entity = iterator->nextElement();
810  }
811  delete iterator;
812
813  glCallList (objectList);
814
815  ParticleEngine::getInstance()->draw();
816
817  if (unlikely(this->showPNodes))
818    NullParent::getInstance()->debugDraw(0);
819
820  GraphicsEngine::getInstance()->draw();
821  //TextEngine::getInstance()->draw();
822}
823
824/**
825 *  add and spawn a new entity to this world
826 * @param entity to be added
827*/
828void World::spawn(WorldEntity* entity)
829{
830  this->entities->add (entity);
831  entity->postSpawn ();
832}
833
834
835/**
836 *  add and spawn a new entity to this world
837 * @param entity to be added
838 * @param absCoor At what coordinates to add this entity.
839 * @param absDir In which direction should it look.
840*/
841void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
842{
843  this->entities->add (entity);
844
845  entity->setAbsCoor (*absCoor);
846  entity->setAbsDir (*absDir);
847
848  entity->postSpawn ();
849}
850
851
852/**
853 *  add and spawn a new entity to this world
854 * @param entity to be added
855 * @param entity to be added to (PNode)
856 * @param At what relative  coordinates to add this entity.
857 * @param In which relative direction should it look.
858*/
859void World::spawn(WorldEntity* entity, PNode* parentNode,
860                  Vector* relCoor, Quaternion* relDir)
861{
862  if( parentNode != NULL)
863    {
864      parentNode->addChild (entity);
865
866      entity->setRelCoor (*relCoor);
867      entity->setRelDir (*relDir);
868
869      this->entities->add (entity);
870
871      entity->postSpawn ();
872    }
873}
874
875void World::setPath( const char* name)
876{
877  if (this->path)
878    delete this->path;
879  if (ResourceManager::isFile(name))
880  {
881    this->path = new char[strlen(name)+1];
882    strcpy(this->path, name);
883  }
884  else
885    {
886      this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];
887      sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);
888    }
889}
890
891const char* World::getPath( void)
892{
893  return path;
894}
Note: See TracBrowser for help on using the repository browser.