Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/chris/src/world.cc @ 3178

Last change on this file since 3178 was 2194, checked in by chris, 20 years ago

orxonox/branches/chris: Implemented is_a() query for WorldEntities

File size: 8.0 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 ()
34{
35        entities = new List<WorldEntity>();
36}
37
38/**
39   \brief remove the World from memory
40*/
41World::~World ()
42{
43        unload ();
44        delete entities;
45}
46
47/**
48   \brief checks for collisions
49   
50   This method runs through all WorldEntities known to the world and checks for collisions between them.
51   In case of collisions the collide() method of the corresponding entities is called.
52*/
53void World::collide ()
54{
55        List<WorldEntity> *a, *b;
56        WorldEntity *aobj, *bobj;
57       
58        a = entities->get_next();
59       
60        while( a != NULL)
61        {
62                aobj = a->get_object();
63                if( aobj->bCollide && aobj->collisioncluster != NULL)
64                {
65                        b = a->get_next();
66                        while( b != NULL)
67                        {
68                                bobj = b->get_object();
69                                if( bobj->bCollide && bobj->collisioncluster != NULL)
70                                {
71                                        unsigned long ahitflg, bhitflg;
72                                        if( check_collision ( &aobj->place, aobj->collisioncluster, &ahitflg, &bobj->place, bobj->collisioncluster, &bhitflg))
73                                        {
74                                                aobj->collide (bobj, ahitflg, bhitflg);
75                                                bobj->collide (aobj, bhitflg, ahitflg);
76                                        }
77                                }
78                                b = b->get_next();
79                        }
80                }
81                a = a->get_next();
82        }
83}
84
85/**
86   \brief runs through all entities calling their draw() methods
87*/
88void World::draw ()
89{
90        // draw geometry
91       
92        // draw entities
93        List<WorldEntity> *l;
94        WorldEntity* entity;
95       
96        l = entities->get_next(); 
97        while( l != NULL) 
98        { 
99                entity = l->get_object();
100                if(     entity->bDraw) entity->draw();
101          l = l->get_next();
102        }
103       
104        // draw debug coord system
105        glLoadIdentity();
106        glBegin(GL_LINES);
107        for( float x = -128.0; x < 128.0; x += 25.0)
108        {
109                for( float y = -128.0; y < 128.0; y += 25.0)
110                {
111                        glColor3f(1,0,0);
112                        glVertex3f(x,y,-128.0);
113                        glVertex3f(x,y,0.0);
114                        glColor3f(0.5,0,0);
115                        glVertex3f(x,y,0.0);
116                        glVertex3f(x,y,128.0);
117                }
118        }
119        for( float y = -128.0; y < 128.0; y += 25.0)
120        {
121                for( float z = -128.0; z < 128.0; z += 25.0)
122                {
123                        glColor3f(0,1,0);
124                        glVertex3f(-128.0,y,z);
125                        glVertex3f(0.0,y,z);
126                        glColor3f(0,0.5,0);
127                        glVertex3f(0.0,y,z);
128                        glVertex3f(128.0,y,z);
129                }
130        }
131        for( float x = -128.0; x < 128.0; x += 25.0)
132        {
133                for( float z = -128.0; z < 128.0; z += 25.0)
134                {
135                        glColor3f(0,0,1);
136                        glVertex3f(x,-128.0,z);
137                        glVertex3f(x,0.0,z);
138                        glColor3f(0,0,0.5);
139                        glVertex3f(x,0.0,z);
140                        glVertex3f(x,128.0,z);
141                }
142        }
143        //draw track
144        glColor3f(0,1,1);
145        for( int i = 0; i < tracklen; i++)
146        {
147                glVertex3f(pathnodes[i].x,pathnodes[i].y,pathnodes[i].z);
148                glVertex3f(pathnodes[(i+1)%tracklen].x,pathnodes[(i+1)%tracklen].y,pathnodes[(i+1)%tracklen].z);
149        }
150        glEnd();
151}
152
153/**
154   \brief updates Placements and notifies entities when they left the world
155   
156   This runs trough all WorldEntities and maps Locations to Placements if they are bound, checks
157   whether they left the level boundaries and calls appropriate functions.
158*/
159void World::update ()
160{
161        List<WorldEntity> *l;
162        WorldEntity* entity;
163        Location* loc;
164        Placement* plc;
165        Uint32 t;
166       
167        l = entities->get_next(); 
168        while( l != NULL) 
169        { 
170                entity = l->get_object();
171               
172                if( !entity->isFree())
173                {
174                        loc = entity->get_location();
175                        plc = entity->get_placement();
176                        t = loc->part;
177                       
178                        if( t >= tracklen)
179                        {
180                                printf("An entity is out of the game area\n");
181                                entity->left_world ();
182                        }
183                        else
184                        {
185                                while( track[t]->map_coords( loc, plc))
186                                {
187                                        track[t]->post_leave (entity);
188                                        if( loc->part >= tracklen)
189                                        {
190                                                printf("An entity has left the game area\n");
191                                                entity->left_world ();
192                                                break;
193                                        }
194                                        track[loc->part]->post_enter (entity);
195                                }
196                        }
197                }
198                else
199                {
200                        // TO DO: implement check whether this particular free entity is out of the game area
201                        // TO DO: call function to notify the entity that it left the game area
202                }
203               
204          l = l->get_next();
205        }
206       
207}
208
209/**
210  \brief relays the passed time since the last frame to entities and Track parts
211        \param deltaT: the time passed since the last frame in milliseconds
212*/
213void World::time_slice (Uint32 deltaT)
214{
215        List<WorldEntity> *l;
216        WorldEntity* entity;
217        float seconds = deltaT;
218       
219        seconds /= 1000;
220       
221        l = entities->get_next(); 
222        while( l != NULL) 
223        { 
224                entity = l->get_object();
225                entity->tick (seconds);
226          l = l->get_next();
227        }
228       
229        for( int i = 0; i < tracklen; i++) track[i]->tick (seconds);
230}
231
232/**
233        \brief removes level data from memory
234*/
235void World::unload()
236{
237        if( pathnodes) delete []pathnodes;
238        if( track) delete []pathnodes;
239}
240
241/**
242        \brief loads a simple level for testing purposes
243*/
244void World::load_debug_level()
245{
246        // create some path nodes
247        pathnodes = new Vector[6];
248        pathnodes[0] = Vector(0, 0, 0);
249        pathnodes[1] = Vector(-100, 40, 0);
250        pathnodes[2] = Vector(-100, 140, 0);
251        pathnodes[3] = Vector(0, 180, 0);
252        pathnodes[4] = Vector(100, 140, 0);
253        pathnodes[5] = Vector(100, 40, 0);     
254       
255        // create the tracks
256        tracklen = 6;
257        track = new Track*[6];
258        for( int i = 0; i < tracklen; i++)
259        {
260                track[i] = new Track( i, (i+1)%tracklen, &pathnodes[i], &pathnodes[(i+1)%tracklen]);
261        }
262       
263        // create a player
264        WorldEntity* myPlayer = (WorldEntity*) spawn<Player>();
265       
266        // bind input
267  Orxonox *orx = Orxonox::getInstance();
268  orx->get_localinput()->bind (myPlayer);
269 
270        // bind camera
271        orx->get_camera()->bind (myPlayer);
272}
273
274/**
275        \brief calls the correct mapping function to convert a given "look at"-Location to a Camera Placement
276*/
277void World::calc_camera_pos (Location* loc, Placement* plc)
278{
279  track[loc->part]->map_camera (loc, plc);
280}
281
282/**
283        \brief sends a damage message to all WorldEntities in the specified vicinity
284        \param loc: the Location of the epicenter of the explosion
285        \param dmg: the damage dealt
286        \param r: the radius of the explosion
287        \param instigator: a pointer to the entity that caused the explosion
288       
289        This is a rather expensive function to call, so I suggest you do not call this every tick when you want to
290        create something that deals damage over time (use a countdown instead that calls this function every second or so).
291*/
292void World::explosion (Location* loc, Damage* dmg, float r, WorldEntity* instigator)
293{
294        Placement mapped;
295       
296        track[loc->part]->map_coords (loc, &mapped);
297        CollisionCluster boom( r, Vector(0,0,0));
298       
299        unsigned long boomflags, hflags;
300        List<WorldEntity> *a;
301        WorldEntity *aobj;
302       
303        a = entities->get_next();
304       
305        while( a != NULL)
306        {
307                aobj = a->get_object();
308                if( aobj->bCollide && aobj->collisioncluster != NULL)
309                {
310                        hflags = 0;
311                        if( check_collision ( &aobj->place, aobj->collisioncluster, &hflags, &mapped, &boom, &boomflags))
312                        {
313                                aobj->hit (dmg, instigator, hflags);
314                        }
315                }
316                a = a->get_next();
317        }
318}
319
320/**
321        \brief sends a damage message to all WorldEntities in the specified vicinity
322        \param plc: the Placement of the epicenter of the explosion
323        \param dmg: the damage dealt
324        \param r: the radius of the explosion
325        \param instigator: a pointer to the entity that caused the explosion
326       
327        This is a rather expensive function to call, so I suggest you do not call this every tick when you want to
328        create something that deals damage over time (use a countdown instead that calls this function every second or so).
329*/
330void World::explosion (Placement* plc, Damage* dmg, float r, WorldEntity* instigator)
331{
332        CollisionCluster boom( r, Vector(0,0,0));
333       
334        unsigned long boomflags, hflags;
335        List<WorldEntity> *a;
336        WorldEntity *aobj;
337       
338        a = entities->get_next();
339       
340        while( a != NULL)
341        {
342                aobj = a->get_object();
343                if( aobj->bCollide && aobj->collisioncluster != NULL)
344                {
345                        hflags = 0;
346                        if( check_collision ( &aobj->place, aobj->collisioncluster, &hflags, plc, &boom, &boomflags))
347                        {
348                                aobj->hit (dmg, instigator, hflags);
349                        }
350                }
351                a = a->get_next();
352        }
353}
Note: See TracBrowser for help on using the repository browser.