Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: attenuation works, and the Light is now in lib/graphics

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