0
\$\begingroup\$

I'm working on a project that remakes mario 3 (NES). In my game loop, i face a strange thing. Here is my code:

 while (true)
{
    if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
    {
        if (msg.message == WM_QUIT)
        {
            break;
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    else
    {
        //Game logic
        c1++;
        _Mario.Update(1.0 / FPS);

        //Render
        _Timer.SetBeginTick();
        _LpD3dDevice9->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(102, 255, 255), 1.0f, 0);
        if (_LpD3dDevice9->BeginScene())
        {
            c2++;
            _Mario.Render();
            _LpD3dDevice9->EndScene();
        }
        _Keyboard->GetState();
        _Mario.Move(_Keyboard);
        _LpD3dDevice9->Present(0, 0, 0, 0);
        _Timer.SetCurrTick();
        _Timer.UpdateGameTIme();
        if (_Timer.ElapsedTime < (1.0 / FPS))
        {
            Sleep(1000.0 / FPS - _Timer.ElapsedTime * 1000);
        }
    }
}

Update function :

void ImageMove::Update(float t)
{
    _Image_X += _Image_Vx * t;
    _Image_Y -= _Image_Vy * t;
    _SpriteTimer.SetCurrTick();
    _SpriteTimer.UpdateGameTIme();
    if (_SpriteTimer.ElapsedTime >= 1.0 / ANIMATE_RATE)
    {
        if (_Image_Vx > 0) _Image_Right.Next(); //change to next sprite
        if (_Image_Vx < 0) _Image_Left.Next(); // change to next sprite
        _SpriteTimer.SetBeginTick();
    }
}

Render Function :

void ImageMove::Render()
{
    int vpx = _Image_X - 400;
    int VIEW_PORT_Y = _Image_Y + 500;
    _SpriteHandler->Begin(D3DXSPRITE_ALPHABLEND);
    if (_Image_Vy > 0 && _Image_Vx_Last > 0) _Image_Jump_Right.Render(_Image_X, _Image_Y);
    else if (_Image_Vy > 0 && _Image_Vx_Last < 0) _Image_Jump_Left.Render(_Image_X, _Image_Y);
    else
    if (_Image_Vx > 0)_Image_Right.Render(_Image_X, _Image_Y);
    else if (_Image_Vx < 0)_Image_Left.Render(_Image_X, _Image_Y);
    else if (_Image_Vx_Last < 0)_Image_Left.Render(_Image_X, _Image_Y);
    else _Image_Right.Render(_Image_X, _Image_Y);
    _SpriteHandler->End();
}

I put c1 and c2 in my game loop to measure how many times Update and Render are called. I set fps = 60, while debuging, I let my game loop run for 5s, then set a breakpoint to view c1 and c2. The value of c1 = 320, and c2 = 160 ( = 1/2 c1 for sure, i have run it many times, so the times render is called only ~1/2 fps, i think with fps = 60, it should be ~300 for 5s, shoudn't It?).

If i debug with F10 (on Visual studio) , I can see a loop will execute with _LpD3dDevice9->BeginScene() success, and _LpD3dDevice9->BeginScene() in next loop always failed.

Is it error? Because i have tested on another small project, and c2 = 1/2 c1 too. This problem cause an issue in my game. In Update() function, I change my sprite here, and draw it in Render() , so I always miss some sprite. Because It only render = 1/2 time game update.

If it is an error How can I fix my game loop? And if It is not an error, what can I do to prevent missing sprites?

P/S : sorry for bad English.

\$\endgroup\$
1
\$\begingroup\$

I think documentation on : IDirect3DDevice9::EndScene method can enlight

"When this method succeeds, the scene has been queued up for rendering by the driver. This is not a synchronous method, so the scene is not guaranteed to have completed rendering when this method returns."

As the EndScene is not syncronous , you are not garanted that the next loop you're ready for a new BeginScene. Try using less FPS.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.