//////////////////////////////////////////////////////////////// // File : AppStart.cpp // Description : Application main entry point. // (Not Part of DirectSkeleton). // //////////////////////////////////////////////////////////////// /////////////////// #includes /////////////////// #include "DirectSkeleton.h" #include "DSKApp.h" #include "resource.h" #include /////////////////// #defines /////////////////// #define DSKAPP_NAME "DirectSkeleton®" #define MAXSOUNDS 8 #define LIGHTL 0 #define LIGHTR 1 // Actions Times #define WALKSTART 1.0f #define WALKEND 32.0f #define SLEEPSTART 33.0f #define SLEEPEND 45.0f #define SHOTSTART 46.0f #define SHOTEND 50.0f #define WAKEUPSTART 50.0f #define WAKEUPEND 63.0f // Actions Verbs #define WALKING 1 #define SLEEPING 2 #define SHOOTING 3 #define WAKINGUP 4 // Time Way #define TIMEFORWARD 1.0f #define TIMEBACKWARD -1.0f // Keyboard Controls #define KEYPRESSED(vkKey) GetAsyncKeyState(vkKey)&0x8000 #define SHOOTKEY VK_SPACE #define WALKKEY VK_UP #define GUNUPKEY VK_SHIFT #define GUNDOWNKEY VK_CONTROL // Sounds #define WALKSOUND 0 #define SHOTSOUND 1 #define LIGHTONSOUND 2 #define LIGHTOFSOUND 3 #define BGSOUND 4 #define WAKEUPSOUND 5 #define STEPDOWNSOUND 6 #define GUNMOVESOUND 7 /////////////////// Information /////////////////// // Common Settings for Scene Ambience: // Material = 1.0f // Light = 0.0f // RenderState = Variable // // Common Settings for Object Specular: // Material = Variable (+Power) // Light = 1.0f /////////////////// Global Variables /////////////////// DSK3DMesh *g_pLightConeMesh[2]; DSK3DNode *g_pGunRight=NULL; DSK3DNode *g_pGunLeft=NULL; DSK3DNode *g_pLightL=NULL; DSK3DNode *g_pLightR=NULL; DSKList g_pAnimatedNodes; DSKList*> g_pAnimations; DSKAnimation *g_pAnimation; BYTE g_TerminatorAction=0; float g_TimeWay; DSKSound *g_pSounds[MAXSOUNDS]; /////////////////// Global Functions /////////////////// void SwitchTerminatorLights(void) { g_pLightL->SetVisibility(!g_pLightL->GetVisibility()); g_pLightR->SetVisibility(!g_pLightL->GetVisibility()); DSK3DMaterial *pMaterial = g_App.Scene.FindMaterial("headPolygon"); if (!g_pLightL->GetVisibility()) { pMaterial->SetEmmisive(0.0f,0.0f,0.0f); // Turn off g_pSounds[LIGHTOFSOUND]->Play(false,false); } else { pMaterial->SetEmmisive(1.0f,1.0f,0.0f); // Turn on g_pSounds[LIGHTONSOUND]->Play(false,false); } } bool IsAnimationStopped(void) { // Use global body animation as an indicator if (g_TimeWay == TIMEFORWARD) { if (g_pAnimation->GetFilteredTime() >= g_pAnimation->GetClipEnd()) return true; return false; } // Backward Animation if (g_pAnimation->GetFilteredTime() <= g_pAnimation->GetClipStart()) return true; return false; } void SetAnimationsClips(float ClipStart,float ClipEnd) { DSKPOSITION Pos; Pos = g_pAnimations.GetHeadPosition(); while (Pos) { DSKAnimation *pAnim; pAnim = g_pAnimations.GetNext(Pos); pAnim->SetClipStart(ClipStart); pAnim->SetClipEnd(ClipEnd); } } void SetAnimationsTime(float Time,bool Relative) { DSKPOSITION Pos; Pos = g_pAnimatedNodes.GetHeadPosition(); while (Pos) g_pAnimatedNodes.GetNext(Pos)->SetTime(Time,Relative); } void SetAnimationsType(BYTE Type) { DSKPOSITION Pos; Pos = g_pAnimations.GetHeadPosition(); while (Pos) g_pAnimations.GetNext(Pos)->SetAnimType(Type); } void LoadSounds(void) { for (int i=0;i *pNodes = g_App.Scene.GetNodes(); DSKPOSITION Pos; Pos = pNodes->GetHeadPosition(); while (Pos) { DSKAnimation *pAnim; DSK3DNode *pNode; pNode = pNodes->GetNext(Pos); bool NodeAdded = false; pAnim = pNode->GetTransformationAnim(DSK3DNode::TRANSLATION); if (pAnim != NULL) { NodeAdded = true; g_pAnimatedNodes.AddTail(pNode); g_pAnimations.AddTail(pAnim); } pAnim = pNode->GetTransformationAnim(DSK3DNode::ROTATION); if (pAnim == NULL) continue; if (strcmp(pAnim->GetObjectID(),"light_cone-ROTATION-Y") == 0) { g_pLightL = pNode; // It's the left light.. Keep it aside continue; } if (strcmp(pAnim->GetObjectID(),"light_cone1-ROTATION-Y") == 0) { g_pLightR = pNode; // It's the right light.. Keep it aside continue; } if (!NodeAdded) g_pAnimatedNodes.AddTail(pNode); g_pAnimations.AddTail(pAnim); } // All animations range to 63.. Pick one to use for info g_pAnimation = g_pAnimations.GetHead(); // At start, Terminator is shut down SetAnimationsClips(SLEEPSTART,SLEEPEND); SetAnimationsType(DSKANIMTYPE_FORWARD); SetAnimationsTime(SLEEPEND+1,false); g_TerminatorAction = SLEEPING; // Stop Moving g_App.AdvanceTime = false; // Prepare for wake up g_TimeWay = TIMEFORWARD; } void RenderLightCones(void) { // Don't render if turned off... if (!g_pLightL->GetVisibility()) return; DSK3DNode *pNode=NULL; // Setup correct render states g_App.Device3D.m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); g_App.Device3D.m_pDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE); g_App.Device3D.m_pDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE); g_App.Device3D.m_pDevice->SetRenderState(D3DRS_LIGHTING,FALSE); g_App.Device3D.m_pDevice->SetRenderState(D3DRS_SPECULARENABLE,FALSE); g_App.Device3D.m_pDevice->SetTexture(0,g_pLightConeMesh[0]->GetTexture(0,0)->GetD3DTexture()); g_App.Device3D.m_pDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); g_App.Device3D.m_pDevice->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE); g_App.Device3D.m_pDevice->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE|D3DTA_ALPHAREPLICATE); g_App.Device3D.m_pDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1); g_App.Device3D.m_pDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE|D3DTA_ALPHAREPLICATE); g_App.Device3D.m_pDevice->SetTextureStageState(1,D3DTSS_COLOROP,D3DTOP_DISABLE); g_App.Device3D.m_pDevice->SetTextureStageState(1,D3DTSS_ALPHAOP,D3DTOP_DISABLE); // Disable z-writes g_App.Device3D.m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE); for (BYTE i=0;i<2;i++) { pNode = g_pLightConeMesh[i]->GetParentNode(); pNode->WorldTransform(); g_App.Device3D.m_pDevice->SetTransform( D3DTS_WORLD, &pNode->WorldMatrix); g_pLightConeMesh[i]->RenderSubset(0); g_pLightConeMesh[i]->RenderSubset(0); g_pLightConeMesh[i]->RenderSubset(0); } // Return them back g_App.Device3D.m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE); g_App.Device3D.m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE); g_App.Device3D.m_pDevice->SetRenderState(D3DRS_LIGHTING,TRUE); g_App.Device3D.m_pDevice->SetRenderState(D3DRS_SPECULARENABLE,TRUE); } void HandleControls(void) { bool Idle=true; if (KEYPRESSED(GUNUPKEY)) { if (g_pGunLeft->GetRotationVec3(false).x < -1.18f) { g_pGunLeft->Rotate(0.01f,0.0f,0.0f,true); g_pGunRight->Rotate(0.01f,0.0f,0.0f,true); g_pSounds[GUNMOVESOUND]->Play(false,false); } } if (KEYPRESSED(GUNDOWNKEY)) { if (g_pGunLeft->GetRotationVec3(false).x > -2.08f) { g_pGunLeft->Rotate(-0.01f,0.0f,0.0f,true); g_pGunRight->Rotate(-0.01f,0.0f,0.0f,true); g_pSounds[GUNMOVESOUND]->Play(false,false); } } // Behaviour: don't accept input until animation is done if (!IsAnimationStopped()) return; // Filter up user input.. if (KEYPRESSED(SHOOTKEY)) { // If he was walking, let him stop first if (g_TerminatorAction != WALKING) { Idle = false; SetAnimationsClips(SHOTSTART,SHOTEND); g_App.AdvanceTime = true; g_App.AnimTimer.Restart(); g_TerminatorAction = SHOOTING; SetAnimationsTime(SHOTSTART,false); g_TimeWay = TIMEFORWARD; g_pSounds[SHOTSOUND]->Play(false,true); } } if (KEYPRESSED(WALKKEY)) { Idle = false; if ((g_TerminatorAction == SLEEPING) || (g_TerminatorAction == SHOOTING)) { // He was sleeping/shooting.. Now he must wake up SetAnimationsClips(SLEEPSTART,SLEEPEND); SetAnimationsType(DSKANIMTYPE_FORWARD); SetAnimationsTime(SLEEPEND,false); g_App.AnimTimer.Restart(); g_TerminatorAction = WALKING; g_App.AdvanceTime = true; g_TimeWay = TIMEBACKWARD; g_pSounds[WAKEUPSOUND]->Play(false,false); } else { SetAnimationsClips(WALKSTART,WALKEND); g_App.AdvanceTime = true; g_App.AnimTimer.Restart(); g_TerminatorAction = WALKING; SetAnimationsTime(WALKSTART,false); g_TimeWay = TIMEFORWARD; g_pSounds[WALKSOUND]->Play(false,false); } } if (Idle) { if (g_TerminatorAction == WALKING) { // He was walking.. Now he must stop SetAnimationsClips(SLEEPSTART,SLEEPEND); SetAnimationsType(DSKANIMTYPE_FORWARD); SetAnimationsTime(SLEEPSTART,false); g_TerminatorAction = SLEEPING; g_App.AdvanceTime = true; g_TimeWay = TIMEFORWARD; g_pSounds[STEPDOWNSOUND]->Play(false,false); return; } SetAnimationsClips(SLEEPSTART,SLEEPEND); SetAnimationsType(DSKANIMTYPE_FORWARD); SetAnimationsTime(SLEEPEND,false); g_TerminatorAction = SLEEPING; g_App.AdvanceTime = false; g_TimeWay = TIMEFORWARD; } } /////////////////// WinMain. Start of Application /////////////////// int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { // Basic Application initialization... g_App.hinst = hInstance; g_App.hwnd = NULL; g_App.FPSMultiplier = 1000 / 30.0f; // Run in 30 FPS g_App.Scene.AssociateDevice(&g_App.Device3D); if (FAILED(CreateDSK3DWindow(DSKAPP_NAME,false,hInstance,640,480))) return -1; HACCEL hAccel = LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_MAINFRAME)); if (FAILED(InitDSKSound(g_App.hwnd,false,22050,8))) { DestroyWindow(g_App.hwnd); return -1; } // Attempt to initialize Direct3D 8 if (FAILED(g_App.Device3D.InitDSK3D())) { // If we didn't choose silent mode for DSK, // it'll display an error message automatiacally DestroyWindow(g_App.hwnd); return -1; } // Find a suitable device to start with if (FAILED(FindRequired3DDevice())) { // Tell that to the user, then exit MessageBox(g_App.hwnd,"Failed to find a suitable 3D adapter..\nExiting..","Device Requirements Error...",MB_OK|MB_ICONERROR); DestroyWindow(g_App.hwnd); return -1; } ShowWindow(g_App.hwnd,SW_SHOW); // Activate application if (FAILED(g_App.Device3D.UpdateDevice(g_App.hwnd))) { char Msg[500] = "Failed to initialize 3D device..\n"; strcat(Msg,"Terminator(TM) requires a 3D card capable of windowed Direct3D rendering..\n"); strcat(Msg,"Make sure you have DirectX 8.1 runtime installed. Also update your hardware's drivers for best performance.."); ReleaseDSKSound(); g_App.Device3D.ReleaseDSK3D(); MessageBox(g_App.hwnd,Msg,"Device Initialization Error...",MB_OK|MB_ICONERROR); DestroyWindow(g_App.hwnd); return -1; } // Load the opening scene DSKXSIScene scnXSI; scnXSI.Identifier = ".\\Terminator.xsi"; scnXSI.pScene = &g_App.Scene; scnXSI.TexturesModule = g_App.hinst; scnXSI.ResourceType = "Textures"; scnXSI.TexturesPath = NULL; if (FAILED(LoadXSIScene(&scnXSI))) { // Ooops! char Msg[500] = "Missing Terminator™ main scene file..\n"; strcat(Msg,"Please make sure that the file: Terminator.xsi is in the same working directory, then try again..\n"); ReleaseDSKSound(); g_App.Device3D.ReleaseDSK3D(); MessageBox(g_App.hwnd,Msg,"Scene Initialization Error...",MB_OK|MB_ICONERROR); DestroyWindow(g_App.hwnd); return -1; } g_App.Scene.TrackBall.SetRadius(40.650002f); g_App.Scene.TrackBall.SetUV(2.356194f,0.293215f); g_App.Scene.TrackBall.SetCenter(D3DXVECTOR3(-5.546974f,0.835549f,-5.504783f)); g_App.Scene.TrackBall.SetUser(0.133333f); // Setup controls ManageScene(); // Load the sounds LoadSounds(); // Create scene defaluts SetSceneDefaults(); // Set application flags g_App.Paused = 0; g_App.FPSTimer.Restart(); g_App.FPSTimer.WaitFor(1000); // Wait for 1 second g_App.AnimTimer.Restart(); g_App.LightsTimer.Restart(); // Start playing the background g_pSounds[BGSOUND]->Play(true,false); // Enter typical message loop // Now we're ready to recieve and process Windows messages. BOOL bGotMsg; MSG msg; PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE ); while( msg.message != WM_QUIT ) { // Use PeekMessage() if the app is active, so we can use idle time to // render the scene. Else, use GetMessage() to avoid eating CPU time. if( g_App.Paused ) bGotMsg = GetMessage( &msg, NULL, 0U, 0U ); else bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ); if( bGotMsg ) { // Translate and dispatch the message if(TranslateAccelerator( g_App.hwnd, hAccel, &msg ) == 0) { TranslateMessage( &msg ); DispatchMessage( &msg ); } g_App.Scene.TrackBall.HandleMouseMessages(msg.message,msg.wParam,msg.lParam); } else { static DWORD FramesPresented=0; static UINT Width,Height; static float AnimFrames=0.0f; static float LightsAnimFrames=0.0f; // Render a frame during idle time (no messages are waiting) if (g_App.Paused) continue; if (g_App.FPSTimer.IsFired()) { char FramesText[50]; sprintf(FramesText,"Terminator™ running at %d FPS",FramesPresented); if (FAILED(g_App.Device3D.IsFullScreen())) SetWindowText(g_App.hwnd,FramesText); FramesPresented=0; g_App.FPSTimer.WaitFor(1000); } HandleControls(); if (g_App.AdvanceTime) { AnimFrames = g_App.AnimTimer.GetElapsed()/g_App.FPSMultiplier; SetAnimationsTime(AnimFrames*g_TimeWay,true); } // Always update the lights anim LightsAnimFrames = g_App.LightsTimer.GetElapsed()/g_App.FPSMultiplier; g_pLightL->SetTime(LightsAnimFrames,true); g_pLightR->SetTime(LightsAnimFrames,true); g_App.Device3D.GetRenderWindowSize(&Width,&Height); // Update camera g_App.Scene.ActiveCamera->SetPerspectiveParams(D3DX_PI/4+g_App.Scene.TrackBall.GetUser(),(float)Width/Height, 1.0f, 100.0f); g_App.Scene.ActiveCamera->SetEyePoint(g_App.Scene.TrackBall.GetEye()); g_App.Scene.ActiveCamera->SetTargetPoint(g_App.Scene.TrackBall.GetCenter()); g_App.Scene.ActiveCamera->SetUpVector(g_App.Scene.TrackBall.GetUpVector()); g_App.Scene.ActiveCamera->UpdateViewMatrices(); // Prepare for renderingeringering g_App.Scene.SetLights(); g_App.Scene.SetAmbience(D3DCOLOR_RGBA(25,25,25,255)); g_App.Device3D.m_pDevice->BeginScene(); g_App.Device3D.m_pDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_ARGB(0,0,0,0),1.0f,0); g_App.Device3D.m_pDevice->SetTransform( D3DTS_PROJECTION, &g_App.Scene.ActiveCamera->ProjMatrix); g_App.Device3D.m_pDevice->SetTransform( D3DTS_VIEW, &g_App.Scene.ActiveCamera->ViewMatrix); DSKList *pMeshes = g_App.Scene.GetMeshes(); DSKPOSITION Pos; Pos = pMeshes->GetHeadPosition(); while (Pos) { DSK3DMesh *pMesh = pMeshes->GetNext(Pos); DSK3DNode *pNode = pMesh->GetParentNode(); pNode->WorldTransform(); g_App.Device3D.m_pDevice->SetTransform( D3DTS_WORLD, &pNode->WorldMatrix); pMesh->SetRenderStates(0); pMesh->RenderSubset(0); } // Render the light cones RenderLightCones(); g_App.Device3D.m_pDevice->EndScene(); g_App.Device3D.Present(); FramesPresented++; } } DSKSAFE_DELETE(g_pLightConeMesh[LIGHTL]); DSKSAFE_DELETE(g_pLightConeMesh[LIGHTR]); // Destroy all sounds for (int i=0;i