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 "CoDefault.hpp" 00023 #include "../thing/Actor.hpp" 00024 #include "../action/all.hpp" 00025 00026 00027 00028 namespace se_core { 00029 00030 CoDefault 00031 ::CoDefault() : ThingCollide("Default") 00032 , PROPERTY_COLLIDE_SELF(Property::hash("Collide.SELF")) 00033 { 00034 } 00035 00036 CoDefault 00037 ::CoDefault(const char* name) : ThingCollide(name) 00038 , PROPERTY_COLLIDE_SELF(Property::hash("Collide.SELF")) 00039 { 00040 } 00041 00042 bool CoDefault 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 CoDefault 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 CoDefault 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 CoDefault 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 CoDefault 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 CoDefault 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 CoDefault 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.cc_)->planAction(CHANNEL_MOVEMENT, *propPusher->action()); 00234 break; 00235 } 00236 return false; 00237 } 00238 00239 00240 bool CoDefault 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 CoDefault coDefault; 00278 }
Home Page | SagaEngine trunk (updated nightly) reference generated Sun Dec 2 20:06:11 2007 by Doxygen version 1.3.9.1.