PhysicsParticleObject.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <engine/PhysicsParticleObject.h>
00022 #include <engine/ScorchedContext.h>
00023 #include <engine/ActionController.h>
00024 #include <landscapemap/LandscapeMaps.h>
00025 #include <target/TargetSpace.h>
00026 #include <target/TargetShield.h>
00027 #include <target/TargetLife.h>
00028 #include <tank/TankContainer.h>
00029 #include <tank/TankPosition.h>
00030 #include <weapons/Accessory.h>
00031 #include <weapons/Shield.h>
00032 #include <weapons/ShieldRoundReflective.h>
00033 #include <weapons/ShieldSquareReflective.h>
00034 #include <weapons/ShieldRoundMag.h>
00035 #include <actions/ShotBounce.h>
00036 #include <actions/ShotProjectile.h>
00037 #include <actions/ShieldHit.h>
00038 #include <common/Defines.h>
00039 #include <common/Logger.h>
00040 #include <common/OptionsTransient.h>
00041 
00042 PhysicsParticleObject::PhysicsParticleObject() : 
00043         handler_(0), context_(0), underGroundCollision_(false), iterations_(0),
00044         info_(ParticleTypeNone, 0, 0), rotateOnCollision_(false), wallCollision_(true)
00045 {
00046 }
00047 
00048 PhysicsParticleObject::~PhysicsParticleObject()
00049 {
00050 }
00051 
00052 void PhysicsParticleObject::applyForce(FixedVector &force)
00053 {
00054         velocity_ += force;
00055 }
00056 
00057 void PhysicsParticleObject::setPhysics(
00058         PhysicsParticleInfo info,
00059         ScorchedContext &context, 
00060         FixedVector &position, FixedVector &velocity,
00061         fixed sphereSize, fixed sphereDensity, fixed windFactor,
00062         bool underGroundCollision, bool rotateOnCollision, bool wallCollision)
00063 {
00064         info_ = info;
00065         context_ = &context;
00066         underGroundCollision_ = underGroundCollision;
00067         rotateOnCollision_ = rotateOnCollision;
00068         wallCollision_ = wallCollision;
00069 
00070         FixedVector zaxis(0, 0, 1);
00071         rotation_.setQuatFromAxisAndAngle(zaxis, 0);
00072         position_ = position;
00073         velocity_ = velocity;
00074         windFactor_ = 
00075                 context_->getOptionsTransient().getWindDirection() * 
00076                 context_->getOptionsTransient().getWindSpeed() / 
00077                 fixed(true, 25000) * windFactor;
00078 
00079         FixedVector gravity(0, 0, context_->getOptionsGame().getGravity());
00080         windFactor_ += gravity;
00081         windFactor_ /= 70;
00082 }
00083 
00084 void PhysicsParticleObject::simulate(fixed frameTime)
00085 {
00086         iterations_++;
00087         velocity_ += windFactor_;
00088         position_ += velocity_ / 100;
00089 
00090         if (rotateOnCollision_)
00091         {
00092                 rotation_ += avelocity_;
00093                 rotation_.Normalize();
00094         }
00095 
00096         if (!handler_ || !context_) return;
00097 
00098         checkCollision();
00099 }
00100 
00101 void PhysicsParticleObject::checkCollision()
00102 {
00103         CollisionInfo collision;
00104         collision.collisionId = CollisionIdNone;
00105 
00106         fixed bounceFactor = 2;
00107 
00108         // Find if we have had a collision
00109         CollisionAction action = CollisionActionNone;
00110         Target *target = context_->getTargetSpace().getCollision(position_);
00111         switch (info_.type_)
00112         {
00113         case ParticleTypeShot:
00114                 if (getTargetCollision(collision, target) ||
00115                         getShieldCollision(collision, target) ||
00116                         getLandscapeCollision(collision) ||
00117                         getRoofCollision(collision) ||
00118                         getWallCollision(collision)) 
00119                 {
00120                         action = checkShotCollision(collision, target);
00121                         if (action != CollisionActionNone)
00122                         {
00123                                 if (context_->getOptionsGame().getActionSyncCheck())
00124                                 {
00125                                         context_->getActionController().addSyncCheck(
00126                                                 S3D::formatStringBuffer("Shot Collision : %i %i %i,%i,%i", 
00127                                                         (int) action,
00128                                                         (int) collision.collisionId,
00129                                                         position_[0].getInternal(),
00130                                                         position_[1].getInternal(),
00131                                                         position_[2].getInternal()));
00132                                 }
00133                         }
00134                 }
00135                 break;
00136         case ParticleTypeBounce:
00137                 if (getTargetBounceCollision(collision, target) ||
00138                         getTargetCollision(collision, target) ||
00139                         getShieldCollision(collision, target) ||
00140                         getLandscapeCollision(collision) ||
00141                         getWallCollision(collision))
00142                 {
00143                         action = checkBounceCollision(collision, target);
00144 
00145                         velocity_[2] = MIN(velocity_[2], 1);
00146                         bounceFactor = fixed(true, 1750);
00147                 }
00148                 break;
00149         case ParticleTypeFalling:
00150                 if (getLandscapeCollision(collision) ||
00151                         getWallCollision(collision))
00152                 {
00153                         action = checkFallingCollision(collision, target);
00154                 }
00155                 break;
00156         }       
00157 
00158         // Perform the result of the collision (if any)
00159         switch (action)
00160         {
00161         case CollisionActionCollision:
00162                 handler_->collision(*this, collision.collisionId);
00163                 break;
00164         case CollisionActionBounce:
00165                 {
00166                         // Move the shot back to the original position so that the
00167                         // shot is outside the object after the bounce
00168                         position_ -= velocity_ / 100;
00169 
00170                         // Calculate the new bounce position
00171                         fixed strength = velocity_.Magnitude();
00172                         FixedVector direction = velocity_ / strength;
00173                         fixed dotp = -collision.normal.dotP(direction);
00174                         direction = direction + collision.normal * (dotp * bounceFactor);
00175                         velocity_ = direction * strength * collision.deflectFactor;
00176 
00177                         fixed landHeight = 
00178                                 context_->getLandscapeMaps().getGroundMaps().
00179                                         getInterpHeight(position_[0], position_[1]);
00180                         fixed particleHeight = position_[2] - landHeight;
00181                         if (underGroundCollision_)
00182                         {
00183                                 if (particleHeight > fixed(true, -1000)) 
00184                                         position_[2] = landHeight - fixed(true, 1000);
00185                         }
00186                         else
00187                         {
00188                                 if (particleHeight < fixed(true, 1000)) 
00189                                         position_[2] = landHeight + fixed(true, 1000);
00190                         }
00191 
00192                         if (rotateOnCollision_)
00193                         {
00194                                 FixedVector up(0, 0, -1);
00195                                 FixedVector rotAxis = velocity_ * up;
00196                                 rotAxis.StoreNormalize();
00197                                 avelocity_.setQuatFromAxisAndAngle(rotAxis, velocity_.Magnitude() * 5);
00198                         }
00199                 }
00200                 break;
00201         }
00202 }
00203 
00204 PhysicsParticleObject::CollisionAction PhysicsParticleObject::checkShotCollision(
00205         CollisionInfo &collision, Target *target)
00206 {
00207         int arenaX = context_->getLandscapeMaps().getGroundMaps().getArenaX();
00208         int arenaY = context_->getLandscapeMaps().getGroundMaps().getArenaY();
00209         int arenaWidth = context_->getLandscapeMaps().getGroundMaps().getArenaWidth();
00210         int arenaHeight = context_->getLandscapeMaps().getGroundMaps().getArenaHeight();
00211 
00212         switch(collision.collisionId)
00213         {
00214         case CollisionIdLandscape:
00215         case CollisionIdRoof:
00216         case CollisionIdTarget:
00217                 return CollisionActionCollision;
00218                 break;
00219         case CollisionIdShield:
00220                 if (target && target->getShield().getCurrentShield())
00221                 {
00222                         shotShieldHit(target);
00223 
00224                         if (target->getShield().getCurrentShield()) // shotShieldHit may have removed shield
00225                         {
00226                                 Shield *shield = (Shield *) target->getShield().getCurrentShield()->getAction();
00227                                 switch (shield->getShieldType())
00228                                 {
00229                                 case Shield::ShieldTypeRoundNormal:
00230                                 case Shield::ShieldTypeSquareNormal:
00231                                         return CollisionActionCollision;
00232                                 case Shield::ShieldTypeRoundReflective:
00233                                 case Shield::ShieldTypeSquareReflective:
00234                                         return CollisionActionBounce;
00235                                 case Shield::ShieldTypeRoundMag:
00236                                         {
00237                                                 ShieldRoundMag *magShield = (ShieldRoundMag *) shield;
00238                                                 FixedVector force(0, 0, magShield->getDeflectPower() / 50);
00239                                                 velocity_ += force;
00240                                         }
00241                                         return CollisionActionNone;
00242                                 }
00243                         }
00244                 }
00245                 break;
00246         case CollisionIdWallLeft:
00247         case CollisionIdWallRight:
00248         case CollisionIdWallTop:
00249         case CollisionIdWallBottom:
00250 
00251                 switch(collision.collisionId)
00252                 {
00253                 case CollisionIdWallLeft:
00254                         position_[0] = arenaX + 1;
00255                         break;
00256                 case CollisionIdWallRight:
00257                         position_[0] = arenaX + arenaWidth - 1;
00258                         break;
00259                 case CollisionIdWallTop:
00260                         position_[1] = arenaY + 1;
00261                         break;
00262                 case CollisionIdWallBottom:
00263                         position_[1] = arenaY + arenaHeight - 1;
00264                         break;
00265                 }
00266 
00267                 shotWallHit(collision);
00268 
00269                 handler_->wallCollision(*this, collision.collisionId);
00270 
00271                 switch (context_->getOptionsTransient().getWallType())
00272                 {
00273                 case OptionsTransient::wallBouncy:
00274                         return CollisionActionBounce;
00275                 case OptionsTransient::wallWrapAround:
00276 
00277                         switch (collision.collisionId)
00278                         {
00279                         case CollisionIdWallLeft:
00280                                 position_[0] = arenaX + arenaWidth - 10;
00281                                 break;
00282                         case CollisionIdWallRight:
00283                                 position_[0] = arenaX + 10;
00284                                 break;
00285                         case CollisionIdWallTop:
00286                                 position_[1] = arenaY + arenaHeight - 10;
00287                                 break;
00288                         case CollisionIdWallBottom:
00289                                 position_[1] = arenaX + 10;
00290                                 break;
00291                         }
00292                         return CollisionActionNone;
00293                 case OptionsTransient::wallConcrete:
00294                         return CollisionActionCollision;
00295                 }
00296                 break;
00297         }
00298         return CollisionActionNone;
00299 }
00300 
00301 PhysicsParticleObject::CollisionAction PhysicsParticleObject::checkBounceCollision(
00302         CollisionInfo &collision, Target *target)
00303 {
00304         int arenaX = context_->getLandscapeMaps().getGroundMaps().getArenaX();
00305         int arenaY = context_->getLandscapeMaps().getGroundMaps().getArenaY();
00306         int arenaWidth = context_->getLandscapeMaps().getGroundMaps().getArenaWidth();
00307         int arenaHeight = context_->getLandscapeMaps().getGroundMaps().getArenaHeight();
00308 
00309         switch(collision.collisionId)
00310         {
00311         case CollisionIdRoof:
00312                 return CollisionActionNone;
00313                 break;
00314         case CollisionIdLandscape:
00315                 return CollisionActionBounce;
00316         case CollisionIdWallLeft:
00317         case CollisionIdWallRight:
00318         case CollisionIdWallTop:
00319         case CollisionIdWallBottom:
00320 
00321                 if (context_->getOptionsTransient().getWallType() == OptionsTransient::wallBouncy ||
00322                         context_->getOptionsTransient().getWallType() == OptionsTransient::wallConcrete)
00323                 {
00324                         switch(collision.collisionId)
00325                         {
00326                         case CollisionIdWallLeft:
00327                                 position_[0] = arenaX + 1;
00328                                 break;
00329                         case CollisionIdWallRight:
00330                                 position_[0] = arenaX + arenaWidth - 1;
00331                                 break;
00332                         case CollisionIdWallTop:
00333                                 position_[1] = arenaY + 1;
00334                                 break;
00335                         case CollisionIdWallBottom:
00336                                 position_[1] = arenaY + arenaHeight - 1;
00337                                 break;
00338                         }
00339                 }
00340 
00341                 switch (context_->getOptionsTransient().getWallType())
00342                 {
00343                 case OptionsTransient::wallBouncy:
00344                         return CollisionActionBounce;
00345                 case OptionsTransient::wallWrapAround:
00346                         return CollisionActionNone;
00347                 case OptionsTransient::wallConcrete:
00348                         return CollisionActionCollision;
00349                 }
00350                 break;
00351         case CollisionIdShield:
00352                 bounceShieldHit(target);
00353                 return CollisionActionBounce;
00354                 break;
00355         case CollisionIdTarget:
00356                 return CollisionActionCollision;
00357                 break;
00358         }
00359         return CollisionActionNone;
00360 }
00361 
00362 PhysicsParticleObject::CollisionAction PhysicsParticleObject::checkFallingCollision(
00363         CollisionInfo &collision, Target *target)
00364 {
00365         int arenaX = context_->getLandscapeMaps().getGroundMaps().getArenaX();
00366         int arenaY = context_->getLandscapeMaps().getGroundMaps().getArenaY();
00367         int arenaWidth = context_->getLandscapeMaps().getGroundMaps().getArenaWidth();
00368         int arenaHeight = context_->getLandscapeMaps().getGroundMaps().getArenaHeight();
00369 
00370         switch(collision.collisionId)
00371         {
00372         case CollisionIdTarget:
00373         case CollisionIdShield:
00374                 return CollisionActionNone;
00375                 break;
00376         case CollisionIdRoof:
00377         case CollisionIdWallLeft:
00378         case CollisionIdWallRight:
00379         case CollisionIdWallTop:
00380         case CollisionIdWallBottom:
00381                 switch(collision.collisionId)
00382                 {
00383                 case CollisionIdWallLeft:
00384                         position_[0] = arenaX + 1;
00385                         break;
00386                 case CollisionIdWallRight:
00387                         position_[0] = arenaX + arenaWidth - 1;
00388                         break;
00389                 case CollisionIdWallTop:
00390                         position_[1] = arenaY + 1;
00391                         break;
00392                 case CollisionIdWallBottom:
00393                         position_[1] = arenaY + arenaHeight - 1;
00394                         break;
00395                 }
00396 
00397                 return CollisionActionBounce;
00398                 break;
00399         case CollisionIdLandscape:
00400                 return CollisionActionCollision;
00401                 break;
00402         }
00403         return CollisionActionNone;
00404 }
00405 
00406 bool PhysicsParticleObject::getLandscapeCollision(CollisionInfo &collision)
00407 {
00408         // Check for collision with the ground
00409         // (or underground collision if applicable)
00410         fixed landHeight = 
00411                 context_->getLandscapeMaps().getGroundMaps().
00412                         getInterpHeight(position_[0], position_[1]);
00413         if (underGroundCollision_)
00414         {
00415                 if (position_[2] <= 0) 
00416                 {
00417                         collision.collisionId = CollisionIdLandscape;
00418                         collision.deflectFactor = 1;
00419                         collision.normal = FixedVector(0, 0, -1);
00420                         return true;
00421                 }
00422                 if (position_[2] >= landHeight)
00423                 {
00424                         collision.collisionId = CollisionIdLandscape;
00425                         collision.deflectFactor = 1;
00426                         context_->getLandscapeMaps().getGroundMaps().
00427                                 getInterpNormal(position_[0], position_[1], collision.normal);
00428                         collision.normal = -collision.normal;
00429                         return true;
00430                 }
00431         }
00432         else
00433         {
00434                 if (position_[2] <= 0)
00435                 {
00436                         collision.collisionId = CollisionIdLandscape;
00437                         collision.deflectFactor = 1;
00438                         collision.normal = FixedVector(0, 0, 1);
00439                         return true;
00440                 }
00441                 if (position_[2] <= landHeight)
00442                 {
00443                         collision.collisionId = CollisionIdLandscape;
00444                         collision.deflectFactor = 1;
00445                         context_->getLandscapeMaps().getGroundMaps().
00446                                 getInterpNormal(position_[0], position_[1], collision.normal);
00447                         return true;
00448                 }
00449         }
00450         return false;
00451 }
00452 
00453 bool PhysicsParticleObject::getRoofCollision(CollisionInfo &collision)
00454 {
00455         // This will return MAX_FLT when there is no roof
00456         fixed maxHeight = context_->getLandscapeMaps().getRoofMaps().getInterpRoofHeight(
00457                 position_[0], position_[1]);
00458         if (position_[2] >= maxHeight)
00459         {
00460                 collision.collisionId = CollisionIdRoof;
00461                 collision.deflectFactor = 1;
00462                 collision.normal = FixedVector(0, 0, -1);
00463                 return true;
00464         }
00465         return false;
00466 }
00467 
00468 bool PhysicsParticleObject::getWallCollision(CollisionInfo &collision)
00469 {
00470         // Check for collision with the walls (if enabled)
00471         if (context_->getOptionsTransient().getWallType() == OptionsTransient::wallNone)
00472         {
00473                 return false;
00474         }
00475 
00476         // Check if we collide with walls
00477         if (!wallCollision_) return false;
00478 
00479         int arenaX = context_->getLandscapeMaps().getGroundMaps().getArenaX();
00480         int arenaY = context_->getLandscapeMaps().getGroundMaps().getArenaY();
00481         int arenaWidth = context_->getLandscapeMaps().getGroundMaps().getArenaWidth();
00482         int arenaHeight = context_->getLandscapeMaps().getGroundMaps().getArenaHeight();
00483         if (position_[0] <= arenaX)
00484         {
00485                 collision.collisionId = CollisionIdWallLeft;
00486                 collision.deflectFactor = 1;
00487                 collision.normal = FixedVector(1, 0, 0);
00488                 return true;
00489         }
00490         else if (position_[0] >= arenaX + arenaWidth)
00491         {
00492                 collision.collisionId = CollisionIdWallRight;
00493                 collision.deflectFactor = 1;
00494                 collision.normal = FixedVector(-1, 0, 0);
00495                 return true;
00496         }
00497         else if (position_[1] <= arenaY)
00498         {
00499                 collision.collisionId = CollisionIdWallTop;
00500                 collision.deflectFactor = 1;
00501                 collision.normal = FixedVector(0, 1, 0);
00502                 return true;
00503         }
00504         else if (position_[1] >= arenaY + arenaHeight)
00505         {
00506                 collision.collisionId = CollisionIdWallBottom;
00507                 collision.deflectFactor = 1;
00508                 collision.normal = FixedVector(0, -1, 0);
00509                 return true;
00510         }
00511         return false;
00512 }
00513 
00514 bool PhysicsParticleObject::getShieldCollision(CollisionInfo &collision, Target *target)
00515 {
00516         if (!target) return false;
00517 
00518         // Get the shield
00519         Accessory *shieldAcc = target->getShield().getCurrentShield();                  
00520         if (!shieldAcc) return false;
00521         Shield *shield = (Shield *) shieldAcc->getAction();
00522 
00523         // Check if this is the shield of the current tank/target
00524         if (target->getPlayerId() == info_.playerId_)
00525         {
00526                 return false;
00527         }
00528 
00529         // Is this tank in the shield
00530         // This should always be a tank as it is the one firing
00531         Tank *shotTank = context_->getTankContainer().getTankById(info_.playerId_);
00532         if (shotTank)
00533         {
00534                 FixedVector offset = shotTank->getPosition().getTankPosition() -
00535                         target->getLife().getTargetPosition();
00536                 if (shield->tankInShield(offset))
00537                 {
00538                         // We can ignore this shield as this tank is in the shield
00539                         return false;
00540                 }
00541         }
00542 
00543         // Check we are in this shield
00544         FixedVector direction = position_ - target->getLife().getTargetPosition();
00545         if (!shield->inShield(direction)) return false;
00546 
00547         // Perform the shield action
00548         switch (shield->getShieldType())
00549         {
00550         case Shield::ShieldTypeRoundMag:
00551                 collision.collisionId = CollisionIdShield;
00552                 collision.deflectFactor = 1;
00553                 collision.normal = FixedVector(0, 0, 1);
00554                 return true;
00555         case Shield::ShieldTypeRoundNormal:
00556         case Shield::ShieldTypeRoundReflective:
00557                 {
00558                         // Find the deflect factor
00559                         fixed deflectFactor = 1;
00560                         if (shield->getShieldType() == Shield::ShieldTypeRoundReflective)
00561                         {
00562                                 ShieldRoundReflective *squareRoundReflective = 
00563                                         (ShieldRoundReflective *) shield;
00564                                 deflectFactor = squareRoundReflective->getDeflectFactor();
00565                         }
00566 
00567                         collision.collisionId = CollisionIdShield;
00568                         collision.deflectFactor = deflectFactor;
00569                         collision.normal = (position_ - target->getLife().getTargetPosition()).Normalize();
00570                 }
00571                 return true;
00572         case Shield::ShieldTypeSquareReflective:
00573         case Shield::ShieldTypeSquareNormal:
00574                 {
00575                         // Find the deflect factor
00576                         fixed deflectFactor = 1;
00577                         if (shield->getShieldType() == Shield::ShieldTypeSquareReflective)
00578                         {
00579                                 ShieldSquareReflective *squareSquareReflective = 
00580                                         (ShieldSquareReflective *) shield;
00581                                 deflectFactor = squareSquareReflective->getDeflectFactor();
00582                         }
00583 
00584                         // Find the smallest penetration side
00585                         ShieldSquare *squareShield = (ShieldSquare *) shield;
00586                         FixedVector &size = squareShield->getSize();
00587 
00588                         fixed diff0 = size[0] - (direction[0].abs());
00589                         fixed diff1 = size[1] - (direction[1].abs());
00590                         fixed diff2 = size[2] - (direction[2].abs());
00591                         if (diff0 <= diff1 && diff0 <= diff2)
00592                         {
00593                                 if (direction[0] > 0) collision.normal = FixedVector(-1, 0, 0);
00594                                 else collision.normal = FixedVector(1, 0, 0);
00595                         }
00596                         if (diff1 <= diff0 && diff1 <= diff2)
00597                         {
00598                                 if (direction[1] > 0) collision.normal = FixedVector(0, -1, 0);
00599                                 else collision.normal = FixedVector(0, 1, 0);
00600                         }
00601                         if (diff2 <= diff0 && diff2 <= diff1)
00602                         {
00603                                 if (direction[2] > 0) collision.normal = FixedVector(0, 0, -1);
00604                                 else collision.normal = FixedVector(0, 0, 1);
00605                         }
00606 
00607                         collision.collisionId = CollisionIdShield;
00608                         collision.deflectFactor = deflectFactor;
00609                 }
00610                 return true;
00611         }
00612 
00613         return false;
00614 }
00615 
00616 bool PhysicsParticleObject::getTargetCollision(CollisionInfo &collision, Target *target)
00617 {
00618         if (!target) return false;
00619 
00620         // We cannot collide with ourselves
00621         if (target->getPlayerId() == info_.playerId_) return false;
00622 
00623         // Check we are in this target
00624         if (target->getLife().collision(position_))
00625         {
00626                 collision.normal = (position_ - target->getLife().getCenterPosition()).Normalize();     
00627                 collision.deflectFactor = 1;
00628                 collision.collisionId = CollisionIdTarget;
00629                 return true;
00630         }
00631         
00632         return false;
00633 }
00634 
00635 bool PhysicsParticleObject::getTargetBounceCollision(CollisionInfo &collision, Target *target)
00636 {
00637         if (info_.type_ != ParticleTypeBounce) return false;
00638 
00639         // A special case, to add some width to the bounce particle to make it easier
00640         // to hit targets with
00641         std::map<unsigned int, Target *> collisionTargets;
00642         context_->getTargetSpace().getCollisionSet(position_, 1, collisionTargets, false);
00643         std::map<unsigned int, Target *>::iterator itor;
00644         for (itor = collisionTargets.begin();
00645                 itor != collisionTargets.end();
00646                 itor++)
00647         {
00648                 Target *target = (*itor).second;
00649                 if (target->getLife().collision(position_) ||
00650                         target->getLife().collisionDistance(position_) < 1)
00651                 {
00652                         collision.normal = (position_ - target->getLife().getCenterPosition()).Normalize();     
00653                         collision.deflectFactor = 1;
00654                         collision.collisionId = CollisionIdTarget;
00655                         return true;
00656                 }
00657         }
00658 
00659         return false;
00660 }
00661 
00662 void PhysicsParticleObject::shotShieldHit(Target *target)
00663 {
00664 }
00665 
00666 void PhysicsParticleObject::bounceShieldHit(Target *target)
00667 {
00668 }
00669 
00670 void PhysicsParticleObject::shotWallHit(CollisionInfo &collision)
00671 {
00672 }
00673 
00674 PhysicsParticleActionObject::PhysicsParticleActionObject()
00675 {
00676 }
00677 
00678 PhysicsParticleActionObject::~PhysicsParticleActionObject()
00679 {
00680 }
00681 
00682 void PhysicsParticleActionObject::shotShieldHit(Target *target)
00683 {
00684         Shield *shield = (Shield *) target->getShield().getCurrentShield()->getAction();
00685         ShotProjectile *shot = (ShotProjectile *) info_.data_;
00686         fixed hurtFactor = shot->getWeapon()->getShieldHurtFactor(*context_);
00687         if (hurtFactor > 0)
00688         {
00689                 if (shield->getShieldType() != Shield::ShieldTypeRoundMag)
00690                 {
00691                         context_->getActionController().addAction(
00692                                 new ShieldHit(target->getPlayerId(),
00693                                         position_,
00694                                         hurtFactor));
00695                 }
00696                 else
00697                 {
00698                         target->getShield().setShieldPower(
00699                                 target->getShield().getShieldPower() -
00700                                 shield->getHitRemovePower() * hurtFactor);
00701                 }
00702         }
00703 }
00704 
00705 void PhysicsParticleActionObject::bounceShieldHit(Target *target)
00706 {
00707         Shield *shield = (Shield *) target->getShield().getCurrentShield()->getAction();
00708         ShotBounce *shot = (ShotBounce *) info_.data_;
00709         fixed hurtFactor = shot->getWeapon()->getShieldHurtFactor(*context_);
00710         if (shield->getShieldType() != Shield::ShieldTypeRoundMag && hurtFactor > 0)
00711         {
00712                 context_->getActionController().addAction(
00713                         new ShieldHit(target->getPlayerId(),
00714                                 position_,
00715                                 hurtFactor));
00716         }
00717 }
00718 
00719 #ifndef S3D_SERVER
00720 
00721 #include <client/ScorchedClient.h>
00722 #include <graph/ParticleEmitter.h>
00723 
00724 static void addWallCollisionParticle(Vector &position, ScorchedCollisionId collisionId)
00725 {
00726         Vector color(1.0f, 1.0f, 1.0f);
00727         ParticleEmitter emitter;
00728         emitter.setAttributes(
00729                 8.5f, 8.0f, // Life
00730                 0.2f, 0.5f, // Mass
00731                 0.01f, 0.02f, // Friction
00732                 Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 0.0f, 0.0f), // Velocity
00733                 color, 1.0f, // StartColor1
00734                 color, 1.0f, // StartColor2
00735                 color, 0.0f, // EndColor1
00736                 color, 0.0f, // EndColor2
00737                 2.0f, 2.0f, 2.0f, 2.0f, // Start Size
00738                 2.0f, 2.0f, 2.0f, 2.0f, // EndSize
00739                 Vector(0.0f, 0.0f, 0.0f), // Gravity
00740                 false,
00741                 false);
00742 
00743         switch (collisionId)
00744         {
00745         case CollisionIdWallLeft:
00746                 emitter.emitWallHit(position,
00747                         ScorchedClient::instance()->getParticleEngine(),
00748                         OptionsTransient::LeftSide);
00749                 break;
00750         case CollisionIdWallRight:
00751                 emitter.emitWallHit(position,
00752                         ScorchedClient::instance()->getParticleEngine(),
00753                         OptionsTransient::RightSide);
00754                 break;
00755         case CollisionIdWallTop:
00756                 emitter.emitWallHit(position,
00757                         ScorchedClient::instance()->getParticleEngine(),
00758                         OptionsTransient::TopSide);
00759                 break;
00760         case CollisionIdWallBottom:
00761                 emitter.emitWallHit(position,
00762                         ScorchedClient::instance()->getParticleEngine(),
00763                         OptionsTransient::BotSide);
00764                 break;
00765         }
00766 }
00767 #endif
00768 
00769 void PhysicsParticleActionObject::shotWallHit(CollisionInfo &collision)
00770 {
00771 #ifndef S3D_SERVER
00772                 addWallCollisionParticle(position_.asVector(), collision.collisionId);
00773 #endif
00774 }

Generated on Mon Feb 16 15:14:49 2009 for Scorched3D by  doxygen 1.5.3