Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: putted a sphere infornt of the player. no style at all… just for debugging…

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