/* orxonox - the future of 3D-vertical-scrollersf Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Patrick Boenzli */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_COLLISION_REACTION #include "collision_handle.h" #include "world_entity.h" #include "collision.h" #include "collision_event.h" #include "collision_reaction.h" #include "cr_object_damage.h" #include "cr_physics_ground_walk.h" #include "cr_physics_full_walk.h" #include "debug.h" namespace CoRe { ObjectListDefinition(CollisionHandle); /** * standard constructor * @todo this constructor is not jet implemented - do it */ CollisionHandle::CollisionHandle (WorldEntity* owner, CREngine::ReactionType type) { this->registerObject(this, CollisionHandle::_objectList); this->owner = owner; this->type = type; this->bCollided = false; this->bDispatched = true; this->collisionReaction = NULL; this->bContinuousPoll = false; this->bStopOnFirstCollision = false; switch( type) { case CREngine::CR_PHYSICS_FULL_WALK: this->collisionReaction = new CRPhysicsFullWalk(); this->bContinuousPoll = true; break; case CREngine::CR_PHYSICS_GROUND_WALK: this->collisionReaction = new CRPhysicsGroundWalk(); this->bContinuousPoll = true; break; case CREngine::CR_OBJECT_DAMAGE: this->collisionReaction = new CRObjectDamage(); this->bStopOnFirstCollision = true; break; default: break; }; } /** * standard deconstructor */ CollisionHandle::~CollisionHandle () { // delete what has to be deleted here if( this->collisionReaction != NULL) delete this->collisionReaction; } /** * restores the CollisionHandle to its initial state */ void CollisionHandle::reset() { this->flushCollisions(); } /** * add more filter targets to this collision handle * @param classID the classid to look for */ void CollisionHandle::addTarget(const ClassID& target) { // make sure there is no dublicate std::vector::iterator it = this->targetList.begin(); for( ; it < this->targetList.end(); it++) if( (*it) == target) return; // add element this->targetList.push_back(target); PRINTF(5)("addTarget: %i \n", target.id()); } /** * handles the collisions and react according to algorithm */ void CollisionHandle::handleCollisions() { // if continuous poll the reaction if( this->bContinuousPoll && !this->bCollided) { this->collisionReaction->update(this->owner); return; } // collision reaction calculations (for every collision there will be a reaction) std::vector::iterator it = this->collisionList.begin(); for(; it < this->collisionList.end(); it++) { if( !(*it)->isDispatched()) { this->collisionReaction->reactToCollision(*it); (*it)->flushCollisionEvents(); } } // now set state to dispatched this->bDispatched = true; this->bCollided = false; this->flushCollisions(); } /** * filter out the CollisionEvents that are not wanted * @param collisionEvent the collision event to filter */ bool CollisionHandle::filterCollisionEvent(CollisionEvent* collisionEvent) { std::vector::iterator it = this->targetList.begin(); for(; it < this->targetList.end(); it++) { // if(collisionEvent->getEntityB()->isA(CL_AIMING_SYSTEM) || collisionEvent->getEntityA()->isA(CL_AIMING_SYSTEM)) // { // PRINTF(0)("I am: %s colliding with: %s\n", owner->getClassCName(), collisionEvent->getEntityB()->getClassCName(), *it); // if( collisionEvent->getEntityA() == this->owner) { // PRINTF(0)("I am owner -> I am: %s colliding with: %s is a %i filter?\n", owner->getClassCName(), // collisionEvent->getEntityB()->getClassCName(), *it); // if( collisionEvent->getEntityB()->isA((ClassID)(*it))) { // PRINTF(0)("I am owner -> I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(), // collisionEvent->getEntityB()->getClassCName(), *it); // } // } // else { // PRINTF(0)("I am not owner -> I am: %s colliding with: %s is a %i filter?\n", owner->getClassCName(), // collisionEvent->getEntityB()->getClassCName(), *it); // if( collisionEvent->getEntityA()->isA((ClassID)(*it))) { // PRINTF(0)("I'm not owner -> I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(), // collisionEvent->getEntityA()->getClassCName(), *it); // } // } // // } if( collisionEvent->getEntityA() == this->owner) { if( collisionEvent->getEntityB()->isA((*it))) { PRINTF(5)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(), collisionEvent->getEntityB()->getClassCName(), (*it).id()); return true; } } else { if( collisionEvent->getEntityA()->isA((*it))) { PRINTF(5)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(), collisionEvent->getEntityA()->getClassCName(), (*it).id()); return true; } } } return false; } /** * filter Collisions that are not wanted to be reacted to * @param collision the collision object to filter */ bool CollisionHandle::filterCollision(Collision* collision) { std::vector::iterator it = this->targetList.begin(); for(; it < this->targetList.end(); it++) { // if(collision->getEntityB()->isA(CL_AIMING_SYSTEM) || collision->getEntityA()->isA(CL_AIMING_SYSTEM)) // { // PRINTF(0)("Shared!!! I am: %s colliding with: %s\n", owner->getClassCName(), collision->getEntityB()->getClassCName(), *it); // if( collision->getEntityA() == this->owner) { // PRINTF(0)("I am owner -> I am: %s colliding with: %s is a %i filter?\n", owner->getClassCName(), // collision->getEntityB()->getClassCName(), *it); // if( collision->getEntityB()->isA((ClassID)(*it))) { // PRINTF(0)("I am owner -> I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(), // collision->getEntityB()->getClassCName(), *it); // } // } // else { // PRINTF(0)("I'm not owner -> I am: %s colliding with: %s is a %i filter?\n", owner->getClassCName(), // collision->getEntityB()->getClassCName(), *it); // if( collision->getEntityA()->isA((ClassID)(*it))) { // PRINTF(0)("I'm not owner -> I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(), // collision->getEntityA()->getClassCName(), *it); // } // } // } if( collision->getEntityA() == this->owner) { if( collision->getEntityA()->isA(*it)) return true; } else { if( collision->getEntityB()->isA(*it)) return true; } } return false; } }