Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: doxygen-tags

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