Quad Pang
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Controllers.cpp
Go to the documentation of this file.
00001 #include <cmath>
00002 #include <stdlib.h>
00003 #include <stdio.h>
00004 #include "Internal.h"
00005 #include "QVector.h"
00006 #include "Controllers.h"
00007 #include "MenuDisplay.h"
00008 #include "XRes.h"
00009 #include "Bongo.h"
00010 #include "Arrow.h"
00011 
00012 using namespace std;
00013 
00014 MenuController::MenuController(MenuDisplay* menu)
00015     : mpMenu(menu) 
00016 {
00017 }  
00018 
00019 bool MenuController::ProcessKey(int key, Engine::KeyEvent type, int x, int y)
00020 {
00021     if (type == Engine::KEY_UP_EX)
00022         return false;
00023 
00024     switch (key)
00025     {
00026     case GLUT_SPEC_KEY_UP:
00027         mpMenu->FocusPrev();
00028         return true;
00029     case GLUT_SPEC_KEY_DOWN:
00030         mpMenu->FocusNext();
00031         return true;
00032     case ' ':
00033     case 13:
00034         mpMenu->Select();
00035     return true;
00036     }
00037 
00038     return false;
00039 }
00040 
00041 bool ShortcutController::ProcessKey(int key, Engine::KeyEvent type, int x, int y)
00042 {
00043     if (type == Engine::KEY_UP_EX)
00044     {
00045         return false;
00046     }
00047     switch (key)
00048     {
00049     case 'p':
00050     case 'P':
00051         if (mbPaused)
00052             mpParent->Resume(true);
00053         else
00054             mpParent->Pause();
00055 
00056         mbPaused = !mbPaused;
00057         return true;
00058     case 27: //< Escape
00059         // send cancelation event ot whoever cares
00060         mpParent->SendEvent(EventListener::EV_CANCEL);
00061 
00062         // If Active Menu is Display Menu get back to game.
00063         if (mpParent->ActiveDisplay() == mpParent->GetMenuDisplay() )
00064         {
00065             mpParent->SetActiveDisplay(mpParent->StatusDisplay() );
00066             mpParent->SetActiveController(mpParent->BongoMover() );
00067             mpParent->Resume(true);              
00068         }
00069         else
00070         {
00071             // Pause game and go to display menu.
00072             mpParent->Pause();
00073             mpParent->SetActiveController(mpParent->GetMenuController() );
00074             mpParent->SetActiveDisplay(mpParent->GetMenuDisplay() );
00075             glutPostRedisplay();
00076         }
00077 
00078         return true;   
00079         // Cheat key. Next Level.
00080     case 'n':
00081     case 'N':
00082         mpParent->NextLevel();
00083         return true; 
00084         // Cheat key. Previous Level.
00085     case 'b':  
00086     case 'B':
00087         {
00088             if (mpParent->CurrentLevel() == 1)
00089             {
00090                 break;
00091             }
00092             if (!mpParent->LoadLevel(mpParent->CurrentLevel() - 1) )
00093             {
00094                 printf("error: failed to load level: %d\n", mpParent->CurrentLevel() - 1);
00095             }
00096             return true;   
00097         }
00098 
00099     }
00100     return false;
00101 }  
00102 
00103 bool BongoOrthoMover::Init(XRes* resource, XCongo *xcongo)
00104 {
00105     if (!resource->DoubleValue("mPower", &mPower) )
00106     {
00107         fprintf(stderr, "error: BongoOrthoMover power\n");
00108         return false;
00109     }
00110   
00111     return true;
00112 }
00113 
00114 BongoOrthoMover::BongoOrthoMover(Engine* parent, Bongo* pquad)
00115 : mpParent(parent), mpBongo(pquad), mPower(2.0)
00116 {
00117     m_k = mpParent->mBoxDim[2] / mpParent->mBoxDim[0];
00118     m_lz = mpParent->mBoxDim[2];
00119     mnMoving = 0;
00120     memset(mDirectionLU, 0, sizeof(mDirectionLU) );
00121     memset(mDirectionRD, 0, sizeof(mDirectionRD) );
00122 }
00123 
00129 bool BongoOrthoMover::ProcessKey(int key, Engine::KeyEvent type, int px, int py)
00130 {
00131     double nula[] = { 0.0, 0.0, 0.0 };
00132     
00133     if (!mpParent->mbAnimeEnabled)
00134         return true;
00135 
00136     if (!mpBongo->IsActive() )
00137         return true;
00138 
00139   /*  if (mnMoving > 1)
00140     {
00141         memset(mDirectionRD, 0, sizeof(mDirectionRD) );
00142         memset(mDirectionLU, 0, sizeof(mDirectionLU) );
00143         mnMoving = 0;
00144     }
00145     */ 
00146     bool moved = false;
00147 
00148     double  x, y, z;
00149     mpParent->GetViewer(&x, &y, &z);
00150     
00151     double 
00152         t1 = m_k * x + z - m_lz,
00153         t2 = -m_k * x + z;
00154  
00155     double pow = 0.0;
00156     int    movd = -1;
00157 
00158     if (type == Engine::KEY_DOWN_EX)
00159     {
00160         movd = +1;
00161         pow = mPower;
00162     }
00163 
00164     switch (key)
00165     {
00166     case GLUT_SPEC_KEY_LEFT:       
00167         if (t1 >=0 && t2 >= 0)
00168             mDirectionLU[0] = -pow;
00169         else if (t1 >=0)
00170             mDirectionLU[2] = pow;
00171         else if (t2 >=0)
00172             mDirectionLU[2] = -pow;
00173         else
00174             mDirectionLU[0] = pow;
00175               
00176         mnMoving += movd;
00177         moved = true;       
00178         break;  
00179      case GLUT_SPEC_KEY_RIGHT:
00180         if (t1 >=0 && t2 >= 0)
00181             mDirectionRD[0] = pow;
00182         else if (t1 >=0)
00183             mDirectionRD[2] = -pow;
00184         else if (t2 >=0)
00185             mDirectionRD[2] = pow;
00186         else
00187             mDirectionRD[0] = -pow;
00188         mnMoving += movd;
00189         moved = true;       
00190         break; 
00191      
00192      case GLUT_SPEC_KEY_UP:
00193         if (t1 >=0 && t2 >= 0)
00194             mDirectionLU[2] = -pow;
00195         else if (t1 >=0)
00196             mDirectionLU[0] = -pow;
00197         else if (t2 >=0)
00198             mDirectionLU[0] = pow;
00199         else
00200             mDirectionLU[2] = pow;
00201 
00202         mnMoving += movd;
00203         moved = true;
00204         break; 
00205      case GLUT_SPEC_KEY_DOWN:
00206         if (t1 >=0 && t2 >= 0)
00207             mDirectionRD[2] = pow;
00208         else if (t1 >=0)
00209             mDirectionRD[0] = pow;
00210         else if (t2 >=0)
00211             mDirectionRD[0] = -pow;
00212         else
00213             mDirectionRD[2] = -pow;
00214         moved = true;
00215         
00216         mnMoving += movd;
00217         break; 
00218     
00219      case ' ': 
00220         {
00221             if (Engine::KEY_UP_EX == type)
00222                 break;
00223             Quad *q = mpBongo->Fire();
00224             if (q)
00225             {
00226                 mpParent->mQuads.push_front(q);
00227             }
00228         }
00229         break;
00230     }
00231 
00232     if (moved)
00233     {
00234         double dir[3];
00235         memset(dir, 0, sizeof(dir) );
00236         vec_add(dir, mDirectionLU);
00237         vec_add(dir, mDirectionRD);
00238         mpBongo->SetDirection(dir);
00239     }
00240 
00241     return true;
00242 }
00243 
00244 BongoRealMover::BongoRealMover(Engine* parent, Bongo* pquad)
00245 : mpParent(parent), mpBongo(pquad), mbMoving(false)
00246 {
00247     mpParent->GetViewer(mDirection, mDirection + 1, mDirection + 2);
00248 
00249     vec_ofpow(mDirection, -mPower);
00250     mDirection[1] = 0.0;
00251 }
00252 
00253 
00254 bool BongoRealMover::Init(XRes* resource, XCongo *xcongo)
00255 {
00256     if (!resource->DoubleValue("mPower", &mPower) )
00257     {
00258         fprintf(stderr, "error: BongoRealMover power\n");
00259         return false;
00260     }
00261   
00262     return true;
00263 }
00264 
00265 
00266 bool BongoRealMover::ProcessKey(int key, Engine::KeyEvent type, int x, int y)
00267 {
00268     double dir[3] = { 0.0, 0.0, 0.0 };
00269     if (Engine::KEY_UP_EX == type)
00270     {
00271         if (GLUT_SPEC_KEY_UP == key || GLUT_SPEC_KEY_DOWN == key)
00272         {
00273             mbMoving  = false;
00274             mpBongo->SetDirection(dir);
00275         }
00276         return true;
00277     }
00278 
00279     switch (key)
00280     {
00281     case GLUT_SPEC_KEY_UP:
00282         mpBongo->SetDirection(mDirection);
00283         mbMoving = true;
00284           
00285         break;
00286     case GLUT_SPEC_KEY_DOWN:
00287         {
00288             memcpy(dir, mDirection, sizeof(dir) );
00289             vec_mul(dir, -1.0);
00290             mpBongo->SetDirection(dir);
00291             mbMoving = true;
00292           
00293             break;
00294         }
00295     case GLUT_SPEC_KEY_LEFT:
00296         {
00297             
00298             vec_rotateY(mDirection, M_PI * 5 *mPower /2);
00299             if (mbMoving)
00300                 mpBongo->SetDirection(mDirection);
00301             break;
00302         }
00303     case GLUT_SPEC_KEY_RIGHT:
00304         {
00305             vec_rotateY(mDirection, -M_PI * 5 *mPower /2);
00306             if (mbMoving)
00307                 mpBongo->SetDirection(mDirection);
00308             break;
00309         }
00310     case ' ': 
00311         {
00312             Quad *q = mpBongo->Fire();
00313             if (q)
00314                 mpParent->mQuads.push_back(q);
00315         }
00316         break;
00317     }
00318 
00319     return true;
00320 }
00321 
00322 ViewController::ViewController(Engine* parent) 
00323     : mpParent(parent), mbKeyInProcessing(false)
00324 {
00325 }
00326 
00327 bool ViewController::Init(XRes* resource, XCongo *xcongo)
00328 {
00329     if (!resource->DoubleValue("mDeltaAngle", &mDeltaAngle) ||
00330         !resource->DoubleValue("mDeltaDis", &mDeltaDis) )
00331     {
00332         fprintf(stderr, "error: reading ViewControler parameters\n");
00333         return false;   
00334     }
00335     
00336     return true;
00337 }
00338 
00339 static void count_depolar(double teta, double gama, double rad, 
00340                           double* x, double* y, double* z)
00341 {   
00342     *y = rad * sin(gama);
00343     double xz = rad * cos(gama);
00344     *x = xz * cos(teta);
00345     *z = xz * sin(teta);
00346 }
00347 
00348 
00349 bool ViewController::Handle(EventListener::EventType etype)
00350 {
00351     switch (etype)
00352     {
00353     case EV_CANCEL:
00354         mpParent->RemoveEventListener(this);
00355         return true;
00356     case EV_TICK:
00357         return ProcessKey(mLastKey, Engine::KEY_DOWN_EX, 0, 0);        
00358     }
00359 
00360     return false;
00361 }
00362     
00363 bool ViewController::ProcessKey(int key, Engine::KeyEvent type, int x, int y)
00364 {
00365     if (type == Engine::KEY_UP_EX)
00366     {
00367         mbKeyInProcessing = false;
00368         mpParent->RemoveEventListener(this);
00369         return false;    
00370     }
00371 
00372     mLastKey = key;
00373     double vx, vy, vz;
00374     mpParent->GetViewer(&vx, &vy, &vz);
00375     
00376     double xz = pow(vx*vx + vz*vz, 0.5);
00377     double rad = pow(xz*xz + vy*vy, 0.5);
00378     double gama = asin(vy/rad);
00379     double teta = asin(vz/xz);
00380     if (vx < 0)
00381         teta = M_PI - teta;
00382     
00383     switch (key)
00384     {
00385     case GLUT_SPEC_KEY_RIGHT:
00386         {
00387             teta = teta - mDeltaAngle;
00388             if (teta < 0)
00389                 teta = teta + 2 * M_PI;
00390                 
00391             count_depolar(teta, gama, rad, &vx, &vy, &vz);
00392             mpParent->SetViewer(vx, vy, vz);
00393         }        
00394         break;
00395     
00396     case GLUT_SPEC_KEY_UP:
00397         {
00398             gama = gama + mDeltaAngle;
00399             if (gama > M_PI_2)
00400                 gama = M_PI_2;
00401             
00402             count_depolar(teta, gama, rad, &vx, &vy, &vz);
00403             mpParent->SetViewer(vx, vy, vz);
00404         }
00405         break;
00406     
00407     case GLUT_SPEC_KEY_LEFT:
00408         {
00409             teta = teta + mDeltaAngle;
00410             if (teta > 2 * M_PI) 
00411                 teta = teta - 2 * M_PI;
00412             
00413             count_depolar(teta, gama, rad, &vx, &vy, &vz);
00414             mpParent->SetViewer(vx, vy, vz);
00415         }
00416         break;
00417     
00418     case GLUT_SPEC_KEY_DOWN:
00419         {
00420             gama = gama - mDeltaAngle;
00421             if (gama < -M_PI_2)
00422                 gama = -M_PI_2;
00423             
00424             count_depolar(teta, gama, rad, &vx, &vy, &vz);
00425             mpParent->SetViewer(vx, vy, vz);
00426         }
00427         break;
00428     
00429     case 'x':
00430     case 'X':
00431         {
00432             rad = rad - mDeltaDis;
00433             if (rad < 0)
00434                 rad = 0;
00435             
00436             count_depolar(teta, gama, rad, &vx, &vy, &vz);
00437             mpParent->SetViewer(vx, vy, vz);
00438         }
00439         break;
00440     case 'z':
00441     case 'Z':
00442         {
00443             rad = rad + mDeltaDis;
00444             if (rad > 30)
00445                 rad = 30;
00446             
00447             count_depolar(teta, gama, rad, &vx, &vy, &vz);
00448             mpParent->SetViewer(vx, vy, vz);
00449         }
00450         break;
00451     default:
00452         return false;
00453     }
00454 
00455     if (!mbKeyInProcessing)
00456     {
00457         mbKeyInProcessing = true;
00458         mpParent->AddEventListener(this);
00459     }
00460     return true;
00461 }
00462 
00463 
00464 ViewBongoFollower::ViewBongoFollower(Engine* parent, Bongo* bongo)
00465 : mpParent(parent), mpBongo(bongo)
00466 {
00467     bongo->RegisterListener(this);
00468     memcpy(mpParent->mViewCenter, bongo->Position(), 3 * sizeof(double) );
00469     memcpy(mOldCenter, mpParent->mViewCenter, 3 * sizeof(double) );
00470     mPower = 0.04;
00471     mDistance = 0.0;
00472     memset(mDirection, 0, sizeof(mDirection) );
00473 }
00474 
00475 bool ViewBongoFollower::Move()
00476 { 
00477     double far1 = mPower;
00478     if (mDistance == 0)
00479         return false;
00480 
00481     if (far1 > mDistance)
00482     {
00483         vec_mul(mDirection, mDistance/far1);
00484         far1 = mDistance;   
00485     }
00486     vec_add(mpParent->mViewPos, mDirection);
00487     vec_add(mOldCenter, mDirection);
00488   
00489     mDistance -= far1;
00490     if (0 == mDistance)
00491     {
00492         memset(mDirection, 0, sizeof(mDirection) );
00493     }
00494     return true;
00495 }
00496 
00497 void ViewBongoFollower::QuadEvent()
00498 {
00499     memcpy(mpParent->mViewCenter, mpBongo->Position(), 3 * sizeof(double) );    
00500 
00501     memcpy(mDirection, mOldCenter, sizeof(mDirection) );    
00502     vec_mul(mDirection, -1);
00503     vec_add(mDirection, mpParent->mViewCenter);
00504 
00505     mDistance = vec_magnitude(mDirection);
00506     vec_mul(mDirection, mPower/mDistance);
00507 }
00508