Of input loops and games
Of input loops and games
- Subject: Of input loops and games
- From: Hari Seldon <email@hidden>
- Date: Mon, 19 Sep 2005 21:52:13 -0500
Hello Cocoa-Dev! I'm new to these parts, but I've been lurking in the
shadows for several weeks. Everyone here seems so helpful and
intelligent, so I thought I'd post a real stumper of a problem that's
been taking me for a pony ride these past few days.
For my very first Cocoa development project, I decided to port a
classic tty, turn-based C game to OS X, utilizing Cocoa APIs and
Objective C. The said game has excellent support for adding on new
"windowing" systems, the only requirement being that you define
certain functions in a special way (ie: give them a specified return
type, name, and parameter count). The function that's got me perplexed
is the one that processes a user's input. It expects an int of the key
the user pressed to be returned. The game processes the keystroke,
updates itself, then immediately calls the "get_key_from_user"
function again, ad infinitum. For the sake of example:
int get_key_from_user()
{
int currently_pressed_key = <the system's function for getting a keypress>;
return currently_pressed_key;
}
When I was trying to work this function into my Cocoa application, I
immediately realized the problem; it would be devastating to block the
entire application waiting for a keypress. After much hair pulling, I
finally cooked up a (shoddy) solution. The sub-classed NSView
responsible for handling game input would pass keystrokes back to a
setter function in the controller. For example:
<TheView.m>
- (void)keyDown:(NSEvent*)event
{
// get pressed key
NSString * keyString = [event charactersIgnoringModifiers];
[theController processKey:keyString];
}
<Controller.m>
int get_key_from_user()
{
do
{
NSAutoreleasePool* thePool = [[NSAutoreleasePool alloc] init];
NSEvent* theEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode
dequeue:YES];
[NSApp sendEvent:theEvent];
[thePool release];
}
while ([c_controller getCurrentKey] == 0);
return [c_controller getCurrentKeyAndClear];
}
c_controller is a pointer to self; this allows me access to the
controller object in the C functions. processKey merely assigns the
first character of the passed string to an internal 'current_key'
variable, which can be accessed with the getCurrentKey method.
This solution "works" to a certain extent; users can move about the
map and perform various tasks without the app blocking while it waits
for keyboard input. However, I believe this solution is having a
devastatingly detrimental effect on the performance of the app. The
game starts off very responsively, with the character moving
immediately when a key is pressed. However, as play continues, input
becomes sluggish. Watching the app in the activity monitor is
revealing; at the start, pressing a key consumes 5-8% of the CPU and
memory usage increases by roughly .03MB. As time wears on, pressing a
key or two results in almost 80% CPU usage. The pleasant little graph
at the bottom of the activity monitor is completely full with those
precious green squares, and the fan on my trusty Powerbook whirs to
life.
I believe I've isolated this problem to the input loop. I had a few
small memory leaks in my Objective-C code which I picked up with
ObjectAlloc, and those have all been fixed. The original game exhibits
none of these symptoms when played in its original tty glory or other
various windowed-ports on other platforms.
I now throw myself at the mercy of this group, and thank you for
reading this lengthy post. Have a wonderful evening :)
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden