Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: new Collision-detection algorithm, checking for framerate-increase now

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