Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/parenting/src/world.cc @ 3307

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

orxonox/branches/parenting: now parenting works visibly good :) meaning, that the old abilities have been reimplemented and are working now. turned coord system again to the old one to be able to enjoy the terrific green lands of orxonox

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