2013-05-11 109 views
0

我正在使用SetTimer在我的游戏中放置一个定时器,定时器会每1000毫秒触发一段时间后,我想改变定时器的时间间隔,所以我再次调用SetTimer与相同的timerId(根据MSDN,这将取代旧超时计时器),但它似乎不起作用,计时器没有被解雇。SetTimer不改变时间间隔

这是我的代码,这是一个典型的游戏循环。

INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR szCmdLine, int iCmdShow) 
{ 
    WNDCLASSEX winClass ; 

    winClass.lpszClassName = L"RotationBySetTimer"; 
    winClass.cbSize  = sizeof(WNDCLASSEX); 
    winClass.style   = CS_HREDRAW | CS_VREDRAW; 
    winClass.lpfnWndProc = MsgProc; 
    winClass.hInstance  = hInstance; 
    winClass.hIcon   = NULL ; 
    winClass.hIconSm  = NULL ; 
    winClass.hCursor  = LoadCursor(NULL, IDC_ARROW) ; 
    winClass.hbrBackground = NULL ; 
    winClass.lpszMenuName = NULL ; 
    winClass.cbClsExtra = 0; 
    winClass.cbWndExtra = 0; 

    RegisterClassEx (&winClass) ; 

    HWND hWnd = CreateWindowEx(NULL, 
     winClass.lpszClassName,  // window class name 
     L"RotationBySetTimer",     // window caption 
     WS_OVERLAPPEDWINDOW,  // window style 
     32,       // initial x position 
     32,       // initial y position 
     600,      // initial window width 
     600,      // initial window height 
     NULL,      // parent window handle 
     NULL,      // window menu handle 
     hInstance,     // program instance handle 
     NULL) ;      // creation parameters 

    **SetTimer(hWnd, 1, 1000, NULL);** 

    // Initialize Direct3D 
    if(SUCCEEDED(InitD3D(hWnd))) 
    { 
     // Show the window 
     ShowWindow(hWnd, SW_SHOWDEFAULT); 
     UpdateWindow(hWnd); 

     MSG msg ; 
     ZeroMemory(&msg, sizeof(msg)); 
     PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE); 

     // Get last time 
     static DWORD lastTime = timeGetTime(); 

     while (msg.message != WM_QUIT) 
     { 
      if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) != 0) 
      { 
       TranslateMessage (&msg) ; 
       DispatchMessage (&msg) ; 
      } 
      else // Render the game if there is no message to process 
      { 
       // Get current time 
       DWORD currTime = timeGetTime(); 

       // Calculate time elapsed 
       float timeDelta = (currTime - lastTime) * 0.001f; 

       // Render 
       Render(hWnd, timeDelta) ; 

       // Update last time to current 
       lastTime = currTime; 
      } 
     } 
    } 

    UnregisterClass(winClass.lpszClassName, hInstance) ; 
    return 0; 
} 

我在Render函数中再次调用SetTimer来更改时间间隔。

void Render(HWND hWnd, float timeDelta) 
{ 
    **SetTimer(hWnd, 1, 2000, NULL);** 

    if (!g_bActive) 
    { 
     Sleep(50) ; 
    } 

    SetupMatrix() ; 

    // Clear the back-buffer to a RED color 
    g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); 

    // Begin the scene 
    if(SUCCEEDED(g_pd3dDevice->BeginScene())) 
    { 
     // Draw teapot 
     g_pTeapotMesh->DrawSubset(0) ; 

     // End the scene 
     g_pd3dDevice->EndScene(); 
    } 

    // Present the back-buffer contents to the display 
    g_pd3dDevice->Present(NULL, NULL, NULL, NULL); 
} 

代码工作好之前,我在SetTimer的再次调用渲染功能,但加入这一行,为什么后停止工作?

+0

为了让您收到'WM_TIMER'消息,您的代码必须抽取消息循环。如果您陷入计算密集的渲染中,并不会定期停止抽取消息循环,则无论计时器的间隔如何,都不会收到“WM_TIMER”消息。如果你注释掉第二次调用SetTimer,你实际上是否每1000毫秒收到一次WM_TIMER消息? – 2013-05-11 08:26:36

+0

是的,当我将第二个调用注释到SetTimer时,它就可以工作。 – zdd 2013-05-11 11:47:31

回答

3

您编写它的方式,您一次又一次地高速调用SetTimer()。不断重置计时器,因此永远不会让WM_TIMER消息有足够的时间传递以便发布。

显然你需要找到一个更好的触发器来更新计时器。也许只有在间隔值实际需要改变时才调用SetTimer。由于它没有明显的触发条件,所以不太清楚如何从发布的代码中做到最好。

+0

情况并非如此,我将时间间隔更改为500毫秒,但仍然无效。 – zdd 2013-05-11 11:48:00

+0

我发布的代码仅仅是一个例子,真正的逻辑是当用户得分超过20时,游戏速度会改变,所以定时器在得分达到20时触发。 – zdd 2013-05-11 11:49:28

+0

我想我得到了你,渲染函数被称为每帧,并且定时器每帧被重置,如果帧速率大于时间间隔,它将永远不会被触发。 – zdd 2013-05-11 11:53:57