Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk/src: state-freeze - redefinig destroy functions, some comments

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