Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3200 was 3200, checked in by bensch, 19 years ago

orxonox/trunk: a little bit more dynamic Mountain-creation (dave-algorithm)

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