Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3608 was 3608, checked in by patrick, 19 years ago

orxonox/trunk: now there is a real speedup in compiling time when dependencies are modified: just realy only includes, what is needed. Byside the speedup, there is more overview! never add an orxonox class to stdincl.h if it doesn't have to be

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