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
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
26using namespace std;
27
28
29/**
30    \brief create a new World
31   
32    This creates a new empty world!
33*/
34World::World (char* name)
35{
36  this->worldName = name;
37  this->debugWorldNr = -1;
38  this->entities = new tList<WorldEntity>();
39}
40
41World::World (int worldID)
42{
43  this->debugWorldNr = worldID;
44  this->worldName = NULL;
45  this->entities = new tList<WorldEntity>();
46}
47
48/**
49    \brief remove the World from memory
50*/
51World::~World ()
52{
53  Orxonox *orx = Orxonox::getInstance();
54  orx->get_localinput()->unbind (this->localPlayer);
55  delete this->entities;
56  delete this->localCamera;
57}
58
59
60/**
61    \brief initialize the world before use.
62*/
63Error World::init()
64{
65  this->bPause = false;
66  Orxonox::getInstance()->get_localinput()->enable(true);
67}
68
69Error World::start()
70{
71  this->mainLoop();
72}
73
74Error World::stop()
75{
76  this->bQuitCurrentGame = true;
77  this->localCamera->setWorld(NULL);
78  this->localCamera->destroy();
79
80
81  WorldEntity* entity = entities->enumerate(); 
82  while( entity != NULL ) 
83    { 
84      entity->destroy();
85      entity = entities->nextElement();
86    }
87  this->entities->destroy();
88  Orxonox::getInstance()->get_localinput()->reset();
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);
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);
117           
118            // create the tracks
119            this->tracklen = 2;
120            this->track = new Track[2];
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              }
125            // !\todo old track-system has to be removed
126
127            // create a player
128            WorldEntity* myPlayer = new Player();
129            this->spawn(myPlayer);
130            this->localPlayer = myPlayer;           
131
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); 
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
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              }
166
167            // create a player
168            WorldEntity* myPlayer = new Player();
169            this->spawn(myPlayer);
170            this->localPlayer = myPlayer;           
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    }
189
190  // initialize debug coord system
191  objectList = glGenLists(1);
192  glNewList (objectList, GL_COMPILE);
193  glLoadIdentity();
194  glColor3f(1.0,0,0);
195  glBegin(GL_QUADS);
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);
203 
204  float height [sizeX][sizeY];
205  Vector normal_vectors[sizeX][sizeY];
206 
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;
211#ifdef __WIN32__
212      height[i][j]=(sin((float)j/3)*rand()*i/182400)*.5;
213#else
214      height[i][j]=(sin((float)j/3)*rand()*(long)i/6282450500.0)*.5;
215#endif
216
217  //Die Hügel ein wenig glätten
218  for (int h=1; h<2;h++)
219    for (int i=1;i<sizeX-2 ;i+=1 )
220      for(int j=1;j<sizeY-2;j+=1)
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
224
225  for(int i=1;i<sizeX-2;i+=1)
226    for(int j=1;j<sizeY-2 ;j+=1)
227      {
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]);
233       
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);
240        normal_vectors[i][j].normalize();
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);
257        }
258        else{
259            a[0]=1.0;
260            a[1]=1.0;
261            a[2]=1.0;
262            glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
263           
264        }
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      }
314  glEnd();
315  /* 
316  glBegin(GL_LINES);
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    }
354  */ 
355  //draw track
356  glBegin(GL_LINES);
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();
365}
366
367
368/**
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.
374*/
375void World::collide ()
376{
377  /*
378  List *a, *b;
379  WorldEntity *aobj, *bobj;
380   
381  a = entities;
382 
383  while( a != NULL)
384    {
385      aobj = a->nextElement();
386      if( aobj->bCollide && aobj->collisioncluster != NULL)
387        {
388          b = a->nextElement();
389          while( b != NULL )
390            {
391              bobj = b->nextElement();
392              if( bobj->bCollide && bobj->collisioncluster != NULL )
393                {
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                  }
402                }
403              b = b->nextElement();
404            }
405        }
406      a = a->enumerate();
407    }
408  */
409}
410
411/**
412    \brief runs through all entities calling their draw() methods
413*/
414void World::draw ()
415{
416  // draw geometry
417 
418  // draw entities
419  WorldEntity* entity;
420 
421  entity = this->entities->enumerate();
422  while( entity != NULL ) 
423    { 
424      if( entity->bDraw ) entity->draw();
425      entity = this->entities->nextElement();
426    }
427 
428 
429  // draw debug coord system
430  glCallList (objectList);
431
432
433}
434
435/**
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.
442*/
443void World::update ()
444{
445  //List<WorldEntity> *l;
446  WorldEntity* entity;
447  Location* loc;
448  Placement* plc;
449  Uint32 t;
450 
451  //  l = entities->enumerate();
452  entity = this->entities->enumerate();
453  while( entity != NULL ) 
454    { 
455
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) )
472                {
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);
481                }
482            }
483        }
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     
493      entity = entities->nextElement();
494    }
495 
496}
497
498/**
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
501*/
502void World::time_slice (Uint32 deltaT)
503{
504  //List<WorldEntity> *l;
505  WorldEntity* entity;
506  float seconds = deltaT / 1000.0;
507 
508  entity = entities->enumerate(); 
509  while( entity != NULL) 
510    { 
511      entity->tick (seconds);
512      entity = entities->nextElement();
513    }
514
515  //for( int i = 0; i < tracklen; i++) track[i].tick (seconds);
516}
517
518/**
519   \brief removes level data from memory
520*/
521void World::unload()
522{
523  if( pathnodes) delete []pathnodes;
524  if( track) delete []pathnodes;
525}
526
527
528
529/**
530   \brief calls the correct mapping function to convert a given "look at"-Location to a
531   Camera Placement
532*/
533void World::calc_camera_pos (Location* loc, Placement* plc)
534{
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
549void World::debug()
550{
551  //List<WorldEntity> *l;
552  WorldEntity* entity;
553 
554  printf("counting all entities\n");
555  printf("World::debug() - enumerate()\n");
556  entity = entities->enumerate(); 
557  while( entity != NULL ) 
558    { 
559      if( entity->bDraw ) printf("got an entity\n");
560      entity = entities->nextElement();
561    }
562}
563
564
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 ?!?!?*/
572    {
573      //debug routine
574      //debug();
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();
585 
586      for(int i = 0; i < 10000000; i++) {}
587    }
588  printf("World|Exiting the main loop\n");
589}
590
591/**
592   \brief synchronize local data with remote data
593*/
594void World::synchronize ()
595{
596  // Get remote input
597  // Update synchronizables
598}
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;
619     
620      if(dt > 0)
621        {
622          float fps = 1000/dt;
623          printf("fps = %f\n", fps);
624        }
625      else
626        {
627          printf("fps = 1000 - frame rate is adjusted\n");
628          SDL_Delay(10);
629          dt = 10;
630        }
631     
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}
682
683
684void World::spawn(WorldEntity* entity)
685{
686  Location zeroloc;
687  Location* loc = NULL;
688  WorldEntity* owner;
689
690  entities->add (entity);
691  zeroloc.dist = 0;
692  zeroloc.part = 0;
693  zeroloc.pos = Vector();
694  zeroloc.rot = Quaternion();
695  loc = &zeroloc;
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 ();
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 ();
724  //return entity;
725}
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.