/* orxonox - the future of 3D-vertical-scrollers 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 co-programmer: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_COLLISION_REACTION #include "cr_object_damage.h" #include "cr_physics_full_walk.h" #include "cr_physics_ground_walk.h" #include "collision.h" #include "collision_event.h" #include "collision_filter.h" #include "collision_tube.h" #include "cr_defs.h" #include "cr_engine.h" #include "debug.h" namespace CoRe { ObjectListDefinition(CREngine); /** * standard constructor */ CREngine::CREngine () : BaseObject() { this->registerObject(this, CREngine::_objectList); this->setName("CREngine"); this->init(); } /** * the singleton reference to this class */ CREngine* CREngine::singletonRef = NULL; /** @brief standard deconstructor */ CREngine::~CREngine () { CREngine::singletonRef = NULL; if( this->collisionsUnused.size() != CR_MAX_COLLISIONS) PRINTF(0)("CollisionReaction Error: Collision cache size missmatch: %i of %i\n", this->collisionsUnused.size(), CR_MAX_COLLISIONS); if( this->collisionEventsUnused.size() != CR_MAX_COLLISION_EVENTS) PRINTF(0)("CollisionReaction Error: CollisionEvent cache size missmatch: %i of %i\n", this->collisionEventsUnused.size(), CR_MAX_COLLISION_EVENTS); this->flushCollisions(); CollisionIterator it1 = this->collisionsUnused.begin(); for(; it1 < this->collisionsUnused.end(); it1++) delete *it1; CollisionEventIterator it2 = this->collisionEventsUnused.begin(); for(; it2 < this->collisionEventsUnused.end(); it2++) delete *it2; this->collisionsUnused.clear(); this->collisionEventsUnused.clear(); } /** * inits the CREngine to a working state */ void CREngine::init() { // precaching: // create a list of Collisions and CollisionEvents for fast object recycling purposes for( int i = 0; i < CR_MAX_COLLISIONS; i++) this->collisionsUnused.push_back(new Collision()); for( int i = 0; i < CR_MAX_COLLISION_EVENTS; i++) this->collisionEventsUnused.push_back(new CollisionEvent()); // push the collision reaction object on the list in the right order // physical reactions this->_reactionList[CREngine::CR_PHYSICS_MOMENTUM] = NULL; this->_reactionList[CREngine::CR_PHYSICS_STEP_BACK] = NULL; this->_reactionList[CREngine::CR_PHYSICS_GROUND_WALK] = new CRPhysicsGroundWalk(); this->_reactionList[CREngine::CR_PHYSICS_FULL_WALK] = new CRPhysicsFullWalk(); this->_reactionList[CREngine::CR_PHYSICS_DAMAGE] = NULL; // object based reactions this->_reactionList[CREngine::CR_OBJECT_DAMAGE] = new CRObjectDamage(); this->_reactionList[CREngine::CR_OBJECT_PICKUP] = NULL; // misc reactions this->_reactionList[CREngine::CR_VERTEX_TRAFO] = NULL; this->_reactionList[CREngine::CR_SPECIAL_CALLBACK] = NULL; } /** * @returns an instance to a collision object. instead of creating new object this ones can be resycled */ Collision* CREngine::popCollisionObject() { if( !this->collisionsUnused.empty()) { this->collisionsUsed.push_back(this->collisionsUnused.back()); this->collisionsUnused.pop_back(); return this->collisionsUsed.back(); } else return NULL; } /** * @return an instanco of a CollisionEvent object. instead of creating a new object this ones can be used and resycled */ CollisionEvent* CREngine::popCollisionEventObject() { if( !this->collisionEventsUnused.empty()) { this->collisionEventsUsed.push_back(this->collisionEventsUnused.back()); this->collisionEventsUnused.pop_back(); return this->collisionEventsUsed.back(); } else return NULL; } /** * handles all collisions in registered in this tube */ void CREngine::handleCollisions() { // for all collisions: CollisionIterator ci = CollisionTube::getInstance()->begin(); for(; ci < CollisionTube::getInstance()->end(); ++ci) { for( int i = CREngine::CR_PHYSICS_MOMENTUM; i < CREngine::CR_NUMBER; i++) { if( _reactionList[i] == NULL) continue; // check if entity A or B is subscibed for this event if( (*ci)->getEntityA()->isReactive(*(*ci)->getEntityB(), (CREngine::ReactionType)i) || (*ci)->getEntityB()->isReactive(*(*ci)->getEntityA(), (CREngine::ReactionType)i)) { this->_reactionList[i]->reactToCollision(*ci); PRINTF(0)("react to %i\n", i); } (*ci)->reset(); } } this->flushCollisions(); } /** * flushes all the collision lists and puts them to their initial state */ void CREngine::flushCollisions() { CollisionIterator it1 = this->collisionsUsed.begin(); for(; it1 < this->collisionsUsed.end(); it1++) this->collisionsUnused.push_back(*it1); CollisionEventIterator it2 = this->collisionEventsUsed.begin(); for(; it2 < this->collisionEventsUsed.end(); it2++) this->collisionEventsUnused.push_back(*it2); this->collisionsUsed.clear(); this->collisionEventsUsed.clear(); } void CREngine::debug() { } }