Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/world.cc @ 3213

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

orxonox/trunk: enhanced the CommandNode - cleaning up garbage doing the wash etc

File size: 16.1 KB
RevLine 
[1853]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.
[1855]11
12   ### File Specific:
13   main-programmer: Patrick Boenzli
[2190]14   co-programmer: Christian Meyer
[1853]15*/
16
[2190]17#include "world.h"
18#include "world_entity.h"
19#include "collision.h"
20#include "track.h"
[2036]21#include "player.h"
[2190]22#include "command_node.h"
23#include "camera.h"
[2816]24#include "environment.h"
[2036]25
[1856]26using namespace std;
[1853]27
28
[1858]29/**
[2551]30    \brief create a new World
31   
32    This creates a new empty world!
[1858]33*/
[2636]34World::World (char* name)
[1855]35{
[2636]36  this->worldName = name;
37  this->debugWorldNr = -1;
[2822]38  this->entities = new tList<WorldEntity>();
[1855]39}
40
[2636]41World::World (int worldID)
42{
43  this->debugWorldNr = worldID;
44  this->worldName = NULL;
[2822]45  this->entities = new tList<WorldEntity>();
[2636]46}
47
[1858]48/**
[2551]49    \brief remove the World from memory
[1858]50*/
[2190]51World::~World ()
[1872]52{
[2640]53  Orxonox *orx = Orxonox::getInstance();
[2644]54  orx->get_localinput()->unbind (this->localPlayer);
55  delete this->entities;
56  delete this->localCamera;
[1872]57}
[1858]58
[2636]59
[1855]60/**
[2636]61    \brief initialize the world before use.
62*/
63Error World::init()
64{
65  this->bPause = false;
[3213]66  Orxonox::getInstance()->get_localinput()->enable(true);
[2636]67}
68
69Error World::start()
70{
71  this->mainLoop();
72}
73
74Error World::stop()
75{
76  this->bQuitCurrentGame = true;
77  this->localCamera->setWorld(NULL);
[3213]78  this->localCamera->destroy();
79
80
[3194]81  WorldEntity* entity = entities->enumerate(); 
82  while( entity != NULL ) 
83    { 
84      entity->destroy();
85      entity = entities->nextElement();
86    }
87  this->entities->destroy();
[2816]88  Orxonox::getInstance()->get_localinput()->reset();
[2636]89}
90
91Error World::pause()
92{
93  this->isPaused = true;
94}
95
96Error World::resume()
97{
98  this->isPaused = false;
99}
100
101void World::load()
102{
103  if(this->debugWorldNr != -1)
104    {
105      switch(this->debugWorldNr)
106        {
107        case DEBUG_WORLD_0:
108          {
109            // create some path nodes
110            this->pathnodes = new Vector[6];
111            this->pathnodes[0] = Vector(0, 0, 0);
[2792]112            this->pathnodes[1] = Vector(1000, 0, 0);
113            //      this->pathnodes[2] = Vector(-100, 140, 0);
114            //      this->pathnodes[3] = Vector(0, 180, 0);
115            //      this->pathnodes[4] = Vector(100, 140, 0);
116            //      this->pathnodes[5] = Vector(100, 40, 0);
[2636]117           
118            // create the tracks
[2816]119            this->tracklen = 2;
120            this->track = new Track[2];
[2636]121            for( int i = 0; i < this->tracklen; i++)
122              {
123                this->track[i] = Track( i, (i+1)%this->tracklen, &this->pathnodes[i], &this->pathnodes[(i+1)%this->tracklen]);
124              }
[3194]125            // !\todo old track-system has to be removed
126
[2636]127            // create a player
[2644]128            WorldEntity* myPlayer = new Player();
129            this->spawn(myPlayer);
[2640]130            this->localPlayer = myPlayer;           
131
[2636]132            // bind input
133            Orxonox *orx = Orxonox::getInstance();
134            orx->get_localinput()->bind (myPlayer);
135           
136            // bind camera
137            this->localCamera = new Camera(this);
138            this->getCamera()->bind (myPlayer); 
[2816]139
140            Placement* plc = new Placement;
141            plc->r = Vector(100, 10, 10);
142            plc->w = Quaternion();
143            WorldEntity* env = new Environment();
144            this->spawn(env, plc);
145
[2636]146            break;
147          }
148        case DEBUG_WORLD_1:
149          {
150            // create some path nodes
151            this->pathnodes = new Vector[6];
152            this->pathnodes[0] = Vector(0, 0, 0);
153            this->pathnodes[1] = Vector(20, 10, 10);
154            this->pathnodes[2] = Vector(40, 0, 10);
155            this->pathnodes[3] = Vector(60, 10, 0);
156            this->pathnodes[4] = Vector(80, 20, 10);
157            this->pathnodes[5] = Vector(30, 50, 0);
158           
159            // create the tracks
160            this->tracklen = 6;
161            this->track = new Track[6];
162            for( int i = 0; i < this->tracklen; i++)
163              {
164                this->track[i] = Track( i, (i+1)%this->tracklen, &this->pathnodes[i], &this->pathnodes[(i+1)%this->tracklen]);
165              }
[3194]166
[2636]167            // create a player
[2644]168            WorldEntity* myPlayer = new Player();
169            this->spawn(myPlayer);
[3194]170            this->localPlayer = myPlayer;           
[2636]171           
172            // bind input
173            Orxonox *orx = Orxonox::getInstance();
174            orx->get_localinput()->bind (myPlayer);
175           
176            // bind camera
177            this->localCamera = new Camera(this);
178            this->getCamera()->bind (myPlayer); 
179            break;
180          }
181        default:
182          printf("World::load() - no world with ID %i found", this->debugWorldNr );
183        }
184    }
185  else if(this->worldName != NULL)
186    {
187
188    }
[2731]189
190  // initialize debug coord system
191  objectList = glGenLists(1);
192  glNewList (objectList, GL_COMPILE);
193  glLoadIdentity();
[2792]194  glColor3f(1.0,0,0);
[2817]195  glBegin(GL_QUADS);
[3200]196
197  int sizeX = 100;
198  int sizeY = 80;
199  float length = 1000;
200  float width = 200;
201  float widthX = float (length /sizeX);
202  float widthY = float (width /sizeY);
[3199]203 
[3200]204  float height [sizeX][sizeY];
205  Vector normal_vectors[sizeX][sizeY];
[3199]206 
[3200]207 
208  for ( int i = 0; i<sizeX-1; i+=1)
209    for (int j = 0; j<sizeY-1;j+=1)
210      //height[i][j] = rand()/20046 + (j-25)*(j-25)/30;
[3199]211#ifdef __WIN32__
[3200]212      height[i][j]=(sin((float)j/3)*rand()*i/182400)*.5;
[3199]213#else
[3200]214      height[i][j]=(sin((float)j/3)*rand()*(long)i/6282450500.0)*.5;
[3199]215#endif
[3200]216
[3199]217  //Die Hügel ein wenig glätten
218  for (int h=1; h<2;h++)
[3200]219    for (int i=1;i<sizeX-2 ;i+=1 )
220      for(int j=1;j<sizeY-2;j+=1)
[3199]221        height[i][j]=(height[i+1][j]+height[i][j+1]+height[i-1][j]+height[i][j-1])/4;
222 
223  //Berechnung von normalen Vektoren
[3200]224
225  for(int i=1;i<sizeX-2;i+=1)
226    for(int j=1;j<sizeY-2 ;j+=1)
[2792]227      {
[3200]228        Vector v1 = Vector (widthX*(1),      widthY*(j)  ,      height[i][j]);
229        Vector v2 = Vector (widthX*(i-1),    widthY*(j)  ,      height[i-1][j]);
230        Vector v3 = Vector (widthX*(i),      widthY*(j+1),      height[i][j+1]);
231        Vector v4 = Vector (widthX*(i+1),    widthY*(j),        height[i+1][j]);
232        Vector v5 = Vector (widthX*(i),      widthY*(j-1),      height[i][j-1]);
[3199]233       
[3200]234        Vector c1 = v2 - v1;
235        Vector c2 = v3 - v1;
236        Vector c3=  v4 - v1;
237        Vector c4 = v5 - v1;
238        Vector zero = Vector (0,0,0);
239        normal_vectors[i][j]=c1.cross(v4-v2)+c2.cross(v1-v3)+c3.cross(v2-v4)+c4.cross(v3-v1);
[3199]240        normal_vectors[i][j].normalize();
[3200]241      }
242
243  int snowheight=3;
244  for ( int i = 0; i<sizeX; i+=1)
245    for (int j = 0; j<sizeY;j+=1)
246      {   
247        Vector v1 = Vector (widthX*(i),      widthY*(j)  -width/2,      height[i][j]-20 );
248        Vector v2 = Vector (widthX*(i+1),    widthY*(j)  -width/2,      height[i+1][j]-20);
249        Vector v3 = Vector (widthX*(i+1),    widthY*(j+1)-width/2,    height[i+1][j+1]-20);
250        Vector v4 = Vector (widthX*(i),      widthY*(j+1)-width/2,    height[i][j+1]-20);
251        float a[3];
252        if(height[i][j]<snowheight){
253          a[0]=0;
254          a[1]=1.0-height[i][j]/10-.3;
255          a[2]=0;
256          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
[3199]257        }
[3200]258        else{
[3199]259            a[0]=1.0;
260            a[1]=1.0;
261            a[2]=1.0;
262            glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
[2817]263           
[3199]264        }
[3200]265        glNormal3f(normal_vectors[i][j].x, normal_vectors[i][j].y, normal_vectors[i][j].z);
266        glVertex3f(v1.x, v1.y, v1.z);
267        if(height[i+1][j]<snowheight){
268          a[0]=0;
269          a[1] =1.0-height[i+1][j]/10-.3;
270          a[2]=0;
271          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
272        }
273        else{
274          a[0]=1.0;
275          a[1]=1.0;
276          a[2]=1.0;
277          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
278         
279        }
280        glNormal3f(normal_vectors[i+1][j].x, normal_vectors[i+1][j].y, normal_vectors[i+1][j].z);
281        glVertex3f(v2.x, v2.y, v2.z);
282        if(height[i+1][j+1]<snowheight){
283          a[0]=0;
284          a[1] =1.0-height[i+1][j+1]/10-.3;
285          a[2]=0;
286          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
287        }
288        else{
289          a[0]=1.0;
290          a[1]=1.0;
291          a[2]=1.0;
292          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
293         
294         
295        }
296        glNormal3f(normal_vectors[i+1][j+1].x, normal_vectors[i+1][j+1].y, normal_vectors[i+1][j+1].z);
297        glVertex3f(v3.x, v3.y, v3.z);
298        if(height[i][j+1]<snowheight){
299          a[0]=0;
300          a[1] =1.0-height[i+1][j+1]/10-.3;
301          a[2]=0;
302          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
303        }
304        else{
305          a[0]=1.0;
306          a[1]=1.0;
307          a[2]=1.0;
308          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
309        }
310        glNormal3f(normal_vectors[i][j+1].x, normal_vectors[i][j+1].y, normal_vectors[i][j+1].z);
311        glVertex3f(v4.x, v4.y, v4.z);
312       
313      }
[3199]314  glEnd();
315  /* 
[2792]316  glBegin(GL_LINES);
[2731]317  for( float x = -128.0; x < 128.0; x += 25.0)
318    {
319      for( float y = -128.0; y < 128.0; y += 25.0)
320        {
321          glColor3f(1,0,0);
322          glVertex3f(x,y,-128.0);
323          glVertex3f(x,y,0.0);
324          glColor3f(0.5,0,0);
325          glVertex3f(x,y,0.0);
326          glVertex3f(x,y,128.0);
327        }
328    }
329  for( float y = -128.0; y < 128.0; y += 25.0)
330    {
331      for( float z = -128.0; z < 128.0; z += 25.0)
332        {
333          glColor3f(0,1,0);
334          glVertex3f(-128.0,y,z);
335          glVertex3f(0.0,y,z);
336          glColor3f(0,0.5,0);
337          glVertex3f(0.0,y,z);
338          glVertex3f(128.0,y,z);
339        }
340    }
341  for( float x = -128.0; x < 128.0; x += 25.0)
342    {
343      for( float z = -128.0; z < 128.0; z += 25.0)
344        {
345          glColor3f(0,0,1);
346          glVertex3f(x,-128.0,z);
347          glVertex3f(x,0.0,z);
348          glColor3f(0,0,0.5);
349          glVertex3f(x,0.0,z);
350          glVertex3f(x,128.0,z);
351        }
352     
353    }
[2792]354  */ 
[2731]355  //draw track
[2792]356  glBegin(GL_LINES);
[2731]357  glColor3f(0,1,1);
358  for( int i = 0; i < tracklen; i++)
359    {
360      glVertex3f(pathnodes[i].x,pathnodes[i].y,pathnodes[i].z);
361      glVertex3f(pathnodes[(i+1)%tracklen].x,pathnodes[(i+1)%tracklen].y,pathnodes[(i+1)%tracklen].z);
362    }
363  glEnd();
364  glEndList();
[2636]365}
366
367
368/**
[2551]369    \brief checks for collisions
370   
371    This method runs through all WorldEntities known to the world and checks for collisions
372    between them. In case of collisions the collide() method of the corresponding entities
373    is called.
[1858]374*/
[2190]375void World::collide ()
[1858]376{
[2816]377  /*
378  List *a, *b;
[2551]379  WorldEntity *aobj, *bobj;
[2816]380   
381  a = entities;
[2551]382 
383  while( a != NULL)
384    {
[2816]385      aobj = a->nextElement();
[2551]386      if( aobj->bCollide && aobj->collisioncluster != NULL)
[2190]387        {
[2816]388          b = a->nextElement();
[2551]389          while( b != NULL )
390            {
[2816]391              bobj = b->nextElement();
[2551]392              if( bobj->bCollide && bobj->collisioncluster != NULL )
[2190]393                {
[2551]394                  unsigned long ahitflg, bhitflg;
395                  if( check_collision ( &aobj->place, aobj->collisioncluster,
396                                        &ahitflg, &bobj->place, bobj->collisioncluster,
397                                        &bhitflg) );
398                  {
399                    aobj->collide (bobj, ahitflg, bhitflg);
400                    bobj->collide (aobj, bhitflg, ahitflg);
401                  }
[2190]402                }
[2816]403              b = b->nextElement();
[2551]404            }
[2190]405        }
[2816]406      a = a->enumerate();
[2551]407    }
[2816]408  */
[1858]409}
410
411/**
[2551]412    \brief runs through all entities calling their draw() methods
[1931]413*/
[2190]414void World::draw ()
[2077]415{
[2551]416  // draw geometry
417 
418  // draw entities
419  WorldEntity* entity;
420 
[2822]421  entity = this->entities->enumerate();
[2816]422  while( entity != NULL ) 
[2551]423    { 
[2822]424      if( entity->bDraw ) entity->draw();
425      entity = this->entities->nextElement();
[2551]426    }
427 
428 
429  // draw debug coord system
[2731]430  glCallList (objectList);
[2551]431
[2731]432
[1931]433}
434
435/**
[2551]436    \brief updates Placements and notifies entities when they left the
437    world
438   
439    This runs trough all WorldEntities and maps Locations to Placements
440    if they are bound, checks whether they left the level boundaries
441    and calls appropriate functions.
[1883]442*/
[2190]443void World::update ()
[1883]444{
[2816]445  //List<WorldEntity> *l;
[2551]446  WorldEntity* entity;
447  Location* loc;
448  Placement* plc;
449  Uint32 t;
450 
[2816]451  //  l = entities->enumerate();
452  entity = this->entities->enumerate();
453  while( entity != NULL ) 
[2551]454    { 
[2816]455
[2551]456     
457      if( !entity->isFree() )
458        {
459          loc = entity->get_location();
460          plc = entity->get_placement();
461          t = loc->part;
462         
463          /* check if entity has still a legal track-id */
464          if( t >= tracklen )
465            {
466              printf("An entity is out of the game area\n");
467              entity->left_world ();
468            }
469          else
470            {
471              while( track[t].map_coords( loc, plc) )
[2190]472                {
[2551]473                  track[t].post_leave (entity);
474                  if( loc->part >= tracklen )
475                    {
476                      printf("An entity has left the game area\n");
477                      entity->left_world ();
478                      break;
479                    }
480                  track[loc->part].post_enter (entity);
[2190]481                }
[2551]482            }
[2190]483        }
[2551]484      else
485        {
486          /* TO DO: implement check whether this particular free entity
487             is out of the game area
488             TO DO: call function to notify the entity that it left
489             the game area
490          */
491        }
492     
[2816]493      entity = entities->nextElement();
[2551]494    }
495 
[1883]496}
497
[2077]498/**
[2551]499    \brief relays the passed time since the last frame to entities and Track parts
500    \param deltaT: the time passed since the last frame in milliseconds
[2077]501*/
[2190]502void World::time_slice (Uint32 deltaT)
[2077]503{
[2816]504  //List<WorldEntity> *l;
[2551]505  WorldEntity* entity;
[3175]506  float seconds = deltaT / 1000.0;
[2551]507 
[2816]508  entity = entities->enumerate(); 
509  while( entity != NULL) 
[2551]510    { 
511      entity->tick (seconds);
[2816]512      entity = entities->nextElement();
[2551]513    }
[2816]514
[3209]515  //for( int i = 0; i < tracklen; i++) track[i].tick (seconds);
[2077]516}
[1883]517
[2190]518/**
[2551]519   \brief removes level data from memory
[1858]520*/
[2190]521void World::unload()
[1858]522{
[2551]523  if( pathnodes) delete []pathnodes;
524  if( track) delete []pathnodes;
[1883]525}
[1879]526
[2636]527
528
[2190]529/**
[2636]530   \brief calls the correct mapping function to convert a given "look at"-Location to a
531   Camera Placement
[1858]532*/
[2636]533void World::calc_camera_pos (Location* loc, Placement* plc)
[1858]534{
[2636]535  track[loc->part].map_camera (loc, plc);
536}
537
538
539void World::setTrackLen(Uint32 len)
540{
541  this->tracklen = len;
542}
543
544int World::getTrackLen()
545{
546  return this->tracklen;
547}
548
[2640]549void World::debug()
550{
[2816]551  //List<WorldEntity> *l;
[2640]552  WorldEntity* entity;
553 
554  printf("counting all entities\n");
[2816]555  printf("World::debug() - enumerate()\n");
556  entity = entities->enumerate(); 
557  while( entity != NULL ) 
[2640]558    { 
559      if( entity->bDraw ) printf("got an entity\n");
[2816]560      entity = entities->nextElement();
[2640]561    }
562}
[2636]563
[2640]564
[2636]565void World::mainLoop()
566{
567  this->lastFrame = SDL_GetTicks();
568  this->bQuitOrxonox = false;
569  this->bQuitCurrentGame = false;
570  printf("World|Entering main loop\n");
571  while(!this->bQuitOrxonox && !this->bQuitCurrentGame) /* pause pause pause ?!?!?*/
[2551]572    {
[2640]573      //debug routine
574      //debug();
[2636]575      // Network
576      synchronize();
577      // Process input
578      handle_input();
579      // Process time
580      time_slice();
581      // Process collision
582      collision();
583      // Draw
584      display();
[2816]585 
[3210]586      for(int i = 0; i < 10000000; i++) {}
[2551]587    }
[2636]588  printf("World|Exiting the main loop\n");
[1899]589}
590
[2190]591/**
[2636]592   \brief synchronize local data with remote data
[1855]593*/
[2636]594void World::synchronize ()
[1855]595{
[2636]596  // Get remote input
597  // Update synchronizables
[1855]598}
[2636]599
600/**
601   \brief run all input processing
602*/
603void World::handle_input ()
604{
605  // localinput
606  Orxonox::getInstance()->get_localinput()->process();
607  // remoteinput
608}
609
610/**
611   \brief advance the timeline
612*/
613void World::time_slice ()
614{
615  Uint32 currentFrame = SDL_GetTicks();
616  if(!this->bPause)
617    {
618      Uint32 dt = currentFrame - this->lastFrame;
[2816]619     
[2636]620      if(dt > 0)
621        {
622          float fps = 1000/dt;
623          printf("fps = %f\n", fps);
624        }
625      else
626        {
[3194]627          printf("fps = 1000 - frame rate is adjusted\n");
628          SDL_Delay(10);
629          dt = 10;
[2636]630        }
[2816]631     
[2636]632      this->time_slice (dt);
633      this->update ();
634      this->localCamera->time_slice (dt);
635    }
636  this->lastFrame = currentFrame;
637}
638
639/**
640   \brief compute collision detection
641*/
642void World::collision ()
643{
644  this->collide ();
645}
646
647/**
648   \brief handle keyboard commands that are not meant for WorldEntities
649   \param cmd: the command to handle
650   \return true if the command was handled by the system or false if it may be passed to the WorldEntities
651*/
652bool World::system_command (Command* cmd)
653{
654  if( !strcmp( cmd->cmd, "quit"))
655    {
656      if( !cmd->bUp) this->bQuitOrxonox = true;
657      return true;
658    }
659  return false;
660}
661
662/**
663        \brief render the current frame
664*/
665void World::display ()
666{
667  // clear buffer
668  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
669  // set camera
670  this->localCamera->apply ();
671  // draw world
672  this->draw();
673  // draw HUD
674  // flip buffers
675  SDL_GL_SwapBuffers();
676}
677
678Camera* World::getCamera()
679{
680  return this->localCamera;
681}
[2644]682
683
684void World::spawn(WorldEntity* entity)
685{
686  Location zeroloc;
687  Location* loc = NULL;
688  WorldEntity* owner;
[2816]689
690  entities->add (entity);
691  zeroloc.dist = 0;
692  zeroloc.part = 0;
693  zeroloc.pos = Vector();
694  zeroloc.rot = Quaternion();
695  loc = &zeroloc;
[2644]696  entity->init (loc, owner);
697  if (entity->bFree)
698    {
699      this->track[loc->part].map_coords( loc, entity->get_placement());
700    }
701  entity->post_spawn ();
[2816]702}
703
704
705void World::spawn(WorldEntity* entity, Location* loc)
706{
707  Location zeroLoc;
708  WorldEntity* owner;
709  this->entities->add (entity);
710  if( loc == NULL)
711    {
712      zeroLoc.dist = 0;
713      zeroLoc.part = 0;
714      zeroLoc.pos = Vector();
715      zeroLoc.rot = Quaternion();
716      loc = &zeroLoc;
717    }
718  entity->init (loc, owner);
719  if (entity->bFree)
720    {
721      this->track[loc->part].map_coords( loc, entity->get_placement());
722    }
723  entity->post_spawn ();
[2644]724  //return entity;
725}
[2816]726
727
728void World::spawn(WorldEntity* entity, Placement* plc)
729{
730  Placement zeroPlc;
731  WorldEntity* owner;
732  if( plc == NULL)
733    {
734      zeroPlc.r = Vector();
735      zeroPlc.w = Quaternion();
736      plc = &zeroPlc;
737    }
738  this->entities->add (entity);
739  entity->init (plc, owner);
740  entity->post_spawn ();
741  //return entity;
742}
Note: See TracBrowser for help on using the repository browser.