Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: Error → ErrorMessage

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