00001 #include "ScreenFPS2.h"
00002 #include "MercuryDisplay.h"
00003 #include "MercuryTheme.h"
00004 #include "MercuryInput.h"
00005 #include "MercuryShapes.h"
00006 #include "MercuryLog.h"
00007 #include "MercuryTextureManager.h"
00008
00009 KeyMappingWithCode( button_a, "0-97" );
00010 KeyMappingWithCode( button_b, "0-98" );
00011 KeyMappingWithCode( button_s, "0-115" );
00012 KeyMappingWithCode( button_d, "0-100" );
00013 KeyMappingWithCode( button_w, "0-119" );
00014 KeyMappingWithCode( button_mouse1, "0-1" );
00015 KeyMappingWithCode( button_mouse2, "0-2" );
00016 KeyMappingWithCode( button_u, "0-117" );
00017 KeyMappingWithCode( button_t, "0-116" );
00018 KeyMappingWithCode( button_space, "0-32" );
00019
00020 REGISTER_SCREEN_CLASS( ScreenFPS2 );
00021
00022 #define MC_INPUTMAPPED 1 //convention: MESSAGE CODE
00023 #define MC_EXPLOSION 2 //convention: MESSAGE CODE
00024
00025 ScreenFPS2::~ScreenFPS2()
00026 {
00027 m_pCamera = NULL;
00028 }
00029
00030 void ScreenFPS2::Init()
00031 {
00032 ScreenOutdoors::Init();
00033
00034 pTweenCommands.resize(4);
00035 pTweenCommands[0].sAnimationName = "run_lower";
00036 pTweenCommands[0].fPercent = .5;
00037 pTweenCommands[1].sAnimationName = "run_upper";
00038 pTweenCommands[1].fPercent = .25;
00039
00040 pTweenCommands[2].sAnimationName = "shootright_upper";
00041 pTweenCommands[2].bLoop = pTweenCommands[2].bRunning = false;
00042 pTweenCommands[3].sAnimationName = "shootleft_upper";
00043 pTweenCommands[3].fRate = 2;
00044 pTweenCommands[3].bLoop = pTweenCommands[3].bRunning = false;
00045
00046 m_pPlayer.SetName( "jupiter" );
00047 m_pPlayer.Init();
00048 m_pPlayer.SetRotX( 90 );
00049 m_pPlayer.SetScale( MercuryPoint( 0.1f,0.1f,0.1f ) );
00050 m_pPlayer.Load( GET_MODEL_BY_NAME( "jupiter" ) );
00051 m_pPlayer.SetAnimationState( pTweenCommands );
00052 AddPerspObject( &m_pPlayer );
00053
00054 pBullet.SetName( "BULLET" );
00055 pBullet.Init();
00056 pBullet.NotifyClass( this, "rayhit" );
00057 pBullet.SetDrawOrder( 10000 );
00058 AddPerspObject( &pBullet, false );
00059
00060 m_Aimer.SetName( "BULLET Aimer" );
00061 m_Aimer.Init();
00062 m_Aimer.NotifyClass( this, "aimhit" );
00063 m_oldInter = m_interactable = false;
00064 fClosestAimerObject = 100000;
00065
00066 pPhysics.SetName( "PHYSGUN" );
00067 pPhysics.Init();
00068 pPhysics.NotifyClass( this, "physhit" );
00069 pPhysics.SetDrawOrder( 10000 );
00070 AddPerspObject( &pPhysics, false );
00071 iPhysicsObject = 0;
00072 fClosestPhysicsObject = 100000;
00073
00074 m_pINI.Open( GET_FILE_BY_NAME( "IniFile" ) );
00075
00076 m_pWorld.Init();
00077 m_pWorld.LoadFromINI( m_pINI, THEME.GetMetricS( m_name, "WorldName" ) );
00078 AddPerspObject( &m_pWorld );
00079
00080 m_fCamera.SetName( "Camera" );
00081 m_fCamera.Init();
00082 m_fCamera.SetUp(MercuryPoint(0,0,1));
00083 m_pCamera = &m_fCamera;
00084 m_fCamera.Tweening.AddCommand( THEME.GetMetricS( m_name, "CamTween" ), MercuryTweenState::LOCAL, "CamTween" );
00085
00086 m_fTimeSinceLastShot = 0;
00087 m_fForwardMovement = 0;
00088
00089 m_bFPS = true;
00090 m_sprCrosshairs.SetName( "Crosshairs" );
00091 m_sprCrosshairs.Init();
00092 m_sprCrosshairs.LoadImage( "GRAPHIC:targetret2.png" );
00093 m_sprCrosshairs.SetPosition( MercuryPoint( 320,240, 0 ) );
00094 m_sprCrosshairs.SetDrawOrder( 10001 );
00095 m_sprCrosshairs.Tweening.AddCommand( THEME.GetMetricS( m_name, "CrosshairsOnTarget" ), MercuryTweenState::LOCAL, "OnTarget" );
00096 m_sprCrosshairs.Tweening.AddCommand( THEME.GetMetricS( m_name, "CrosshairsOffTarget" ), MercuryTweenState::LOCAL, "OffTarget" );
00097 m_sprCrosshairs.Tweening.ExecuteCommand("OffTarget", PStack());
00098 AddOrthoObject( &m_sprCrosshairs );
00099
00100 m_sprCrosshairsCenter.SetName( "CrosshairsCenter" );
00101 m_sprCrosshairsCenter.Init();
00102 m_sprCrosshairsCenter.LoadImage( "GRAPHIC:targetret.png" );
00103 m_sprCrosshairsCenter.SetPosition( MercuryPoint( 320,240, 0 ) );
00104 m_sprCrosshairsCenter.SetDrawOrder( 10000 );
00105 AddOrthoObject( &m_sprCrosshairsCenter );
00106
00107
00108 m_DynTex.AttachTexture( "DYNCUBE:hello,256,256,0" );
00109
00110 m_DynTex.Init();
00111
00112 MercuryShape * k = new MercuryShape;
00113 k->SetName( "testshape" );
00114 k->Init();
00115 k->LoadImage( "GRAPHIC:test3.ini" );
00116 k->SetScale( MercuryPoint( 4,4,4 ) );
00117 k->MakeBox();
00118 k->SetPosition( MercuryPoint( 0,0,5));
00119 k->Tweening.AddCommand( "linear,1000;rotationx,108000" );
00120 m_DynTex.AddObject( k, true );
00121
00122 m_DynTex.SetDrawOrder( -100 );
00123 AddPerspObject( &m_DynTex, false );
00124
00125
00126 RegisterMessage( MC_INPUTMAPPED, "mappedinput" );
00127 RegisterMessage( MC_EXPLOSION, "DoExplosion" );
00128 m_slowDown = false;
00129 m_fistExplosion = m_donefirst = false;
00130 }
00131
00132 void ScreenFPS2::CalculateMovement(MercuryODEObject* control)
00133 {
00134 int dx=0;
00135 int dy=0;
00136 if ( INPUTMAN->IsButtonDown( button_d ) )
00137 dy -= 5;
00138 if ( INPUTMAN->IsButtonDown( button_a ) )
00139 dy += 5;
00140 if ( INPUTMAN->IsButtonDown( button_w ) )
00141 dx += 5;
00142 if ( INPUTMAN->IsButtonDown( button_s ) )
00143 dx -= 5;
00144
00145 float Amplitude = SQRT(float((dx*dx)+(dy*dy)));
00146 float AngleToGo=ATAN2(float(dx),float(-dy));
00147
00148 MercuryPoint Target = m_pWorld.GetODEObjectByName( "Control" )->GetPosition();
00149 MercuryPoint From = Target - pTarget;
00150
00151 float AngleDiff=ATAN2((From-Target).x,(From-Target).y);
00152 float RealAngle = AngleToGo - AngleDiff - 1.57f;
00153
00154 dBodyEnable( control->m_oBody );
00155 dBodySetAngularVel( control->m_oBody, COS(RealAngle)*Amplitude,SIN(RealAngle)*Amplitude,0);
00156
00157
00158 if( INPUTMAN->IsButtonDown( button_space ) )
00159 {
00160 dBodyAddForce( control->m_oBody, SIN(RealAngle)*Amplitude*800,-COS(RealAngle)*Amplitude*800,3900 );
00161 }
00162
00163
00164 PlayRobotAnimations(dx);
00165 }
00166
00167 void ScreenFPS2::PlayRobotAnimations(int dx)
00168 {
00169 if (m_fForwardMovement > 0 )
00170 m_fForwardMovement = (m_fForwardMovement + float(dx)/50) - 0.025f;
00171 else
00172 m_fForwardMovement = (m_fForwardMovement + float(dx)/50) + 0.025f;
00173
00174 m_fForwardMovement = Clamp( m_fForwardMovement, -1.0f, 1.0f );
00175
00176 if( m_fForwardMovement < 0.05 && m_fForwardMovement > -0.05f )
00177 m_fForwardMovement = 0;
00178
00179 m_pPlayer.GetAllAnimationStates( pTweenCommands );
00180 pTweenCommands[0].fPercent = m_fForwardMovement;
00181 pTweenCommands[0].fRate = ABS(m_fForwardMovement)*1.5f;
00182 pTweenCommands[1].fPercent = m_fForwardMovement/2;
00183 pTweenCommands[1].fRate = ABS(m_fForwardMovement)*1.5f;
00184
00185 if( m_fTimeSinceLastShot == 0 )
00186 pTweenCommands[3].Trigger();
00187
00188 m_pPlayer.SetAnimationState( pTweenCommands );
00189 }
00190
00191 void ScreenFPS2::Update( const float dTime )
00192 {
00193 if (dTime == 0)
00194 return;
00195
00196 if ( m_bFirstUpdate )
00197 {
00198 m_bFirstUpdate = false;
00199 return;
00200 }
00201
00202 float adjTime = dTime;
00203 if (m_slowDown > 0)
00204 {
00205 m_slowDown -= dTime;
00206 adjTime /= 5;
00207 }
00208
00209 if ((m_slowDown <= 0) && m_fistExplosion)
00210 {
00211 m_donefirst = true;
00212 m_slowDown = 0;
00213 }
00214
00215
00216 MercuryODEObjectLoadable* water = (MercuryODEObjectLoadable*)m_pWorld.GetODEObjectByName("Water");
00217 if (water)
00218 {
00219 water->GetGLState().Disable(MGLS_OPAQUE);
00220 MercuryShape* s = (MercuryShape*)water->m_vMercuryShapes[0];
00221 if (s)
00222 {
00223 MercuryMaterial* mw = s->GetMaterial(0);
00224 if (mw)
00225 {
00226 mw->EditTexture(0)->MoveY( dTime/THEME.GetMetricF( m_name, "WaterPeriodSecY" ));
00227 mw->EditTexture(0)->MoveX( dTime/THEME.GetMetricF( m_name, "WaterPeriodSecX" ));
00228 }
00229 }
00230 }
00231
00232 int x, y;
00233 INPUTMAN->GetCursorPosition(x, y);
00234 MercuryODEObject* control = m_pWorld.GetODEObjectByName( "Control" );
00235
00236 CalculateMovement(control);
00237
00238
00239 CalculateLook(x, y, control);
00240
00241
00242 m_Aimer.Disable();
00243 m_Aimer.EnableForShot( m_pWorld.GetWorldSpaceID(), 50000, m_pGun, pLookAt );
00244
00245 ScreenOutdoors::Update( adjTime );
00246
00247
00248 TweenCamera(x, y, control);
00249
00250 m_pPlayer.SetPosition( control->GetPosition( ) );
00251
00252 pPhysics.Disable();
00253
00254 if ( iPhysicsObject != 0 )
00255 {
00256
00257 MercuryPoint pNewPos = m_pGun + pLookAt.Normalize() * fClosestPhysicsObject;
00258 fClosestPhysicsObject = fClosestPhysicsObject * 0.95f + 2;
00259 MercuryPoint pCurrentPos( dBodyGetPosition( (dBodyID)iPhysicsObject ) );
00260
00261
00262 MercuryPoint pDir = pNewPos-pCurrentPos;
00263 pDir *= (0.4f/dTime);
00264 dBodySetLinearVel( (dBodyID)iPhysicsObject, pDir.x, pDir.y, pDir.z );
00265 dBodyEnable( (dBodyID)iPhysicsObject );
00266 }
00267
00268
00269
00270 m_fTimeSinceLastShot += dTime;
00271 pBullet.Disable();
00272 if( m_fTimeSinceLastShot > .25 && INPUTMAN->IsButtonDown( button_mouse1 ) )
00273 {
00274 m_fTimeSinceLastShot = 0;
00275 pBullet.EnableForShot( m_pWorld.GetWorldSpaceID(), 50000,
00276 m_pGun, pLookAt );
00277 }
00278
00279
00280 {
00281 if ( m_interactable )
00282 {
00283 if( m_interactable != m_oldInter )
00284 {
00285 m_sprCrosshairs.Tweening.StopTweening();
00286 m_sprCrosshairs.Tweening.ExecuteCommand("OnTarget", PStack());
00287 }
00288 }
00289 else
00290 {
00291 if( m_interactable != m_oldInter )
00292 {
00293 m_sprCrosshairs.Tweening.StopTweening();
00294 m_sprCrosshairs.Tweening.ExecuteCommand("OffTarget", PStack());
00295 }
00296 }
00297 m_oldInter = m_interactable;
00298 MercuryPoint xy = PointToScreenCoord(m_perspProjection.m_matrix, m_pCamera->GetFinalMatrix(), m_aimPos, DISPLAY->GetDimensions());
00299 xy.z = 0;
00300 m_sprCrosshairs.SetPosition(xy);
00301 fClosestAimerObject = 10000;
00302 }
00303
00304 m_pPlayer.SetRotY( -float(x)/300*RADDEG );
00305
00306
00307 m_pGun = control->GetPosition();
00308 m_pGun.x += cos( -float(x)/300 + Q_PI/4)*7;
00309 m_pGun.y += sin( -float(x)/300 + Q_PI/4)*7;
00310 }
00311
00312 void ScreenFPS2::CalculateLook(int x, int y, MercuryODEObject* control)
00313 {
00314
00315 if( ( y - m_iSlidingF ) > 470 )
00316 m_iSlidingF = y - 470;
00317 if( ( y - m_iSlidingF ) < -470 )
00318 m_iSlidingF = y + 470;
00319
00320 pTarget.x = cos( -float(x)/300 );
00321 pTarget.y = sin( -float(x)/300 );
00322 pTarget.z = 0;
00323
00324 pLookAt = pTarget;
00325
00326 pLookAt.x *= cos( -float(y-m_iSlidingF)/300 );
00327 pLookAt.y *= cos( -float(y-m_iSlidingF)/300 );
00328 pLookAt.z = sin( -float(y-m_iSlidingF)/300 );
00329 }
00330
00331 void ScreenFPS2::TweenCamera(int x, int y, MercuryODEObject* control)
00332 {
00333 if ( !((m_slowDown > 0) && !m_donefirst))
00334 if( !m_bFPS )
00335 {
00336 m_fCamera.Tweening.StopTweening();
00337
00338 m_fCamera.Tweening.ExecuteCommand( "CamTween", PStack(
00339 PSElement( control->GetX()-COS(-float(x)/300)*30 ),
00340 PSElement( control->GetY()-SIN(-float(x)/300)*30 ),
00341 PSElement( (control->GetZ())+25)));
00342
00343 MercuryPoint pos = m_fCamera.GetPosition();
00344
00345 m_pPlayer.SetHide( false );
00346 m_fCamera.SetTarget( pLookAt + pos );
00347
00348 MercuryPoint pNewUp = pLookAt.CrossProduct( MercuryPoint( 0,0,1 ) );
00349 pNewUp = pNewUp.CrossProduct( pLookAt );
00350 m_fCamera.SetUp( pNewUp );
00351
00352 } else {
00353 m_fCamera.SetPosition( control->GetPosition() );
00354 m_pPlayer.SetHide( true );
00355 m_fCamera.SetTarget( pLookAt + control->GetPosition() );
00356
00357 MercuryPoint pNewUp = pLookAt.CrossProduct( MercuryPoint( 0,0,1 ) );
00358 pNewUp = pNewUp.CrossProduct( pLookAt );
00359 m_fCamera.SetUp( pNewUp );
00360 }
00361 }
00362
00363 void ScreenFPS2::Message( int Message, PStack & data, const MString &name )
00364 {
00365 switch ( Message )
00366 {
00367 case MC_INPUTMAPPED:
00368 {
00369 InputMessageStruct c(data);
00370 if ( c.code == button_u )
00371 {
00372 if ( c.type == IET_DOWN )
00373 {
00374 m_bFPS = !m_bFPS;
00375 }
00376 } else if ( c.code == button_b && c.type != IET_RELEASE ) {
00377 m_pWorld.GenAndAddToWorld( m_pINI, "MyBall", "Ball", "MercuryODEObjectLoadable", 1, MercuryPoint(0,0,100));
00378 } else if ( c.code == button_t && c.type == IET_DOWN ) {
00379 m_pWorld.GenAndAddToWorld( m_pINI, "MyBall", "coke", "ExplodingCokeCan", 1, MercuryPoint(0,0,100));
00380 } else if ( c.code == button_mouse2 )
00381 {
00382 if ( c.type == IET_DOWN )
00383 {
00384 pPhysics.EnableForShot( m_pWorld.GetWorldSpaceID(), 50000,
00385 m_pGun, pLookAt );
00386 }
00387 else if( c.type == IET_RELEASE )
00388 {
00389 iPhysicsObject = 0;
00390 fClosestPhysicsObject = 100000;
00391 }
00392 }
00393 }
00394 break;
00395 case MC_EXPLOSION:
00396 {
00397 if (!m_fistExplosion)
00398 {
00399 m_slowDown += 2;
00400
00401
00402 MercuryPoint coke;
00403 coke.SetX(data.PeekItem(0).GetValueF());
00404 coke.SetY(data.PeekItem(1).GetValueF());
00405 coke.SetZ(data.PeekItem(2).GetValueF());
00406 MercuryPoint a = (coke - m_fCamera.GetPosition()).CrossProduct( MercuryPoint(0,0,1));
00407 a.NormalizeSelf();
00408 m_fCamera.Tweening.StopTweening();
00409 m_fCamera.Tweening.AddCommand( ssprintf( "linear,%f;x,%f;y,%f;z,%f", m_slowDown/5, coke.x-50, coke.y-50, coke.z+50));
00410
00411
00412
00413 m_fCamera.SetTarget(coke);
00414
00415
00416 MercuryPoint pNewUp = pLookAt.CrossProduct( MercuryPoint( 0,0,1 ) );
00417 pNewUp = pNewUp.CrossProduct( pLookAt );
00418 m_fCamera.SetUp( pNewUp );
00419 m_pPlayer.SetHide( false );
00420 m_fistExplosion = true;
00421 }
00422 }
00423 break;
00424 };
00425
00426 ScreenOutdoors::Message( Message, data, name );
00427 }
00428
00429 bool ScreenFPS2::Command( PStack & ret, const char * command, PStack & args )
00430 {
00431 if ( strcmp( command, "physhit" ) == 0 )
00432 {
00433 if( args.PeekItem( 0 ).GetValueS().compare( "EarthControl" ) == 0 )
00434 return true;
00435 MercuryODEObjectLoadable * L = (MercuryODEObjectLoadable*)args.PeekItem( 1 ).GetValueV();
00436 if( L->m_oBody )
00437 {
00438 MercuryPoint pPos = MercuryPoint( args.PeekItem( 2 ).GetValueF(),
00439 args.PeekItem( 3 ).GetValueF(),
00440 args.PeekItem( 4 ).GetValueF() ) - m_pGun;
00441
00442 float fDistance = pPos.Magnitude();
00443
00444 if( fDistance < fClosestPhysicsObject )
00445 {
00446 iPhysicsObject = (MVPtr)L->m_oBody;
00447 fClosestPhysicsObject = fDistance;
00448 }
00449 }
00450 return true;
00451 }
00452 else if ( strcmp( command, "rayhit" ) == 0 )
00453 {
00454 if( args.PeekItem( 0 ).GetValueS().compare( "EarthControl" ) == 0 )
00455 return true;
00456
00457 MercuryODEObjectLoadable * L = (MercuryODEObjectLoadable*)args.PeekItem( 1 ).GetValueV();
00458 if( L->m_oBody )
00459 {
00460 dBodyEnable( L->m_oBody );
00461
00462 dBodyAddForce( L->m_oBody, 70000*args.PeekItem( 5 ).GetValueF(),
00463 70000*args.PeekItem( 6 ).GetValueF(),
00464 70000*args.PeekItem( 7 ).GetValueF() );
00465 }
00466
00467 MercuryShape * k = (MercuryShape*)Spawn( "MercuryShape", "bob" );
00468 k->MakeSphere();
00469 k->LoadImage( "GRAPHIC:Explosion.ini" );
00470 k->SetDiffuse( MercuryColor( 1,1,1,1 ) );
00471 k->SetScale( gpOne );
00472 MercuryPoint p(MercuryPoint( args.PeekItem( 2 ).GetValueF(), args.PeekItem( 3 ).GetValueF(), args.PeekItem( 4 ).GetValueF() ));
00473 k->SetPosition( p );
00474 k->Tweening.AddCommand( THEME.GetMetricS( GetName(), "BulletExplosion", "" ) );
00475 k->GetGLState().Disable(MGLS_OPAQUE);
00476
00477 MercuryMaterial m;
00478 MercuryLight* l = (MercuryLight*)Spawn("MercuryLight", "Explosion light");
00479 l->SetColors(m);
00480 l->SetPosition(p);
00481 l->SetStatic(true);
00482 l->SetLightType(LT_POINT);
00483 l->SetAttenuation(.001f,Attenuation::QUADRATIC);
00484 l->Tweening.AddCommand(THEME.GetMetricS( GetName(), "LightExplosion", "" ));
00485 DISPLAY->AddLight(l);
00486
00487 return true;
00488 }
00489 else if ( strcmp( command, "aimhit" ) == 0 )
00490 {
00491 if( args.PeekItem( 0 ).GetValueS().compare( "EarthControl" ) == 0 )
00492 return true;
00493 MercuryODEObjectLoadable * L = (MercuryODEObjectLoadable*)args.PeekItem( 1 ).GetValueV();
00494
00495 MercuryPoint pPos = MercuryPoint( args.PeekItem( 2 ).GetValueF(),
00496 args.PeekItem( 3 ).GetValueF(),
00497 args.PeekItem( 4 ).GetValueF() );
00498
00499 float fDistance = (m_pPlayer.GetPosition()-pPos).Magnitude();
00500
00501 if( fDistance < fClosestAimerObject )
00502 {
00503 if (L->m_oBody)
00504 m_interactable = true;
00505 else
00506 m_interactable = false;
00507
00508 fClosestAimerObject = fDistance;
00509 m_aimPos = pPos;
00510 }
00511
00512 return true;
00513 }
00514
00515 return ScreenOutdoors::Command( ret, command, args );
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544