Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: A Presentation, that the light-class can be handled as PNode, see the second level (push x) to see the effect

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