Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3177 was 3175, checked in by bensch, 20 years ago

orxonox/trunk/src: small efficienxy fixes

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