Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: a first redesign of the CommandNode and its cmd passing system - others will follow.

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