DefaultTC.cpp

Go to the documentation of this file.
00001 /*
00002 SagaEngine library
00003 Copyright (c) 2002-2006 Skalden Studio AS
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to distribute the library under the terms of the 
00010 Q Public License version 1.0. Be sure to read and understand the license
00011 before using the library. It should be included here, or you may read it
00012 at http://www.trolltech.com/products/qt/licenses/licensing/qpl
00013 
00014 The original version of this library can be located at:
00015 http://www.sagaengine.com/
00016 
00017 Rune Myrland
00018 rune@skalden.com
00019 */
00020 
00021 
00022 #include "DefaultTC.hpp"
00023 #include "../thing/Actor.hpp"
00024 #include "../action/all.hpp"
00025 
00026 
00027 
00028 namespace se_core {
00029 
00030     DefaultTC
00031     ::DefaultTC() : ThingCollide("default")
00032                 , PROPERTY_COLLIDE_SELF(Property::hash("Collide.SELF"))
00033     {
00034     }
00035 
00036     DefaultTC
00037     ::DefaultTC(const char* name) : ThingCollide(name)
00038                 , PROPERTY_COLLIDE_SELF(Property::hash("Collide.SELF"))
00039     {
00040     }
00041 
00042     bool DefaultTC
00043     ::collide(ContactInfo& pusher, const ContactInfo& target) const {
00044         switch(target.cc_->substance()) {
00045         case UNDEFINED:
00046             LogFatal(target.cc_->name());
00047         case MOBILE: // Mobile
00048             slideOrBounce(pusher, target);
00049             popAndDie(pusher, target);
00050             break;
00051         case STATIC: // Static
00052             slideOrRebound(pusher, target);
00053             popAndDie(pusher, target);
00054             break;
00055         case GAS: // Gas
00056         case MISSILE: // Missile
00057             popAndDie(pusher, target);
00058             break;
00059         case PICK: // Pick
00060             popAndDie(pusher, target);
00061             break;
00062         }
00063         return false;
00064     }
00065 
00066 
00067     void DefaultTC
00068     ::bounce(ContactInfo& pusher
00069               , const ContactInfo& target) const {
00070         PhysicsComponent::Ptr pPhysics(pusher.cc_);
00071         const PhysicsComponent::Ptr tPhysics(target.cc_);
00072         PosComponent::Ptr pPos(pusher.cc_);
00073         const PosComponent::Ptr tPos(target.cc_);
00074 
00075         // First, find the normalized vector n from the center of 
00076         // circle1 to the center of circle2
00077         const Vector3& v1 = pPhysics->move().velocity_;
00078         const Vector3& v2 = tPhysics->move().velocity_;
00079 
00080         const Point3& p1 = pusher.bouncePoint_;
00081         const Point3& p2 = target.bouncePoint_;
00082 
00083         Vector3 n;
00084         n.sub(p1, p2);
00085         n.y_ = 0;
00086         if(n.isZero())
00087             n.x_ = 1;
00088         n.normalize(); 
00089 
00090         // Find the length of the component of each of the movement
00091         // vectors along n. 
00092         // a1 = v1 . n
00093         // a2 = v2 . n
00094         float a1 = v1.dot(n);
00095         float a2 = v2.dot(n);
00096 
00097         // Using the optimized version, 
00098         // optimizedP =  2(a1 - a2)
00099         //              -----------
00100         //                m1 + m2
00101         float optimizedP = (2.0f * (a1 - a2)) / (pPhysics->move().mass_ + tPhysics->move().mass_);
00102 
00103 
00104         // Calculate v1', the new movement vector of circle1
00105         // v1' = v1 - optimizedP * m2 * n
00106         Vector3 v1d;
00107         //scale_t bounceDecay = (1 - pPhysics->move().bounceMaintain_);
00108         //v1d.scale(-optimizedP * tPhysics->move().mass_ * (1 - bounceDecay * .5f) , n);
00109         v1d.scale(-optimizedP * tPhysics->move().mass_, n);
00110         pPhysics->nextMove().didBounce_ = true;
00111         v1d.y_ = 0;
00112         pPhysics->nextMove().addForce(v1d);
00113     }
00114 
00115 
00116     void DefaultTC
00117     ::rebound(ContactInfo& pusher, const ContactInfo& target) const {
00119         PhysicsComponent::Ptr pPhysics(*pusher.cc_);
00120         PosComponent::Ptr pPos(*pusher.cc_);
00121 
00122         const Point3& p1 = pusher.bouncePoint_;
00123         const Point3& p2 = target.bouncePoint_;
00124         const Vector3& v1 = pPhysics->move().velocity_;
00125 
00126         //LogWarning(p1.distance(p2));
00127         // First, find the normalized vector n from the center of 
00128         // circle1 to the center of circle2
00129         Vector3 n;
00130         n.sub(p1, p2);
00131         n.y_ = 0;
00132         if(n.isZero())
00133             return;
00134         n.normalize(); 
00135 
00136         // Find the length of the component of each of the movement
00137         // vectors along n. 
00138         // a1 = v1 . n
00139         // a2 = v2 . n
00140         float a1 = v1.dot(n);
00141 
00142         // Calculate v1', the new movement vector of circle1
00143         Vector3 v1d;
00144         //scale_t bounceDecay = (1 - pPhysics->move().bounceMaintain_);
00145         //v1d.scale(-2 * a1 * (1 - bounceDecay * .5f) , n);
00146         v1d.scale(-2 * a1, n);
00147         pPhysics->nextMove().didBounce_ = true;
00148         v1d.y_ = 0;
00149         pPhysics->nextMove().addForce(v1d);
00150 
00151         //haltIfGuilty(pusher, target);
00152     }
00153 
00154     void DefaultTC
00155     ::_away(ContactInfo& pusher
00156               , const ContactInfo& target, coor_t speed) const {
00157         PhysicsComponent::Ptr pPhysics(pusher.cc_);
00158         const PhysicsComponent::Ptr tPhysics(target.cc_);
00159 
00160         const Point3& p1 = pusher.bouncePoint_;
00161         const Point3& p2 = target.bouncePoint_;
00162         Point3 aw;
00163 
00164         aw.sub(p2, p1);
00165         aw.y_ = 0;
00166         if(aw.isZero()) {
00167             aw.x_ = 1;
00168         }
00169         else {
00170             aw.normalize();
00171         }
00172         aw.scale(-speed);
00173         aw.y_ = 0;
00174         pPhysics->nextMove().addForce(aw);
00175     }
00176 
00177 
00178     bool DefaultTC
00179     ::slide(ContactInfo& pusher
00180               , const ContactInfo& target) const {
00181         const coor_double_t SLIDE_THRESHOLD_SQ = 0.25f * 0.25f;
00182         // 
00183         coor_t distanceSq = pusher.bouncePoint_.xzDistanceSquared(target.bouncePoint_);
00184         if(distanceSq > SLIDE_THRESHOLD_SQ) {
00185             return false;
00186         }
00187 
00188         coor_t radSum = (pusher.radius_ + target.radius_);
00189         coor_t penetration = radSum - CoorT::sqrt(distanceSq);
00190         if(penetration < 0)
00191             penetration = 0;
00192         _away(pusher, target, penetration * penetration + 4 * COOR_STEP);
00193 
00194         return true;
00195     }
00196 
00197 
00198     bool DefaultTC
00199     ::popAndDie(ContactInfo& pusher
00200                 , const ContactInfo& target) const {
00201         if(pop(pusher, target)) {
00202             pusher.cc_->owner()->scheduleForDestruction();
00203         }
00204         return false;
00205 
00206     }
00207 
00208 
00209     bool DefaultTC
00210     ::pop(ContactInfo& pusher
00211                 , const ContactInfo& target) const {
00212         StatComponent::Ptr tStat(target.cc_);
00213         const Property* prop = tStat->property(PROPERTY_COLLIDE_SELF);
00214         AssertWarning(prop, "Missing property Collide.SELF in " << target.cc_->owner()->name());
00215         if(!prop) {
00216             return false;
00217         }
00218 
00219         StatComponent::Ptr pStat(pusher.cc_);
00220         const Property* propPusher = pStat->property(prop->hashValue());
00221         if(!propPusher)
00222             return false;
00223 
00224         switch(propPusher->type()) {
00225         case Property::PT_STRING:
00226         case Property::PT_STRING_LIST:
00227             if(_pop(*pusher.cc_->owner(), prop->hashValue())) {
00228                 return true;
00229             }
00230             break;
00231 
00232         case Property::PT_ACTION:
00233             //ActionComponent::Ptr(pusher)->planAction(CHANNEL_MOVEMENT, *propPusher->action());
00234             break;
00235         }
00236         return false;
00237     }
00238 
00239 
00240     bool DefaultTC
00241     ::_pop(se_core::Composite& spawner, unsigned int hash) {
00242         if(spawner.isDead())
00243             // Didn't pop - return false
00244             return false;
00245 
00246         StatComponent::Ptr pStat(spawner);
00247         const Property* propPop = pStat->property(hash);
00248         if(!propPop)
00249             // Didn't pop - return false
00250             return false;
00251 
00252         SpawnComponent::Ptr pSpawn(spawner);
00253         PosComponent::Ptr pPos(spawner);
00254 
00255         Composite* pop = 0;
00256         int c = propPop->valueCount();
00257         for(int i = 0; i < c; ++i) {
00258             pop = pSpawn->spawn(propPop->string(i), 0, 0);
00259             AssertFatal(pop, "Couldn't create " << propPop->string() << " for " << spawner.name());
00260             if(pop) {
00261                 PosComponent* sPos = PosComponent::get(*pop);
00262                 sPos->nextPos().anim(0).setAnim( pPos->pos().anim(0) );
00263                 sPos->nextPos().anim(1).setAnim( pPos->pos().anim(1) );
00264                 sPos->nextPos().anim(2).setAnim( pPos->pos().anim(2) );
00265                 sPos->nextPos().anim(3).setAnim( pPos->pos().anim(3) );
00266 
00267                 PhysicsComponent::Ptr pPhysics(spawner);
00268                 PhysicsComponent::Ptr sPhysics(*pop);
00269 
00270                 sPhysics->nextMove().setMove(pPhysics->nextMove());
00271             }
00272         }
00273         // Did pop - return true
00274         return true;
00275     }
00276 
00277     const DefaultTC tcDefault;
00278 }

Home Page | SagaEngine trunk (updated nightly) reference generated Sun Dec 2 20:06:11 2007 by Doxygen version 1.3.9.1.

SourceForge.net Logo