Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: reimplemented the Camera.
Camera is now a PNode and not a WorldEntity. I have taken out all the unnecessary stuff like ELLIPTIC_CAMERA and so on, and now it is more like it should be in the new Framework

File size: 20.4 KB
Line 
1
2/*
3   orxonox - the future of 3D-vertical-scrollers
4
5   Copyright (C) 2004 orx
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2, or (at your option)
10   any later version.
11
12   ### File Specific:
13   main-programmer: Patrick Boenzli
14   co-programmer: Christian Meyer
15*/
16
17#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD
18
19#include "world.h"
20
21#include "orxonox.h"
22
23#include "p_node.h"
24#include "null_parent.h"
25#include "helper_parent.h"
26#include "track_node.h"
27#include "world_entity.h"
28#include "track_manager.h"
29#include "player.h"
30#include "camera.h"
31#include "environment.h"
32#include "primitive.h"
33#include "skysphere.h"
34#include "terrain.h"
35#include "light.h"
36
37#include "command_node.h"
38#include "glmenu_imagescreen.h"
39#include "fontset.h"
40#include "list.h"
41
42
43
44using namespace std;
45
46
47WorldInterface* WorldInterface::singletonRef = 0;
48
49
50/**
51   \brief private constructor because of singleton
52*/
53WorldInterface::WorldInterface()
54{
55  this->worldIsInitialized = false;
56  this->worldReference = NULL;
57}
58
59/**
60   \brief public deconstructor
61*/
62WorldInterface::~WorldInterface()
63{
64  this->singletonRef = NULL;
65  this->worldIsInitialized = false;
66  this->worldReference = NULL;
67}
68
69/**
70   \brief gets the singleton instance
71   \returns singleton instance
72*/
73WorldInterface* WorldInterface::getInstance()
74{
75  if( singletonRef == NULL)
76    singletonRef = new WorldInterface();
77  return singletonRef;
78}
79
80
81/**
82   \brief initializes the interface
83   \param reference to the world
84
85   if the worldinterface is not initilizes, there wont be any
86   useable interface
87*/
88void WorldInterface::init(World* world)
89{
90  this->worldReference = world;
91  if( world != NULL)
92    {
93      this->worldIsInitialized = true;
94      PRINTF(3)("WorldInterface up and running\n");
95    }
96}
97
98
99/**
100   \brief gets the entity list from the world
101   \return entity list
102*/
103tList<WorldEntity>* WorldInterface::getEntityList()
104{
105  if( this->worldIsInitialized)
106    return this->worldReference->getEntities();
107  PRINT(1)("Someone tried to use the WorldInterface before it has been initizlized! this can result in SEGFAULTs!\n");
108  return NULL;
109}
110
111
112
113/**
114    \brief create a new World
115   
116    This creates a new empty world!
117*/
118World::World (char* name)
119{
120  this->init(name, -1);
121  //NullParent* np = NullParent::getInstance();
122}
123
124/**
125   \brief creates a new World...
126   \param worldID with this ID
127*/
128World::World (int worldID)
129{
130  printf(">>>>>>>>>>>>>>>>>WORLD::WORLD called NEW WORLD created\n");
131  this->init(NULL, worldID);
132}
133
134/**
135    \brief remove the World from memory
136   
137    delete everything explicitly, that isn't contained in the parenting tree!
138    things contained in the tree are deleted automaticaly
139*/
140World::~World ()
141{
142  PRINTF(3)("World::~World() - deleting current world\n");
143  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
144  cn->unbind(this->localPlayer);
145  cn->reset();
146
147  delete WorldInterface::getInstance();
148
149  delete this->nullParent;
150  delete this->entities;
151  delete this->lightMan;
152  delete this->trackManager;
153}
154
155/**
156   \brief initializes the 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::init(char* name, int worldID)
165{
166  this->setClassName ("World");
167
168  this->worldName = name;
169  this->debugWorldNr = worldID;
170  this->entities = new tList<WorldEntity>();
171}
172
173
174/**
175   \brief this is executed before load
176
177   since the load function sometimes needs data, that has been init before
178   the load and after the proceeding storyentity has finished
179*/
180ErrorMessage World::preLoad()
181{
182  /* init the world interface */
183  WorldInterface* wi = WorldInterface::getInstance();
184  wi->init(this);
185}
186
187
188/**
189   \brief loads the World by initializing all resources, and set their default values.
190*/
191ErrorMessage World::load()
192{
193  //  BezierCurve* tmpCurve = new BezierCurve();
194  if(this->debugWorldNr != -1)
195    {
196      // initializing Font
197      testFont = new FontSet();
198      testFont->buildFont("../data/pictures/font.tga");
199
200      // initializing the TrackManager
201      trackManager = TrackManager::getInstance();
202      trackManager->addPoint(Vector(0,0,0));
203      trackManager->addPoint(Vector(100, -40, 5));
204      trackManager->addPoint(Vector(200,-40,-8));
205      trackManager->addPoint(Vector(250, -35, -2));
206      trackManager->addPoint(Vector(320,-33,-.55));
207      trackManager->setDuration(3);
208      trackManager->setSavePoint();
209      trackManager->addPoint(Vector(410, 0, 0));
210      trackManager->addPoint(Vector(510, 20, -10));
211      trackManager->addPoint(Vector(550, 20, -10));
212      trackManager->addPoint(Vector(570, 20, -10));
213      trackManager->setDuration(5);
214     
215      int fork11, fork12;
216      trackManager->fork(2, &fork11, &fork12);
217      trackManager->workOn(fork11);
218      trackManager->addPoint(Vector(640, 25, -30));
219      trackManager->addPoint(Vector(700, 40, -120));
220      trackManager->addPoint(Vector(800, 50, -150));
221      trackManager->addPoint(Vector(900, 60, -100));
222      trackManager->addPoint(Vector(900, 60, -70));
223      trackManager->addPoint(Vector(990, 65, -15));
224      trackManager->addPoint(Vector(1050, 65, -10));
225      trackManager->addPoint(Vector(1100, 65, -20));
226      trackManager->setDuration(10);
227
228      trackManager->workOn(fork12);
229      trackManager->addPoint(Vector(640, 25, 20));
230      trackManager->addPoint(Vector(670, 50, 120));
231      trackManager->addPoint(Vector(700, 70, 80));
232      trackManager->addPoint(Vector(800, 70, 65));
233      trackManager->addPoint(Vector(850, 65, 65));
234      trackManager->addPoint(Vector(920, 35, 40));
235      trackManager->addPoint(Vector(945, 40, 40));
236      trackManager->addPoint(Vector(970, 24, 40));
237      trackManager->addPoint(Vector(1000, 40, -7));
238      trackManager->setDuration(10);
239     
240
241      trackManager->join(2, fork11, fork12);
242
243      trackManager->workOn(5);
244      trackManager->addPoint(Vector(1200, 60, -50));
245      trackManager->addPoint(Vector(1300, 50, -50));
246      trackManager->addPoint(Vector(1400, 40, -50));
247      trackManager->addPoint(Vector(1500, 40, -60));
248      trackManager->addPoint(Vector(1600, 35, -55));
249      trackManager->addPoint(Vector(1700, 45, -40));
250      trackManager->addPoint(Vector(1750, 60, -40));
251      trackManager->addPoint(Vector(1770, 80, -40));
252      trackManager->addPoint(Vector(1800, 100, -40));
253      trackManager->setDuration(10);
254
255      trackManager->finalize();
256
257     
258      /*monitor progress*/
259      this->glmis->step();
260
261      // LIGHT initialisation
262      lightMan = LightManager::getInstance();
263      lightMan->setAmbientColor(.1,.1,.1);
264      lightMan->addLight();
265      //      lightMan->setAttenuation(1.0, .01, 0.0);
266      //      lightMan->setDiffuseColor(1,1,1);
267      //  lightMan->addLight(1);
268      //  lightMan->setPosition(20, 10, -20);
269      //  lightMan->setDiffuseColor(0,0,0);
270      lightMan->debug();
271
272      switch(this->debugWorldNr)
273        {
274          /*
275            this loads the hard-coded debug world. this only for simplicity and will be
276            removed by a reald world-loader, which interprets a world-file.
277            if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
278            make whatever you want...
279           */
280        case DEBUG_WORLD_0:
281          {
282            lightMan->setPosition(-5.0, 10.0, -40.0);
283            this->nullParent = NullParent::getInstance ();
284            this->nullParent->setName ("NullParent");
285
286            // !\todo old track-system has to be removed
287
288            //create helper for player
289            //HelperParent* hp = new HelperParent ();
290            /* the player has to be added to this helper */
291
292            // create a player
293            this->localPlayer = new Player ();
294            this->localPlayer->setName ("player");
295            this->spawn (this->localPlayer);
296            /*monitor progress*/
297            this->glmis->step();           
298
299            // bind input
300            Orxonox *orx = Orxonox::getInstance ();
301            orx->getLocalInput()->bind (this->localPlayer);
302           
303            // bind camera
304            this->localCamera = new Camera();
305            this->localCamera->setName ("camera");
306            this->localCamera->lookAt(this->localPlayer);
307
308            /*monitor progress*/
309            this->glmis->step();           
310
311            // Create SkySphere
312            this->skySphere = new Skysphere("../data/pictures/sky-replace.jpg");
313            this->skySphere->setName("SkySphere");
314            this->localCamera->addChild(this->skySphere);
315            this->skySphere->setMode(PNODE_MOVEMENT);
316
317            /*monitor progress*/
318            this->glmis->step();
319
320           
321            WorldEntity* env = new Environment();
322            env->setName ("env");
323            this->spawn(env);
324
325           
326            Vector* es = new Vector (10, 5, 0);
327            Quaternion* qs = new Quaternion ();
328            WorldEntity* pr = new Primitive(P_CYLINDER);
329            pr->setName("primitive");
330            this->spawn(pr, this->localPlayer, es, qs, PNODE_MOVEMENT);
331           
332
333            /*monitor progress*/
334            this->glmis->step();
335
336            //      trackManager->setBindSlave(env);
337            PNode* tn = trackManager->getTrackNode();
338            tn->addChild(this->localPlayer);
339
340            //localCamera->setParent(TrackNode::getInstance());
341            tn->addChild (this->localCamera);
342            this->localPlayer->setMode(PNODE_ALL);
343            //Vector* cameraOffset = new Vector (0, 5, -10);
344            Vector* cameraOffset = new Vector (-10, 5, 0);
345            this->localCamera->setRelCoor (cameraOffset);
346            trackManager->condition(2, LEFTRIGHT, this->localPlayer);
347
348            break;
349          }
350        case DEBUG_WORLD_1:
351          {
352            lightMan->setPosition(.0, .0, .0);
353            lightMan->setAttenuation(1.0, .01, 0.0);
354            lightMan->setSpecularColor(1,0,0);
355            this->nullParent = NullParent::getInstance ();
356            this->nullParent->setName ("NullParent");
357
358            // create a player
359            WorldEntity* myPlayer = new Player();
360            myPlayer->setName ("player");
361            this->spawn(myPlayer);
362            this->localPlayer = myPlayer;           
363           
364            // bind input
365            Orxonox *orx = Orxonox::getInstance();
366            orx->getLocalInput()->bind (myPlayer);
367           
368            // bind camera
369            this->localCamera = new Camera ();
370            this->localCamera->setName ("camera");
371            this->localCamera->lookAt(this->localPlayer);
372            this->localPlayer->addChild (this->localCamera);
373
374            // Create SkySphere
375            skySphere = new Skysphere("../data/pictures/sky-replace.jpg");
376            this->localPlayer->addChild(this->skySphere);
377
378            Vector* es = new Vector (20, 0, 0);
379            Quaternion* qs = new Quaternion ();
380            WorldEntity* pr = new Primitive(P_SPHERE);
381            pr->setName("primitive");
382            this->spawn(pr, this->localPlayer, es, qs, PNODE_ROTATE_AND_MOVE);
383
384            lightMan->getLight(0)->setParent(trackManager->getTrackNode());
385            break;
386          }
387        default:
388          printf("World::load() - no world with ID %i found", this->debugWorldNr );
389        }
390    }
391  else if(this->worldName != NULL)
392    {
393
394    }
395
396  // initialize debug coord system
397  objectList = glGenLists(1);
398  glNewList (objectList, GL_COMPILE);
399 
400  trackManager->drawGraph(.01);
401  trackManager->debug(2);
402  glEndList();
403
404  terrain = new Terrain("../data/worlds/newGround.obj");
405  terrain->setRelCoor(new Vector(0,-10,0));
406  this->spawn(terrain);
407
408}
409
410
411/**
412   \brief initializes a new World shortly before start
413
414   this is the function, that will be loaded shortly before the world is
415   started
416*/
417ErrorMessage World::init()
418{
419  this->bPause = false;
420  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
421  cn->addToWorld(this);
422  cn->enable(true);
423}
424
425
426/**
427   \brief starts the World
428*/
429ErrorMessage World::start()
430{
431  PRINTF(3)("World::start() - starting current World: nr %i\n", this->debugWorldNr);
432  this->bQuitOrxonox = false;
433  this->bQuitCurrentGame = false;
434  this->mainLoop();
435}
436
437/**
438   \brief stops the world.
439
440   This happens, when the player decides to end the Level.
441*/
442ErrorMessage World::stop()
443{
444  PRINTF(3)("World::stop() - got stop signal\n");
445  this->bQuitCurrentGame = true;
446}
447
448/**
449   \brief pauses the Game
450*/
451ErrorMessage World::pause()
452{
453  this->isPaused = true;
454}
455
456/**
457   \brief ends the pause Phase
458*/
459ErrorMessage World::resume()
460{
461  this->isPaused = false;
462}
463
464/**
465   \brief destroys the World
466*/
467ErrorMessage World::destroy()
468{
469
470}
471
472/**
473   \brief shows the loading screen
474*/
475void World::displayLoadScreen ()
476{
477  PRINTF(3)("World::displayLoadScreen - start\n"); 
478 
479  //GLMenuImageScreen*
480  this->glmis = GLMenuImageScreen::getInstance();
481  this->glmis->init();
482  this->glmis->setMaximum(10);
483  this->glmis->draw();
484 
485  PRINTF(3)("World::displayLoadScreen - end\n"); 
486}
487
488/**
489   \brief removes the loadscreen, and changes over to the game
490
491   \todo take out the delay
492*/
493void World::releaseLoadScreen ()
494{
495  PRINTF(3)("World::releaseLoadScreen - start\n"); 
496  this->glmis->setValue(this->glmis->getMaximum());
497  SDL_Delay(500);
498  PRINTF(3)("World::releaseLoadScreen - end\n"); 
499}
500
501
502/**
503   \brief gets the list of entities from the world
504   \returns entity list
505*/
506tList<WorldEntity>* World::getEntities()
507{
508  return this->entities;
509}
510
511
512/**
513    \brief checks for collisions
514   
515    This method runs through all WorldEntities known to the world and checks for collisions
516    between them. In case of collisions the collide() method of the corresponding entities
517    is called.
518*/
519void World::collide ()
520{
521  /*
522  List *a, *b;
523  WorldEntity *aobj, *bobj;
524   
525  a = entities;
526 
527  while( a != NULL)
528    {
529      aobj = a->nextElement();
530      if( aobj->bCollide && aobj->collisioncluster != NULL)
531        {
532          b = a->nextElement();
533          while( b != NULL )
534            {
535              bobj = b->nextElement();
536              if( bobj->bCollide && bobj->collisioncluster != NULL )
537                {
538                  unsigned long ahitflg, bhitflg;
539                  if( check_collision ( &aobj->place, aobj->collisioncluster,
540                                        &ahitflg, &bobj->place, bobj->collisioncluster,
541                                        &bhitflg) );
542                  {
543                    aobj->collide (bobj, ahitflg, bhitflg);
544                    bobj->collide (aobj, bhitflg, ahitflg);
545                  }
546                }
547              b = b->nextElement();
548            }
549        }
550      a = a->enumerate();
551    }
552  */
553}
554
555/**
556    \brief runs through all entities calling their draw() methods
557*/
558void World::draw ()
559{
560  /* draw entities */
561  WorldEntity* entity;
562  glLoadIdentity();
563
564  entity = this->entities->enumerate();
565  while( entity != NULL ) 
566    { 
567      if( entity->bDraw ) entity->draw();
568      entity = this->entities->nextElement();
569    } 
570 
571  glCallList (objectList);
572  //! \todo skysphere is a WorldEntity and should be inside of the world-entity-list.
573  skySphere->draw();
574
575  testFont->printText(0, 0, 1, "orxonox_" PACKAGE_VERSION);
576
577  lightMan->draw(); // must be at the end of the drawing procedure, otherwise Light cannot be handled as PNodes //
578}
579
580
581/**
582   \brief function to put your own debug stuff into it. it can display informations about
583   the current class/procedure
584*/
585void World::debug()
586{
587  PRINTF(2)("debug() - starting debug\n");
588  PNode* p1 = NullParent::getInstance ();
589  PNode* p2 = new PNode (new Vector(2, 2, 2), p1);
590  PNode* p3 = new PNode (new Vector(4, 4, 4), p1);
591  PNode* p4 = new PNode (new Vector(6, 6, 6), p2);
592
593  p1->debug ();
594  p2->debug ();
595  p3->debug ();
596  p4->debug ();
597
598  p1->shiftCoor (new Vector(-1, -1, -1));
599
600  printf("World::debug() - shift\n");
601  p1->debug ();
602  p2->debug ();
603  p3->debug ();
604  p4->debug ();
605 
606  p1->update ();
607
608  printf ("World::debug() - update\n");
609  p1->debug ();
610  p2->debug ();
611  p3->debug ();
612  p4->debug ();
613
614  p2->shiftCoor (new Vector(-1, -1, -1));
615  p1->update ();
616
617  p1->debug ();
618  p2->debug ();
619  p3->debug ();
620  p4->debug ();
621
622  p2->setAbsCoor (new Vector(1,2,3));
623
624
625 p1->update ();
626
627  p1->debug ();
628  p2->debug ();
629  p3->debug ();
630  p4->debug ();
631
632  delete p1;
633 
634 
635  /*
636  WorldEntity* entity;
637  printf("counting all entities\n");
638  printf("World::debug() - enumerate()\n");
639  entity = entities->enumerate(); 
640  while( entity != NULL )
641    {
642      if( entity->bDraw ) printf("got an entity\n");
643      entity = entities->nextElement();
644    }
645  */
646}
647
648
649/**
650  \brief main loop of the world: executing all world relevant function
651
652  in this loop we synchronize (if networked), handle input events, give the heart-beat to
653  all other member-entities of the world (tick to player, enemies etc.), checking for
654  collisions drawing everything to the screen.
655*/
656void World::mainLoop()
657{
658  this->lastFrame = SDL_GetTicks ();
659  PRINTF(3)("World::mainLoop() - Entering main loop\n");
660  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* \todo implement pause */
661    {
662      PRINTF(3)("World::mainloop() - number of entities: %i\n", this->entities->getSize());
663      // Network
664      this->synchronize ();
665      // Process input
666      this->handleInput ();
667      if( this->bQuitCurrentGame || this->bQuitOrxonox)
668          break;
669      // Process time
670      this->tick ();
671      // Update the state
672      this->update ();     
673      // Process collision
674      this->collide ();
675      // Draw
676      this->display ();
677
678      //      for( int i = 0; i < 5000000; i++) {}
679      /* \todo this is to slow down the program for openGl Software emulator computers, reimplement*/
680    }
681  PRINTF(3)("World::mainLoop() - Exiting the main loop\n");
682}
683
684
685/**
686   \brief synchronize local data with remote data
687*/
688void World::synchronize ()
689{
690  // Get remote input
691  // Update synchronizables
692}
693
694
695/**
696   \brief run all input processing
697
698   the command node is the central input event dispatcher. the node uses the even-queue from
699   sdl and has its own event-passing-queue.
700*/
701void World::handleInput ()
702{
703  // localinput
704  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
705  cn->process();
706  // remoteinput
707}
708
709
710/**
711   \brief advance the timeline
712
713   this calculates the time used to process one frame (with all input handling, drawing, etc)
714   the time is mesured in ms and passed to all world-entities and other classes that need
715   a heart-beat.
716*/
717void World::tick ()
718{
719  Uint32 currentFrame = SDL_GetTicks();
720  if(!this->bPause)
721    {
722      Uint32 dt = currentFrame - this->lastFrame;
723     
724      if(dt > 0)
725        {
726          float fps = 1000/dt;
727          PRINTF(3)("fps = %f\n", fps);
728        }
729      else
730        {
731          /* the frame-rate is limited to 100 frames per second, all other things are for
732             nothing.
733          */
734          PRINTF(2)("fps = 1000 - frame rate is adjusted\n");
735          SDL_Delay(10);
736          dt = 10;
737        }
738      //this->timeSlice (dt);
739     
740      /* function to let all entities tick (iterate through list) */
741      WorldEntity* entity;
742      float seconds = dt / 1000.0;     
743      entity = entities->enumerate(); 
744      while( entity != NULL) 
745        { 
746          entity->tick (seconds);
747          entity = entities->nextElement();
748        }
749      //skySphere->updatePosition(localCamera->absCoordinate);
750     
751      /* update tick the rest */
752      this->trackManager->tick(dt);
753    }
754  this->lastFrame = currentFrame;
755}
756
757
758/**
759   \brief this function gives the world a consistant state
760
761   after ticking (updating the world state) this will give a constistant
762   state to the whole system.
763*/
764void World::update()
765{
766  this->nullParent->update ();
767}
768
769
770/**
771   \brief render the current frame
772   
773   clear all buffers and draw the world
774*/
775void World::display ()
776{
777  // clear buffer
778  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
779  // set camera
780  this->localCamera->apply ();
781  // draw world
782  this->draw();
783  // draw HUD
784  /* \todo draw HUD */
785  // flip buffers
786  SDL_GL_SwapBuffers();
787  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
788  //SDL_Flip (screen);
789}
790
791
792/**
793   \brief add and spawn a new entity to this world
794   \param entity to be added
795*/
796void World::spawn(WorldEntity* entity)
797{
798  this->entities->add (entity);
799  entity->postSpawn ();
800}
801
802
803/**
804   \brief add and spawn a new entity to this world
805   \param entity to be added
806   \param absCoor At what coordinates to add this entity.
807   \param absDir In which direction should it look.
808*/
809void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
810{
811  this->entities->add (entity);
812
813  entity->setAbsCoor (absCoor);
814  entity->setAbsDir (absDir);
815
816  entity->postSpawn ();
817}
818
819
820/**
821   \brief add and spawn a new entity to this world
822   \param entity to be added
823   \param entity to be added to (PNode)
824   \param At what relative  coordinates to add this entity.
825   \param In which relative direction should it look.
826*/
827void World::spawn(WorldEntity* entity, PNode* parentNode, 
828                  Vector* relCoor, Quaternion* relDir, 
829                  int parentingMode)
830{
831  this->nullParent = NullParent::getInstance();
832  if( parentNode != NULL)
833    {
834      parentNode->addChild (entity);
835     
836      entity->setRelCoor (relCoor);
837      entity->setRelDir (relDir);
838      entity->setMode(parentingMode);
839     
840      this->entities->add (entity);
841     
842      entity->postSpawn ();
843    }
844}
845
846
847
848/**
849  \brief commands that the world must catch
850  \returns false if not used by the world
851*/
852bool World::command(Command* cmd)
853{
854  return false;
855}
856
Note: See TracBrowser for help on using the repository browser.