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 Answer 1

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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .