Game from Scratch 002 - Fighting Windows
Last time, I said I’d create a window and handle the Windows message loop and that’s what I did! Before diving into the code, I want to clarify something: this blog series won’t be a step-by-step tutorial on building a game from scratch in C. Instead, I’ll share my progress and focus on interesting problems and how I solve them.
The Bug
Right now, I have an awesome looking game: a square bouncing back and forth. But there’s one tiny problem stopping me from selling a million copies. Check out the gif below, can you spot it?
Pretty obvious, right? The game freezes when you resize or drag the window. You might call it an edge case, but it bugged me enough to investigate. I checked games made with Godot and SDL and they don’t freeze, so I had to be missing something.
The Message Loop
First, some background. Windows communicates with applications using messages: keystrokes, window movement, close requests, etc. These come in as numeric codes with metadata attached, and it’s up to us to handle them using a message loop.
Here’s my setup:
|
|
This works well, except when the user drags or resizes the window.
Why It Freezes
When you drag or resize a window, Windows enters an internal modal loop that blocks the thread that created the window. I’m not entirely sure why but I think it’s to handle mouse interaction. But the key point is: the application freezes which isn’t great for a game.
The Fix
One option is to run rendering on a separate thread. That works, but it can add a frame of latency, and I don’t want that for this project.
Instead, I used the same trick that Godot and SDL uses. When Windows enters a modal loop, it sends a message. You can catch that and set a timer that fires regularly. Each time the timer triggers, Windows sends a WM_TIMER message where I call my frame function. When the modal loop ends, I kill the timer.
It feels like a hack, but it’s simple and it works.
|
|
And just like that, the game no longer freezes when dragging or resizing the window:
What’s Next?
Not sure yet! It might be input, DirectX, or something else entirely. I’ll keep it a surprise.