Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/parenting/src/world.cc @ 3308

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

orxonox/branches/parenting: fixed a bug that prevented the program from changing to a new level (SEGFAULT), NOT yet following track

File size: 18.4 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 "collision.h"
20#include "track.h"
21#include "player.h"
22#include "command_node.h"
23#include "camera.h"
24#include "environment.h"
25#include "p_node.h"
26#include "null_parent.h"
27
28using namespace std;
29
30
31/**
32    \brief create a new World
33   
34    This creates a new empty world!
35*/
36World::World (char* name)
37{
38  this->setClassName ("World");
39  this->worldName = name;
40  this->debugWorldNr = -1;
41  this->entities = new tList<WorldEntity>();
42}
43
44World::World (int worldID)
45{
46  this->debugWorldNr = worldID;
47  this->worldName = NULL;
48  this->entities = new tList<WorldEntity>();
49}
50
51/**
52    \brief remove the World from memory
53*/
54World::~World ()
55{
56  printf("World::~World() - deleting current world\n");
57  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
58  cn->unbind(this->localPlayer);
59  cn->reset();
60  this->localCamera->destroy();
61
62  WorldEntity* entity = entities->enumerate(); 
63  while( entity != NULL ) 
64    { 
65      entity->destroy();
66      entity = entities->nextElement();
67    }
68  this->entities->destroy();
69
70  /* FIX the parent list has to be cleared - not possible if we got the old list also*/
71  //this->nullParent->destroy ();
72
73  delete this->entities;
74  delete this->localCamera;
75  /* this->localPlayer hasn't to be deleted explicitly, it is
76     contained in entities*/
77}
78
79
80ErrorMessage World::init()
81{
82  this->bPause = false;
83  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
84  cn->addToWorld(this);
85  cn->enable(true);
86
87  /* this is only for test purposes */
88  this->debug ();
89}
90
91ErrorMessage World::start()
92{
93  printf("World::start() - starting current World: nr %i\n", this->debugWorldNr);
94  this->bQuitOrxonox = false;
95  this->bQuitCurrentGame = false;
96  this->mainLoop();
97}
98
99ErrorMessage World::stop()
100{
101  printf("World::stop() - got stop signal\n");
102  this->bQuitCurrentGame = true;
103}
104
105ErrorMessage World::pause()
106{
107  this->isPaused = true;
108}
109
110ErrorMessage World::resume()
111{
112  this->isPaused = false;
113}
114
115void World::destroy()
116{
117
118}
119
120void World::load()
121{
122  if(this->debugWorldNr != -1)
123    {
124      switch(this->debugWorldNr)
125        {
126          /*
127            this loads the hard-coded debug world. this only for simplicity and will be
128            removed by a reald world-loader, which interprets a world-file.
129            if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
130            make whatever you want...
131           */
132        case DEBUG_WORLD_0:
133          {
134            this->nullParent = new NullParent ();
135            this->nullParent->setName ("NullParent");
136
137            // create some path nodes
138            this->pathnodes = new Vector[6];
139            this->pathnodes[0] = Vector(0, 0, 0);
140            this->pathnodes[1] = Vector(1000, 0, 0);
141            //      this->pathnodes[2] = Vector(-100, 140, 0);
142            //      this->pathnodes[3] = Vector(0, 180, 0);
143            //      this->pathnodes[4] = Vector(100, 140, 0);
144            //      this->pathnodes[5] = Vector(100, 40, 0);
145           
146            // create the tracks
147            this->tracklen = 2;
148            this->track = new Track[2];
149            for( int i = 0; i < this->tracklen; i++)
150              {
151                this->track[i] = Track( i, (i+1)%this->tracklen, &this->pathnodes[i], &this->pathnodes[(i+1)%this->tracklen]);
152              }
153            // !\todo old track-system has to be removed
154
155            // create a player
156            WorldEntity* myPlayer = new Player();
157            myPlayer->setName ("player");
158            this->spawn(myPlayer);
159            this->localPlayer = myPlayer;           
160
161            // bind input
162            Orxonox *orx = Orxonox::getInstance();
163            orx->getLocalInput()->bind (myPlayer);
164           
165            // bind camera
166            this->localCamera = new Camera(this);
167            this->localCamera->setName ("camera");
168            this->getCamera()->bind (myPlayer);
169            this->localPlayer->addChild (this->localCamera);
170           
171
172            Vector* es = new Vector (20, 0, 10);
173            Quaternion* qs = new Quaternion ();
174            WorldEntity* env = new Environment();
175            this->spawn(env, es, qs);
176
177
178            break;
179          }
180        case DEBUG_WORLD_1:
181          {
182            this->nullParent = new NullParent ();
183
184            // create some path nodes
185            this->pathnodes = new Vector[6];
186            this->pathnodes[0] = Vector(0, 0, 0);
187            this->pathnodes[1] = Vector(20, 10, 10);
188            this->pathnodes[2] = Vector(40, 0, 10);
189            this->pathnodes[3] = Vector(60, 10, 0);
190            this->pathnodes[4] = Vector(80, 20, 10);
191            this->pathnodes[5] = Vector(30, 50, 0);
192           
193            // create the tracks
194            this->tracklen = 6;
195            this->track = new Track[6];
196            for( int i = 0; i < this->tracklen; i++)
197              {
198                this->track[i] = Track( i, (i+1)%this->tracklen, &this->pathnodes[i], &this->pathnodes[(i+1)%this->tracklen]);
199              }
200
201            // create a player
202            WorldEntity* myPlayer = new Player();
203            myPlayer->setName ("player");
204            this->spawn(myPlayer);
205            this->localPlayer = myPlayer;           
206           
207            // bind input
208            Orxonox *orx = Orxonox::getInstance();
209            orx->getLocalInput()->bind (myPlayer);
210           
211            // bind camera
212            this->localCamera = new Camera (this);
213            this->localCamera->setName ("camera");
214            this->getCamera()->bind (myPlayer); 
215            this->localPlayer->addChild (this->localCamera);
216            break;
217          }
218        default:
219          printf("World::load() - no world with ID %i found", this->debugWorldNr );
220        }
221    }
222  else if(this->worldName != NULL)
223    {
224
225    }
226
227  // initialize debug coord system
228  objectList = glGenLists(1);
229  glNewList (objectList, GL_COMPILE);
230  glLoadIdentity();
231  glColor3f(1.0,0,0);
232  glBegin(GL_QUADS);
233
234  int sizeX = 100;
235  int sizeY = 80;
236  float length = 1000;
237  float width = 200;
238  float widthX = float (length /sizeX);
239  float widthY = float (width /sizeY);
240 
241  float height [sizeX][sizeY];
242  Vector normal_vectors[sizeX][sizeY];
243 
244 
245  for ( int i = 0; i<sizeX-1; i+=1)
246    for (int j = 0; j<sizeY-1;j+=1)
247      //height[i][j] = rand()/20046 + (j-25)*(j-25)/30;
248#ifdef __WIN32__
249      height[i][j]=(sin((float)j/3)*rand()*i/182400)*.5;
250#else
251      height[i][j]=(sin((float)j/3)*rand()*(long)i/6282450500.0)*.5;
252#endif
253
254  //Die Hügel ein wenig glätten
255  for (int h=1; h<2;h++)
256    for (int i=1;i<sizeX-2 ;i+=1 )
257      for(int j=1;j<sizeY-2;j+=1)
258        height[i][j]=(height[i+1][j]+height[i][j+1]+height[i-1][j]+height[i][j-1])/4;
259 
260  //Berechnung von normalen Vektoren
261 
262  for(int i=1;i<sizeX-2;i+=1)
263    for(int j=1;j<sizeY-2 ;j+=1)
264      {
265        Vector v1 = Vector (widthX*(1),      widthY*(j)  ,      height[i][j]);
266        Vector v2 = Vector (widthX*(i-1),    widthY*(j)  ,      height[i-1][j]);
267        Vector v3 = Vector (widthX*(i),      widthY*(j+1),      height[i][j+1]);
268        Vector v4 = Vector (widthX*(i+1),    widthY*(j),        height[i+1][j]);
269        Vector v5 = Vector (widthX*(i),      widthY*(j-1),      height[i][j-1]);
270       
271        Vector c1 = v2 - v1;
272        Vector c2 = v3 - v1;
273        Vector c3=  v4 - v1;
274        Vector c4 = v5 - v1;
275        Vector zero = Vector (0,0,0);
276        normal_vectors[i][j]=c1.cross(v4-v2)+c2.cross(v1-v3)+c3.cross(v2-v4)+c4.cross(v3-v1);
277        normal_vectors[i][j].normalize();
278      }
279
280  int snowheight=3;
281  for ( int i = 0; i<sizeX; i+=1)
282    for (int j = 0; j<sizeY;j+=1)
283      {   
284        Vector v1 = Vector (widthX*(i),      widthY*(j)  -width/2,      height[i][j]-20 );
285        Vector v2 = Vector (widthX*(i+1),    widthY*(j)  -width/2,      height[i+1][j]-20);
286        Vector v3 = Vector (widthX*(i+1),    widthY*(j+1)-width/2,    height[i+1][j+1]-20);
287        Vector v4 = Vector (widthX*(i),      widthY*(j+1)-width/2,    height[i][j+1]-20);
288        float a[3];
289        if(height[i][j]<snowheight){
290          a[0]=0;
291          a[1]=1.0-height[i][j]/10-.3;
292          a[2]=0;
293          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
294        }
295        else{
296            a[0]=1.0;
297            a[1]=1.0;
298            a[2]=1.0;
299            glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
300           
301        }
302        glNormal3f(normal_vectors[i][j].x, normal_vectors[i][j].y, normal_vectors[i][j].z);
303        glVertex3f(v1.x, v1.y, v1.z);
304        if(height[i+1][j]<snowheight){
305          a[0]=0;
306          a[1] =1.0-height[i+1][j]/10-.3;
307          a[2]=0;
308          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
309        }
310        else{
311          a[0]=1.0;
312          a[1]=1.0;
313          a[2]=1.0;
314          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
315         
316        }
317        glNormal3f(normal_vectors[i+1][j].x, normal_vectors[i+1][j].y, normal_vectors[i+1][j].z);
318        glVertex3f(v2.x, v2.y, v2.z);
319        if(height[i+1][j+1]<snowheight){
320          a[0]=0;
321          a[1] =1.0-height[i+1][j+1]/10-.3;
322          a[2]=0;
323          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
324        }
325        else{
326          a[0]=1.0;
327          a[1]=1.0;
328          a[2]=1.0;
329          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
330         
331         
332        }
333        glNormal3f(normal_vectors[i+1][j+1].x, normal_vectors[i+1][j+1].y, normal_vectors[i+1][j+1].z);
334        glVertex3f(v3.x, v3.y, v3.z);
335        if(height[i][j+1]<snowheight){
336          a[0]=0;
337          a[1] =1.0-height[i+1][j+1]/10-.3;
338          a[2]=0;
339          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
340        }
341        else{
342          a[0]=1.0;
343          a[1]=1.0;
344          a[2]=1.0;
345          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
346        }
347        glNormal3f(normal_vectors[i][j+1].x, normal_vectors[i][j+1].y, normal_vectors[i][j+1].z);
348        glVertex3f(v4.x, v4.y, v4.z);
349       
350      }
351  glEnd();
352  /* 
353  glBegin(GL_LINES);
354  for( float x = -128.0; x < 128.0; x += 25.0)
355    {
356      for( float y = -128.0; y < 128.0; y += 25.0)
357        {
358          glColor3f(1,0,0);
359          glVertex3f(x,y,-128.0);
360          glVertex3f(x,y,0.0);
361          glColor3f(0.5,0,0);
362          glVertex3f(x,y,0.0);
363          glVertex3f(x,y,128.0);
364        }
365    }
366  for( float y = -128.0; y < 128.0; y += 25.0)
367    {
368      for( float z = -128.0; z < 128.0; z += 25.0)
369        {
370          glColor3f(0,1,0);
371          glVertex3f(-128.0,y,z);
372          glVertex3f(0.0,y,z);
373          glColor3f(0,0.5,0);
374          glVertex3f(0.0,y,z);
375          glVertex3f(128.0,y,z);
376        }
377    }
378  for( float x = -128.0; x < 128.0; x += 25.0)
379    {
380      for( float z = -128.0; z < 128.0; z += 25.0)
381        {
382          glColor3f(0,0,1);
383          glVertex3f(x,-128.0,z);
384          glVertex3f(x,0.0,z);
385          glColor3f(0,0,0.5);
386          glVertex3f(x,0.0,z);
387          glVertex3f(x,128.0,z);
388        }
389     
390    }
391  */ 
392  //draw track
393  glBegin(GL_LINES);
394  glColor3f(0,1,1);
395  for( int i = 0; i < tracklen; i++)
396    {
397      glVertex3f(pathnodes[i].x,pathnodes[i].y,pathnodes[i].z);
398      glVertex3f(pathnodes[(i+1)%tracklen].x,pathnodes[(i+1)%tracklen].y,pathnodes[(i+1)%tracklen].z);
399    }
400  glEnd();
401  glEndList();
402}
403
404
405/**
406    \brief checks for collisions
407   
408    This method runs through all WorldEntities known to the world and checks for collisions
409    between them. In case of collisions the collide() method of the corresponding entities
410    is called.
411*/
412void World::collide ()
413{
414  /*
415  List *a, *b;
416  WorldEntity *aobj, *bobj;
417   
418  a = entities;
419 
420  while( a != NULL)
421    {
422      aobj = a->nextElement();
423      if( aobj->bCollide && aobj->collisioncluster != NULL)
424        {
425          b = a->nextElement();
426          while( b != NULL )
427            {
428              bobj = b->nextElement();
429              if( bobj->bCollide && bobj->collisioncluster != NULL )
430                {
431                  unsigned long ahitflg, bhitflg;
432                  if( check_collision ( &aobj->place, aobj->collisioncluster,
433                                        &ahitflg, &bobj->place, bobj->collisioncluster,
434                                        &bhitflg) );
435                  {
436                    aobj->collide (bobj, ahitflg, bhitflg);
437                    bobj->collide (aobj, bhitflg, ahitflg);
438                  }
439                }
440              b = b->nextElement();
441            }
442        }
443      a = a->enumerate();
444    }
445  */
446}
447
448/**
449    \brief runs through all entities calling their draw() methods
450*/
451void World::draw ()
452{
453  // draw entities
454  WorldEntity* entity;
455  entity = this->entities->enumerate();
456  while( entity != NULL ) 
457    { 
458      if( entity->bDraw ) entity->draw();
459      entity = this->entities->nextElement();
460    } 
461 
462  // draw debug coord system
463  glCallList (objectList);
464
465
466}
467
468/**
469    \brief updates Placements and notifies entities when they left the
470    world
471   
472    This runs trough all WorldEntities and maps Locations to Placements
473    if they are bound, checks whether they left the level boundaries
474    and calls appropriate functions.
475*/
476void World::update ()
477{
478  /*
479  //List<WorldEntity> *l;
480  WorldEntity* entity;
481  Location* loc;
482  Placement* plc;
483  Uint32 t;
484 
485  //  l = entities->enumerate();
486  entity = this->entities->enumerate();
487  while( entity != NULL )
488    {
489
490     
491      if( !entity->isFree() )
492        {
493          loc = entity->getLocation();
494          plc = entity->getPlacement();
495          t = loc->part;
496         
497          if( t >= tracklen )
498            {
499              printf("An entity is out of the game area\n");
500              entity->leftWorld ();
501            }
502          else
503            {
504              while( track[t].mapCoords( loc, plc) )
505                {
506                  track[t].postLeave (entity);
507                  if( loc->part >= tracklen )
508                    {
509                      printf("An entity has left the game area\n");
510                      entity->leftWorld ();
511                      break;
512                    }
513                  track[loc->part].postEnter (entity);
514                }
515            }
516        }
517      else
518        {
519        }
520     
521      entity = entities->nextElement();
522    }
523  */ 
524}
525
526/**
527    \brief relays the passed time since the last frame to entities and Track parts
528    \param deltaT: the time passed since the last frame in milliseconds
529*/
530void World::timeSlice (Uint32 deltaT)
531{
532  //List<WorldEntity> *l;
533  WorldEntity* entity;
534  float seconds = deltaT / 1000.0;
535 
536  this->nullParent->update (seconds);
537  //this->nullParent->processTick (seconds);
538
539  entity = entities->enumerate(); 
540  while( entity != NULL) 
541    { 
542      entity->tick (seconds);
543      entity = entities->nextElement();
544    }
545
546  //for( int i = 0; i < tracklen; i++) track[i].tick (seconds);
547}
548
549/**
550   \brief removes level data from memory
551*/
552void World::unload()
553{
554  if( pathnodes) delete []pathnodes;
555  if( track) delete []pathnodes;
556}
557
558
559
560/**
561   \brief calls the correct mapping function to convert a given "look at"-Location to a
562   Camera Placement
563*/
564void World::calcCameraPos (Location* loc, Placement* plc)
565{
566  track[loc->part].mapCamera (loc, plc);
567}
568
569
570void World::setTrackLen(Uint32 len)
571{
572  this->tracklen = len;
573}
574
575int World::getTrackLen()
576{
577  return this->tracklen;
578}
579
580
581
582/**
583   \brief function to put your own debug stuff into it. it can display informations about
584   the current class/procedure
585*/
586void World::debug()
587{
588  printf ("World::debug() - starting debug\n");
589  PNode* p1 = new NullParent ();
590  PNode* p2 = new PNode (new Vector(2, 2, 2), p1);
591  PNode* p3 = new PNode (new Vector(4, 4, 4), p1);
592  PNode* p4 = new PNode (new Vector(6, 6, 6), p2);
593
594  p1->debug ();
595  p2->debug ();
596  p3->debug ();
597  p4->debug ();
598
599  p1->shiftCoor (new Vector(-1, -1, -1));
600
601  printf("World::debug() - shift\n");
602  p1->debug ();
603  p2->debug ();
604  p3->debug ();
605  p4->debug ();
606 
607  p1->update (1);
608
609  printf ("World::debug() - update\n");
610  p1->debug ();
611  p2->debug ();
612  p3->debug ();
613  p4->debug ();
614
615  p2->shiftCoor (new Vector(-1, -1, -1));
616  p1->update (2);
617
618  p1->debug ();
619  p2->debug ();
620  p3->debug ();
621  p4->debug ();
622
623  p2->setAbsCoor (new Vector(1,2,3));
624
625
626 p1->update (2);
627
628  p1->debug ();
629  p2->debug ();
630  p3->debug ();
631  p4->debug ();
632
633  p1->destroy ();
634 
635 
636  /*
637  WorldEntity* entity;
638  printf("counting all entities\n");
639  printf("World::debug() - enumerate()\n");
640  entity = entities->enumerate(); 
641  while( entity != NULL )
642    {
643      if( entity->bDraw ) printf("got an entity\n");
644      entity = entities->nextElement();
645    }
646  */
647}
648
649
650/*
651  \brief main loop of the world: executing all world relevant function
652
653  in this loop we synchronize (if networked), handle input events, give the heart-beat to
654  all other member-entities of the world (tick to player, enemies etc.), checking for
655  collisions drawing everything to the screen.
656*/
657void World::mainLoop()
658{
659  this->lastFrame = SDL_GetTicks ();
660  printf("World::mainLoop() - Entering main loop\n");
661  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* \todo implement pause */
662    {
663      // Network
664      this->synchronize ();
665      // Process input
666      this->handleInput ();
667      if( this->bQuitCurrentGame || this->bQuitOrxonox)
668        {
669          printf("World::mainLoop() - leaving loop earlier...\n");
670          break;
671        }
672      // Process time
673      this->timeSlice ();
674      // Process collision
675      this->collision ();
676      // Draw
677      this->display ();
678 
679      for( int i = 0; i < 10000000; i++) {}
680    }
681  printf("World::mainLoop() - Exiting the main loop\n");
682}
683
684/**
685   \brief synchronize local data with remote data
686*/
687void World::synchronize ()
688{
689  // Get remote input
690  // Update synchronizables
691}
692
693/**
694   \brief run all input processing
695
696   the command node is the central input event dispatcher. the node uses the even-queue from
697   sdl and has its own event-passing-queue.
698*/
699void World::handleInput ()
700{
701  // localinput
702  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
703  cn->process();
704  // remoteinput
705}
706
707/**
708   \brief advance the timeline
709
710   this calculates the time used to process one frame (with all input handling, drawing, etc)
711   the time is mesured in ms and passed to all world-entities and other classes that need
712   a heart-beat.
713*/
714void World::timeSlice ()
715{
716  Uint32 currentFrame = SDL_GetTicks();
717  if(!this->bPause)
718    {
719      Uint32 dt = currentFrame - this->lastFrame;
720     
721      if(dt > 0)
722        {
723          float fps = 1000/dt;
724          printf("fps = %f\n", fps);
725        }
726      else
727        {
728          /* the frame-rate is limited to 100 frames per second, all other things are for
729             nothing.
730          */
731          printf("fps = 1000 - frame rate is adjusted\n");
732          SDL_Delay(10);
733          dt = 10;
734        }
735      this->timeSlice (dt);
736      this->update ();
737      this->localCamera->timeSlice(dt);
738    }
739  this->lastFrame = currentFrame;
740}
741
742
743/**
744   \brief compute collision detection
745*/
746void World::collision ()
747{
748  this->collide ();
749}
750
751
752/**
753   \brief render the current frame
754   
755   clear all buffers and draw the world
756*/
757void World::display ()
758{
759  // clear buffer
760  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
761  // set camera
762  this->localCamera->apply ();
763  // draw world
764  this->draw();
765  // draw HUD
766  // flip buffers
767  SDL_GL_SwapBuffers();
768}
769
770/**
771   \brief give back active camera
772   
773   this passes back the actualy active camera
774   \todo ability to define more than one camera or camera-places
775*/
776Camera* World::getCamera()
777{
778  return this->localCamera;
779}
780
781
782/**
783   \brief add and spawn a new entity to this world
784   \param entity to be added
785*/
786void World::spawn(WorldEntity* entity)
787{
788  if( this->nullParent != NULL && entity->parent == NULL)
789    this->nullParent->addChild (entity);
790
791  this->entities->add (entity);
792
793  entity->postSpawn ();
794}
795
796
797/**
798   \brief add and spawn a new entity to this world
799   \param entity to be added
800   \param location where to add
801*/
802void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
803{
804  entity->setAbsCoor (absCoor);
805  entity->setAbsDir (absDir);
806 
807  if( this->nullParent != NULL && entity->parent == NULL)
808    this->nullParent->addChild (entity);
809
810  this->entities->add (entity);
811
812  entity->postSpawn ();
813}
814
815
816
817/*
818  \brief commands that the world must catch
819  \returns false if not used by the world
820*/
821bool World::command(Command* cmd)
822{
823  return false;
824}
825
Note: See TracBrowser for help on using the repository browser.