Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3349 was 3233, checked in by patrick, 20 years ago

orxonox/trunk: unstable - minor changes everywhere

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