Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2636 was 2636, checked in by patrick, 20 years ago
  • Added a GameLoader to the game. This enables orxonox to load a campaign consisting of multimple worlds and cinematics etc. However, cinematics are not yet implemented.

In the game you can jump from one level to the other by pressing x. Currently there are only two very simple levels defined. (DEBUG_LEVEL_0, DEBUG_LEVEL_1).

  • Added Error Handling structs to signal the error source and code
File size: 10.2 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
25using namespace std;
26
27
28/**
29    \brief create a new World
30   
31    This creates a new empty world!
32*/
33World::World (char* name)
34{
35  this->worldName = name;
36  this->debugWorldNr = -1;
37  this->entities = new List<WorldEntity>();
38}
39
40World::World (int worldID)
41{
42  this->debugWorldNr = worldID;
43  this->worldName = NULL;
44  this->entities = new List<WorldEntity>();
45}
46
47/**
48    \brief remove the World from memory
49*/
50World::~World ()
51{
52  unload ();
53  delete entities;
54}
55
56
57/**
58    \brief initialize the world before use.
59*/
60Error World::init()
61{
62  this->bPause = false;
63}
64
65Error World::start()
66{
67  this->mainLoop();
68}
69
70Error World::stop()
71{
72  this->bQuitCurrentGame = true;
73  this->localCamera->setWorld(NULL);
74}
75
76Error World::pause()
77{
78  this->isPaused = true;
79}
80
81Error World::resume()
82{
83  this->isPaused = false;
84}
85
86void World::load()
87{
88  if(this->debugWorldNr != -1)
89    {
90      switch(this->debugWorldNr)
91        {
92        case DEBUG_WORLD_0:
93          {
94            // create some path nodes
95            this->pathnodes = new Vector[6];
96            this->pathnodes[0] = Vector(0, 0, 0);
97            this->pathnodes[1] = Vector(-100, 40, 0);
98            this->pathnodes[2] = Vector(-100, 140, 0);
99            this->pathnodes[3] = Vector(0, 180, 0);
100            this->pathnodes[4] = Vector(100, 140, 0);
101            this->pathnodes[5] = Vector(100, 40, 0);
102           
103            // create the tracks
104            this->tracklen = 6;
105            this->track = new Track[6];
106            for( int i = 0; i < this->tracklen; i++)
107              {
108                this->track[i] = Track( i, (i+1)%this->tracklen, &this->pathnodes[i], &this->pathnodes[(i+1)%this->tracklen]);
109              }
110           
111            // create a player
112            WorldEntity* myPlayer = (WorldEntity*) this->spawn<Player>();
113           
114            // bind input
115            Orxonox *orx = Orxonox::getInstance();
116            orx->get_localinput()->bind (myPlayer);
117           
118            // bind camera
119            this->localCamera = new Camera(this);
120            this->getCamera()->bind (myPlayer); 
121            break;
122          }
123        case DEBUG_WORLD_1:
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(20, 10, 10);
129            this->pathnodes[2] = Vector(40, 0, 10);
130            this->pathnodes[3] = Vector(60, 10, 0);
131            this->pathnodes[4] = Vector(80, 20, 10);
132            this->pathnodes[5] = Vector(30, 50, 0);
133           
134            // create the tracks
135            this->tracklen = 6;
136            this->track = new Track[6];
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           
142            // create a player
143            WorldEntity* myPlayer = (WorldEntity*) this->spawn<Player>();
144           
145            // bind input
146            Orxonox *orx = Orxonox::getInstance();
147            orx->get_localinput()->bind (myPlayer);
148           
149            // bind camera
150            this->localCamera = new Camera(this);
151            this->getCamera()->bind (myPlayer); 
152            break;
153          }
154        default:
155          printf("World::load() - no world with ID %i found", this->debugWorldNr );
156        }
157    }
158  else if(this->worldName != NULL)
159    {
160
161    }
162}
163
164
165/**
166    \brief checks for collisions
167   
168    This method runs through all WorldEntities known to the world and checks for collisions
169    between them. In case of collisions the collide() method of the corresponding entities
170    is called.
171*/
172void World::collide ()
173{
174  List<WorldEntity> *a, *b;
175  WorldEntity *aobj, *bobj;
176 
177  a = entities->get_next();
178 
179  while( a != NULL)
180    {
181      aobj = a->get_object();
182      if( aobj->bCollide && aobj->collisioncluster != NULL)
183        {
184          b = a->get_next();
185          while( b != NULL )
186            {
187              bobj = b->get_object();
188              if( bobj->bCollide && bobj->collisioncluster != NULL )
189                {
190                  unsigned long ahitflg, bhitflg;
191                  if( check_collision ( &aobj->place, aobj->collisioncluster, 
192                                        &ahitflg, &bobj->place, bobj->collisioncluster, 
193                                        &bhitflg) );
194                  {
195                    aobj->collide (bobj, ahitflg, bhitflg);
196                    bobj->collide (aobj, bhitflg, ahitflg);
197                  }
198                }
199              b = b->get_next();
200            }
201        }
202      a = a->get_next();
203    }
204}
205
206/**
207    \brief runs through all entities calling their draw() methods
208*/
209void World::draw ()
210{
211  // draw geometry
212 
213  // draw entities
214  List<WorldEntity> *l;
215  WorldEntity* entity;
216 
217  l = entities->get_next(); 
218  while( l != NULL ) 
219    { 
220      entity = l->get_object();
221      if( entity->bDraw ) entity->draw();
222      l = l->get_next();
223    }
224 
225 
226  // draw debug coord system
227  glLoadIdentity();
228 
229
230  glBegin(GL_LINES);
231 
232  for( float x = -128.0; x < 128.0; x += 25.0)
233    {
234      for( float y = -128.0; y < 128.0; y += 25.0)
235        {
236          glColor3f(1,0,0);
237          glVertex3f(x,y,-128.0);
238          glVertex3f(x,y,0.0);
239          glColor3f(0.5,0,0);
240          glVertex3f(x,y,0.0);
241          glVertex3f(x,y,128.0);
242        }
243    }
244  for( float y = -128.0; y < 128.0; y += 25.0)
245    {
246      for( float z = -128.0; z < 128.0; z += 25.0)
247        {
248          glColor3f(0,1,0);
249          glVertex3f(-128.0,y,z);
250          glVertex3f(0.0,y,z);
251          glColor3f(0,0.5,0);
252          glVertex3f(0.0,y,z);
253          glVertex3f(128.0,y,z);
254        }
255    }
256  for( float x = -128.0; x < 128.0; x += 25.0)
257    {
258      for( float z = -128.0; z < 128.0; z += 25.0)
259        {
260          glColor3f(0,0,1);
261          glVertex3f(x,-128.0,z);
262          glVertex3f(x,0.0,z);
263          glColor3f(0,0,0.5);
264          glVertex3f(x,0.0,z);
265          glVertex3f(x,128.0,z);
266        }
267     
268    }
269 
270  //draw track
271  glColor3f(0,1,1);
272  for( int i = 0; i < tracklen; i++)
273    {
274      glVertex3f(pathnodes[i].x,pathnodes[i].y,pathnodes[i].z);
275      glVertex3f(pathnodes[(i+1)%tracklen].x,pathnodes[(i+1)%tracklen].y,pathnodes[(i+1)%tracklen].z);
276    }
277  glEnd();
278}
279
280/**
281    \brief updates Placements and notifies entities when they left the
282    world
283   
284    This runs trough all WorldEntities and maps Locations to Placements
285    if they are bound, checks whether they left the level boundaries
286    and calls appropriate functions.
287*/
288void World::update ()
289{
290  List<WorldEntity> *l;
291  WorldEntity* entity;
292  Location* loc;
293  Placement* plc;
294  Uint32 t;
295 
296  l = entities->get_next(); 
297  while( l != NULL ) 
298    { 
299      entity = l->get_object();
300     
301      if( !entity->isFree() )
302        {
303          loc = entity->get_location();
304          plc = entity->get_placement();
305          t = loc->part;
306         
307          /* check if entity has still a legal track-id */
308          if( t >= tracklen )
309            {
310              printf("An entity is out of the game area\n");
311              entity->left_world ();
312            }
313          else
314            {
315              while( track[t].map_coords( loc, plc) )
316                {
317                  track[t].post_leave (entity);
318                  if( loc->part >= tracklen )
319                    {
320                      printf("An entity has left the game area\n");
321                      entity->left_world ();
322                      break;
323                    }
324                  track[loc->part].post_enter (entity);
325                }
326            }
327        }
328      else
329        {
330          /* TO DO: implement check whether this particular free entity
331             is out of the game area
332             TO DO: call function to notify the entity that it left
333             the game area
334          */
335        }
336     
337      l = l->get_next();
338    }
339 
340}
341
342/**
343    \brief relays the passed time since the last frame to entities and Track parts
344    \param deltaT: the time passed since the last frame in milliseconds
345*/
346void World::time_slice (Uint32 deltaT)
347{
348  List<WorldEntity> *l;
349  WorldEntity* entity;
350  float seconds = deltaT;
351 
352  seconds /= 1000;
353 
354  l = entities->get_next(); 
355  while( l != NULL) 
356    { 
357      entity = l->get_object();
358      entity->tick (seconds);
359      l = l->get_next();
360    }
361 
362  for( int i = 0; i < tracklen; i++) track[i].tick (seconds);
363}
364
365/**
366   \brief removes level data from memory
367*/
368void World::unload()
369{
370  if( pathnodes) delete []pathnodes;
371  if( track) delete []pathnodes;
372}
373
374
375
376/**
377   \brief calls the correct mapping function to convert a given "look at"-Location to a
378   Camera Placement
379*/
380void World::calc_camera_pos (Location* loc, Placement* plc)
381{
382  track[loc->part].map_camera (loc, plc);
383}
384
385
386void World::setTrackLen(Uint32 len)
387{
388  this->tracklen = len;
389}
390
391int World::getTrackLen()
392{
393  return this->tracklen;
394}
395
396
397void World::mainLoop()
398{
399  this->lastFrame = SDL_GetTicks();
400  this->bQuitOrxonox = false;
401  this->bQuitCurrentGame = false;
402  printf("World|Entering main loop\n");
403  while(!this->bQuitOrxonox && !this->bQuitCurrentGame) /* pause pause pause ?!?!?*/
404    {
405      // Network
406      synchronize();
407      // Process input
408      handle_input();
409      // Process time
410      time_slice();
411      // Process collision
412      collision();
413      // Draw
414      display();
415    }
416  printf("World|Exiting the main loop\n");
417}
418
419/**
420   \brief synchronize local data with remote data
421*/
422void World::synchronize ()
423{
424  // Get remote input
425  // Update synchronizables
426}
427
428/**
429   \brief run all input processing
430*/
431void World::handle_input ()
432{
433  // localinput
434  Orxonox::getInstance()->get_localinput()->process();
435  // remoteinput
436}
437
438/**
439   \brief advance the timeline
440*/
441void World::time_slice ()
442{
443  Uint32 currentFrame = SDL_GetTicks();
444  if(!this->bPause)
445    {
446      Uint32 dt = currentFrame - this->lastFrame;
447      /*
448      if(dt > 0)
449        {
450          float fps = 1000/dt;
451          printf("fps = %f\n", fps);
452        }
453      else
454        {
455          printf("fps = 1000\n");
456        }
457      */
458      this->time_slice (dt);
459      this->update ();
460      this->localCamera->time_slice (dt);
461    }
462  this->lastFrame = currentFrame;
463}
464
465/**
466   \brief compute collision detection
467*/
468void World::collision ()
469{
470  this->collide ();
471}
472
473/**
474   \brief handle keyboard commands that are not meant for WorldEntities
475   \param cmd: the command to handle
476   \return true if the command was handled by the system or false if it may be passed to the WorldEntities
477*/
478bool World::system_command (Command* cmd)
479{
480  if( !strcmp( cmd->cmd, "quit"))
481    {
482      if( !cmd->bUp) this->bQuitOrxonox = true;
483      return true;
484    }
485  return false;
486}
487
488/**
489        \brief render the current frame
490*/
491void World::display ()
492{
493  // clear buffer
494  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
495  // set camera
496  this->localCamera->apply ();
497  // draw world
498  this->draw();
499  // draw HUD
500  // flip buffers
501  SDL_GL_SwapBuffers();
502}
503
504Camera* World::getCamera()
505{
506  return this->localCamera;
507}
Note: See TracBrowser for help on using the repository browser.