Boid2.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 <movement/Boid2.h>
00022 #include <movement/TargetMovementEntryBoids.h>
00023 #include <common/OptionsScorched.h>
00024 #include <landscapemap/LandscapeMaps.h>
00025 #include <engine/ScorchedContext.h>
00026 #include <engine/ActionController.h>
00027 #include <target/Target.h>
00028 #include <target/TargetLife.h>
00029 
00030 Boid2::Boid2(ScorchedContext &context, Target *target, TargetMovementEntryBoids *world) :
00031         context_(context), target_(target), world_(world)
00032 {
00033 }
00034 
00035 Boid2::~Boid2()
00036 {
00037 }
00038 
00039 FixedVector &Boid2::getPosition()
00040 {
00041         static FixedVector result;
00042         if (target_) return target_->getLife().getTargetPosition();
00043         return result;
00044 }
00045 
00046 FixedVector &Boid2::getVelocity()
00047 {
00048         static FixedVector result;
00049         if (target_) return target_->getLife().getVelocity();
00050         return result;
00051 }
00052 
00053 void Boid2::clearTarget()
00054 {
00055         target_ = 0;
00056 }
00057 
00058 void Boid2::update(fixed frameTime, std::vector<Boid2*> &boidSet, bool complexUpdate)
00059 {
00060         // Limit Velocity
00061         directionMag_ = getVelocity().Magnitude();
00062         direction_ = getVelocity() / directionMag_;
00063         if (directionMag_ > world_->getMaxVelocity()) 
00064         {
00065                 getVelocity() = direction_ * world_->getMaxVelocity();
00066                 directionMag_ = world_->getMaxVelocity();
00067         }
00068 
00069         // Update position and rotation
00070         if (target_)
00071         {
00072                 fixed yaw = atan2x(getVelocity()[0], getVelocity()[1]);
00073                 fixed newRotation = -fixed(yaw) / fixed::XPI * 180;
00074 
00075                 FixedVector newPosition = getPosition() + getVelocity();
00076                 target_->getLife().setTargetPositionAndRotation(newPosition, newRotation);
00077         }
00078 
00079         // Calculate new velocity
00080         FixedVector collisionNormal;
00081         FixedVector newVelocity;
00082         if (checkCollision(collisionNormal))
00083         {
00084                 // Collision
00085                 newVelocity = collisionNormal / 10;
00086         }
00087         else
00088         {
00089                 if (complexUpdate)
00090                 {
00091                         newVelocity = checkGrouping(boidSet);
00092                 }
00093 
00094                 // Wander
00095                 {
00096                         fixed cruiseDiff = world_->getCruiseVelocity() - directionMag_;
00097                         fixed cruiseChange = cruiseDiff / 10;
00098                         newVelocity += direction_ * cruiseDiff;
00099                 }
00100 
00101                 // Level out the flight
00102                 {
00103                         newVelocity[2] -= getVelocity()[2] / 100;
00104                 }
00105         }
00106 
00107         // Limit acceleration
00108         fixed velocityMag = newVelocity.Magnitude();
00109         if (velocityMag > world_->getMaxAcceleration())
00110         {
00111                 newVelocity.StoreNormalize();
00112                 newVelocity *= world_->getMaxAcceleration();
00113         }
00114 
00115         if (target_)
00116         {
00117                 newVelocity += getVelocity();
00118                 target_->getLife().setVelocity(newVelocity);
00119 
00120                 if (complexUpdate)
00121                 {
00122                         if (context_.getOptionsGame().getActionSyncCheck())
00123                         {
00124                                 context_.getActionController().addSyncCheck(
00125                                         S3D::formatStringBuffer("TargetMovement: %u %i, %i, %i %i, %i, %i", 
00126                                                 target_->getPlayerId(),
00127                                                 target_->getLife().getTargetPosition()[0].getInternal(),
00128                                                 target_->getLife().getTargetPosition()[1].getInternal(),
00129                                                 target_->getLife().getTargetPosition()[2].getInternal(),
00130                                                 target_->getLife().getVelocity()[0].getInternal(),
00131                                                 target_->getLife().getVelocity()[1].getInternal(),
00132                                                 target_->getLife().getVelocity()[2].getInternal()));
00133                         }
00134                 }
00135         }
00136 }
00137 
00138 FixedVector Boid2::checkGrouping(std::vector<Boid2*> &boidSet)
00139 {
00140         FixedVector posMatch, velMatch, velDist;
00141         FixedVector normalizedVelocity = direction_;
00142 
00143         int count = 0, countDist = 0;
00144         std::vector<Boid2*>::iterator itor;
00145         for (itor = boidSet.begin(); itor != boidSet.end(); itor++)
00146         {
00147                 Boid2 *other = (Boid2 *) *itor;
00148                 if (!other || other == this) continue; 
00149 
00150                 FixedVector direction = getPosition() - other->getPosition();
00151                 fixed distance = direction.Magnitude();
00152                 FixedVector normalizedDirection = direction / distance;
00153                 fixed dp = normalizedDirection.dotP(normalizedVelocity);
00154                 if (dp.abs() < fixed(true, 3000))
00155                 {
00156                         count++;
00157 
00158                         posMatch += other->getPosition();
00159                         velMatch += other->getVelocity();
00160 
00161                         if (distance < world_->getCruiseDistance())
00162                         {
00163                                 velDist += direction;
00164                                 countDist++;
00165                         }
00166                 }
00167         }
00168 
00169         if (countDist > 0)
00170         {
00171                 velDist /= countDist;
00172                 velDist /= 10;
00173         }
00174 
00175         if (count > 0)
00176         {
00177                 posMatch /= count;
00178                 posMatch = (posMatch - getPosition()) / 10;
00179 
00180                 velMatch /= count;
00181                 velMatch = (velMatch - getVelocity()) / 10;
00182         }
00183 
00184         FixedVector velocity;
00185         velocity += posMatch;
00186         velocity += velMatch;
00187         velocity += velDist;
00188         return velocity;
00189 }
00190 
00191 bool Boid2::checkCollision(FixedVector &normal)
00192 {
00193         int collision = 0;
00194         FixedVector &position = getPosition();
00195         if (position[0] < world_->getMinBounds()[0])
00196         {
00197                 collision++;
00198                 normal += FixedVector(1, 0, 0);
00199         }
00200         else if (position[0] > world_->getMaxBounds()[0])
00201         {
00202                 collision++;
00203                 normal += FixedVector(-1, 0, 0);
00204         }
00205 
00206         if (position[1] < world_->getMinBounds()[1])
00207         {
00208                 collision++;
00209                 normal += FixedVector(0, 1, 0);
00210         }
00211         else if (position[1] > world_->getMaxBounds()[1])
00212         {
00213                 collision++;
00214                 normal += FixedVector(0, -1, 0);
00215         }
00216 
00217         if (position[2] < world_->getMinBounds()[2])
00218         {
00219                 collision++;
00220                 normal += FixedVector(0, 0, 1);
00221         }
00222         else if (position[2] > world_->getMaxBounds()[2])
00223         {
00224                 collision++;
00225                 normal += FixedVector(0, 0, -1);
00226         }
00227 
00228         for (int i=0; i<4; i++)
00229         {
00230                 fixed dist = fixed(i) * 3;
00231                 FixedVector newPosition = position + direction_ * dist;
00232 
00233                 if (context_.getLandscapeMaps().getGroundMaps().getHeight(
00234                         newPosition[0].asInt(), newPosition[1].asInt()) > newPosition[2] - fixed(5))
00235                 {
00236                         collision++;
00237                         normal += context_.getLandscapeMaps().getGroundMaps().getNormal(
00238                                 newPosition[0].asInt(), newPosition[1].asInt());
00239                         break;
00240                 }
00241         }
00242 
00243         if (collision > 0)
00244         {
00245                 normal.StoreNormalize();
00246                 return true;
00247         }
00248 
00249         return false;
00250 }

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