Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to drive Main Loop in Cocoa

I'm writing a game that currently runs in both Windows and Mac OS X. My main game loop looks like this:

while(running)
{
    ProcessOSMessages(); // Using Peek/Translate message in Win32
                         // and nextEventMatchingMask in Cocoa
    GameUpdate();
    GameRender();
}

Thats obviously simplified a bit, but thats the gist of it. In Windows where I have full control over the application, it works great. Unfortunately Apple has their own way of doing things in Cocoa apps.

When I first tried to implement my main loop in Cocoa, I couldn't figure out where to put it so I created my own NSApplication per this post. I threw my GameFrame() right in my run function and everything worked correctly.

However, I don't feel like its the "right" way to do it. I would like to play nicely within Apple's ecosystem rather than trying to hack a solution that works.

This article from apple describes the old way to do it, with an NSTimer, and the "new" way to do it using CVDisplayLink. I've hooked up the CVDisplayLink version, but it just feels....odd. I don't like the idea of my game being driven by the display rather than the other way around.

Are my only two options to use a CVDisplayLink or overwrite my own NSApplication? Neither one of those solutions feels quite right.

like image 789
Kyle Avatar asked Mar 25 '12 22:03

Kyle


Video Answer


1 Answers

I am curious to see if anyone who has actually done this cares to weigh in, but here is my understanding:

Apple pushes the CVDisplayLink solution over doing a loop on the main thread that uses -nextEventMatchingMask:untilDate:inMode:dequeue: because, I think, it provides better responsiveness for UI controls. This may not be relevant for full-screen games. (Note: You don't need to replace NSApplication to use that form of game loop.) I think the main potential issue with using CVDisplayLink is that it will only run one frame in advance and it does this determination early, which is even stronger than vertical sync. On the plus side, it might improve latency.

Other solutions include decoupling rendering from game logic and running game logic periodically on the main thread and rendering on the CVDisplayLink thread. I would probably only recommend this, however, if you run into issues with the game-driven-by-display paradigm.

like image 51
John Calsbeek Avatar answered Oct 27 '22 15:10

John Calsbeek