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:
00059
00060 mpParent->SendEvent(EventListener::EV_CANCEL);
00061
00062
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
00072 mpParent->Pause();
00073 mpParent->SetActiveController(mpParent->GetMenuController() );
00074 mpParent->SetActiveDisplay(mpParent->GetMenuDisplay() );
00075 glutPostRedisplay();
00076 }
00077
00078 return true;
00079
00080 case 'n':
00081 case 'N':
00082 mpParent->NextLevel();
00083 return true;
00084
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
00140
00141
00142
00143
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