Freeze Frame: Shoop, shoop, doodle, oodle, oop

While working on Jiggle Balls HD for the iPad I’ve come across several things I didn’t experience while writing iPhone/iPod Touch games.  Specifically having to do with UIPopoverControllers and orientation handling.  Today I’m gonna discuss an issue I had with popovers, scrollviews, and how they can FREEZE up your main animation loop (I’ll leave the orientation stuff for a later post).  I’m gonna include a link to a sample app I sent to Apple to demonstrate the problem.

Disclaimer: I have not upgraded my iPad to 3.2.1, so this problem could entirely be fixed on that version (let me know).  I’m waiting to upgrade until I finish development and do my first round of beta-testing.

Starting with iOS3.1 the preferred method for creating an animation loop is CADisplayLink (over using an NSTimer).  This became apparent to me when I started testing Tramp Stamp on an iPhone 3GS and the framerate seemed jittery to me (my iPod Touch did not exhibit the same behavior).  CADisplayLink allows you to synch your animation loop to the refresh rate of the display.  You set it up as follows:

displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(drawView:)];
[displayLink setFrameInterval:1];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

Your animation loop (drawView) will now be called every screen refresh (60 times a second).  This solved my jittery problems and things became incredibly smooth on a 3GS device.

Then I started working on Jiggle Balls HD for the iPad.  It has a main view that allows you to drop different types of balls into the arena.  On top of that is a floating toolbar with icons that bring up the specific menus.  These menus are UIPopoverControllers (introduced on the iPad).  These are dialogs that display in front of your content and usually have an indicator pointing to the button or region that caused them to pop-up.  Tapping outside the content area of the popover causes it to dismiss.  The popover can contain any UI widget you want.  In my case I wanted a UIPickerView to select sound-effect for the bouncing balls.  Here’s what it looks like:

jbhd1

Everything worked great!  Except that I noticed 2 issues.

1) My drawView loop wasn’t getting called whenever I scrolled the picker.  As soon as I released the picker, my animation would start again.

2) The picker would occasionally get stuck between values and the didSelectRow delegate method would never get called.

Argh!  I downloaded several other iPad apps and noticed the same behavior, so I considered releasing like this.  But it really bothered me.  Then I stumbled across this:

[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

If you ALSO add your display link to the NSRunLoopCommonModes run loop, in addition to NSDefaultRunLoopMode, your drawView loop will continue to get called during the picker scrolling.  However… this now made the picker REALLY erratic.  The scrolling would barely work (no bounciness) and it was easy to get stuck in between items.  Yuck!

What turned out to be the problem?  The CADisplayLink frame interval.  If I switched it to 2 while the popover was displayed, everything worked great.  So now when I display my popover I decrease the framerate (which also means advancing all the world objects to compensate) and when the popover is dismissed I reset it back.  Not 100% happy with it but that’s why I filed a bug report with Apple.

This wouldn’t be a big deal if it was just the UIPickerView that was having issues.  However, I also bring up a UIWebView and MFMailComposeViewController that are not full screen (UIModalPresentationFormSheet).  Scrolling any of these had the same behavior.  Probably wasn’t noticeable on the iPhone where these views were basically modal and took over the screen.  Although I do know I’ve used some iPhone apps who had erratic scrollview issues, so perhaps the view behind was conflicting just as I’ve explained.

Hopefully this helps some of you.  If anyone has more information or ideas on this, please post a comment.  Here’s the project if you want to play around with it:

UIPickerProblem

If anything, this gives you a framework to start your iPad development with if you haven’t already done so.

Enjoy!


(P.S.  Sorry about the down-time last week during my first iDevBlogADay blog entry.  We had a huge thunderstorm here in Columbus, OH and the power was out for about 2 hours.  I’m working on moving my blog off-site, instead of running on an old HP desktop running Ubuntu that is sitting in the corner of my office)

(P.P.S  I’m looking for Jiggle Balls HD beta-testers.  If you are interested, please sign-up here).

(P.P.P.S  The first person to comment correctly with the name of the group this blog entry is titled after wins a FREE Jiggle Balls: Spikes! promocode and jiggleballs.com sticker)

sticker

Comments

5 Responses to “Freeze Frame: Shoop, shoop, doodle, oodle, oop”

  1. Brandon on August 11th, 2010 10:30 am

    I came across this same problem while working on the level editor of my new game. At first I thought it had to do with showing a popover over an OpenGL view, but then finally I just changed the update time interval and it worked perfectly. I think I filed a bug report about this, but it was awhile ago.

    P.S. I can’t believe I know this, but salt n’ pepa…

  2. Doug on August 11th, 2010 11:43 am

    @Brandon Nope, not Salt N’ Pepa (well, at least not the original)

  3. Brandon on August 11th, 2010 12:29 pm

    Ah, I melodized the title a little differently in my head…

  4. Tom on August 12th, 2010 7:56 am

    Excellent post — nice work! I had noticed the same behavior with an animation getting funky when a popover was presented. However, I solved it by removing the popover (not needed based on beta tester feedback)

    A: J. Geils Band

  5. Doug on August 12th, 2010 8:49 am

    @Tom… glad the post was helpful. I think Apple definitely has some cpu issues with the scrollview. Yes, it’s the J Geils Band. Congrats! I’m sending you the promocode now and a request for your address if you want the jiggleballs.com sticker.

Leave a Reply