Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged branches/spaceshipControll back to the trunk:
merged with command:
svn merge -r5835:HEAD branches/spaceshipcontroll trunk
conflicts resolved with dynamic indentation methodology algorithms

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