Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: updated the terrain class to more functionality
view goes farther 2000 instead of 250
model gets deleted by world_entity instead of childs

File size: 17.3 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->nullParent;
72  delete this->entities;
73
74  delete this->trackManager;
75
76
77  /*
78  WorldEntity* entity = entities->enumerate(); 
79  while( entity != NULL )
80    {
81      entity->destroy();
82      entity = entities->nextElement();
83    }
84  this->entities->destroy();
85  */
86
87  /* FIX the parent list has to be cleared - not possible if we got the old list also*/
88
89
90  //delete this->entities;
91  //delete this->localCamera;
92  /* this->localPlayer hasn't to be deleted explicitly, it is
93     contained in entities*/
94}
95
96/**
97   \brief initializes a new World
98*/
99void World::init(char* name, int worldID)
100{
101  this->setClassName ("World");
102
103  this->worldName = name;
104  this->debugWorldNr = worldID;
105  this->entities = new tList<WorldEntity>();
106
107  // Enable default GL stuff
108  glEnable(GL_DEPTH_TEST);
109
110}
111
112
113/**
114   \brief loads the World by initializing all resources, and set their default values.
115*/
116ErrorMessage World::load()
117{
118  //  BezierCurve* tmpCurve = new BezierCurve();
119  if(this->debugWorldNr != -1)
120    {
121      // initializing Font
122      testFont = new FontSet();
123      testFont->buildFont("../data/pictures/font.tga");
124
125      // initializing the TrackManager
126      trackManager = TrackManager::getInstance();
127      trackManager->addPoint(Vector(0,-5,0));
128      trackManager->addPoint(Vector(10,0,5));
129      trackManager->addPoint(Vector(20,0,-5));
130      trackManager->addPoint(Vector(30,0,5));
131      trackManager->addPoint(Vector(40,0,5));
132      trackManager->setDuration(4);
133      int fork11, fork12, fork13;
134      trackManager->fork(3, &fork11, &fork12, &fork13);
135      trackManager->workOn(fork11);
136      trackManager->addPoint(Vector(70, 0, -10));
137      trackManager->addPoint(Vector(100, 0, -15));
138      trackManager->addPoint(Vector(300, 0, -15));
139      trackManager->setDuration(10);
140      trackManager->workOn(fork12);
141      trackManager->addPoint(Vector(70,  0, 0));
142      trackManager->addPoint(Vector(100, 0, 0));
143      trackManager->addPoint(Vector(120,10, 0));
144      trackManager->addPoint(Vector(150,10, 0));
145      trackManager->addPoint(Vector(180,15, 0));
146      trackManager->addPoint(Vector(200,10, 0));
147      trackManager->setDuration(7);
148      trackManager->workOn(fork13);
149      trackManager->addPoint(Vector(70,  0, 10));
150      trackManager->addPoint(Vector(100, 0, 30));
151      trackManager->addPoint(Vector(120,-10, 30));
152      trackManager->addPoint(Vector(150,-10, 30));
153      trackManager->setDuration(10);
154      trackManager->join(2, fork12, fork13);
155
156      trackManager->workOn(5);
157      trackManager->addPoint(Vector(250, 20, 10));
158      trackManager->addPoint(Vector(290, 20, 10));
159      trackManager->setDuration(5);
160      trackManager->setSavePoint();
161      trackManager->addPoint(Vector(350, 20, 10));
162      trackManager->addPoint(Vector(360, 20, 10));
163      trackManager->addPoint(Vector(370, 20, 10));
164      trackManager->setDuration(5);
165
166      trackManager->join(2, 6, fork11);
167
168      trackManager->finalize();
169
170     
171      /*monitor progress*/
172      this->glmis->step();
173
174      switch(this->debugWorldNr)
175        {
176          /*
177            this loads the hard-coded debug world. this only for simplicity and will be
178            removed by a reald world-loader, which interprets a world-file.
179            if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
180            make whatever you want...
181           */
182        case DEBUG_WORLD_0:
183          {
184            this->nullParent = NullParent::getInstance ();
185            this->nullParent->setName ("NullParent");
186
187            // !\todo old track-system has to be removed
188
189            //create helper for player
190            HelperParent* hp = new HelperParent ();
191            /* the player has to be added to this helper */
192
193            // create a player
194            WorldEntity* myPlayer = new Player ();
195            myPlayer->setName ("player");
196            this->spawn (myPlayer);
197            this->localPlayer = myPlayer;
198            /*monitor progress*/
199            this->glmis->step();           
200
201            // bind input
202            Orxonox *orx = Orxonox::getInstance ();
203            orx->getLocalInput()->bind (myPlayer);
204           
205            // bind camera
206            this->localCamera = new Camera(this);
207            this->localCamera->setName ("camera");
208            this->localCamera->bind (myPlayer);
209            /*monitor progress*/
210            this->glmis->step();           
211
212            // Create SkySphere
213            this->skySphere = new Skysphere("../data/pictures/sky-replace.jpg");
214            this->skySphere->setName("SkySphere");
215            this->localCamera->addChild(this->skySphere);
216            this->skySphere->setMode(PNODE_MOVEMENT);
217
218            /*monitor progress*/
219            this->glmis->step();
220
221           
222            WorldEntity* env = new Environment();
223            env->setName ("env");
224            this->spawn(env);
225
226            /*
227            Vector* es = new Vector (50, 2, 0);
228            Quaternion* qs = new Quaternion ();
229            WorldEntity* pr = new Primitive(PSPHERE);
230            pr->setName("primitive");
231            this->spawn(pr, this->localPlayer, es, qs, ROTATION);
232            */
233
234
235            /*monitor progress*/
236            this->glmis->step();
237
238            //      trackManager->setBindSlave(env);
239            PNode* tn = trackManager->getTrackNode();
240            tn->addChild(myPlayer);
241
242            //localCamera->setParent(TrackNode::getInstance());
243            tn->addChild (this->localCamera);
244            myPlayer->setMode(PNODE_ROTATE_AND_MOVE);
245            //Vector* cameraOffset = new Vector (0, 5, -10);
246            Vector* cameraOffset = new Vector (-10, 5, 0);
247            this->localCamera->setRelCoor (cameraOffset);
248            trackManager->condition(1, NEAREST, myPlayer);
249
250            break;
251          }
252        case DEBUG_WORLD_1:
253          {
254            this->nullParent = NullParent::getInstance ();
255            this->nullParent->setName ("NullParent");
256
257            // create a player
258            WorldEntity* myPlayer = new Player();
259            myPlayer->setName ("player");
260            this->spawn(myPlayer);
261            this->localPlayer = myPlayer;           
262           
263            // bind input
264            Orxonox *orx = Orxonox::getInstance();
265            orx->getLocalInput()->bind (myPlayer);
266           
267            // bind camera
268            this->localCamera = new Camera (this);
269            this->localCamera->setName ("camera");
270            this->localCamera->bind (myPlayer); 
271            this->localPlayer->addChild (this->localCamera);
272
273            // Create SkySphere
274            skySphere = new Skysphere("../data/pictures/sky-replace.jpg");
275            this->localPlayer->addChild(this->skySphere);
276
277            break;
278          }
279        default:
280          printf("World::load() - no world with ID %i found", this->debugWorldNr );
281        }
282    }
283  else if(this->worldName != NULL)
284    {
285
286    }
287
288  // initialize debug coord system
289  objectList = glGenLists(1);
290  glNewList (objectList, GL_COMPILE);
291 
292  trackManager->drawGraph(.01);
293  trackManager->debug(2);
294  glEndList();
295
296  terrain = new Terrain("nGround.obj");
297  terrain->setRelCoor(&Vector(0,-10,0));
298  this->spawn(terrain);
299  // LIGHT initialisation
300  light = Light::getInstance();
301  light->addLight(0);
302  light->setAttenuation(QUADRATIC, 1.0);
303  light->setAttenuation(CONSTANT, 2.0);
304  light->setAttenuation(QUADRATIC, 1.0);
305  light->setPosition(10.0, 10.0, 50.0);
306  light->setDiffuseColor(1,1,1);
307  //  light->addLight(1);
308  //  light->setPosition(20, 10, -20);
309  //  light->setDiffuseColor(0,0,0);
310  light->debug();
311
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}
470
471
472/**
473   \brief function to put your own debug stuff into it. it can display informations about
474   the current class/procedure
475*/
476void World::debug()
477{
478  PRINTF(2)("debug() - starting debug\n");
479  PNode* p1 = NullParent::getInstance ();
480  PNode* p2 = new PNode (new Vector(2, 2, 2), p1);
481  PNode* p3 = new PNode (new Vector(4, 4, 4), p1);
482  PNode* p4 = new PNode (new Vector(6, 6, 6), p2);
483
484  p1->debug ();
485  p2->debug ();
486  p3->debug ();
487  p4->debug ();
488
489  p1->shiftCoor (new Vector(-1, -1, -1));
490
491  printf("World::debug() - shift\n");
492  p1->debug ();
493  p2->debug ();
494  p3->debug ();
495  p4->debug ();
496 
497  p1->update ();
498
499  printf ("World::debug() - update\n");
500  p1->debug ();
501  p2->debug ();
502  p3->debug ();
503  p4->debug ();
504
505  p2->shiftCoor (new Vector(-1, -1, -1));
506  p1->update ();
507
508  p1->debug ();
509  p2->debug ();
510  p3->debug ();
511  p4->debug ();
512
513  p2->setAbsCoor (new Vector(1,2,3));
514
515
516 p1->update ();
517
518  p1->debug ();
519  p2->debug ();
520  p3->debug ();
521  p4->debug ();
522
523  delete p1;
524 
525 
526  /*
527  WorldEntity* entity;
528  printf("counting all entities\n");
529  printf("World::debug() - enumerate()\n");
530  entity = entities->enumerate(); 
531  while( entity != NULL )
532    {
533      if( entity->bDraw ) printf("got an entity\n");
534      entity = entities->nextElement();
535    }
536  */
537}
538
539
540/**
541  \brief main loop of the world: executing all world relevant function
542
543  in this loop we synchronize (if networked), handle input events, give the heart-beat to
544  all other member-entities of the world (tick to player, enemies etc.), checking for
545  collisions drawing everything to the screen.
546*/
547void World::mainLoop()
548{
549  this->lastFrame = SDL_GetTicks ();
550  PRINTF(3)("World::mainLoop() - Entering main loop\n");
551  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* \todo implement pause */
552    {
553      PRINTF(3)("World::mainloop() - number of entities: %i\n", this->entities->getSize());
554      // Network
555      this->synchronize ();
556      // Process input
557      this->handleInput ();
558      if( this->bQuitCurrentGame || this->bQuitOrxonox)
559          break;
560      // Process time
561      this->tick ();
562      // Update the state
563      this->update ();     
564      // Process collision
565      this->collide ();
566      // Draw
567      this->display ();
568
569      //      for( int i = 0; i < 5000000; i++) {}
570      /* \todo this is to slow down the program for openGl Software emulator computers, reimplement*/
571    }
572  PRINTF(3)("World::mainLoop() - Exiting the main loop\n");
573}
574
575
576/**
577   \brief synchronize local data with remote data
578*/
579void World::synchronize ()
580{
581  // Get remote input
582  // Update synchronizables
583}
584
585
586/**
587   \brief run all input processing
588
589   the command node is the central input event dispatcher. the node uses the even-queue from
590   sdl and has its own event-passing-queue.
591*/
592void World::handleInput ()
593{
594  // localinput
595  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
596  cn->process();
597  // remoteinput
598}
599
600
601/**
602   \brief advance the timeline
603
604   this calculates the time used to process one frame (with all input handling, drawing, etc)
605   the time is mesured in ms and passed to all world-entities and other classes that need
606   a heart-beat.
607*/
608void World::tick ()
609{
610  Uint32 currentFrame = SDL_GetTicks();
611  if(!this->bPause)
612    {
613      Uint32 dt = currentFrame - this->lastFrame;
614     
615      if(dt > 0)
616        {
617          float fps = 1000/dt;
618          PRINTF(3)("fps = %f\n", fps);
619        }
620      else
621        {
622          /* the frame-rate is limited to 100 frames per second, all other things are for
623             nothing.
624          */
625          PRINTF(2)("fps = 1000 - frame rate is adjusted\n");
626          SDL_Delay(10);
627          dt = 10;
628        }
629      //this->timeSlice (dt);
630     
631      /* function to let all entities tick (iterate through list) */
632      WorldEntity* entity;
633      float seconds = dt / 1000.0;     
634      entity = entities->enumerate(); 
635      while( entity != NULL) 
636        { 
637          entity->tick (seconds);
638          entity = entities->nextElement();
639        }
640      //skySphere->updatePosition(localCamera->absCoordinate);
641     
642      /* update tick the rest */
643      this->localCamera->tick(dt);
644      this->trackManager->tick(dt);
645    }
646  this->lastFrame = currentFrame;
647}
648
649
650/**
651   \brief this function gives the world a consistant state
652
653   after ticking (updating the world state) this will give a constistant
654   state to the whole system.
655*/
656void World::update()
657{
658  this->nullParent->update ();
659}
660
661
662/**
663   \brief render the current frame
664   
665   clear all buffers and draw the world
666*/
667void World::display ()
668{
669  // clear buffer
670  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
671  // set camera
672  this->localCamera->apply ();
673  // draw world
674  this->draw();
675  // draw HUD
676  /* \todo draw HUD */
677  // flip buffers
678  SDL_GL_SwapBuffers();
679  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
680  //SDL_Flip (screen);
681}
682
683
684/**
685   \brief add and spawn a new entity to this world
686   \param entity to be added
687*/
688void World::spawn(WorldEntity* entity)
689{
690  this->entities->add (entity);
691  entity->postSpawn ();
692}
693
694
695/**
696   \brief add and spawn a new entity to this world
697   \param entity to be added
698   \param absCoor At what coordinates to add this entity.
699   \param absDir In which direction should it look.
700*/
701void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
702{
703  this->entities->add (entity);
704
705  entity->setAbsCoor (absCoor);
706  entity->setAbsDir (absDir);
707
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 entity to be added to (PNode)
716   \param At what relative  coordinates to add this entity.
717   \param In which relative direction should it look.
718*/
719void World::spawn(WorldEntity* entity, PNode* parentNode, 
720                  Vector* relCoor, Quaternion* relDir, 
721                  int parentingMode)
722{
723  this->nullParent = NullParent::getInstance();
724  if( parentNode != NULL)
725    {
726      parentNode->addChild (entity);
727     
728      entity->setRelCoor (relCoor);
729      entity->setRelDir (relDir);
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.