Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3218 was 3216, checked in by patrick, 20 years ago

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

File size: 16.1 KB
RevLine 
[1853]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.
[1855]11
12   ### File Specific:
13   main-programmer: Patrick Boenzli
[2190]14   co-programmer: Christian Meyer
[1853]15*/
16
[2190]17#include "world.h"
18#include "world_entity.h"
19#include "collision.h"
20#include "track.h"
[2036]21#include "player.h"
[2190]22#include "command_node.h"
23#include "camera.h"
[2816]24#include "environment.h"
[2036]25
[1856]26using namespace std;
[1853]27
28
[1858]29/**
[2551]30    \brief create a new World
31   
32    This creates a new empty world!
[1858]33*/
[2636]34World::World (char* name)
[1855]35{
[2636]36  this->worldName = name;
37  this->debugWorldNr = -1;
[2822]38  this->entities = new tList<WorldEntity>();
[1855]39}
40
[2636]41World::World (int worldID)
42{
43  this->debugWorldNr = worldID;
44  this->worldName = NULL;
[2822]45  this->entities = new tList<WorldEntity>();
[2636]46}
47
[1858]48/**
[2551]49    \brief remove the World from memory
[1858]50*/
[2190]51World::~World ()
[1872]52{
[2640]53  Orxonox *orx = Orxonox::getInstance();
[2644]54  orx->get_localinput()->unbind (this->localPlayer);
55  delete this->entities;
56  delete this->localCamera;
[1872]57}
[1858]58
[2636]59
[1855]60/**
[2636]61    \brief initialize the world before use.
62*/
63Error World::init()
64{
65  this->bPause = false;
[3216]66  CommandNode* cn = Orxonox::getInstance()->get_localinput();
67  cn->addToWorld(this);
68  cn->enable(true);
[2636]69}
70
71Error World::start()
72{
73  this->mainLoop();
74}
75
76Error World::stop()
77{
78  this->bQuitCurrentGame = true;
[3215]79  //this->localCamera->setWorld(NULL);
80  this->localPlayer->destroy();
[3213]81  this->localCamera->destroy();
82
[3194]83  WorldEntity* entity = entities->enumerate(); 
84  while( entity != NULL ) 
85    { 
86      entity->destroy();
87      entity = entities->nextElement();
88    }
89  this->entities->destroy();
[2816]90  Orxonox::getInstance()->get_localinput()->reset();
[2636]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);
[2792]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);
[2636]119           
120            // create the tracks
[2816]121            this->tracklen = 2;
122            this->track = new Track[2];
[2636]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              }
[3194]127            // !\todo old track-system has to be removed
128
[2636]129            // create a player
[2644]130            WorldEntity* myPlayer = new Player();
131            this->spawn(myPlayer);
[2640]132            this->localPlayer = myPlayer;           
133
[2636]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); 
[2816]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
[2636]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              }
[3194]168
[2636]169            // create a player
[2644]170            WorldEntity* myPlayer = new Player();
171            this->spawn(myPlayer);
[3194]172            this->localPlayer = myPlayer;           
[2636]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    }
[2731]191
192  // initialize debug coord system
193  objectList = glGenLists(1);
194  glNewList (objectList, GL_COMPILE);
195  glLoadIdentity();
[2792]196  glColor3f(1.0,0,0);
[2817]197  glBegin(GL_QUADS);
[3200]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);
[3199]205 
[3200]206  float height [sizeX][sizeY];
207  Vector normal_vectors[sizeX][sizeY];
[3199]208 
[3200]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;
[3199]213#ifdef __WIN32__
[3200]214      height[i][j]=(sin((float)j/3)*rand()*i/182400)*.5;
[3199]215#else
[3200]216      height[i][j]=(sin((float)j/3)*rand()*(long)i/6282450500.0)*.5;
[3199]217#endif
[3200]218
[3199]219  //Die Hügel ein wenig glätten
220  for (int h=1; h<2;h++)
[3200]221    for (int i=1;i<sizeX-2 ;i+=1 )
222      for(int j=1;j<sizeY-2;j+=1)
[3199]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
[3200]226
227  for(int i=1;i<sizeX-2;i+=1)
228    for(int j=1;j<sizeY-2 ;j+=1)
[2792]229      {
[3200]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]);
[3199]235       
[3200]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);
[3199]242        normal_vectors[i][j].normalize();
[3200]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);
[3199]259        }
[3200]260        else{
[3199]261            a[0]=1.0;
262            a[1]=1.0;
263            a[2]=1.0;
264            glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
[2817]265           
[3199]266        }
[3200]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      }
[3199]316  glEnd();
317  /* 
[2792]318  glBegin(GL_LINES);
[2731]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    }
[2792]356  */ 
[2731]357  //draw track
[2792]358  glBegin(GL_LINES);
[2731]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();
[2636]367}
368
369
370/**
[2551]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.
[1858]376*/
[2190]377void World::collide ()
[1858]378{
[2816]379  /*
380  List *a, *b;
[2551]381  WorldEntity *aobj, *bobj;
[2816]382   
383  a = entities;
[2551]384 
385  while( a != NULL)
386    {
[2816]387      aobj = a->nextElement();
[2551]388      if( aobj->bCollide && aobj->collisioncluster != NULL)
[2190]389        {
[2816]390          b = a->nextElement();
[2551]391          while( b != NULL )
392            {
[2816]393              bobj = b->nextElement();
[2551]394              if( bobj->bCollide && bobj->collisioncluster != NULL )
[2190]395                {
[2551]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                  }
[2190]404                }
[2816]405              b = b->nextElement();
[2551]406            }
[2190]407        }
[2816]408      a = a->enumerate();
[2551]409    }
[2816]410  */
[1858]411}
412
413/**
[2551]414    \brief runs through all entities calling their draw() methods
[1931]415*/
[2190]416void World::draw ()
[2077]417{
[2551]418  // draw geometry
419 
420  // draw entities
421  WorldEntity* entity;
422 
[2822]423  entity = this->entities->enumerate();
[2816]424  while( entity != NULL ) 
[2551]425    { 
[2822]426      if( entity->bDraw ) entity->draw();
427      entity = this->entities->nextElement();
[2551]428    }
429 
430 
431  // draw debug coord system
[2731]432  glCallList (objectList);
[2551]433
[2731]434
[1931]435}
436
437/**
[2551]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.
[1883]444*/
[2190]445void World::update ()
[1883]446{
[2816]447  //List<WorldEntity> *l;
[2551]448  WorldEntity* entity;
449  Location* loc;
450  Placement* plc;
451  Uint32 t;
452 
[2816]453  //  l = entities->enumerate();
454  entity = this->entities->enumerate();
455  while( entity != NULL ) 
[2551]456    { 
[2816]457
[2551]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) )
[2190]474                {
[2551]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);
[2190]483                }
[2551]484            }
[2190]485        }
[2551]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     
[2816]495      entity = entities->nextElement();
[2551]496    }
497 
[1883]498}
499
[2077]500/**
[2551]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
[2077]503*/
[2190]504void World::time_slice (Uint32 deltaT)
[2077]505{
[2816]506  //List<WorldEntity> *l;
[2551]507  WorldEntity* entity;
[3175]508  float seconds = deltaT / 1000.0;
[2551]509 
[2816]510  entity = entities->enumerate(); 
511  while( entity != NULL) 
[2551]512    { 
513      entity->tick (seconds);
[2816]514      entity = entities->nextElement();
[2551]515    }
[2816]516
[3209]517  //for( int i = 0; i < tracklen; i++) track[i].tick (seconds);
[2077]518}
[1883]519
[2190]520/**
[2551]521   \brief removes level data from memory
[1858]522*/
[2190]523void World::unload()
[1858]524{
[2551]525  if( pathnodes) delete []pathnodes;
526  if( track) delete []pathnodes;
[1883]527}
[1879]528
[2636]529
530
[2190]531/**
[2636]532   \brief calls the correct mapping function to convert a given "look at"-Location to a
533   Camera Placement
[1858]534*/
[2636]535void World::calc_camera_pos (Location* loc, Placement* plc)
[1858]536{
[2636]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
[2640]551void World::debug()
552{
[2816]553  //List<WorldEntity> *l;
[2640]554  WorldEntity* entity;
555 
556  printf("counting all entities\n");
[2816]557  printf("World::debug() - enumerate()\n");
558  entity = entities->enumerate(); 
559  while( entity != NULL ) 
[2640]560    { 
561      if( entity->bDraw ) printf("got an entity\n");
[2816]562      entity = entities->nextElement();
[2640]563    }
564}
[2636]565
[2640]566
[2636]567void World::mainLoop()
568{
569  this->lastFrame = SDL_GetTicks();
570  this->bQuitOrxonox = false;
571  this->bQuitCurrentGame = false;
572  printf("World|Entering main loop\n");
[3215]573  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* \todo implement pause */
[2551]574    {
[2640]575      //debug routine
576      //debug();
[2636]577      // Network
578      synchronize();
579      // Process input
580      handle_input();
[3215]581      if( this->bQuitCurrentGame || this->bQuitOrxonox)
582        {
583          printf("World::mainLoop() - leaving loop earlier...\n");
584          break;
585        }
[2636]586      // Process time
587      time_slice();
588      // Process collision
589      collision();
590      // Draw
591      display();
[2816]592 
[3210]593      for(int i = 0; i < 10000000; i++) {}
[2551]594    }
[3215]595  printf("World::mainLoop() - Exiting the main loop\n");
[1899]596}
597
[2190]598/**
[2636]599   \brief synchronize local data with remote data
[1855]600*/
[2636]601void World::synchronize ()
[1855]602{
[2636]603  // Get remote input
604  // Update synchronizables
[1855]605}
[2636]606
607/**
608   \brief run all input processing
609*/
610void World::handle_input ()
611{
612  // localinput
[3216]613  CommandNode* cn = Orxonox::getInstance()->get_localinput();
614  cn->process();
[2636]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;
[2816]627     
[2636]628      if(dt > 0)
629        {
630          float fps = 1000/dt;
631          printf("fps = %f\n", fps);
632        }
633      else
634        {
[3194]635          printf("fps = 1000 - frame rate is adjusted\n");
636          SDL_Delay(10);
637          dt = 10;
[2636]638        }
[2816]639     
[2636]640      this->time_slice (dt);
641      this->update ();
642      this->localCamera->time_slice (dt);
643    }
644  this->lastFrame = currentFrame;
645}
646
[3216]647
[2636]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}
[2644]677
678
679void World::spawn(WorldEntity* entity)
680{
681  Location zeroloc;
682  Location* loc = NULL;
683  WorldEntity* owner;
[2816]684
685  entities->add (entity);
686  zeroloc.dist = 0;
687  zeroloc.part = 0;
688  zeroloc.pos = Vector();
689  zeroloc.rot = Quaternion();
690  loc = &zeroloc;
[2644]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 ();
[2816]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 ();
[2644]719  //return entity;
720}
[2816]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}
[3216]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.