controller.h

00001 
00002 
00003 
00004 /*
00005 #define MEDIAFILE_SKYBOX_TOP            "skyBoxTop.jpg"
00006 #define MEDIAFILE_SKYBOX_BOTTOM         "skyBoxBottom.jpg"
00007 #define MEDIAFILE_SKYBOX_RIGHT          "skyBoxLeft.jpg"
00008 #define MEDIAFILE_SKYBOX_LEFT           "skyBoxRight.jpg" 
00009 #define MEDIAFILE_SKYBOX_FRONT          "skyBoxFront.jpg"
00010 #define MEDIAFILE_SKYBOX_BACK           "skyBoxBack.jpg"
00011 
00012 #define MEDIAFILE_SKYBOX_TOP            "boxSide1.PNG"
00013 #define MEDIAFILE_SKYBOX_BOTTOM         "boxSide2.PNG"
00014 #define MEDIAFILE_SKYBOX_RIGHT          "boxSide3.PNG"
00015 #define MEDIAFILE_SKYBOX_LEFT           "boxSide4.PNG"
00016 #define MEDIAFILE_SKYBOX_FRONT          "boxSide5.PNG"
00017 #define MEDIAFILE_SKYBOX_BACK           "boxSide6.PNG"
00018 */
00019 #define MEDIAFILE_SKYBOX_TOP            "skybox_1.jpg"
00020 #define MEDIAFILE_SKYBOX_BOTTOM         "skybox_2.jpg"
00021 #define MEDIAFILE_SKYBOX_RIGHT          "skybox_3.jpg"
00022 #define MEDIAFILE_SKYBOX_LEFT           "skybox_4.jpg"
00023 #define MEDIAFILE_SKYBOX_FRONT          "skybox_5.jpg"
00024 #define MEDIAFILE_SKYBOX_BACK           "skybox_6.jpg"
00025 
00026 //#define MEDIAFILE_TEXTURE_LIGHT               "particlewhite.bmp"
00027 #define MEDIAFILE_ARROW                         "arrow.3ds"
00028 
00029 #define PLAYER_MAX_SPEED                        8.0f
00030 #define PLAYER_ACCELERATION                     0.001f
00031 #define PLAYER_MAX_ACCEL                        0.1f
00032 
00033 #define PLAYER_ACCEL_Y                          0.01f
00034 #define PLAYER_MAX_SPEED_Y                      3.0f
00035 #define PLAYER_MAX_ACCEL_Y                      0.1f
00036 #define RECOGNIZE_FLAP_UP                       3.0f
00037 #define RECOGNIZE_FLAP_DOWN                     -3.0f
00038 
00039 
00040 #define CAMERA_Y_DIRECTION_MAX          10.0f   // range = -10..+10
00041 
00042 
00043 
00044 void reset()
00045 {
00046         if (dbg) dbg->remove();
00047         dbg = guienv->addStaticText(L"", rect<s32>(10,10,300,300), true, true, 0, -1, true);
00048         
00049         if (cam) cam->remove();
00050         cam = smgr->addCameraSceneNode();// FPS(0,100,100);
00051         cam->setFarValue(8000); // render also far objects
00052 
00053         if (light) light->remove();
00054         light = smgr->addLightSceneNode(0, v3(100,100,100), SColorf(0.3f, 0.3f, 1.0f), 10);
00055         
00056         
00057         if (skyBox) skyBox->remove();
00058         skyBox = smgr->addSkyBoxSceneNode(
00059                                 driver->getTexture(makeMediaString(MEDIAFILE_SKYBOX_TOP).c_str()),
00060                                 driver->getTexture(makeMediaString(MEDIAFILE_SKYBOX_BOTTOM).c_str()),
00061                                 driver->getTexture(makeMediaString(MEDIAFILE_SKYBOX_LEFT).c_str()),
00062                                 driver->getTexture(makeMediaString(MEDIAFILE_SKYBOX_RIGHT).c_str()),
00063                                 driver->getTexture(makeMediaString(MEDIAFILE_SKYBOX_FRONT).c_str()),
00064                                 driver->getTexture(makeMediaString(MEDIAFILE_SKYBOX_BACK).c_str())
00065                          );
00066 
00067         if (arrow) arrow->remove();
00068         arrow = smgr->addMeshSceneNode(smgr->getMesh(makeMediaString(MEDIAFILE_ARROW).c_str())->getMesh(0));
00069         arrow->setScale(v3(0.005f,0.005f,0.005f));
00070         //arrow->setScale(v3(0.1f,0.1f,0.1f));
00071         arrow->setMaterialFlag(EMF_WIREFRAME, false);
00072         arrow->setMaterialFlag(EMF_LIGHTING, true);
00073 
00074         timer = device->getTimer();
00075         nextRingPosition = v3(0,0,0);
00076         
00077         // remove all items in list
00078         list<Obj*>::Iterator it = objects.begin();
00079         while(it != objects.end())
00080         {
00081                 (*it)->node->remove();
00082                 delete (*it);
00083                 it++;
00084         }
00085         objects.clear();
00086 
00087         // remove player
00088         if (player.node)
00089         {       
00090                 player.node->remove();
00091                 delete player.node;
00092                 player.node = 0;
00093         }
00094         player.velocity = v3(0, 0, 0);
00095         player.acceleration = v3(0, 0, PLAYER_ACCELERATION);
00096 
00097         // create number[0..9] font to display levelTime
00098         for (int i=0; i<10; i++)
00099         {
00100                 stringc fileName(MEDIAPATH_NUMBERS);
00101                 fileName.append(makeASCII(i));
00102                 fileName.append(".png");
00103                 numbers[i] = driver->getTexture(fileName.c_str());
00104         }
00105 
00106         // create images for time display [123]
00107         for (int i=0; i<3; i++)
00108         {
00109                 s32 offset = 800 / 3 - (128/2);
00110                 if (time[i]) time[i]->remove();
00111                 time[i] = guienv->addImage(rect<s32>(i*128+offset, 20, i*128+128+offset, 148));
00112                 time[i]->setUseAlphaChannel(true);
00113                 time[i]->setVisible(true);
00114         }
00115 
00116         // load image to present at end of level
00117         endImgTexture = driver->getTexture(makeMediaString(MEDIAFILE_END_IMAGE).c_str());
00118         endImg = guienv->addImage(rect<s32>(0, 0, 800, 600));
00119         endImg->setImage(endImgTexture);
00120         endImg->setVisible(false);
00121 
00122         // center mouse-pointer and get rid of em
00123         device->getCursorControl()->setPosition( 0.5f, 0.5f );
00124         device->getCursorControl()->setVisible(false);
00125 
00126         // init game time
00127         oldTime = timer->getTime();
00128 }
00129 
00130 void recognizeFlap()
00131 {
00132         static u32 recognizeTime = timer->getTime();
00133         static float yTop = 0.0f;
00134         static float yDown = 0.0f;
00135 
00136 
00137         if (true)//recognizeTime + 100 < now) // 10ms elapsed
00138         {
00139                 recognizeTime = now;
00140                 /*
00141                 if (ydirection > RECOGNIZE_FLAP_UP)
00142                 {
00143                         //player.acceleration.Y += PLAYER_ACCEL_Y;
00144                         player.acceleration.Y += ydirection/10.0f;
00145                 }
00146                 if (ydirection < RECOGNIZE_FLAP_DOWN)
00147                 {
00148                         //player.acceleration.Y -= PLAYER_ACCEL_Y;
00149                         player.acceleration.Y += ydirection/10.0f;
00150                 }
00151                 */
00152                 
00153                 player.acceleration.Y += ydirection/100.0f;
00154                 /*
00155                 if (ydirection > RECOGNIZE_FLAP_DOWN && ydirection < RECOGNIZE_FLAP_UP)
00156                 {
00157                         player.velocity.Y /= 2.0f;
00158                 }
00159                 */
00160                 player.velocity.Y += player.acceleration.Y;
00161 
00162                 if (player.acceleration.Y > PLAYER_MAX_ACCEL_Y)
00163                         player.acceleration.Y = PLAYER_MAX_ACCEL_Y;
00164                 if (player.acceleration.Y < -PLAYER_MAX_ACCEL_Y)
00165                         player.acceleration.Y = -PLAYER_MAX_ACCEL_Y;
00166                 if (player.velocity.Y > PLAYER_MAX_SPEED_Y)
00167                         player.velocity.Y = PLAYER_MAX_SPEED_Y;
00168                 if (player.velocity.Y < -PLAYER_MAX_SPEED_Y)
00169                         player.velocity.Y = -PLAYER_MAX_SPEED_Y;
00170         }
00171 }
00172 
00173 void animateLeftWing(float trackedBodyPos, float rangeMin, float rangeMax)
00174 {
00175 /*
00176         static float sinCnt;
00177         sinCnt += 0.1f;
00178         float trackedBodyPos = sin(sinCnt) * 100;       // swing -100 .. +100
00179 */
00180         if (! player.node) return;
00181 
00182         /* bone 2 is left wing:
00183         ---------------------------------
00184         Pos     x               y               z               w
00185         /       -0.567  0.728    0.339  -0.179
00186         -       -0.611  0.791    0.000   0.000
00187         \       -0.606  0.784   -0.114   0.064
00188         ---------------------------------
00189         */
00190 
00191         CalQuaternion q;
00192         if (trackedBodyPos > 0)
00193         {
00194                 q.x =          mapToScale(-0.611f, -0.567f, trackedBodyPos, 0.0f, rangeMax);
00195                 q.y = 0.791f - mapToScale(+0.000f, +0.063f, trackedBodyPos, 0.0f, rangeMax);
00196                 q.z =          mapToScale(+0.000f, +0.339f, trackedBodyPos, 0.0f, rangeMax);
00197                 q.w = 0.000f - mapToScale(+0.000f, +0.179f, trackedBodyPos, 0.0f, rangeMax);
00198         }
00199         else
00200         {
00201                 q.x =-0.606f - mapToScale(+0.000f, +0.005f, trackedBodyPos, rangeMin, 0.0f);
00202                 q.y =          mapToScale(+0.784f, +0.791f, trackedBodyPos, rangeMin, 0.0f);
00203                 q.z =          mapToScale(-0.114f, +0.000f, trackedBodyPos, rangeMin, 0.0f);
00204                 q.w = 0.061f - mapToScale(+0.000f, +0.064f, trackedBodyPos, rangeMin, 0.0f);
00205         }
00206 
00207         player.leftBone = q;
00208         player.node->setBoneRotation(2, player.leftBone);
00209 }
00210 
00211 void animateRightWing(float trackedBodyPos, float rangeMin, float rangeMax)
00212 {
00213 /*
00214         static float sinCnt;
00215         sinCnt += 0.1f;
00216         float trackedBodyPos = sin(sinCnt) * 100;       // swing -100 .. +100
00217 */
00218         if (! player.node) return;
00219 
00220         /* bone 1 is right wing:
00221         ---------------------------------
00222         Pos     x               y               z               w
00223         /       0.220   0.315   0.574   0.723
00224         -       0.000   0.000   0.611   0.790
00225         \       -0.078  -0.110  0.606   0.783
00226         ---------------------------------
00227         */
00228 
00229         CalQuaternion q;
00230         if (trackedBodyPos > 0)
00231         {
00232                 q.x =          mapToScale(+0.000f, +0.220f, trackedBodyPos, 0.0f, rangeMax);
00233                 q.y =          mapToScale(+0.000f, +0.315f, trackedBodyPos, 0.0f, rangeMax);
00234                 q.z = 0.611f - mapToScale(+0.000f, +0.037f, trackedBodyPos, 0.0f, rangeMax);
00235                 q.w = 0.790f - mapToScale(+0.000f, +0.067f, trackedBodyPos, 0.0f, rangeMax);
00236         }
00237         else
00238         {
00239                 q.x =          mapToScale(-0.078f, +0.000f, trackedBodyPos, rangeMin, 0.0f);
00240                 q.y =          mapToScale(-0.110f, +0.000f, trackedBodyPos, rangeMin, 0.0f);
00241                 q.z =          mapToScale(+0.606f, +0.611f, trackedBodyPos, rangeMin, 0.0f);
00242                 q.w =          mapToScale(+0.783f, +0.790f, trackedBodyPos, rangeMin, 0.0f);
00243         }
00244 
00245         player.rightBone = q;
00246         player.node->setBoneRotation(1, player.rightBone);
00247 }
00248 
00249 void thirdPersonCam()
00250 {
00251         position2d<f32> cursorPos = device->getCursorControl()->getRelativePosition(); 
00252         v3 cameraPos = cam->getAbsolutePosition(); 
00253             
00254         float change_x = ( cursorPos.X - 0.5f ) * 128.f;
00255         float change_y = ( cursorPos.Y - 0.5f ) * 128.f;
00256         direction += change_x; 
00257         ydirection -= change_y; 
00258         if( ydirection < -CAMERA_Y_DIRECTION_MAX ) 
00259                 ydirection = -CAMERA_Y_DIRECTION_MAX; 
00260         else 
00261         if( ydirection > CAMERA_Y_DIRECTION_MAX ) 
00262                 ydirection = CAMERA_Y_DIRECTION_MAX; 
00263         device->getCursorControl()->setPosition( 0.5f, 0.5f ); 
00264 
00265         v3 playerPos;
00266         if (player.node)
00267         {
00268                 playerPos = player.node->getPosition();
00269                 playerPos.Y += player.velocity.Y;
00270                 player.node->setPosition(playerPos);
00271         }
00272 /*                         
00273         float yf = playerPos.Y - sin( ydirection * PI / 180.0f ) * 4.0f;
00274         float xf = playerPos.X - cos( ydirection * PI / 180.0f ) * cos( direction * PI / 180.0f ) * 4.0f; 
00275     float zf = playerPos.Z + cos( ydirection * PI / 180.0f ) * sin( direction * PI / 180.0f ) * 4.0f;
00276 */
00277         float yf = playerPos.Y +2.0f;
00278         float xf = playerPos.X - cos( direction * PI / 180.0f ) * 4.0f; 
00279     float zf = playerPos.Z + sin( direction * PI / 180.0f ) * 4.0f;
00280 
00281         cam->setPosition( v3( xf, yf+2.0f, zf ) );      // yf
00282         cam->setTarget( v3( playerPos.X, playerPos.Y+2.0f, playerPos.Z-0.0f ) );
00283         
00284         if (player.node)
00285         {
00286                 player.node->setRotation( v3( 0, direction, 0 ) ); 
00287 
00288                 // make/check speed
00289                 player.acceleration.Z++;
00290                 if (player.acceleration.Z > PLAYER_MAX_ACCEL)
00291                         player.acceleration.Z = PLAYER_MAX_ACCEL;
00292                 player.velocity.Z += player.acceleration.Z;
00293                 if (player.velocity.Z > PLAYER_MAX_SPEED)
00294                         player.velocity.Z = PLAYER_MAX_SPEED;
00295                 
00296                 // move player
00297                 float degree = ( player.node->getRotation().Y + 90.0f ) * PI/180.0f;
00298                 v3 facing( sin(degree), 0, cos(degree)); 
00299                 facing.normalize(); 
00300                 
00301                 v3 newPos = (facing * player.velocity.Z) + player.node->getPosition(); 
00302                 player.node->setPosition(newPos);
00303 
00304                 // correct view on dragon, don't know why...
00305                 player.node->setRotation(player.node->getRotation() +  v3(-90, -90, 0) ); 
00306         }
00307 }
00308 
00309 // can only be called after smgr->drawAll() has been called!
00310 void drawLine(v3 start, v3 end)
00311 {
00312         matrix4 oldMatrix = driver->getTransform(ETS_WORLD);
00313         int mCnt = cam->getMaterialCount();
00314         SMaterial oldMaterial = cam->getMaterial(mCnt);
00315 
00316         driver->setTransform(ETS_WORLD, matrix4());
00317         SMaterial m;
00318         m.EmissiveColor = SColor(255,255,255,255);
00319         driver->setMaterial(m);
00320         driver->draw3DLine(start, end);
00321 
00322         driver->setTransform(ETS_WORLD, oldMatrix);
00323         driver->setMaterial(oldMaterial);
00324 }
00325 
00326 void update()
00327 {
00328         static int collisionCount = 0;  // dbg
00329 
00330         stringc searchName("ring");
00331         bool ringFound = false;
00332         ITriangleSelector* selector = 0;
00333         ISceneNodeAnimator* anim = 0;
00334         
00335         collisionCount = 0;
00336 
00337         if (player.node)
00338         {
00339                 // light up scene
00340                 light->setPosition(player.node->getPosition() + v3(100,100,100));
00341                 // collision: remove all responses, they will be added again, if objects in range
00342                 player.node->removeAnimators();
00343         }
00344 
00345         // iterate through all objects
00346         list<Obj*>::Iterator it = objects.begin();
00347         while(it != objects.end())
00348         {
00349                 // rotate each asteroid
00350                 (*it)->node->setRotation((*it)->node->getRotation() + (*it)->rot);
00351                 
00352                 // search next ring
00353                 if (! ringFound)
00354                 {
00355                         if ( searchName.equals_ignore_case((*it)->name) )
00356                         {
00357                                 // save ring position. arrow will point to this position.
00358                                 nextRingPosition = (*it)->node->getPosition();
00359                                 ringFound = true;
00360                         }
00361                 }
00362 
00363                 // collision:
00364                 //(*it)->node->setMaterialFlag(EMF_LIGHTING, true);     //dbg
00365                 // how far is this asteroid from us?
00366                 f64 distance = (*it)->node->getPosition().getDistanceFrom(player.node->getPosition());
00367                 if ( distance < 800.0f )
00368                 {
00369                         // is it a ring?
00370                         if ( searchName.equals_ignore_case((*it)->name) )
00371                         {
00372                                 // near enough, check for collission
00373                                 // delete ring, if hit
00374                                 v3 distPR = player.node->getPosition() - (*it)->node->getPosition();
00375                                 bool collided = false;
00376                                 if ( distPR.getLength() < 30.0f )
00377                                 {
00378                                         collided = true;
00379                                         /*
00380                                         // dives player really into ring?
00381                                         float angelPR = getTargetAngle(p, r).Y;
00382                                         if ( isInRange(angelPR, 000.00f, 030.0f) ||
00383                                                  isInRange(angelPR, 350.00f, 380.0f) ||
00384                                                  isInRange(angelPR, 150.00f, 210.0f) )
00385                                                 collided = true;
00386                                         */
00387                                 }
00388                                 if (collided)
00389                                 {
00390                                         // delete ring
00391                                         (*it)->mesh = 0;
00392                                         (*it)->name = stringc("deleted ring");
00393                                         (*it)->node->remove();
00394                                         (*it)->node = 0;
00395                                         (*it)->rot = v3(0,0,0);
00396                                         delete (*it);
00397                                         it = objects.erase(it);
00398 
00399                                         if (it == NULL)         // this ring was the last element in list
00400                                                 break;
00401                                         else
00402                                                 continue;
00403                                 }
00404                         }
00405                         else    // its not a ring, its a asteroid
00406                         {
00407                                 // near enough, add collission response
00408                                 selector = smgr->createTriangleSelector((*it)->mesh, (*it)->node);
00409                                 (*it)->node->setTriangleSelector(selector);
00410                                 selector->drop();
00411                                 anim = smgr->createCollisionResponseAnimator( selector, player.node, v3(30,50,30), v3(0,0,0), v3(0,0,0), 0.0f );
00412                                 player.node->addAnimator(anim);
00413                                 anim->drop();
00414 
00415                                 // Dbg: hilight asteroid and count it
00416                                 collisionCount++;
00417                                 //(*it)->node->setMaterialFlag(EMF_LIGHTING, false);    //dbg
00418                         }
00419                 }
00420 
00421                 // goto next asteroid/ring
00422                 it++;
00423         }
00424 
00425         if (! ringFound)
00426         {
00427                 // no more rings in this level, goto next level
00428                 gameState = STATE_LEVEL_END;
00429         }
00430 
00431         addDbg("near collisions", collisionCount);      // dbg
00432 
00433         // count down game time
00434         now = timer->getTime();
00435         //cout << "Level::update() virtual time:" << now << endl;
00436         if (oldTime + 1000 < now)
00437         {
00438                 oldTime = now;
00439                 levelTime--;
00440 
00441                 // render bitmaps onto screen. use numbers font [0..9]
00442                 stringc sTime(makeASCII(levelTime));
00443                 // how many chars?
00444                 int charNum = sTime.size();
00445                 // prepare images
00446                 for (int i=0; i<charNum; i++)
00447                 {
00448                         char cDigit = sTime[i];
00449                         int index = cDigit - '0';
00450                         if (isInRange(index, 0 , 9))
00451                         {
00452                                 time[i]->setImage(numbers[index]);
00453                         }
00454                 }
00455         }
00456 
00457         // up/down movement
00458         recognizeFlap();
00459 
00460         // allways look at player
00461         thirdPersonCam();
00462 
00463         // set arrow in front of camera and rotete its face to next ring
00464         float camDegree = ( direction + 120.0f  ) * PI/180.0f;
00465         v3 camFacing( sin(camDegree), ydirection/90.0f - 0.4f, cos(camDegree));
00466         camFacing.normalize();
00467         arrow->setPosition( camFacing*2.0f + cam->getPosition() );
00468         arrow->setRotation(getTargetAngle(arrow->getPosition(), nextRingPosition));
00469 
00470         // animate the wings according to mouse y-movement
00471         if (! renderOfflineAnim)
00472         {
00473                 animateLeftWing(ydirection, -CAMERA_Y_DIRECTION_MAX, CAMERA_Y_DIRECTION_MAX);
00474                 animateRightWing(ydirection, -CAMERA_Y_DIRECTION_MAX, CAMERA_Y_DIRECTION_MAX);
00475         }
00476 }
00477 

Generated on Sun Dec 2 18:30:26 2007 for DrgonWings by  doxygen 1.5.4