00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
00080 FixedVector collisionNormal;
00081 FixedVector newVelocity;
00082 if (checkCollision(collisionNormal))
00083 {
00084
00085 newVelocity = collisionNormal / 10;
00086 }
00087 else
00088 {
00089 if (complexUpdate)
00090 {
00091 newVelocity = checkGrouping(boidSet);
00092 }
00093
00094
00095 {
00096 fixed cruiseDiff = world_->getCruiseVelocity() - directionMag_;
00097 fixed cruiseChange = cruiseDiff / 10;
00098 newVelocity += direction_ * cruiseDiff;
00099 }
00100
00101
00102 {
00103 newVelocity[2] -= getVelocity()[2] / 100;
00104 }
00105 }
00106
00107
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 }