TargetSpace.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 <target/TargetSpace.h>
00022 #include <target/TargetLife.h>
00023 #include <target/TargetShield.h>
00024 #include <target/TargetState.h>
00025 #include <weapons/Accessory.h>
00026 #include <weapons/ShieldRound.h>
00027 #include <weapons/ShieldSquare.h>
00028 #include <engine/ScorchedContext.h>
00029 #include <engine/ActionController.h>
00030 #include <common/OptionsScorched.h>
00031 #include <common/Logger.h>
00032 
00033 TargetSpace::TargetSpace() :
00034         spaceX_(-128), spaceY_(-128),
00035         spaceW_(1024), spaceH_(1024),
00036         spaceSq_(4), context_(0)
00037 {
00038         spaceWSq_ = (spaceW_ / spaceSq_);
00039         spaceHSq_ = (spaceH_ / spaceSq_);
00040         noSquares_ = spaceWSq_ * spaceHSq_;
00041         squares_ = new Square[noSquares_];
00042         for (int i=0; i<noSquares_; i++) squares_[i].squarenum = i;
00043 }
00044 
00045 TargetSpace::~TargetSpace()
00046 {
00047         delete squares_;
00048 }
00049 
00050 void TargetSpace::updateTarget(Target *target)
00051 {
00052         if (!target->getAlive() ||
00053                 target->getTargetState().getNoCollision())
00054         {
00055                 removeTarget(target);
00056         }
00057         else
00058         {
00059                 static std::vector<Square*> squares;
00060                 squares.clear();
00061                 getSquares(target, squares);
00062 
00063                 bool same = false;
00064                 if (squares.size() == target->getLife().getSpaceContainment().squares.size())
00065                 {
00066                         same = true;
00067                         for (unsigned int i=0; i<squares.size(); i++)
00068                         {
00069                                 if (squares[i]->squarenum != target->getLife().getSpaceContainment().squares[i])
00070                                 {
00071                                         same = false;
00072                                         break;
00073                                 }
00074                         }
00075                 }
00076 
00077                 if (!same)
00078                 {
00079                         removeTarget(target);
00080                         std::vector<Square*>::iterator itor;
00081                         for (itor = squares.begin();
00082                                 itor != squares.end();
00083                                 itor++)
00084                         {
00085                                 Square *square = *itor;
00086                                 target->getLife().getSpaceContainment().squares.push_back(square->squarenum);
00087                                 square->targets.insert(std::pair<unsigned int, Target*>(target->getPlayerId(), target));
00088                         }
00089                 }
00090         }
00091 }
00092 
00093 void TargetSpace::getSquares(Target *target, std::vector<Square*> &squares)
00094 {
00095         // Set the bounding constaints
00096         int x = target->getLife().getTargetPosition()[0].asInt();
00097         int y = target->getLife().getTargetPosition()[1].asInt();
00098         int w = target->getLife().getAabbSize()[0].asInt();
00099         int h = target->getLife().getAabbSize()[1].asInt();
00100 
00101         // Update bounding constraints for shield
00102         Accessory *shieldAcc = target->getShield().getCurrentShield();
00103         if (shieldAcc)
00104         {
00105                 Shield *shield = (Shield *) shieldAcc->getAction();
00106                 if (shield->getRound())
00107                 {
00108                         ShieldRound *round = (ShieldRound *) shield;
00109 
00110                         w = MAX(w, (round->getActualRadius() * 2).asInt());
00111                         h = MAX(h, (round->getActualRadius() * 2).asInt());
00112                 }
00113                 else
00114                 {
00115                         ShieldSquare *square = (ShieldSquare *) shield;
00116 
00117                         w = MAX(w, (square->getSize()[0] * 2).asInt());
00118                         h = MAX(h, (square->getSize()[1] * 2).asInt());
00119                 }
00120         }
00121 
00122         // Find the bounding box coords
00123         int halfW = w / 2;
00124         int halfH = h / 2;
00125         int minX = x - halfW - 1;
00126         int minY = y - halfH - 1;
00127         int maxX = x + halfW + 1;
00128         int maxY = y + halfH + 1;
00129 
00130         // Find the square positions
00131         normalizeCoords(minX, minY);
00132         normalizeCoords(maxX, maxY);
00133 
00134         // Find the square numbers
00135         for (int b=minY; b<=maxY; b++)
00136         {
00137                 for (int a=minX; a<=maxX; a++)
00138                 {
00139                         int num = spaceHSq_ * b + a;
00140                         DIALOG_ASSERT(num >= 0 && num < noSquares_);
00141 
00142                         Square *square = &squares_[num];
00143                         squares.push_back(square);
00144                 }
00145         }
00146 }
00147 
00148 void TargetSpace::removeTarget(Target *target)
00149 {
00150         std::vector<int> &squares = target->getLife().getSpaceContainment().squares;
00151         while (!squares.empty())
00152         {
00153                 int squareNum = squares.back();
00154                 squares.pop_back();
00155 
00156                 Square *square = &squares_[squareNum];
00157                 square->targets.erase(target->getPlayerId());
00158         }
00159 }
00160 
00161 Target *TargetSpace::getCollision(FixedVector &position)
00162 {
00163         int x = position[0].asInt();
00164         int y = position[1].asInt();
00165 
00166         // Find the square positions
00167         normalizeCoords(x, y);
00168 
00169         int num = spaceHSq_ * y + x;
00170         DIALOG_ASSERT(num >= 0 && num < noSquares_);
00171 
00172         Square *square = &squares_[num];
00173 
00174         Target *result = 0;
00175         std::map<unsigned int, Target *> &potentialTargets = square->targets;
00176         std::map<unsigned int, Target *>::iterator itor;
00177         for (itor = potentialTargets.begin();
00178                 itor != potentialTargets.end();
00179                 itor++)
00180         {
00181                 Target *target = (*itor).second;
00182                 if (!target->getAlive())
00183                 {
00184                         Logger::log(S3D::formatStringBuffer("ERROR: Dead target %u:%s in space",
00185                                 target->getPlayerId(), target->getCStrName().c_str()));
00186                         continue;
00187                 }
00188 
00189                 Accessory *shieldAcc = target->getShield().getCurrentShield();
00190                 if (shieldAcc)
00191                 {
00192                         Shield *shield = (Shield *) shieldAcc->getAction();
00193                         FixedVector direction = position - target->getLife().getTargetPosition();
00194                         if (shield->inShield(direction))
00195                         {
00196                                 result = target;
00197                                 break;
00198                         }
00199                 }
00200 
00201                 if (target->getLife().collision(position)) 
00202                 {
00203                         result = target;
00204                         break;
00205                 }
00206         }
00207 
00208         if (context_->getOptionsGame().getActionSyncCheck())
00209         {
00210                 std::string targets;
00211                 if (result)
00212                 {
00213                         targets.append(S3D::formatStringBuffer("%u:%i,%i,%i ", 
00214                                 result->getPlayerId(),
00215                                 result->getLife().getTargetPosition()[0].getInternal(),
00216                                 result->getLife().getTargetPosition()[1].getInternal(),
00217                                 result->getLife().getTargetPosition()[2].getInternal()));
00218                 }
00219 
00220                 context_->getActionController().addSyncCheck(
00221                         S3D::formatStringBuffer("CollisionSet : %i,%i,%i %s", 
00222                                 position[0].getInternal(),
00223                                 position[1].getInternal(),
00224                                 position[2].getInternal(),
00225                                 targets.c_str()));
00226         }
00227 
00228         return result;
00229 }
00230 
00231 void TargetSpace::getCollisionSet(FixedVector &position, fixed radius, 
00232         std::map<unsigned int, Target *> &collisionTargets, 
00233         bool ignoreHeight)
00234 {
00235         int x = position[0].asInt();
00236         int y = position[1].asInt();
00237         int w = radius.asInt();
00238         int h = radius.asInt();
00239 
00240         // Find the bounding box coords
00241         int halfW = w; // Not need 1/2 as its the radius thats passed in
00242         int halfH = h;
00243         int minX = x - halfW - 1;
00244         int minY = y - halfH - 1;
00245         int maxX = x + halfW + 1;
00246         int maxY = y + halfH + 1;
00247 
00248         // Find the square positions
00249         normalizeCoords(minX, minY);
00250         normalizeCoords(maxX, maxY);
00251 
00252         // Find the square numbers
00253         std::map<unsigned int, Target *>::iterator itor;
00254         for (int b=minY; b<=maxY; b++)
00255         {
00256                 for (int a=minX; a<=maxX; a++)
00257                 {
00258                         int num = spaceHSq_ * b + a;
00259                         DIALOG_ASSERT(num >= 0 && num < noSquares_);
00260 
00261                         Square *square = &squares_[num];
00262 
00263                         std::map<unsigned int, Target *> &potentialTargets =
00264                                 square->targets;
00265                         for (itor = potentialTargets.begin();
00266                                 itor != potentialTargets.end();
00267                                 itor++)
00268                         {
00269                                 Target *target = (*itor).second;
00270                                 if (!target->getAlive())
00271                                 {
00272                                         Logger::log(S3D::formatStringBuffer("ERROR: Dead target %u:%s in space",
00273                                                 target->getPlayerId(), target->getCStrName().c_str()));
00274                                         continue;
00275                                 }
00276 
00277                                 FixedVector checkPos = position;
00278                                 if (ignoreHeight)
00279                                 {
00280                                         FixedVector centerPos = target->getLife().getCenterPosition();
00281                                         checkPos[2] = centerPos[2];
00282                                 }
00283                                 fixed distance = target->getLife().collisionDistance(checkPos);
00284                                 if (distance < radius)
00285                                 {
00286                                         collisionTargets[target->getPlayerId()] = target;
00287                                 }
00288                         }
00289                 }
00290         }
00291 
00292         if (context_->getOptionsGame().getActionSyncCheck())
00293         {
00294                 std::string targets;
00295                 std::map<unsigned int, Target *>::iterator itor;
00296                 for (itor = collisionTargets.begin();
00297                         itor != collisionTargets.end();
00298                         itor++)
00299                 {
00300                         targets.append(S3D::formatStringBuffer("%u:%i,%i,%i ", 
00301                                 itor->second->getPlayerId(),
00302                                 itor->second->getLife().getTargetPosition()[0].getInternal(),
00303                                 itor->second->getLife().getTargetPosition()[1].getInternal(),
00304                                 itor->second->getLife().getTargetPosition()[2].getInternal()));
00305                 }
00306 
00307                 context_->getActionController().addSyncCheck(
00308                         S3D::formatStringBuffer("CollisionSet : %i,%i,%i %i \"%s\"", 
00309                                 position[0].getInternal(),
00310                                 position[1].getInternal(),
00311                                 position[2].getInternal(),
00312                                 radius.getInternal(),
00313                                 targets.c_str()));
00314         }
00315 }
00316 
00317 #ifndef S3D_SERVER
00318 #include <GLEXT/GLState.h>
00319 #include <client/ScorchedClient.h>
00320 #include <landscapemap/LandscapeMaps.h>
00321 
00322 static void drawBox(Vector &position, Vector &size)
00323 {
00324         float wid = size[0];
00325         float hgt = size[1];
00326         float dep = size[2];
00327         glPushMatrix();
00328                 glTranslatef(position[0], position[1], position[2]);
00329                 glBegin(GL_LINE_LOOP);
00330                         // Top
00331                         glNormal3f(0,1,0);
00332                         glVertex3f(-wid/2,hgt/2,dep/2);
00333                         glVertex3f(wid/2,hgt/2,dep/2);
00334                         glVertex3f(wid/2,hgt/2,-dep/2);
00335                         glVertex3f(-wid/2,hgt/2,-dep/2);
00336                 glEnd();
00337                 glBegin(GL_LINE_LOOP);
00338                         // Back
00339                         glNormal3f(0,0,1);
00340                         glVertex3f(-wid/2,hgt/2,dep/2);
00341                         glVertex3f(-wid/2,-hgt/2,dep/2);
00342                         glVertex3f(wid/2,-hgt/2,dep/2);
00343                         glVertex3f(wid/2,hgt/2,dep/2);
00344                 glEnd();
00345                 glBegin(GL_LINE_LOOP);
00346                         // Front
00347                         glNormal3f(0,0,-1);
00348                         glVertex3f(-wid/2,hgt/2,-dep/2);
00349                         glVertex3f(wid/2,hgt/2,-dep/2);
00350                         glVertex3f(wid/2,-hgt/2,-dep/2);
00351                         glVertex3f(-wid/2,-hgt/2,-dep/2);
00352                 glEnd();
00353                 glBegin(GL_LINE_LOOP);
00354                         // Left
00355                         glNormal3f(1,0,0);
00356                         glVertex3f(wid/2,hgt/2,-dep/2);
00357                         glVertex3f(wid/2,hgt/2,dep/2);
00358                         glVertex3f(wid/2,-hgt/2,dep/2);
00359                         glVertex3f(wid/2,-hgt/2,-dep/2);
00360                 glEnd();
00361                 glBegin(GL_LINE_LOOP);
00362                         // Right
00363                         glNormal3f(-1,0,0);
00364                         glVertex3f(-wid/2,hgt/2,dep/2);
00365                         glVertex3f(-wid/2,hgt/2,-dep/2);
00366                         glVertex3f(-wid/2,-hgt/2,-dep/2);
00367                         glVertex3f(-wid/2,-hgt/2,dep/2);
00368                 glEnd();
00369                 glBegin(GL_LINE_LOOP);
00370                         // Bottom
00371                         glNormal3f(0,-1,0);
00372                         glVertex3f(-wid/2,-hgt/2,dep/2);
00373                         glVertex3f(-wid/2,-hgt/2,-dep/2);
00374                         glVertex3f(wid/2,-hgt/2,-dep/2);
00375                         glVertex3f(wid/2,-hgt/2,dep/2);
00376                 glEnd();
00377         glPopMatrix();
00378 }
00379 
00380 void TargetSpace::draw()
00381 {
00382         GLState glState(GLState::TEXTURE_OFF | GLState::LIGHTING_OFF);
00383 
00384         for (int b=0; b<spaceHSq_; b++)
00385         {
00386                 for (int a=0; a<spaceWSq_; a++)
00387                 {
00388                         int num = spaceHSq_ * b + a;
00389                         DIALOG_ASSERT(num >= 0 && num < noSquares_);
00390 
00391                         Square *square = &squares_[num];
00392                         if (square->targets.empty())
00393                         {
00394                                 continue;
00395                         }
00396 
00397                         Vector position(a * spaceSq_ + spaceX_ + spaceSq_ / 2,
00398                                 b * spaceSq_ + spaceY_ + spaceSq_ / 2, 0);
00399                         position[2] = 
00400                                 ScorchedClient::instance()->getLandscapeMaps().
00401                                         getGroundMaps().getHeight((int) position[0], (int) position[1]).asFloat() - 7.0f;
00402                         Vector size(spaceSq_, spaceSq_, 20);
00403 
00404                         if (position[0] > ScorchedClient::instance()->getLandscapeMaps().
00405                                 getGroundMaps().getLandscapeWidth() ||
00406                                 position[1] > ScorchedClient::instance()->getLandscapeMaps().
00407                                 getGroundMaps().getLandscapeHeight())
00408                         {
00409                                 continue;
00410                         }
00411 
00412                         glColor3f(1.0f, 0.0f, 0.0f);
00413                         drawBox(position, size);
00414 
00415                         glBegin(GL_LINES);
00416                         std::map<unsigned int, Target *>::iterator itor;
00417                         for (itor = square->targets.begin();
00418                                 itor != square->targets.end();
00419                                 itor++)
00420                         {
00421                                 Target *target = (*itor).second;
00422                                 glVertex3fv(target->getLife().getFloatPosition());
00423                                 glVertex3f(position[0], position[1], position[2] + 10.0f);
00424                         }
00425                         glEnd();
00426                 }
00427         }
00428 }
00429 #endif

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