MissileTracker.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2007 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include "pent_include.h"
00020 
00021 #include "MissileTracker.h"
00022 
00023 #include "CurrentMap.h"
00024 #include "Item.h"
00025 #include "World.h"
00026 #include "getObject.h"
00027 
00028 MissileTracker::MissileTracker(Item* item, sint32 sx, sint32 sy, sint32 sz,
00029                                                            sint32 tx, sint32 ty, sint32 tz,
00030                                                            sint32 speed, sint32 gravity_)
00031 {
00032         objid = item->getObjId();
00033         destx = tx;
00034         desty = ty;
00035         destz = tz;
00036         gravity = gravity_;
00037 
00038         init(sx, sy, sz, speed);
00039 }
00040 
00041 MissileTracker::MissileTracker(Item* item, sint32 tx, sint32 ty, sint32 tz,
00042                                                            sint32 speed, sint32 gravity_)
00043 {
00044         assert(item->getParent() == 0);
00045 
00046         objid = item->getObjId();
00047         destx = tx;
00048         desty = ty;
00049         destz = tz;
00050         gravity = gravity_;
00051 
00052         sint32 x,y,z;
00053         item->getLocation(x,y,z);
00054 
00055         init(x, y, z, speed);
00056 }
00057 
00058 void MissileTracker::init(sint32 x, sint32 y, sint32 z, sint32 speed)
00059 {
00060         int range = abs(x - destx) + abs(y - desty);
00061 
00062         // rounded division: range/speed
00063         frames = (range + (speed/2)) / speed;
00064 
00065         /*
00066 
00067         Item's vertical trajectory:
00068 
00069         z_{i+1} = z_i + s_i
00070         s_{i+1} = s_i - g
00071 
00072         (z_i = vertical position after i frames,
00073          s_i = vertical speed after i frames, g = gravity)
00074 
00075         So:
00076 
00077         z_i = z + sum_{j=0}^{i-1} ( s_0 - jg)
00078             = z + is_0 - 1/2 i(i-1)g
00079 
00080         Conclusion: if we want to reach the destination vertical level in i frames,
00081         we need to set
00082 
00083         s_0 = ((1/2 gi(i-1)) + z_i-z) / i
00084 
00085         */
00086 
00087         if (frames > 0) {
00088                 speedz = ((gravity * frames * (frames-1) / 2) + destz - z) / frames;
00089 
00090                 // check if vertical speed isn't too high
00091                 if (speedz > speed/4) {
00092                         if (gravity == 0 || (speed / (4*gravity)) <= frames) {
00093                                 if (speed >= 4 && (destz-z)/(speed/4) > frames)
00094                                         frames = (destz-z)/(speed/4);
00095                         } else {
00096                                 frames = speed/(4*gravity);
00097                         }
00098                 }
00099 
00100                 speedz = ((gravity * frames * (frames-1) / 2) + destz - z) / frames;
00101 
00102                 // horizontal speed is easier: just divide distance by frames
00103                 speedx = ((destx - x) + (frames/2)) / frames;
00104                 speedy = ((desty - y) + (frames/2)) / frames;
00105 
00106 #if 0
00107                 pout.printf("MissileTracker: from (%d,%d,%d) to (%d,%d,%d)\n", x, y, z, destx, desty, destz);
00108                 pout.printf("speed: %d, gravity: %d, frames: %d\n", speed, gravity, frames);
00109                 pout.printf("resulting speed: (%d,%d,%d)\n", speedx, speedy, speedz);
00110 #endif
00111         } else {
00112 
00113                 // no significant horizontal movement
00114                 if (destz > z)
00115                         speedz = speed/4;
00116                 else
00117                         speedz = -speed/4;
00118 
00119         }
00120 }
00121 
00122 MissileTracker::~MissileTracker()
00123 {
00124 
00125 }
00126 
00127 bool MissileTracker::isPathClear()
00128 {
00129         sint32 start[3];
00130         sint32 end[3];
00131         sint32 dims[3];
00132         sint32 sx,sy,sz;
00133 
00134         sx = speedx;
00135         sy = speedy;
00136         sz = speedz;
00137 
00138         World *world = World::get_instance();
00139         CurrentMap *map = world->getCurrentMap();
00140         Item* item = getItem(objid);
00141 
00142         item->getFootpadWorld(dims[0], dims[1], dims[2]);
00143         item->getLocation(start[0], start[1], start[2]);
00144 
00145         for (int f = 0; f < frames; ++f) {
00146                 end[0] = start[0] + sx;
00147                 end[1] = start[1] + sy;
00148                 end[2] = start[2] + sz;
00149 
00150                 // Do the sweep test
00151                 std::list<CurrentMap::SweepItem> collisions;
00152                 std::list<CurrentMap::SweepItem>::iterator it;
00153                 map->sweepTest(start, end, dims, item->getShapeInfo()->flags, objid,
00154                                            false, &collisions);
00155 
00156                 sint32 hit = 0x4000;
00157                 for (it = collisions.begin(); it != collisions.end(); it++)
00158                 {
00159                         if (it->blocking && !it->touching) {
00160                                 hit = it->hit_time;
00161                                 break;
00162                         }
00163                 }
00164                 if (hit != 0x4000) {
00165                         // didn't reach end of this path segment
00166                         return false;
00167                 }
00168 
00169                 sz -= gravity;
00170                 for (int i = 0; i < 3; ++i) start[i] = end[i];
00171         }
00172 
00173         return true;
00174 }
00175 
00176 
00177 void MissileTracker::launchItem()
00178 {
00179         Item* item = getItem(objid);
00180         if (!item) return;
00181 
00182         item->hurl(speedx, speedy, speedz, gravity);
00183 }

Generated on Fri Jul 27 22:27:25 2007 for pentagram by  doxygen 1.4.7