Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: removed a compiler warning and some minor changes

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