CameraProcess.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2003-2005 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 "CameraProcess.h"
00022 #include "World.h"
00023 #include "CurrentMap.h"
00024 #include "Item.h"
00025 #include "Actor.h"
00026 #include "UCMachine.h"
00027 #include "ShapeInfo.h"
00028 #include "Kernel.h"
00029 #include "CoreApp.h"
00030 #include "getObject.h"
00031 #include <cstdlib>
00032 
00033 #include "IDataSource.h"
00034 #include "ODataSource.h"
00035 
00036 // p_dynamic_cast stuff
00037 DEFINE_RUNTIME_CLASSTYPE_CODE(CameraProcess,Process);
00038 
00039 // 
00040 // Statics
00041 //
00042 CameraProcess *CameraProcess::camera = 0;
00043 sint32 CameraProcess::earthquake = 0;
00044 sint32 CameraProcess::eq_x = 0;
00045 sint32 CameraProcess::eq_y = 0;
00046 
00047 CameraProcess::CameraProcess() : Process()
00048 {
00049 
00050 }
00051 
00052 CameraProcess::~CameraProcess()
00053 {
00054         if (camera == this)
00055                 camera = 0;
00056 }
00057 
00058 uint16 CameraProcess::SetCameraProcess(CameraProcess *cam)
00059 {
00060         if (!cam) cam = new CameraProcess(0);
00061         if (camera) camera->terminate();
00062         camera = cam;
00063         return Kernel::get_instance()->addProcess(camera);
00064 }
00065 
00066 void CameraProcess::ResetCameraProcess()
00067 {
00068         if (camera) camera->terminate();
00069         camera = 0;
00070 }
00071 
00072 void CameraProcess::GetCameraLocation(sint32 &x, sint32 &y, sint32 &z)
00073 {
00074         if (!camera) 
00075         {
00076                 World *world = World::get_instance();
00077                 CurrentMap *map = world->getCurrentMap();
00078                 int map_num = map->getNum();
00079                 Actor* av = getActor(1);
00080                 
00081                 if (!av || av->getMapNum() != map_num)
00082                 {
00083                         x = 8192;
00084                         y = 8192;
00085                         z = 64;
00086                 }
00087                 else
00088                         av->getLocation(x,y,z);
00089 
00090                 if (earthquake)
00091                 {
00092                         x += 2*eq_x + 4*eq_y;
00093                         y += -2*eq_x + 4*eq_y;
00094                 }
00095         }
00096         else
00097         {
00098                 camera->GetLerped(x, y, z, 256, true);
00099         }
00100 }
00101 
00102 //
00103 // Constructors
00104 // 
00105 
00106 // Track item, do nothing
00107 CameraProcess::CameraProcess(uint16 _itemnum) : 
00108         time(0), elapsed(0), itemnum(_itemnum), last_framenum(0)
00109 {
00110         GetCameraLocation(sx,sy,sz);
00111 
00112         if (itemnum)
00113         {
00114                 Item *item = getItem(itemnum);
00115         
00116                 // Got it
00117                 if (item)
00118                 {
00119                         item->setExtFlag(Item::EXT_CAMERA);
00120                         item->getLocation(ex,ey,ez);
00121                         ez += 20; 
00122                 }
00123                 return;
00124         }
00125 
00126         // No item
00127         itemnum = 0;
00128         ex = sx; ey = sy; ez = sz;
00129 }
00130 
00131 // Stay over point
00132 CameraProcess::CameraProcess(sint32 _x, sint32 _y, sint32 _z) : 
00133         ex(_x), ey(_y), ez(_z), time(0), elapsed(0), itemnum(0), last_framenum(0)
00134 {
00135         GetCameraLocation(sx,sy,sz);
00136 }
00137 
00138 // Scroll
00139 CameraProcess::CameraProcess(sint32 _x, sint32 _y, sint32 _z, sint32 _time) : 
00140         ex(_x), ey(_y), ez(_z), time(_time), elapsed(0), itemnum(0), last_framenum(0)
00141 {
00142         GetCameraLocation(sx,sy,sz);
00143         //pout << "Scrolling from (" << sx << "," << sy << "," << sz << ") to (" <<
00144         //      ex << "," << ey << "," << ez << ") in " << time << " frames" << std::endl;
00145 }
00146 
00147 void CameraProcess::terminate()
00148 {
00149         if (itemnum)
00150         {
00151                 Item *item = getItem(itemnum);
00152                 if (item) item->clearExtFlag(Item::EXT_CAMERA);
00153         }
00154 
00155         Process::terminate();
00156 }
00157 
00158 bool CameraProcess::run(const uint32 /* framenum */)
00159 {
00160         if (earthquake)
00161         {
00162                 eq_x = (std::rand()%(earthquake*2+1))-earthquake;
00163                 eq_y = (std::rand()%(earthquake*2+1))-earthquake;
00164         }
00165         else
00166         {
00167                 eq_x = 0;
00168                 eq_y = 0;
00169         }
00170 
00171         if (time && elapsed>time)
00172         {
00173                 result = 0; // do we need this
00174                 CameraProcess::SetCameraProcess(0);     // This will terminate us
00175                 return false;
00176         }
00177 
00178         elapsed++;
00179 
00180         return true;
00181 }
00182 
00183 void CameraProcess::ItemMoved()
00184 {
00185         if (itemnum)
00186         {
00187                 Item *item = getItem(itemnum);
00188 
00189                 // We only update for now if lerping has been disabled
00190                 if (item && (item->getExtFlags() & Item::EXT_LERP_NOPREV))
00191                 {
00192                         item->getLocation(ex,ey,ez);
00193                         sx = ex;
00194                         sy = ey;
00195                         sz = ez += 20;
00196 
00197                         World::get_instance()->getCurrentMap()->updateFastArea(sx,sy,sz,ex,ey,ez);
00198                 }
00199         }
00200 }
00201 
00202 void CameraProcess::GetLerped(sint32 &x, sint32 &y, sint32 &z, sint32 factor, bool noupdate)
00203 {
00204         if (time == 0)
00205         {
00206                 if (!noupdate) { 
00207 
00208                         bool inBetween = true;
00209 
00210                         if (last_framenum != elapsed)
00211                         {
00212                                 // No lerping if we missed a frame
00213                                 if ((elapsed-last_framenum)>1) factor = 256;
00214                                 last_framenum = elapsed;
00215                                 inBetween = false;
00216                         }
00217                         
00218                         if (!inBetween)
00219                         {
00220                                 sx = ex;
00221                                 sy = ey;
00222                                 sz = ez;
00223 
00224                                 if (itemnum)
00225                                 {
00226                                         Item *item = getItem(itemnum);
00227                                         // Got it
00228                                         if (item)
00229                                         {
00230                                                 sx = ex;
00231                                                 sy = ey;
00232                                                 sz = ez;
00233                                                 item->getLocation(ex,ey,ez);
00234                                                 ez += 20; 
00235                                         }
00236                                 }
00237                                 // Update the fast area
00238                                 World::get_instance()->getCurrentMap()->updateFastArea(sx,sy,sz,ex,ey,ez);
00239                         }
00240                 }
00241 
00242                 if (factor == 256)
00243                 {
00244                         x = ex; y = ey; z = ez;
00245                 }
00246                 else if (factor == 0)
00247                 {
00248                         x = sx; y = sy; z = sz;
00249                 }
00250                 else
00251                 {
00252                         // This way while possibly slower is more accurate
00253                         x = ((sx*(256-factor) + ex*factor)>>8);
00254                         y = ((sy*(256-factor) + ey*factor)>>8);
00255                         z = ((sz*(256-factor) + ez*factor)>>8);
00256                 }
00257         }
00258         else
00259         {
00260                 // Do a quadratic interpolation here of velocity (maybe), but not yet 
00261                 sint32 sfactor = elapsed;
00262                 sint32 efactor = elapsed+1;
00263 
00264                 if (sfactor > time) sfactor = time;
00265                 if (efactor > time) efactor = time;
00266 
00267                 sint32 lsx = ((sx*(time-sfactor) + ex*sfactor)/time);
00268                 sint32 lsy = ((sy*(time-sfactor) + ey*sfactor)/time);
00269                 sint32 lsz = ((sz*(time-sfactor) + ez*sfactor)/time);
00270 
00271                 sint32 lex = ((sx*(time-efactor) + ex*efactor)/time);
00272                 sint32 ley = ((sy*(time-efactor) + ey*efactor)/time);
00273                 sint32 lez = ((sz*(time-efactor) + ez*efactor)/time);
00274 
00275                 // Update the fast area
00276                 if (!noupdate) World::get_instance()->getCurrentMap()->updateFastArea(lsx,lsy,lsz,lex,ley,lez);
00277 
00278                 // This way while possibly slower is more accurate
00279                 x = ((lsx*(256-factor) + lex*factor)>>8);
00280                 y = ((lsy*(256-factor) + ley*factor)>>8);
00281                 z = ((lsz*(256-factor) + lez*factor)>>8);
00282         }
00283 
00284         if (earthquake)
00285         {
00286                 x += 2*eq_x + 4*eq_y;
00287                 y += -2*eq_x + 4*eq_y;
00288         }
00289 }
00290 
00291 uint16 CameraProcess::FindRoof(sint32 factor)
00292 {
00293         sint32 x,y,z;
00294         sint32 earthquake_old = earthquake;
00295         earthquake = 0;
00296         GetLerped(x,y,z,factor);
00297         earthquake = earthquake_old;
00298         Item *avatar = getItem(1);
00299         sint32 dx,dy,dz;
00300         avatar->getFootpadWorld(dx,dy,dz);
00301         uint16 roofid;
00302         World::get_instance()->getCurrentMap()->isValidPosition(x, y, z-10, dx/2, dy/2, dz/2, 0, 1, 0, &roofid);
00303         return roofid;
00304 }
00305 
00306 void CameraProcess::saveData(ODataSource* ods)
00307 {
00308         Process::saveData(ods);
00309 
00310         ods->write4(static_cast<uint32>(sx));
00311         ods->write4(static_cast<uint32>(sy));
00312         ods->write4(static_cast<uint32>(sz));
00313         ods->write4(static_cast<uint32>(ex));
00314         ods->write4(static_cast<uint32>(ey));
00315         ods->write4(static_cast<uint32>(ez));
00316         ods->write4(static_cast<uint32>(time));
00317         ods->write4(static_cast<uint32>(elapsed));
00318         ods->write2(itemnum);
00319         ods->write4(last_framenum);
00320         ods->write4(static_cast<uint32>(earthquake));
00321         ods->write4(static_cast<uint32>(eq_x));
00322         ods->write4(static_cast<uint32>(eq_y));
00323 }
00324 
00325 bool CameraProcess::loadData(IDataSource* ids, uint32 version)
00326 {
00327         if (!Process::loadData(ids, version)) return false;
00328 
00329         sx = static_cast<sint32>(ids->read4());
00330         sy = static_cast<sint32>(ids->read4());
00331         sz = static_cast<sint32>(ids->read4());
00332         ex = static_cast<sint32>(ids->read4());
00333         ey = static_cast<sint32>(ids->read4());
00334         ez = static_cast<sint32>(ids->read4());
00335         time = static_cast<sint32>(ids->read4());
00336         elapsed = static_cast<sint32>(ids->read4());
00337         itemnum = ids->read2();
00338         last_framenum = ids->read4();
00339         earthquake = static_cast<sint32>(ids->read4()); //static
00340         eq_x = static_cast<sint32>(ids->read4()); //static
00341         eq_y = static_cast<sint32>(ids->read4()); //static
00342 
00343         camera = this; //static
00344 
00345         return true;
00346 }
00347 
00348 //      "Camera::move_to(uword, uword, ubyte, word)",
00349 uint32 CameraProcess::I_move_to(const uint8* args, unsigned int /*argsize*/)
00350 {
00351         ARG_UINT16(x);
00352         ARG_UINT16(y);
00353         ARG_UINT8(z);
00354         ARG_SINT16(unk);
00355         CameraProcess::SetCameraProcess(new CameraProcess(x,y,z));
00356         return 0;
00357 }
00358 
00359 //      "Camera::setCenterOn(uword)",
00360 uint32 CameraProcess::I_setCenterOn(const uint8* args, unsigned int /*argsize*/)
00361 {
00362         ARG_OBJID(itemnum);
00363         CameraProcess::SetCameraProcess(new CameraProcess(itemnum));
00364         return 0;
00365 }
00366 
00367 //      Camera::scrollTo(uword, uword, ubyte, word)
00368 uint32 CameraProcess::I_scrollTo(const uint8* args, unsigned int /*argsize*/)
00369 {
00370         ARG_UINT16(x);
00371         ARG_UINT16(y);
00372         ARG_UINT8(z);
00373         ARG_SINT16(unk);
00374         return CameraProcess::SetCameraProcess(new CameraProcess(x,y,z, 25));
00375 }
00376 
00377 //      Camera::startQuake(word)
00378 uint32 CameraProcess::I_startQuake(const uint8* args, unsigned int /*argsize*/)
00379 {
00380         ARG_UINT16(strength);
00381         SetEarthquake(strength);
00382         return 0;
00383 }
00384 
00385 //      Camera::stopQuake()
00386 uint32 CameraProcess::I_stopQuake(const uint8* /*args*/, unsigned int /*argsize*/)
00387 {
00388         SetEarthquake(0);
00389         return 0;
00390 }
00391 

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