Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: now terrain is out of the World.cc and is a world-entity

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