Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/collision_reaction/collision_handle.cc @ 8894

Last change on this file since 8894 was 8724, checked in by bensch, 18 years ago

merged the bsp-model-stuff back here

File size: 7.0 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollersf
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13*/
14
15#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_COLLISION_REACTION
16
17#include "collision_handle.h"
18
19#include "world_entity.h"
20
21#include "collision.h"
22#include "collision_event.h"
23#include "collision_reaction.h"
24
25#include "cr_object_damage.h"
26#include "cr_physics_ground_walk.h"
27
28#include "debug.h"
29
30using namespace std;
31
32
33/**
34 * standard constructor
35 * @todo this constructor is not jet implemented - do it
36*/
37CollisionHandle::CollisionHandle (WorldEntity* owner, CREngine::CRType type)
38{
39  this->setClassID(CL_COLLISION_HANDLE, "CollisionHandle");
40
41  this->owner = owner;
42  this->type = type;
43
44  this->bCollided = false;
45  this->bDispatched = true;
46
47  this->collisionReaction = NULL;
48  this->bContinuousPoll = false;
49  this->bStopOnFirstCollision = false;
50
51
52  switch( type)
53  {
54    case CREngine::CR_PHYSICS_STEP_BACK:
55//       this->collisionReaction = new CRPhysicsGroundWalk();
56      this->bContinuousPoll = true;
57      break;
58    case CREngine::CR_PHYSICS_GROUND_WALK:
59      this->collisionReaction = new CRPhysicsGroundWalk();
60      this->bContinuousPoll = true;
61      break;
62    case CREngine::CR_OBJECT_DAMAGE:
63      this->collisionReaction = new CRObjectDamage();
64      this->bStopOnFirstCollision = true;
65      break;
66    default:
67      break;
68  };
69}
70
71
72/**
73 * standard deconstructor
74*/
75CollisionHandle::~CollisionHandle ()
76{
77  // delete what has to be deleted here
78  if( this->collisionReaction != NULL)
79    delete this->collisionReaction;
80}
81
82/**
83 * restores the CollisionHandle to its initial state
84 */
85void CollisionHandle::reset()
86{
87  this->flushCollisions();
88}
89
90
91/**
92 * add more filter targets to this collision handle
93 *  @param classID the classid to look for
94 */
95void CollisionHandle::addTarget(long target)
96{
97  // make sure there is no dublicate
98  std::vector<long>::iterator it = this->targetList.begin();
99  for( ; it < this->targetList.end(); it++)
100    if( (*it) == target)
101      return;
102
103  // add element
104   PRINTF(5)("addTarget: %i \n", target);
105
106   this->targetList.push_back(target);
107}
108
109
110/**
111 * registers a new Collision Object
112 *  @param entityA WorldEntity A of the collision
113 *  @param entityB WorldEntity B of the collision
114 * if a there is already a collision object with the same stats
115 * registration will be skipped and the last collision object is returned
116 */
117Collision* CollisionHandle::registerCollision(WorldEntity* entityA, WorldEntity* entityB)
118{
119  //first get the collision object, multiple sources
120  Collision* c;
121  if( this->collisionList.empty() ||
122      ((this->collisionList.back())->getEntityA() != entityA && (this->collisionList.back())->getEntityB() != entityB )) {
123    c = CREngine::getInstance()->popCollisionObject();
124    c->collide(entityA, entityB);
125    this->collisionList.push_back(c);
126
127    // now register it as a shared collision with the other collision entity
128    CollisionHandle* ch = entityB->getCollisionHandle(this->type);
129    if( ch != NULL)
130      ch->registerSharedCollision(c);
131  }
132  else
133    c = this->collisionList.back();
134
135  return c;
136}
137
138
139/**
140 * register a Collision to the Collision handle.
141 *  @param collision the collision object to register
142 *
143 * This is used for internal collision registration: sharing the collision objects between Collision Reactions
144 * Therefore dispatching it only once
145 */
146void CollisionHandle::registerSharedCollision(Collision* collision)
147{
148  // fist check if we are listening for this Collision
149  if( !this->filterCollision(collision))
150    return;
151
152  // set the state to not dispatched
153  this->bDispatched = false;
154  this->bCollided = true;
155  collision->setEntityBCollide(true);
156
157  this->collisionList.push_back(collision);
158}
159
160
161/**
162 * this is the function to be called on a collision event for this handle
163 *  @param collision the collision objects containing all collision informations
164 */
165void CollisionHandle::registerCollisionEvent(CollisionEvent* collisionEvent)
166{
167  if( !this->filterCollisionEvent(collisionEvent))
168    return;
169
170  // set the state to not dispatched
171  this->bDispatched = false;
172  this->bCollided = true;
173
174  // checks if these WorldEntities have already collided or if its a new collision -> create a new Collision object
175 Collision* c = this->registerCollision(collisionEvent->getEntityA(), collisionEvent->getEntityB());
176 c->setEntityACollide(true);
177
178 c->registerCollisionEvent(collisionEvent);
179 PRINTF(5)("Registering Collision Event: %s, %s\n", collisionEvent->getEntityA()->getClassName(), collisionEvent->getEntityB()->getClassName());
180}
181
182
183/**
184 * flushes the collision list
185 */
186void CollisionHandle::flushCollisions()
187{
188  this->collisionList.clear();
189}
190
191
192/**
193 * handles the collisions and react according to algorithm
194 */
195void CollisionHandle::handleCollisions()
196{
197  // if continuous poll poll the reaction
198  if( this->bContinuousPoll && !this->bCollided)
199  {
200    this->collisionReaction->update(this->owner);
201    return;
202  }
203
204  // collision reaction calculations (for every collision there will be a reaction)
205  vector<Collision*>::iterator it = this->collisionList.begin();
206  for(; it < this->collisionList.end(); it++) {
207    if( !(*it)->isDispatched())
208    {
209      this->collisionReaction->reactToCollision(*it);
210      (*it)->flushCollisionEvents();
211    }
212  }
213
214  // now set state to dispatched
215  this->bDispatched = true;
216  this->bCollided = false;
217
218  this->flushCollisions();
219}
220
221
222/**
223 * filter out the CollisionEvents that are not wanted
224 *  @param collisionEvent the collision event to filter
225 */
226bool CollisionHandle::filterCollisionEvent(CollisionEvent* collisionEvent)
227{
228  vector<long>::iterator it = this->targetList.begin();
229  for(; it < this->targetList.end(); it++)
230  {
231    if( collisionEvent->getEntityA() == this->owner) {
232      if( collisionEvent->getEntityB()->isA((ClassID)(*it))) {
233        PRINTF(5)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassName(),
234                  collisionEvent->getEntityB()->getClassName(), *it);
235        return true; }
236    }
237    else {
238      if( collisionEvent->getEntityA()->isA((ClassID)(*it))) {
239        PRINTF(5)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassName(),
240                  collisionEvent->getEntityA()->getClassName(), *it);
241      return true; }
242    }
243  }
244
245  return false;
246}
247
248
249/**
250 * filter Collisions that are not wanted to be reacted to
251 *  @param collision the collision object to filter
252 */
253bool CollisionHandle::filterCollision(Collision* collision)
254{
255  vector<long>::iterator it = this->targetList.begin();
256  for(; it < this->targetList.end(); it++)
257  {
258    if( collision->getEntityA() == this->owner) {
259      if( collision->getEntityA()->isA((ClassID)(*it)))
260        return true; }
261      else {
262        if( collision->getEntityB()->isA((ClassID)(*it)))
263          return true; }
264  }
265
266  return false;
267}
268
269
270
271
272
273
274
Note: See TracBrowser for help on using the repository browser.