00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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();
00051 cam->setFarValue(8000);
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
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
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
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
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
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
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
00123 device->getCursorControl()->setPosition( 0.5f, 0.5f );
00124 device->getCursorControl()->setVisible(false);
00125
00126
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)
00138 {
00139 recognizeTime = now;
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 player.acceleration.Y += ydirection/100.0f;
00154
00155
00156
00157
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
00177
00178
00179
00180 if (! player.node) return;
00181
00182
00183
00184
00185
00186
00187
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
00215
00216
00217
00218 if (! player.node) return;
00219
00220
00221
00222
00223
00224
00225
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
00274
00275
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 ) );
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
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
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
00305 player.node->setRotation(player.node->getRotation() + v3(-90, -90, 0) );
00306 }
00307 }
00308
00309
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;
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
00340 light->setPosition(player.node->getPosition() + v3(100,100,100));
00341
00342 player.node->removeAnimators();
00343 }
00344
00345
00346 list<Obj*>::Iterator it = objects.begin();
00347 while(it != objects.end())
00348 {
00349
00350 (*it)->node->setRotation((*it)->node->getRotation() + (*it)->rot);
00351
00352
00353 if (! ringFound)
00354 {
00355 if ( searchName.equals_ignore_case((*it)->name) )
00356 {
00357
00358 nextRingPosition = (*it)->node->getPosition();
00359 ringFound = true;
00360 }
00361 }
00362
00363
00364
00365
00366 f64 distance = (*it)->node->getPosition().getDistanceFrom(player.node->getPosition());
00367 if ( distance < 800.0f )
00368 {
00369
00370 if ( searchName.equals_ignore_case((*it)->name) )
00371 {
00372
00373
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
00381
00382
00383
00384
00385
00386
00387 }
00388 if (collided)
00389 {
00390
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)
00400 break;
00401 else
00402 continue;
00403 }
00404 }
00405 else
00406 {
00407
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
00416 collisionCount++;
00417
00418 }
00419 }
00420
00421
00422 it++;
00423 }
00424
00425 if (! ringFound)
00426 {
00427
00428 gameState = STATE_LEVEL_END;
00429 }
00430
00431 addDbg("near collisions", collisionCount);
00432
00433
00434 now = timer->getTime();
00435
00436 if (oldTime + 1000 < now)
00437 {
00438 oldTime = now;
00439 levelTime--;
00440
00441
00442 stringc sTime(makeASCII(levelTime));
00443
00444 int charNum = sTime.size();
00445
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
00458 recognizeFlap();
00459
00460
00461 thirdPersonCam();
00462
00463
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
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