Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3306 was 3306, checked in by patrick, 20 years ago

orxonox/branches/parenting: modified function passing routines - now having two lists: parenting list (tree) and entity list (array), that coexist - this is the only possibility to keep oversight.

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