MovementMap.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 <landscapemap/MovementMap.h>
00022 #include <landscapemap/LandscapeMaps.h>
00023 #include <landscapedef/LandscapeTex.h>
00024 #include <landscapedef/LandscapeDefn.h>
00025 #include <weapons/AccessoryStore.h>
00026 #include <weapons/Shield.h>
00027 #include <weapons/WeaponMoveTank.h>
00028 #include <target/TargetContainer.h>
00029 #include <engine/ScorchedContext.h>
00030 #include <common/FixedVector.h>
00031 #include <common/OptionsScorched.h>
00032 #include <common/Defines.h>
00033 #include <tank/TankContainer.h>
00034 #include <tank/TankPosition.h>
00035 #include <tank/TankAccessories.h>
00036 #include <target/TargetShield.h>
00037 #include <target/TargetLife.h>
00038 #include <target/TargetSpace.h>
00039 #include <image/ImageFactory.h>
00040 #include <memory.h>
00041 
00042 MovementMap::MovementMap(
00043         Tank *tank, 
00044         ScorchedContext &context) :
00045         tank_(tank), context_(context)
00046 {
00047         arenaX_ = context_.getLandscapeMaps().getGroundMaps().getArenaX();
00048         arenaY_ = context_.getLandscapeMaps().getGroundMaps().getArenaY();
00049         arenaWidth_ = context_.getLandscapeMaps().getGroundMaps().getArenaWidth();
00050         arenaHeight_ = context_.getLandscapeMaps().getGroundMaps().getArenaHeight();
00051         landscapeWidth_ = context_.getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00052         landscapeHeight_ = context_.getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00053 
00054         // Create the empty movement map
00055         entries_ = new MovementMapEntry[(landscapeWidth_ + 1) * (landscapeHeight_ + 1)];
00056         memset(entries_, (int) eNotInitialized, sizeof(MovementMapEntry) * (landscapeWidth_ + 1) * (landscapeHeight_ + 1));
00057 
00058         // Get the minimum height we are allowed to move to
00059         minHeight_ = getWaterHeight();
00060 
00061         // Generate a list of all of the targets we need to check
00062         // to see if we are in their shields
00063         std::map<unsigned int, Target *>::iterator targetItor;
00064         std::map<unsigned int, Target *> &targets = 
00065                 context.getTargetContainer().getTargets();
00066         for (targetItor = targets.begin(); 
00067                 targetItor != targets.end();
00068                 targetItor++)
00069         {
00070                 Target *target = (*targetItor).second;
00071                 if (movementProof(context, target, tank))
00072                 {
00073                         checkTargets_.push_back(target);
00074                 }
00075         }
00076 }
00077 
00078 MovementMap::~MovementMap()
00079 {
00080         delete [] entries_;
00081         entries_ = 0;
00082 }
00083 
00084 unsigned int MovementMap::POINT_TO_UINT(unsigned int x, unsigned int y)
00085 {
00086         return (x << 16) | (y & 0xffff);
00087 }
00088 
00089 MovementMap::MovementMapEntry &MovementMap::getEntry(int w, int h)
00090 { 
00091         if (w>=arenaX_ && h>=arenaY_ && w<=arenaX_ + arenaWidth_ && h<=arenaY_ + arenaHeight_)
00092         {
00093                 MovementMapEntry &entry = entries_[(landscapeWidth_+1) * h + w];
00094                 return entry;
00095         }
00096         static MovementMapEntry entry(eNoMovement, fixed(1000), 0, 0);
00097         entry.type = eNoMovement;
00098 
00099         return entry;
00100 }
00101 
00102 MovementMap::MovementMapEntry &MovementMap::getAndCheckEntry(int w, int h)
00103 {
00104         MovementMapEntry &entry = getEntry(w, h);
00105 
00106         // This entry has not been checked
00107         if (entry.type == eNotInitialized)
00108         {
00109                 fixed height = 
00110                         context_.getLandscapeMaps().getGroundMaps().getHeight(w, h);
00111                 FixedVector position(w, h, height);
00112                 entry.type = eNotSeen;
00113 
00114                 // Check if this position is below water level
00115                 if (height < minHeight_)
00116                 {
00117                         entry.type = eNoMovement;
00118                 }
00119                 else
00120                 {
00121                         // Check if this position is inside any shields
00122                         std::list<Target *>::iterator targetItor;
00123                         for (targetItor = checkTargets_.begin(); 
00124                                 targetItor != checkTargets_.end();
00125                                 targetItor++)
00126                         {
00127                                 Target *target = (*targetItor);
00128                                 if (inShield(target, tank_, position))
00129                                 {
00130                                         entry.type = eNoMovement;
00131                                         break;
00132                                 }
00133                         }
00134                 }
00135         }
00136         return entry;
00137 }
00138 
00139 void MovementMap::addPoint(unsigned int x, unsigned int y, 
00140                                          fixed height, fixed dist,
00141                                          std::list<unsigned int> &edgeList,
00142                                          unsigned int sourcePt,
00143                                          unsigned int epoc)
00144 {
00145         // Check that we are not going outside the arena
00146         if (x < (unsigned int) (arenaX_ + 5) || 
00147                 y < (unsigned int) (arenaY_ + 5) ||
00148                 x > (unsigned int) (arenaX_ + arenaWidth_ - 5) ||
00149                 y > (unsigned int) (arenaY_ + arenaHeight_ - 5)) return;
00150 
00151         // Check if we can already reach this point
00152         // Through a shorted already visited path
00153         // That is not a current edge point
00154         MovementMapEntry &priorEntry = getAndCheckEntry(x, y);
00155 
00156         if (priorEntry.type == eNoMovement)
00157         {
00158                 return;
00159         }
00160         if (priorEntry.type == eMovement &&
00161                 priorEntry.epoc < epoc)
00162         {
00163                 return;
00164         }
00165 
00166         // Find how much the tank has to climb to reach this new point
00167         // check that this is acceptable
00168         fixed newHeight = context_.getLandscapeMaps().getGroundMaps().getHeight(
00169                 x, y);
00170 
00171         // Check water height 
00172         if (newHeight < minHeight_) 
00173         {
00174                 return; 
00175         }
00176 
00177         // Check climing height
00178         fixed MaxTankClimbHeight = fixed(context_.getOptionsGame().
00179                 getMaxClimbingDistance()) / fixed(10);
00180         if (newHeight - height > MaxTankClimbHeight) 
00181         {
00182                 return;
00183         }
00184 
00185         // Check if we can also reach this point from another edge point
00186         if (priorEntry.epoc == epoc)
00187         {
00188                 // Check if this prior edge is further than the current
00189                 if (dist < priorEntry.dist)
00190                 {
00191                         // If so set the distance etc
00192                         priorEntry = MovementMap::MovementMapEntry(
00193                                 MovementMap::eMovement,
00194                                 dist,
00195                                 sourcePt,
00196                                 epoc);
00197                 }
00198         }
00199         else
00200         {
00201                 // Add this new edge to the list of edges
00202                 unsigned int pt = POINT_TO_UINT(x, y);
00203 
00204                 // Set the distance etc
00205                 edgeList.push_back(pt);
00206                 priorEntry = MovementMap::MovementMapEntry(
00207                         MovementMap::eMovement,
00208                         dist,
00209                         sourcePt,
00210                         epoc);
00211         }
00212 }
00213 
00214 bool MovementMap::movementProof(ScorchedContext &context, Target *target, Tank *tank)
00215 {
00216         if (!target->getAlive() ||
00217                 !target->getShield().getCurrentShield()) return false;
00218 
00219         Shield *shield = (Shield *)
00220                 (target->getShield().getCurrentShield()->getAction());
00221 
00222         bool movementProof = true;
00223         switch (shield->getMovementProof())
00224         {
00225         case Shield::ShieldMovementAll:
00226                 movementProof = false;
00227                 break;
00228         case Shield::ShieldMovementNone:
00229                 movementProof = true;
00230                 break;
00231         case Shield::ShieldMovementSame:
00232                 if (target->getPlayerId() == tank->getPlayerId())
00233                 {
00234                         movementProof = false;
00235                 }
00236                 else if (context.getOptionsGame().getTeams() > 1 &&
00237                         !target->isTarget())
00238                 {
00239                         Tank *targetTank = (Tank *) target;
00240                         if (targetTank->getTeam() == tank->getTeam())
00241                         {
00242                                 movementProof = false;
00243                         }
00244                 }
00245                 break;
00246         case Shield::ShieldMovementTeam1:
00247                 if (tank->getTeam() == 1 ||
00248                         tank->getTeam() == 0) movementProof = false;
00249                 break;
00250         case Shield::ShieldMovementTeam2:
00251                 if (tank->getTeam() == 2 ||
00252                         tank->getTeam() == 0) movementProof = false;
00253                 break;
00254         case Shield::ShieldMovementTeam3:
00255                 if (tank->getTeam() == 3 ||
00256                         tank->getTeam() == 0) movementProof = false;
00257                 break;
00258         case Shield::ShieldMovementTeam4:
00259                 if (tank->getTeam() == 4 ||
00260                         tank->getTeam() == 0) movementProof = false;
00261                 break;
00262         }
00263         return movementProof;
00264 }
00265 
00266 bool MovementMap::inShield(Target *target, Tank *tank, FixedVector &position)
00267 {
00268         Shield *shield = (Shield *)
00269                 (target->getShield().getCurrentShield()->getAction());
00270 
00271         FixedVector offset = position - target->getLife().getTargetPosition();
00272         offset[0] = offset[0].abs();
00273         offset[1] = offset[1].abs();
00274         offset[2] = fixed(0);
00275         FixedVector surround = offset.Normalize() * fixed(2);
00276         offset[0] = MAX(fixed(0), offset[0] - surround[0]);
00277         offset[1] = MAX(fixed(0), offset[1] - surround[1]);
00278 
00279         return shield->inShield(offset);
00280 }
00281 
00282 bool MovementMap::allowedPosition(ScorchedContext &context, Tank *tank, FixedVector &position)
00283 {
00284         std::map<unsigned int, Target *>::iterator targetItor;
00285         std::map<unsigned int, Target *> targets;
00286         context.getTargetSpace().getCollisionSet(position, fixed(1), targets);
00287         for (targetItor = targets.begin(); 
00288                 targetItor != targets.end();
00289                 targetItor++)
00290         {
00291                 Target *target = (*targetItor).second;
00292 
00293                 if (movementProof(context, target, tank) &&
00294                         inShield(target, tank, position))
00295                 {
00296                         return false;
00297                 }
00298         }
00299         return true;
00300 }
00301 
00302 fixed MovementMap::getWaterHeight()
00303 {
00304         // Calculate the water height
00305         fixed waterHeight = (-10);
00306         if (context_.getOptionsGame().getMovementRestriction() ==
00307                 OptionsGame::MovementRestrictionLand ||
00308                 context_.getOptionsGame().getMovementRestriction() ==
00309                 OptionsGame::MovementRestrictionLandOrAbove)
00310         {
00311                 LandscapeTex &tex = *context_.getLandscapeMaps().getDefinitions().getTex();
00312                 if (tex.border->getType() == LandscapeTexType::eWater)
00313                 {
00314                         LandscapeTexBorderWater *water = 
00315                                 (LandscapeTexBorderWater *) tex.border;
00316 
00317                         waterHeight = water->height;
00318                 }
00319         }
00320 
00321         if (context_.getOptionsGame().getMovementRestriction() ==
00322                 OptionsGame::MovementRestrictionLandOrAbove)
00323         {
00324                 if (waterHeight > tank_->getPosition().getTankPosition()[2] - fixed(true, 1000))
00325                 {
00326                         waterHeight = tank_->getPosition().getTankPosition()[2] - fixed(true, 1000);
00327                 }
00328         }
00329         return waterHeight;
00330 }
00331 
00332 fixed MovementMap::getFuel(WeaponMoveTank *weapon)
00333 {
00334         fixed fuel = fixed(0);
00335         int numberFuel = tank_->getAccessories().getAccessoryCount(weapon->getParent());
00336         if (numberFuel == -1)
00337         {
00338                 fuel = weapon->getMaximumRange();
00339         }
00340         else
00341         {
00342                 fuel = MIN(weapon->getMaximumRange(), numberFuel);
00343         }
00344         return fuel;
00345 }
00346 
00347 bool MovementMap::tankBurried()
00348 {
00349         fixed landscapeHeight = context_.getLandscapeMaps().getGroundMaps().getInterpHeight(
00350                 tank_->getPosition().getTankPosition()[0],
00351                 tank_->getPosition().getTankPosition()[1]);
00352         fixed tankHeight = 
00353                 tank_->getPosition().getTankPosition()[2];
00354         fixed MaxTankClimbHeight = fixed(context_.getOptionsGame().
00355                 getMaxClimbingDistance()) / fixed(10);
00356         if (landscapeHeight > tankHeight + MaxTankClimbHeight)
00357         {
00358                 return true;
00359         }
00360         return false;
00361 }
00362 
00363 bool MovementMap::QueuePosition::operator<(const QueuePosition &rhs) const
00364 {
00365         return fixed(distance) > fixed(rhs.distance);
00366 }
00367 
00368 fixed inline calcDistance(unsigned int pt, FixedVector &position)
00369 {
00370         unsigned int x = pt >> 16;
00371         unsigned int y = pt & 0xffff;
00372         FixedVector pos1((int) x, (int) y, 0);
00373         FixedVector pos2(position[0], position[1], 0);
00374         return (pos1-pos2).Magnitude();
00375 }
00376 
00377 void MovementMap::addPoint(unsigned int x, unsigned int y, 
00378          fixed height, fixed dist,
00379          std::priority_queue<QueuePosition, 
00380                 std::vector<QueuePosition>, 
00381                 std::less<QueuePosition> > &priorityQueue,
00382          unsigned int sourcePt,
00383          FixedVector &position)
00384 {
00385         // Check that we are not going outside the arena
00386         if (x < (unsigned int) (arenaX_ + 5) || 
00387                 y < (unsigned int) (arenaY_ + 5) ||
00388                 x > (unsigned int) (arenaX_ + arenaWidth_ - 5) ||
00389                 y > (unsigned int) (arenaY_ + arenaHeight_ - 5)) return;
00390 
00391         // Check if we can already reach this point
00392         // through a shorter already visited path
00393         MovementMapEntry &priorEntry = getAndCheckEntry(x, y);
00394 
00395         if (priorEntry.type == eNoMovement ||
00396                 priorEntry.type == eMovement) return;
00397 
00398         // Find how much the tank has to climb to reach this new point
00399         // check that this is acceptable
00400         fixed newHeight = context_.getLandscapeMaps().getGroundMaps().getHeight(x, y);
00401 
00402         // Check water height 
00403         if (newHeight < minHeight_) return; 
00404 
00405         // Check climing height
00406         fixed MaxTankClimbHeight = fixed(context_.getOptionsGame().
00407                 getMaxClimbingDistance()) / fixed(10);
00408         if (newHeight - height > MaxTankClimbHeight) return;
00409 
00410         // Add this new edge to the list of edges
00411         unsigned int pt = POINT_TO_UINT(x, y);
00412         QueuePosition queuePosition;
00413         queuePosition.square = pt;
00414         queuePosition.distance = calcDistance(pt, position) + dist;
00415         priorityQueue.push(queuePosition);
00416 
00417         // Set the distance etc
00418         priorEntry = MovementMap::MovementMapEntry(
00419                 MovementMap::eMovement,
00420                 dist,
00421                 sourcePt,
00422                 0);
00423 }
00424 
00425 bool MovementMap::calculatePosition(FixedVector &position, fixed fuel)
00426 {
00427         // Check if the tank is buried and cannot move
00428         if (tankBurried()) return false;
00429 
00430         // A very clever weighted queue thingy
00431         std::priority_queue<QueuePosition, 
00432                 std::vector<QueuePosition>, 
00433                 std::less<QueuePosition> > priorityQueue;
00434 
00435         // Setup movement variables
00436         unsigned int posX = (unsigned int) 
00437                 tank_->getPosition().getTankPosition()[0].asInt();
00438         unsigned int posY = (unsigned int) 
00439                 tank_->getPosition().getTankPosition()[1].asInt();
00440         unsigned int startPt = POINT_TO_UINT(posX, posY);
00441         unsigned int endPt = POINT_TO_UINT(
00442                 (unsigned int)position[0].asInt(), 
00443                 (unsigned int)position[1].asInt());
00444 
00445         // Check we can move at all
00446         if (getAndCheckEntry(posX, posY).type == eNotSeen)
00447         {
00448                 // Add this point to the movement map
00449                 getEntry(posX, posY) = 
00450                         MovementMap::MovementMapEntry(
00451                                 MovementMap::eMovement,
00452                                 fixed(0),
00453                                 0,
00454                                 0);
00455 
00456                 // And add it to the list of next edge points
00457                 QueuePosition queuePosition;
00458                 queuePosition.square = startPt;
00459                 queuePosition.distance = calcDistance(startPt, position);
00460                 priorityQueue.push(queuePosition);
00461         }
00462 
00463         // Itterate
00464         while (!priorityQueue.empty())
00465         {
00466                 QueuePosition queuePosition = priorityQueue.top();
00467                 priorityQueue.pop();
00468 
00469                 unsigned int pt = queuePosition.square;
00470                 unsigned int x = pt >> 16;
00471                 unsigned int y = pt & 0xffff;
00472 
00473                 if (pt == endPt) return true;
00474 
00475                 MovementMapEntry &priorEntry = getAndCheckEntry(x, y);
00476                 fixed dist = priorEntry.dist;
00477                 if (dist <= fuel)
00478                 {
00479                         fixed height = 
00480                                 context_.getLandscapeMaps().getGroundMaps().getHeight(x, y);
00481 
00482                         addPoint(x+1, y, height, dist + 1, priorityQueue, pt, position);
00483                         addPoint(x, y+1, height, dist + 1, priorityQueue, pt, position);
00484                         addPoint(x-1, y, height, dist + 1, priorityQueue, pt, position);
00485                         addPoint(x, y-1, height, dist + 1, priorityQueue, pt, position);
00486                         addPoint(x+1, y+1, height, dist + fixed(true, 14000), priorityQueue, pt, position);
00487                         addPoint(x-1, y+1, height, dist + fixed(true, 14000), priorityQueue, pt, position);
00488                         addPoint(x-1, y-1, height, dist + fixed(true, 14000), priorityQueue, pt, position);
00489                         addPoint(x+1, y-1, height, dist + fixed(true, 14000), priorityQueue, pt, position);
00490                 }
00491         }
00492 
00493         return false;
00494 }
00495 
00496 void MovementMap::calculateAllPositions(fixed fuel)
00497 {
00498         // Check if the tank is buried and cannot move
00499         if (tankBurried()) return;
00500 
00501         std::list<unsigned int> edgeList;
00502         unsigned int epoc = 0;
00503 
00504         // Setup movement variables
00505         unsigned int posX = (unsigned int) 
00506                 tank_->getPosition().getTankPosition()[0].asInt();
00507         unsigned int posY = (unsigned int) 
00508                 tank_->getPosition().getTankPosition()[1].asInt();
00509 
00510         // Check we can move at all
00511         if (getAndCheckEntry(posX, posY).type == eNotSeen)
00512         {
00513                 // Add this point to the movement map
00514                 getEntry(posX, posY) = 
00515                         MovementMap::MovementMapEntry(
00516                                 MovementMap::eMovement,
00517                                 fixed(0),
00518                                 0,
00519                                 epoc);
00520 
00521                 // And add it to the list of next edge points
00522                 unsigned int pt = POINT_TO_UINT(posX, posY);
00523                 edgeList.push_back(pt);
00524         }
00525 
00526         // Find all the edges for the current edges and so on
00527         while (!edgeList.empty())
00528         {
00529                 epoc++;
00530 
00531                 std::list<unsigned int> tmpEdgeList = edgeList;
00532                 edgeList.clear();
00533 
00534                 std::list<unsigned int>::iterator edgeItor;
00535                 for (edgeItor = tmpEdgeList.begin();
00536                         edgeItor != tmpEdgeList.end();
00537                         edgeItor++)
00538                 {
00539                         unsigned int pt = (*edgeItor);
00540                         unsigned int x = pt >> 16;
00541                         unsigned int y = pt & 0xffff;
00542 
00543                         MovementMapEntry &priorEntry = getAndCheckEntry(x, y);
00544                         fixed dist = priorEntry.dist;
00545                         if (dist <= fuel)
00546                         {
00547                                 fixed height = 
00548                                         context_.getLandscapeMaps().getGroundMaps().getHeight(x, y);
00549 
00550                                 addPoint(x+1, y, height, dist + 1, edgeList, pt, epoc);
00551                                 addPoint(x, y+1, height, dist + 1, edgeList, pt, epoc);
00552                                 addPoint(x-1, y, height, dist + 1, edgeList, pt, epoc);
00553                                 addPoint(x, y-1, height, dist + 1, edgeList, pt, epoc);
00554                                 addPoint(x+1, y+1, height, dist + fixed(true, 14000), edgeList, pt, epoc);
00555                                 addPoint(x-1, y+1, height, dist + fixed(true, 14000), edgeList, pt, epoc);
00556                                 addPoint(x-1, y-1, height, dist + fixed(true, 14000), edgeList, pt, epoc);
00557                                 addPoint(x+1, y-1, height, dist + fixed(true, 14000), edgeList, pt, epoc);
00558                         }
00559                 }
00560         }
00561 }
00562 
00563 #ifndef S3D_SERVER
00564 #include <landscape/Landscape.h>
00565 #include <client/ScorchedClient.h>
00566 
00567 void MovementMap::movementTexture()
00568 {
00569         ImageHandle newMap = ImageFactory::createBlank(
00570                 Landscape::instance()->getMainMap().getWidth(),
00571                 Landscape::instance()->getMainMap().getHeight());
00572 
00573         float landscapeWidth = (float)
00574                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00575         float landscpeHeight = (float)
00576                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00577 
00578         GLubyte *src = Landscape::instance()->getMainMap().getBits();
00579         GLubyte *dest = newMap.getBits();
00580         for (int y=0; y<newMap.getHeight(); y++)
00581         {
00582                 int y1 = y + 1;
00583                 if (y1 == newMap.getHeight()) y1--;
00584 
00585                 int posY = int(float(y) / float(newMap.getHeight()) * landscpeHeight);
00586                 int posY1 = int(float(y1) / float(newMap.getHeight()) * landscpeHeight);
00587                 for (int x=0; x<newMap.getWidth(); x++)
00588                 {
00589                         int x1 = x + 1;
00590                         if (x1 == newMap.getWidth()) x1--;
00591 
00592                         int posX = int(float(x) / float(newMap.getWidth()) * landscapeWidth);
00593                         int posX1 = int(float(x1) / float(newMap.getWidth()) * landscapeWidth);
00594 
00595                         MovementMapEntryType type1 = getEntry(posX1, posY).type;
00596                         MovementMapEntryType type2 = getEntry(posX, posY).type;
00597                         MovementMapEntryType type3 = getEntry(posX, posY1).type;
00598 
00599                         if ((type1 == eMovement && type2 != eMovement) || 
00600                                 (type1 != eMovement && type2 == eMovement) ||
00601                                 (type3 == eMovement && type2 != eMovement) || 
00602                                 (type3 != eMovement && type2 == eMovement))
00603                         {
00604                                 dest[0] = 255;
00605                                 dest[1] = 0;
00606                                 dest[2] = 0;
00607                         }
00608                         else if (type2 != eMovement)
00609                         {
00610                                 dest[0] = src[0] / 4;
00611                                 dest[1] = src[1] / 4;
00612                                 dest[2] = src[2] / 4;
00613                         }
00614                         else
00615                         {
00616                                 dest[0] = src[0];
00617                                 dest[1] = src[1];
00618                                 dest[2] = src[2];
00619                         }
00620 
00621                         src+=3;
00622                         dest+=3;
00623                 }
00624         }
00625 
00626         Landscape::instance()->getMainTexture().replace(newMap, false);
00627         Landscape::instance()->setTextureType(Landscape::eOther);
00628 }
00629 
00630 void MovementMap::limitTexture(FixedVector &center, int limit)
00631 {
00632         ImageHandle newMap = ImageFactory::createBlank(
00633                 Landscape::instance()->getMainMap().getWidth(),
00634                 Landscape::instance()->getMainMap().getHeight());
00635 
00636         float landscapeWidth = (float)
00637                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00638         float landscpeHeight = (float)
00639                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00640 
00641         int arenaX = 
00642                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaX();
00643         int arenaY = 
00644                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaY();
00645         int arenaWidth = 
00646                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaWidth();
00647         int arenaHeight = 
00648                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getArenaHeight();
00649 
00650         GLubyte *src = Landscape::instance()->getMainMap().getBits();
00651         GLubyte *dest = newMap.getBits();
00652         for (int y=0; y<newMap.getHeight(); y++)
00653         {
00654                 int y1 = y + 1;
00655                 if (y1 == newMap.getHeight()) y1--;
00656 
00657                 int posY = int(float(y) / float(newMap.getHeight()) * landscpeHeight);
00658                 int posY1 = int(float(y1) / float(newMap.getHeight()) * landscpeHeight);
00659                 for (int x=0; x<newMap.getWidth(); x++)
00660                 {
00661                         int x1 = x + 1;
00662                         if (x1 == newMap.getWidth()) x1--;
00663 
00664                         int posX = int(float(x) / float(newMap.getWidth()) * landscapeWidth);
00665                         int posX1 = int(float(x1) / float(newMap.getWidth()) * landscapeWidth);
00666 
00667                         bool in1 = false;
00668                         bool in2 = false;
00669                         bool in3 = false;
00670                         if (posX > arenaX &&
00671                                 posY > arenaY &&
00672                                 posX > arenaX + arenaWidth &&
00673                                 posY > arenaY + arenaHeight)
00674                         {
00675                                 FixedVector position1(posX1, posY, 0);
00676                                 FixedVector position2(posX, posY, 0);
00677                                 FixedVector position3(posX, posY1, 0);
00678 
00679                                 in1 = (position1 - center).Magnitude() < limit;
00680                                 in2 = (position2 - center).Magnitude() < limit;
00681                                 in3 = (position3 - center).Magnitude() < limit;
00682                         }
00683 
00684                         if (in1 != in2 || in2 != in3)
00685                         {
00686                                 dest[0] = 255;
00687                                 dest[1] = 0;
00688                                 dest[2] = 0;
00689                         }
00690                         else if (!in2)
00691                         {
00692                                 dest[0] = src[0] / 4;
00693                                 dest[1] = src[1] / 4;
00694                                 dest[2] = src[2] / 4;
00695                         }
00696                         else
00697                         {
00698                                 dest[0] = src[0];
00699                                 dest[1] = src[1];
00700                                 dest[2] = src[2];
00701                         }
00702 
00703                         src+=3;
00704                         dest+=3;
00705                 }
00706         }
00707 
00708         Landscape::instance()->getMainTexture().replace(newMap, false);
00709         Landscape::instance()->setTextureType(Landscape::eOther);
00710 }
00711 
00712 #endif // #ifndef S3D_SERVER

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