Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411500 Posts in 69373 Topics- by 58429 Members - Latest Member: Alternalo

April 25, 2024, 01:34:00 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Win32 window moving
Pages: [1]
Print
Author Topic: Win32 window moving  (Read 1489 times)
Deckhead
Level 1
*



View Profile WWW
« on: September 19, 2018, 06:29:03 PM »

I've got a small problem with my game engine that I'm making. In windowed mode, when the user drags the window around on the screen, it's like the game processing continues, but at a much higher rate than normal.

It's hard to explain, and waaaay to much code to fully demonstrate. But. I have a Animation class that moves the position of an element based on the elapsed time. If I quickly click and release the window, the animation jumps to the very end, which I only assume means it processed extremely quickly all of a sudden.

I understand that the window doesn't draw when being dragged, which is fine. What I want to do is detect when the window is being dragged and then pause the simulation, only starting it up again when it's complete. WM_MOVING, WM_MOVE, and WM_EXITSIZEMOVE don't seem to work as expected. It's like there's no real way to determine when the window is being moved. I've also tried WM_NCLBUTTONDOWN to detect the possible start, which works, but then WM_NCLBUTTONUP doesn't seem to fire.

Here's my main loop. Any suggestions to fix this problem of continued animation while being dragged?

Code:
auto previousTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<float,std::milli> lag(0);
const std::chrono::duration<float,std::milli> tickRate(20);
bool paused = false;
MSG msg;
while(true)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;
else if(msg.message == WM_NCLBUTTONDOWN) // my attemps at detecting window moves
paused = true;
else if(msg.message == WM_NCLBUTTONUP)
paused = false;
else
birunji::messaging::process_wnd_msg(msg); // just posts all other relevant messages through a subscription queue
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
auto currentTime = std::chrono::high_resolution_clock::now();
auto elapsed = currentTime - previousTime;
previousTime = currentTime;
if(!paused) // my attempt at pausing the simulation
lag += std::chrono::duration_cast<std::chrono::duration<float,std::milli>>(elapsed);

if(!paused)
{
while(lag >= tickRate)
{
birunji::messaging::Postmaster::ProcessMessages(); // just executes the callbacks of the subscription queue above

uiManager.Update(lag.count()); // this is where the animation takes place that suddenly completes when dragging

lag -= tickRate;
}

uiManager.Draw();
birunji::renderer::Core::Draw();
window.Display();
}
}
}
Logged

qMopey
Level 6
*


View Profile WWW
« Reply #1 on: September 20, 2018, 02:13:52 PM »

You can detect this kind of thing for sure. Finding the right message might be tricky. Have you tried WM_SIZING? Also WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE look promising. https://docs.microsoft.com/en-us/windows/desktop/winmsg/wm-entersizemove

Also if you do want to at least render you game while resizing (which I recommend doing), you can use WM_PAINT, and make sure to (after making a call to your render function) to use ValidateRect with NULL for the second param -- this tells Windows that you've updated (painted) your entire window paint region.
Logged
JWki
Level 4
****


View Profile
« Reply #2 on: September 21, 2018, 12:05:59 AM »

I suspect that the problem isn't that your simulation continues to run while you're moving or resizing the window, but that PeekMessage is blocking while that is happening. If your main loop is single threaded, which I assume, i.e. simulation and animation happens on the same thread as window message processing, this means that nothing is being run while you're manipulating the window - since PeekMessage is blocking - and then when you release the window, the elapsed time you measure will obviously be the time since you started dragging, so the simulation and animation will advance by that timestep. This also explains why WM_ENTERSIZEMOVE / WM_EXITSIZEMOVE, if you tried them, are not working, since the simulation *isn't being ran anyways*, the problem is rather that you are still taking the time elapsed while the window is being dragged into account. So to fix this, you need to measure how long the user has been manipulating the window and then remove that time from the total time elapsed you measured since then.
Alternatively run the window processing loop on a different thread so that your simulation will not be blocked. Then pausing and unpausing should have the desired effect.

For reference: https://stackoverflow.com/questions/3102074/win32-my-application-freezes-while-the-user-resizes-the-window
« Last Edit: September 21, 2018, 12:14:10 AM by JWki » Logged
Deckhead
Level 1
*



View Profile WWW
« Reply #3 on: September 23, 2018, 05:08:37 AM »

Thanks, the problem is that PeekMessage sort of stalls when moving, as you say. I will need to handle things in a second thread in order to handle the game world while being dragged.
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic