I tried to create my own OS X platform layer but came across a problem with the main game loop. How I'm going to implement it with Cocoa since everything in Cocoa is event driven.
As soon [NSApp run] is called, the main method becomes useless and the only entry point for your code are the callback methods of the Delegate Objects. Under windows this question is obsolete because there the main method is always the main entry point and you can do stuff like
while (running) {
//do framecode here
}
So my question is: How do you properly create a game run loop on OS X?
I found "the windows way" on OS X online and merged it with my code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | static void createWindow() { NSUInteger windowStyle = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask; NSRect screenRect = [[NSScreen mainScreen] frame]; NSRect viewRect = NSMakeRect(0, 0, 1024, 768); NSRect windowRect = NSMakeRect(NSMidX(screenRect) - NSMidX(viewRect), NSMidY(screenRect) - NSMidY(viewRect), viewRect.size.width, viewRect.size.height); window = [[NSWindow alloc] initWithContentRect:windowRect styleMask:windowStyle backing:NSBackingStoreBuffered defer:NO]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; id menubar = [[NSMenu new] autorelease]; id appMenuItem = [[NSMenuItem new] autorelease]; [menubar addItem:appMenuItem]; [NSApp setMainMenu:menubar]; // Then we add the quit item to the menu. Fortunately the action is simple since terminate: is // already implemented in NSApplication and the NSApplication is always in the responder chain. id appMenu = [[NSMenu new] autorelease]; id appName = [[NSProcessInfo processInfo] processName]; id quitTitle = [@"Quit " stringByAppendingString:appName]; id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:quitTitle action:@selector(terminate:) keyEquivalent:@"q"] autorelease]; [appMenu addItem:quitMenuItem]; [appMenuItem setSubmenu:appMenu]; NSWindowController * windowController = [[NSWindowController alloc] initWithWindow:window]; [windowController autorelease]; //View view = [[[View alloc] initWithFrame:viewRect] autorelease]; [window setContentView:view]; //Window Delegate windowDelegate = [[WindowDelegate alloc] init]; [window setDelegate:windowDelegate]; [window setAcceptsMouseMovedEvents:YES]; [window setDelegate:view]; // Set app title [window setTitle:appName]; // Add fullscreen button [window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary]; [window makeKeyAndOrderFront:nil]; } void initApp() { [NSApplication sharedApplication]; appDelegate = [[AppDelegate alloc] init]; [NSApp setDelegate:appDelegate]; running = true; [NSApp finishLaunching]; } void frame() { @autoreleasepool { NSEvent* ev; do { ev = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES]; if (ev) { // handle events here [NSApp sendEvent: ev]; } } while (ev); } } int main(int argc, const char * argv[]) { initApp(); createWindow(); while (running) { frame(); RenderWeirdGradient(XOffset, YOffset); [view setNeedsDisplay:YES]; XOffset++; YOffset++; } return (0); |
But doing it that way will make the Delegates absolutely useless and people told me that I will encounter even more problems because a lot of stuff isn't done this way [NSApp run] usually does.
I already asked on stack overflow but this didn't really help.
Custom main application loop in cocoa
So how is a game loop on OS X done the right way?