How to make SDL 2.0, iOS work together. (Game Center too)

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the termination.

    This doesn't give the SDL user's application time to respond to an SDL_Quit event.
    So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
    when the delegate receives the ApplicationWillTerminate message, we execute
    a longjmp statement to get back here, preventing an immediate exit.
 */
if (setjmp(*jump_env()) == 0) {
    /* if we're setting the jump, rather than jumping back */
    SInt32 result;
    do {
        result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
    } while (result == kCFRunLoopRunHandledSource);
}

}

This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)

Code:

#import <UIKit/UIKit.h>
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import <OpenGLES/EAGLDrawable.h>
#import <QuartzCore/QuartzCore.h>
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == 8) {
          /* if user specifically requests rbg888 or some color format higher than 16bpp */
          colorFormat = kEAGLColorFormatRGBA8;
      } else {
          /* default case (faster) */
          colorFormat = kEAGLColorFormatRGB565;
      }
      
      /* Get the layer */
      CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
      
      eaglLayer.opaque = YES;
      eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
      
      if (majorVersion > 1) {
          context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
      } else {
          context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
      }
      if (!context || ![EAGLContext setCurrentContext:context]) {
          [self release];
          SDL_SetError("OpenGL ES %d not supported", majorVersion);
          return nil;
      }
      
      // !!! FIXME: use the screen this is on!
      /* Use the main screen scale (for retina display support) */
      if ([self respondsToSelector:@selector(contentScaleFactor)])
          self.contentScaleFactor = [UIScreen mainScreen].scale;
      
      /* create the buffers */
      glGenFramebuffersOES(1, &viewFramebuffer);
      glGenRenderbuffersOES(1, &viewRenderbuffer);
      
      glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
      glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
      [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
      glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
      
      glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
      glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
      
      if ((useDepthBuffer) || (useStencilBuffer)) {
          if (useStencilBuffer) {
              /* Apparently you need to pack stencil and depth into one buffer. */
              depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
          } else if (useDepthBuffer) {
              /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
              depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
          }
          
          glGenRenderbuffersOES(1, &depthRenderbuffer);
          glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
          glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
          if (useDepthBuffer) {
              glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
          }
          if (useStencilBuffer) {
              glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
          }
      }
      
      if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
          return NO;
      }
      /* end create buffers */
      
      self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
      
      [self startAnimation];
    

    }
    return self;
    }

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”) displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy

If you need access to the application delegate, window, view or view controller here is how to do it.

Code:

#include “./sdl/src/video/uikit/SDL_uikitappDelegate.h”
#include “./sdl/src/video/uikit/SDL_uikitwindow.h”

SDL_uikitviewcontroller *gViewColtroller = NULL;
UIWindow *gWindow = NULL;
SDL_uikitopenglview *gView = NULL;
SDLUIKitDelegate *gApplicationDelegate = NULL;

void SetUIViewController(SDL_Window *aWindow)
{
SDL_WindowData *data = (SDL_WindowData *)aWindow->driverdata;
gViewColtroller = data->viewcontroller;
gWindow = data->uiwindow;
gView = data->view;

gApplicationDelegate = [SDLUIKitDelegate sharedAppDelegate];

}

Just pass in the window, that you have made. Your includes maybe different depending where you have placed the SDL library.

BJ wrote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This is the 3rd different solution for this.

I want to note a couple problems with it.

  1. (I made the same mistake), we don’t need to add some new callback to get events in a callback. SDL_EventFilter will actually handle that already, you just need to add the new events.
  2. You HAVE to have separate events for will suspend, will resume, did enter background, did enter foreground, low memory, and quit. You can NOT just over ride it as if it’s a activate/deactivate, this will NOT follow the guide lines and you WILL have crazy hard to fix crashes.
  3. The changes to pump events is unnecessary, just remove the long jump stuff
  4. The start/stop animation is a bit different than SDL works anywhere else and is a pretty big mountain to climb. Is that what is causing the game center problem?

There’s my patch, there’s Piotr’s patch, and there’s this (which doesn’t solve other problems).

I think the solution is use SDL_EventFilter and just add the necessary 6 events. I can work up a patch that does just this, it’s a small change from my patch.

Adding these additional calls, through whatever callback mechanism, makes SDL work great for me. Not sure exactly what the game center problem is though, so some of this might be required.

[>] Brian

2012/5/5 Brian Barnes

BJ wrote:

The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This is the 3rd different solution for this.

I want to note a couple problems with it.

  1. (I made the same mistake), we don’t need to add some new callback to
    get events in a callback. SDL_EventFilter will actually handle that
    already, you just need to add the new events.
  2. You HAVE to have separate events for will suspend, will resume, did
    enter background, did enter foreground, low memory, and quit. You can NOT
    just over ride it as if it’s a activate/deactivate, this will NOT follow
    the guide lines and you WILL have crazy hard to fix crashes.
  3. The changes to pump events is unnecessary, just remove the long jump
    stuff
  4. The start/stop animation is a bit different than SDL works anywhere
    else and is a pretty big mountain to climb. Is that what is causing the
    game center problem?

There’s my patch, there’s Piotr’s patch, and there’s this (which doesn’t
solve other problems).

I think the solution is use SDL_EventFilter and just add the necessary 6
events. I can work up a patch that does just this, it’s a small change

Adding these additional calls, through whatever callback mechanism, makes
SDL work great for me. Not sure exactly what the game center problem is
though, so some of this might be required.

Hey Brian, I’m looking for any of these patches in Bugzilla but I can’t
seem to find them, do you have the issue number where they’ve been filled?
Thanks!> from my patch.


Gabriel.

BJ, do you have an example of using Game Center with an SDL app set up this
way?

Thanks!On Thu, May 3, 2012 at 12:27 AM, BJ wrote:

**
The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to an

SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top of
the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are
processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c class
and implement as follows. (Header first)

Code:

#import **
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import **
#import **
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == 8) {
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into one

buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES,

depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets
up the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for every
2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using it)
as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Yes, I do. I can’t give you the commercial version; but I did make a little
test app before adding it to the commercial one.

Would you like a copy of the xcode project?On Sun, May 27, 2012 at 3:47 AM, Sam Lantinga wrote:

BJ, do you have an example of using Game Center with an SDL app set up
this way?

Thanks!

On Thu, May 3, 2012 at 12:27 AM, BJ <@Brad_Jackson> wrote:

**
The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to

an SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate
exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top of
the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events
are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c class
and implement as follows. (Header first)

Code:

#import **
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import **
#import **
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == 8) {
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into one

buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES,

depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets
up the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for
every 2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using it)
as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Have you seen Tumblebugs 2 yet?

www.wildfire.com.au

Brad Jackson - Senior Game Programmer
Wildfire Studios Pty. Ltd.
+61 (0)7 3844 1000 (office)
+61 (0)7 3844 8970 (fax)

This email is for the sole use of the addressee/s. It should not be copied,
saved or distributed. If received in error, inform the sender and delete it
from your mailbox and other storage mechanism. Opinions and advice
expressed in this email are those of the sender and may not reflect the
views of the company, Wildfire Studios Pty Ltd.

Yes please. Thanks!On Mon, May 28, 2012 at 12:44 AM, Brad Jackson wrote:

Yes, I do. I can’t give you the commercial version; but I did make a
little test app before adding it to the commercial one.

Would you like a copy of the xcode project?

On Sun, May 27, 2012 at 3:47 AM, Sam Lantinga <@slouken> wrote:

BJ, do you have an example of using Game Center with an SDL app set up
this way?

Thanks!

On Thu, May 3, 2012 at 12:27 AM, BJ wrote:

**
The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to

an SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate
exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top
of the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events
are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c
class and implement as follows. (Header first)

Code:

#import **
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import **
#import **
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == 8) {
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into

one buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES,

depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES,
depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets
up the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for
every 2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using
it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Have you seen Tumblebugs 2 yet?

www.wildfire.com.au

Brad Jackson - Senior Game Programmer
Wildfire Studios Pty. Ltd.
+61 (0)7 3844 1000 (office)
+61 (0)7 3844 8970 (fax)

This email is for the sole use of the addressee/s. It should not
be copied, saved or distributed. If received in error, inform the
sender and delete it from your mailbox and other storage mechanism.
Opinions and advice expressed in this email are those of the sender and may
not reflect the views of the company, Wildfire Studios Pty Ltd.

I have just shared the code from my google docs.

Hope that helps.On Tue, May 29, 2012 at 5:04 AM, Sam Lantinga wrote:

Yes please. Thanks!

On Mon, May 28, 2012 at 12:44 AM, Brad Jackson <@Brad_Jackson>wrote:

Yes, I do. I can’t give you the commercial version; but I did make a
little test app before adding it to the commercial one.

Would you like a copy of the xcode project?

On Sun, May 27, 2012 at 3:47 AM, Sam Lantinga wrote:

BJ, do you have an example of using Game Center with an SDL app set up
this way?

Thanks!

On Thu, May 3, 2012 at 12:27 AM, BJ <@Brad_Jackson> wrote:

**
The problem is that SDL uses a pull messaging system, but iOS requires
a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to

an SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate
message, we execute
a longjmp statement to get back here, preventing an immediate
exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top
of the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events
are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c
class and implement as follows. (Header first)

Code:

#import **
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import **
#import **
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == 8) {
          /* if user specifically requests rbg888 or some color
    

format higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into

one buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES,

depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES,
depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it
sets up the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for
every 2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();
.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using
it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Have you seen Tumblebugs 2 yet?

www.wildfire.com.au

Brad Jackson - Senior Game Programmer
Wildfire Studios Pty. Ltd.
+61 (0)7 3844 1000 (office)
+61 (0)7 3844 8970 (fax)

This email is for the sole use of the addressee/s. It should not
be copied, saved or distributed. If received in error, inform the
sender and delete it from your mailbox and other storage mechanism.
Opinions and advice expressed in this email are those of the sender and may
not reflect the views of the company, Wildfire Studios Pty Ltd.

Have you seen Tumblebugs 2 yet?

www.wildfire.com.au

Brad Jackson - Senior Game Programmer
Wildfire Studios Pty. Ltd.
+61 (0)7 3844 1000 (office)
+61 (0)7 3844 8970 (fax)

This email is for the sole use of the addressee/s. It should not be copied,
saved or distributed. If received in error, inform the sender and delete it
from your mailbox and other storage mechanism. Opinions and advice
expressed in this email are those of the sender and may not reflect the
views of the company, Wildfire Studios Pty Ltd.

The 4th step is essential for Game Center to work, or the messages that the game center windows puts out are lost. iOS expects the applications to take a ‘break’ between updates to allow other processes to happen.

Brian Barnes wrote:> BJ wrote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This is the 3rd different solution for this.

I want to note a couple problems with it.

  1. (I made the same mistake), we don’t need to add some new callback to get events in a callback. SDL_EventFilter will actually handle that already, you just need to add the new events.
  2. You HAVE to have separate events for will suspend, will resume, did enter background, did enter foreground, low memory, and quit. You can NOT just over ride it as if it’s a activate/deactivate, this will NOT follow the guide lines and you WILL have crazy hard to fix crashes.
  3. The changes to pump events is unnecessary, just remove the long jump stuff
  4. The start/stop animation is a bit different than SDL works anywhere else and is a pretty big mountain to climb. Is that what is causing the game center problem?

There’s my patch, there’s Piotr’s patch, and there’s this (which doesn’t solve other problems).

I think the solution is use SDL_EventFilter and just add the necessary 6 events. I can work up a patch that does just this, it’s a small change from my patch.

Adding these additional calls, through whatever callback mechanism, makes SDL work great for me. Not sure exactly what the game center problem is though, so some of this might be required.

[>] Brian


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Thanks BJ, this was incredibly helpful adding Game Center support to
Maelstrom. :slight_smile:

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void
(callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation
callback, and then you have to return from main() to let the Cocoa event
loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
… do frame logic and rendering
}

int main(int argc, char *argv[])
{
… initialize game …

#if IPHONEOS
// Initialize the Game Center for scoring and matchmaking
InitGameCenter();

    // Set up the game to run in the window animation callback on iOS
    // so that Game Center and so forth works correctly.
    SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame,

0);
#else
while ( gRunning ) {
ShowFrame(0);
DelayFrame();
}
CleanUp();
#endif
return 0;
}On Thu, May 3, 2012 at 12:27 AM, BJ wrote:

**
The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to an

SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top of
the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are
processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c class
and implement as follows. (Header first)

Code:

#import **
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import **
#import **
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == 8) {
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into one

buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES,

depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets
up the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for every
2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using it)
as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

That is awesome, I think that pseudo code you posted should go in the iOS
readme.
El 22/06/2012 20:23, “Sam Lantinga” escribi?:> Thanks BJ, this was incredibly helpful adding Game Center support to

Maelstrom. :slight_smile:

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void
(callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation
callback, and then you have to return from main() to let the Cocoa event
loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
… do frame logic and rendering
}

int main(int argc, char *argv[])
{
… initialize game …

#if IPHONEOS
// Initialize the Game Center for scoring and matchmaking
InitGameCenter();

    // Set up the game to run in the window animation callback on iOS
    // so that Game Center and so forth works correctly.
    SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame,

0);
#else
while ( gRunning ) {
ShowFrame(0);
DelayFrame();
}
CleanUp();
#endif
return 0;
}

On Thu, May 3, 2012 at 12:27 AM, BJ wrote:

**
The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to

an SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate
exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top of
the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events
are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c class
and implement as follows. (Header first)

Code:

#import **
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import **
#import **
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == 8) {
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into one

buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES,

depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets
up the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for
every 2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using it)
as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don’t render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks

Sam Lantinga wrote:> Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom. :slight_smile:

I added a function to SDL to make this easier to hook up:
int?SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
? ? … do frame logic and rendering
}

int main(int argc, char *argv[])
{
? ?.. initialize game …

#if IPHONEOS
? ? ? ? // Initialize the Game Center for scoring and matchmaking
? ? ? ? InitGameCenter();

? ? ? ? // Set up the game to run in the window animation callback on iOS
? ? ? ? // so that Game Center and so forth works correctly.
? ? ? ? SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
? ? ? ? while ( gRunning ) {
? ? ? ? ? ? ? ? ShowFrame(0);
?? ? ? ? ? ? ? ?DelayFrame();
? ? ? ? }
? ? ? ? CleanUp();
#endif
? ? ? ? return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <brad at wildfire.com.au (brad at wildfire.com.au)> wrote:

  The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.

(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
? ? return;
? ? /*
? ? ? ? When the user presses the ‘home’ button on the iPod
? ? ? ? the application exits – immediatly.

? ? ? ? Unlike in Mac OS X, it appears there is no way to cancel the termination.

? ? ? ? This doesn’t give the SDL user’s application time to respond to an SDL_Quit event.
? ? ? ? So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
? ? ? ? when the delegate receives the ApplicationWillTerminate message, we execute
? ? ? ? a longjmp statement to get back here, preventing an immediate exit.
? ? ?*/
? ? if (setjmp(jump_env()) == 0) {
? ? ? ? /
if we’re setting the jump, rather than jumping back */
? ? ? ? SInt32 result;
? ? ? ? do {
? ? ? ? ? ? result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
? ? ? ? } while (result == kCFRunLoopRunHandledSource);
? ? }
}

This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.

Code:

?int SystemEventCallback(SDL_Event* event)
?{
? ? ?MyEventHandler::instance().OnEvent(event);
? ? return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
? ?switch (aEvent->type)
? ? ? ?{
? ? case SDL_WINDOWEVENT:
? ? ? ? {
? ? ? ? ? ? switch (aEvent->window.event)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? case SDL_WINDOWEVENT_FOCUS_LOST:
? ? ? ? ? ? ? ? ? ? OnLostFocus();
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case SDL_WINDOWEVENT_FOCUS_GAINED:
? ? ? ? ? ? ? ? ? ? OnGainedFocus();
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? break;
? ? ? ? ? }
? ? ? ?}
}

Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 (http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11) to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)

Code:

#import
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

    Code:

#import “MYOpenGLView.h”
#import
#import
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    ? ? ? retainBacking:(BOOL)retained
    ? ? ? ? ? ? ? rBits:(int)rBits
    ? ? ? ? ? ? ? gBits:(int)gBits
    ? ? ? ? ? ? ? bBits:(int)bBits
    ? ? ? ? ? ? ? aBits:(int)aBits
    ? ? ? ? ? depthBits:(int)depthBits
    ? ? ? ? stencilBits:(int)stencilBits
    ? ? ? ?majorVersion:(int)majorVersion
    {
    ? ? depthBufferFormat = 0;
    ? ?
    ? ? if ((self = [super initWithFrame:frame])) {
    ? ? ? ? const BOOL useStencilBuffer = (stencilBits != 0);
    ? ? ? ? const BOOL useDepthBuffer = (depthBits != 0);
    ? ? ? ? NSString colorFormat = nil;
    ? ? ? ?
    ? ? ? ? if (rBits == 8 && gBits == 8 && bBits == 8) {
    ? ? ? ? ? ? /
    if user specifically requests rbg888 or some color format higher than 16bpp /
    ? ? ? ? ? ? colorFormat = kEAGLColorFormatRGBA8;
    ? ? ? ? } else {
    ? ? ? ? ? ? /
    default case (faster) /
    ? ? ? ? ? ? colorFormat = kEAGLColorFormatRGB565;
    ? ? ? ? }
    ? ? ? ?
    ? ? ? ? /
    Get the layer */
    ? ? ? ? CAEAGLLayer eaglLayer = (CAEAGLLayer )self.layer;
    ? ? ? ?
    ? ? ? ? eaglLayer.opaque = YES;
    ? ? ? ? eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
    ? ? ? ?
    ? ? ? ? if (majorVersion > 1) {
    ? ? ? ? ? ? context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
    ? ? ? ? } else {
    ? ? ? ? ? ? context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
    ? ? ? ? }
    ? ? ? ? if (!context || ![EAGLContext setCurrentContext:context]) {
    ? ? ? ? ? ? [self release];
    ? ? ? ? ? ? SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
    ? ? ? ? ? ? return nil;
    ? ? ? ? }
    ? ? ? ?
    ? ? ? ? // !!! FIXME: use the screen this is on!
    ? ? ? ? /
    Use the main screen scale (for retina display support) /
    ? ? ? ? if ([self respondsToSelector:@selector(contentScaleFactor)])
    ? ? ? ? ? ? self.contentScaleFactor = [UIScreen mainScreen].scale;
    ? ? ? ?
    ? ? ? ? /
    create the buffers /
    ? ? ? ? glGenFramebuffersOES(1, &viewFramebuffer);
    ? ? ? ? glGenRenderbuffersOES(1, &viewRenderbuffer);
    ? ? ? ?
    ? ? ? ? glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    ? ? ? ? glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    ? ? ? ? [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer
    )self.layer];
    ? ? ? ? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
    ? ? ? ?
    ? ? ? ? glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    ? ? ? ? glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
    ? ? ? ?
    ? ? ? ? if ((useDepthBuffer) || (useStencilBuffer)) {
    ? ? ? ? ? ? if (useStencilBuffer) {
    ? ? ? ? ? ? ? ? /
    Apparently you need to pack stencil and depth into one buffer. /
    ? ? ? ? ? ? ? ? depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
    ? ? ? ? ? ? } else if (useDepthBuffer) {
    ? ? ? ? ? ? ? ? /
    iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES /
    ? ? ? ? ? ? ? ? depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
    ? ? ? ? ? ? }
    ? ? ? ? ? ?
    ? ? ? ? ? ? glGenRenderbuffersOES(1, &depthRenderbuffer);
    ? ? ? ? ? ? glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
    ? ? ? ? ? ? glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
    ? ? ? ? ? ? if (useDepthBuffer) {
    ? ? ? ? ? ? ? ? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    ? ? ? ? ? ? }
    ? ? ? ? ? ? if (useStencilBuffer) {
    ? ? ? ? ? ? ? ? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    ? ? ? ? ? ? }
    ? ? ? ? }
    ? ? ? ?
    ? ? ? ? if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
    ? ? ? ? ? ? return NO;
    ? ? ? ? }
    ? ? ? ? /
    end create buffers */
    ? ? ? ?
    ? ? ? ? self.autoresizingMask = 0;? // don’t allow autoresize, since we need to do some magic in -(void)updateFrame.
    ? ? ? ?
    ? ? ? ? [self startAnimation];
    ? ? }
    ? ? return self;
    }

  • (void)startAnimation
    {
    ? ? // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    ? ? // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
    ? ?
    ? ? displayLink = [NSClassFromString(@“CADisplayLink”) displayLinkWithTarget:self selector:@selector(doLoop:)];
    ? ? [displayLink setFrameInterval:animationFrameInterval];
    ? ? [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    ? ? [displayLink invalidate];
    ? ? displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    ? ? runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/ (http://www.ananseproductions.com/game-loops-on-ios/).

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
? ?// iOS uses a push event system instead of a pull event system
#ifdef WIN32
?? ?SDL_Event Event;
?? ?while (SDL_PollEvent(&Event))
?? ?{
?? ?? ?OnEvent(&Event);
?? ?}
#else
? ? /* Check for joystick state change */
? ? SDL_JoystickUpdate();
#endif // WIN32

? ?// do update stuff here

? ?// do render stuff here
? ?SDL_RenderClear(mRenderer);
? ?SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
? ?SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list
SDL at lists.libsdl.org (SDL at lists.libsdl.org)
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)

No idea… anyone?On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 wrote:

**
Sam that function works like a charm, I was able to use that function to
run my main loop then use the initialize stuff from BJ. I successfully
launched game centre in my app but now the issue is how to get the welcome
back message to pop up, or even any notification banner from game kit. If I
don’t render then I see the banner if not it draws over it. I got the idea
of checking for views but it seems to only show the SDL view. I base my
self of the SDL template included in the SDK. So I was wondering if there
was a way to to display this banner?

Thanks

Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to
Maelstrom. [image: Smile]

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void
(callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation
callback, and then you have to return from main() to let the Cocoa event
loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
… do frame logic and rendering
}

int main(int argc, char *argv[])
{
… initialize game …

#if IPHONEOS
// Initialize the Game Center for scoring and matchmaking
InitGameCenter();

    // Set up the game to run in the window animation callback on iOS
    // so that Game Center and so forth works correctly.
    SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame,

0);
#else
while ( gRunning ) {
ShowFrame(0);
DelayFrame();
}
CleanUp();
#endif
return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:

Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to an

SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top of
the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are
processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c class
and implement as follows. (Header first)

Code:

#import
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import
#import
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == [image: Cool] {
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into one

buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES,

depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets up
the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for every
2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using it) as
it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

  • (void) authenticateLocalUser

{

[self becomeFirstResponder];



if([GKLocalPlayer localPlayer].authenticated == NO)

{

    [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(

NSError *error)

    {

        if(error == nil)

        {

            SDL_Delay(1000);

2012/7/5 Sam Lantinga > No idea… anyone?

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 wrote:

**
Sam that function works like a charm, I was able to use that function to
run my main loop then use the initialize stuff from BJ. I successfully
launched game centre in my app but now the issue is how to get the welcome
back message to pop up, or even any notification banner from game kit. If I
don’t render then I see the banner if not it draws over it. I got the idea
of checking for views but it seems to only show the SDL view. I base my
self of the SDL template included in the SDK. So I was wondering if there
was a way to to display this banner?

Thanks

Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to
Maelstrom. [image: Smile]

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval,
void (callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation
callback, and then you have to return from main() to let the Cocoa event
loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
… do frame logic and rendering
}

int main(int argc, char *argv[])
{
… initialize game …

#if IPHONEOS
// Initialize the Game Center for scoring and matchmaking
InitGameCenter();

    // Set up the game to run in the window animation callback on iOS
    // so that Game Center and so forth works correctly.
    SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame,

0);
#else
while ( gRunning ) {
ShowFrame(0);
DelayFrame();
}
CleanUp();
#endif
return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:

Quote:

The problem is that SDL uses a pull messaging system, but iOS requires
a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to

an SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate
exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top of
the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events
are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c class
and implement as follows. (Header first)

Code:

#import
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import
#import
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == [image: Cool] {
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into one

buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES,

depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets up
the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for every
2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using it) as
it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Best Regards

So I tried the above and had no success. After looking at the keyboard code I realized its creating a new window. So I decide to do window count and it happens that game center is doing the same thing as soon as the banner came up it showed another window opening. So I decided to trap any window that opens up .

this code is assuming there will be no other windows popping up but you could always add a count for other windows that is open and just do the math
not sure if it was the best solution but it works and now I understand how its working

//check if theres more then one window
if([[UIApplication sharedApplication].windows count] > 1)
{
if(one_time)
{
//getting the current window
UIWindow *main_window = [[UIApplication sharedApplication] keyWindow];
//get the new window
UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject];
//add the second window view to the main window
[main_window addSubview:window.superview];

            //set window level 
            window.windowLevel = 1;
            
            //run this once every time it opens a new window 
            one_time = false;
        }
    }
    else 
    {
       //reset the flag when window closes 
        one_time = true;
    }

Ye Xing wrote:> - (void) authenticateLocalUser

{
?? ?? [self becomeFirstResponder];
??? ??
?? ?? if([GKLocalPlayer localPlayer].authenticated == NO)
?? ?? {
?? ?? ?? ?? [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error)
?? ?? ?? ?? {
?? ?? ?? ?? ?? ?? if(error == nil)
?? ?? ?? ?? ?? ?? {
?? ?? ?? ?? ?? ?? ?? ???SDL_Delay(1000);
2012/7/5 Sam Lantinga <slouken at libsdl.org (slouken at libsdl.org)>

No idea… anyone?

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 <@stevo5800 (@stevo5800)> wrote:

   	Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks

Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom. 

I added a function to SDL to make this easier to hook up:
int??SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
?? ?? … do frame logic and rendering
}

int main(int argc, char *argv[])
{
?? ??.. initialize game …

#if IPHONEOS
?? ?? ?? ?? // Initialize the Game Center for scoring and matchmaking
?? ?? ?? ?? InitGameCenter();

?? ?? ?? ?? // Set up the game to run in the window animation callback on iOS
?? ?? ?? ?? // so that Game Center and so forth works correctly.
?? ?? ?? ?? SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
?? ?? ?? ?? while ( gRunning ) {
?? ?? ?? ?? ?? ?? ?? ?? ShowFrame(0);
??? ?? ?? ?? ?? ?? ?? ??DelayFrame();
?? ?? ?? ?? }
?? ?? ?? ?? CleanUp();
#endif
?? ?? ?? ?? return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:

Quote:

   	The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.

(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
?? ?? return;
?? ?? /*
?? ?? ?? ?? When the user presses the ‘home’ button on the iPod
?? ?? ?? ?? the application exits – immediatly.

?? ?? ?? ?? Unlike in Mac OS X, it appears there is no way to cancel the termination.

?? ?? ?? ?? This doesn’t give the SDL user’s application time to respond to an SDL_Quit event.
?? ?? ?? ?? So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
?? ?? ?? ?? when the delegate receives the ApplicationWillTerminate message, we execute
?? ?? ?? ?? a longjmp statement to get back here, preventing an immediate exit.
?? ?? ??*/
?? ?? if (setjmp(jump_env()) == 0) {
?? ?? ?? ?? /
if we’re setting the jump, rather than jumping back */
?? ?? ?? ?? SInt32 result;
?? ?? ?? ?? do {
?? ?? ?? ?? ?? ?? result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
?? ?? ?? ?? } while (result == kCFRunLoopRunHandledSource);
?? ?? }
}

This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.

Code:

??int SystemEventCallback(SDL_Event* event)
??{
?? ?? ??MyEventHandler::instance().OnEvent(event);
?? ?? return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
?? ??switch (aEvent->type)
?? ?? ?? ??{
?? ?? case SDL_WINDOWEVENT:
?? ?? ?? ?? {
?? ?? ?? ?? ?? ?? switch (aEvent->window.event)
?? ?? ?? ?? ?? ?? {
?? ?? ?? ?? ?? ?? ?? ?? case SDL_WINDOWEVENT_FOCUS_LOST:
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? OnLostFocus();
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? break;
?? ?? ?? ?? ?? ?? ?? ?? case SDL_WINDOWEVENT_FOCUS_GAINED:
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? OnGainedFocus();
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? break;
?? ?? ?? ?? ?? ?? }
?? ?? ?? ?? ?? ?? break;
?? ?? ?? ?? ?? }
?? ?? ?? ??}
}

Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 (http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11) to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)

Code:

#import
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

    Code:

#import “MYOpenGLView.h”
#import
#import
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    ?? ?? ?? retainBacking:(BOOL)retained
    ?? ?? ?? ?? ?? ?? ?? rBits:(int)rBits
    ?? ?? ?? ?? ?? ?? ?? gBits:(int)gBits
    ?? ?? ?? ?? ?? ?? ?? bBits:(int)bBits
    ?? ?? ?? ?? ?? ?? ?? aBits:(int)aBits
    ?? ?? ?? ?? ?? depthBits:(int)depthBits
    ?? ?? ?? ?? stencilBits:(int)stencilBits
    ?? ?? ?? ??majorVersion:(int)majorVersion
    {
    ?? ?? depthBufferFormat = 0;
    ?? ??
    ?? ?? if ((self = [super initWithFrame:frame])) {
    ?? ?? ?? ?? const BOOL useStencilBuffer = (stencilBits != 0);
    ?? ?? ?? ?? const BOOL useDepthBuffer = (depthBits != 0);
    ?? ?? ?? ?? NSString colorFormat = nil;
    ?? ?? ?? ??
    ?? ?? ?? ?? if (rBits == 8 && gBits == 8 && bBits == {
    ?? ?? ?? ?? ?? ?? /
    if user specifically requests rbg888 or some color format higher than 16bpp /
    ?? ?? ?? ?? ?? ?? colorFormat = kEAGLColorFormatRGBA8;
    ?? ?? ?? ?? } else {
    ?? ?? ?? ?? ?? ?? /
    default case (faster) /
    ?? ?? ?? ?? ?? ?? colorFormat = kEAGLColorFormatRGB565;
    ?? ?? ?? ?? }
    ?? ?? ?? ??
    ?? ?? ?? ?? /
    Get the layer */
    ?? ?? ?? ?? CAEAGLLayer eaglLayer = (CAEAGLLayer )self.layer;
    ?? ?? ?? ??
    ?? ?? ?? ?? eaglLayer.opaque = YES;
    ?? ?? ?? ?? eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
    ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
    ?? ?? ?? ??
    ?? ?? ?? ?? if (majorVersion > 1) {
    ?? ?? ?? ?? ?? ?? context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
    ?? ?? ?? ?? } else {
    ?? ?? ?? ?? ?? ?? context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
    ?? ?? ?? ?? }
    ?? ?? ?? ?? if (!context || ![EAGLContext setCurrentContext:context]) {
    ?? ?? ?? ?? ?? ?? [self release];
    ?? ?? ?? ?? ?? ?? SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
    ?? ?? ?? ?? ?? ?? return nil;
    ?? ?? ?? ?? }
    ?? ?? ?? ??
    ?? ?? ?? ?? // !!! FIXME: use the screen this is on!
    ?? ?? ?? ?? /
    Use the main screen scale (for retina display support) /
    ?? ?? ?? ?? if ([self respondsToSelector:@selector(contentScaleFactor)])
    ?? ?? ?? ?? ?? ?? self.contentScaleFactor = [UIScreen mainScreen].scale;
    ?? ?? ?? ??
    ?? ?? ?? ?? /
    create the buffers /
    ?? ?? ?? ?? glGenFramebuffersOES(1, &viewFramebuffer);
    ?? ?? ?? ?? glGenRenderbuffersOES(1, &viewRenderbuffer);
    ?? ?? ?? ??
    ?? ?? ?? ?? glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    ?? ?? ?? ?? glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    ?? ?? ?? ?? [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer
    )self.layer];
    ?? ?? ?? ?? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
    ?? ?? ?? ??
    ?? ?? ?? ?? glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    ?? ?? ?? ?? glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
    ?? ?? ?? ??
    ?? ?? ?? ?? if ((useDepthBuffer) || (useStencilBuffer)) {
    ?? ?? ?? ?? ?? ?? if (useStencilBuffer) {
    ?? ?? ?? ?? ?? ?? ?? ?? /
    Apparently you need to pack stencil and depth into one buffer. /
    ?? ?? ?? ?? ?? ?? ?? ?? depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
    ?? ?? ?? ?? ?? ?? } else if (useDepthBuffer) {
    ?? ?? ?? ?? ?? ?? ?? ?? /
    iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES /
    ?? ?? ?? ?? ?? ?? ?? ?? depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
    ?? ?? ?? ?? ?? ?? }
    ?? ?? ?? ?? ?? ??
    ?? ?? ?? ?? ?? ?? glGenRenderbuffersOES(1, &depthRenderbuffer);
    ?? ?? ?? ?? ?? ?? glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
    ?? ?? ?? ?? ?? ?? glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
    ?? ?? ?? ?? ?? ?? if (useDepthBuffer) {
    ?? ?? ?? ?? ?? ?? ?? ?? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    ?? ?? ?? ?? ?? ?? }
    ?? ?? ?? ?? ?? ?? if (useStencilBuffer) {
    ?? ?? ?? ?? ?? ?? ?? ?? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    ?? ?? ?? ?? ?? ?? }
    ?? ?? ?? ?? }
    ?? ?? ?? ??
    ?? ?? ?? ?? if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
    ?? ?? ?? ?? ?? ?? return NO;
    ?? ?? ?? ?? }
    ?? ?? ?? ?? /
    end create buffers */
    ?? ?? ?? ??
    ?? ?? ?? ?? self.autoresizingMask = 0;?? // don’t allow autoresize, since we need to do some magic in -(void)updateFrame.
    ?? ?? ?? ??
    ?? ?? ?? ?? [self startAnimation];
    ?? ?? }
    ?? ?? return self;
    }

  • (void)startAnimation
    {
    ?? ?? // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    ?? ?? // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
    ?? ??
    ?? ?? displayLink = [NSClassFromString(@“CADisplayLink”) displayLinkWithTarget:self selector:@selector(doLoop:)];
    ?? ?? [displayLink setFrameInterval:animationFrameInterval];
    ?? ?? [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    ?? ?? [displayLink invalidate];
    ?? ?? displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    ?? ?? runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/ (http://www.ananseproductions.com/game-loops-on-ios/).

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
?? ??// iOS uses a push event system instead of a pull event system
#ifdef WIN32
??? ??SDL_Event Event;
??? ??while (SDL_PollEvent(&Event))
??? ??{
??? ??? ??OnEvent(&Event);
??? ??}
#else
?? ?? /* Check for joystick state change */
?? ?? SDL_JoystickUpdate();
#endif // WIN32

?? ??// do update stuff here

?? ??// do render stuff here
?? ??SDL_RenderClear(mRenderer);
?? ??SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
?? ??SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)


SDL mailing list
SDL at lists.libsdl.org (SDL at lists.libsdl.org)
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)


SDL mailing list
SDL at lists.libsdl.org (SDL at lists.libsdl.org)
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)

Best Regards

David Ludwig discovered the issue with the game center being hidden, and I
put in an untested fix:

Can you let me know if this works? I should be able to test iOS stuff
again in a week or so.On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 wrote:

**
Sam that function works like a charm, I was able to use that function to
run my main loop then use the initialize stuff from BJ. I successfully
launched game centre in my app but now the issue is how to get the welcome
back message to pop up, or even any notification banner from game kit. If I
don’t render then I see the banner if not it draws over it. I got the idea
of checking for views but it seems to only show the SDL view. I base my
self of the SDL template included in the SDK. So I was wondering if there
was a way to to display this banner?

Thanks

Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to
Maelstrom. [image: Smile]

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void
(callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation
callback, and then you have to return from main() to let the Cocoa event
loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
… do frame logic and rendering
}

int main(int argc, char *argv[])
{
… initialize game …

#if IPHONEOS
// Initialize the Game Center for scoring and matchmaking
InitGameCenter();

    // Set up the game to run in the window animation callback on iOS
    // so that Game Center and so forth works correctly.
    SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame,

0);
#else
while ( gRunning ) {
ShowFrame(0);
DelayFrame();
}
CleanUp();
#endif
return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:

Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to an

SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top of
the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are
processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c class
and implement as follows. (Header first)

Code:

#import
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import
#import
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == [image: Cool] {
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into one

buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES,

depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets up
the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for every
2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using it) as
it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I got a black screen but the banner shows up

Sam Lantinga wrote:> David Ludwig discovered the issue with the game center being hidden, and I put in an untested fix:http://hg.libsdl.org/SDL/rev/8f224d0762ab (http://hg.libsdl.org/SDL/rev/8f224d0762ab)

Can you let me know if this works? ?I should be able to test iOS stuff again in a week or so.

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 <@stevo5800 (@stevo5800)> wrote:

  Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks

Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom. 

I added a function to SDL to make this easier to hook up:
int?SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
? ? … do frame logic and rendering
}

int main(int argc, char *argv[])
{
? ?.. initialize game …

#if IPHONEOS
? ? ? ? // Initialize the Game Center for scoring and matchmaking
? ? ? ? InitGameCenter();

? ? ? ? // Set up the game to run in the window animation callback on iOS
? ? ? ? // so that Game Center and so forth works correctly.
? ? ? ? SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
? ? ? ? while ( gRunning ) {
? ? ? ? ? ? ? ? ShowFrame(0);
?? ? ? ? ? ? ? ?DelayFrame();
? ? ? ? }
? ? ? ? CleanUp();
#endif
? ? ? ? return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:

Quote:

   	The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.

(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
? ? return;
? ? /*
? ? ? ? When the user presses the ‘home’ button on the iPod
? ? ? ? the application exits – immediatly.

? ? ? ? Unlike in Mac OS X, it appears there is no way to cancel the termination.

? ? ? ? This doesn’t give the SDL user’s application time to respond to an SDL_Quit event.
? ? ? ? So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
? ? ? ? when the delegate receives the ApplicationWillTerminate message, we execute
? ? ? ? a longjmp statement to get back here, preventing an immediate exit.
? ? ?*/
? ? if (setjmp(jump_env()) == 0) {
? ? ? ? /
if we’re setting the jump, rather than jumping back */
? ? ? ? SInt32 result;
? ? ? ? do {
? ? ? ? ? ? result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
? ? ? ? } while (result == kCFRunLoopRunHandledSource);
? ? }
}

This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.

Code:

?int SystemEventCallback(SDL_Event* event)
?{
? ? ?MyEventHandler::instance().OnEvent(event);
? ? return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
? ?switch (aEvent->type)
? ? ? ?{
? ? case SDL_WINDOWEVENT:
? ? ? ? {
? ? ? ? ? ? switch (aEvent->window.event)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? case SDL_WINDOWEVENT_FOCUS_LOST:
? ? ? ? ? ? ? ? ? ? OnLostFocus();
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case SDL_WINDOWEVENT_FOCUS_GAINED:
? ? ? ? ? ? ? ? ? ? OnGainedFocus();
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? break;
? ? ? ? ? }
? ? ? ?}
}

Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 (http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11) to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)

Code:

#import
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

    Code:

#import “MYOpenGLView.h”
#import
#import
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    ? ? ? retainBacking:(BOOL)retained
    ? ? ? ? ? ? ? rBits:(int)rBits
    ? ? ? ? ? ? ? gBits:(int)gBits
    ? ? ? ? ? ? ? bBits:(int)bBits
    ? ? ? ? ? ? ? aBits:(int)aBits
    ? ? ? ? ? depthBits:(int)depthBits
    ? ? ? ? stencilBits:(int)stencilBits
    ? ? ? ?majorVersion:(int)majorVersion
    {
    ? ? depthBufferFormat = 0;
    ? ?
    ? ? if ((self = [super initWithFrame:frame])) {
    ? ? ? ? const BOOL useStencilBuffer = (stencilBits != 0);
    ? ? ? ? const BOOL useDepthBuffer = (depthBits != 0);
    ? ? ? ? NSString colorFormat = nil;
    ? ? ? ?
    ? ? ? ? if (rBits == 8 && gBits == 8 && bBits == {
    ? ? ? ? ? ? /
    if user specifically requests rbg888 or some color format higher than 16bpp /
    ? ? ? ? ? ? colorFormat = kEAGLColorFormatRGBA8;
    ? ? ? ? } else {
    ? ? ? ? ? ? /
    default case (faster) /
    ? ? ? ? ? ? colorFormat = kEAGLColorFormatRGB565;
    ? ? ? ? }
    ? ? ? ?
    ? ? ? ? /
    Get the layer */
    ? ? ? ? CAEAGLLayer eaglLayer = (CAEAGLLayer )self.layer;
    ? ? ? ?
    ? ? ? ? eaglLayer.opaque = YES;
    ? ? ? ? eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
    ? ? ? ?
    ? ? ? ? if (majorVersion > 1) {
    ? ? ? ? ? ? context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
    ? ? ? ? } else {
    ? ? ? ? ? ? context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
    ? ? ? ? }
    ? ? ? ? if (!context || ![EAGLContext setCurrentContext:context]) {
    ? ? ? ? ? ? [self release];
    ? ? ? ? ? ? SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
    ? ? ? ? ? ? return nil;
    ? ? ? ? }
    ? ? ? ?
    ? ? ? ? // !!! FIXME: use the screen this is on!
    ? ? ? ? /
    Use the main screen scale (for retina display support) /
    ? ? ? ? if ([self respondsToSelector:@selector(contentScaleFactor)])
    ? ? ? ? ? ? self.contentScaleFactor = [UIScreen mainScreen].scale;
    ? ? ? ?
    ? ? ? ? /
    create the buffers /
    ? ? ? ? glGenFramebuffersOES(1, &viewFramebuffer);
    ? ? ? ? glGenRenderbuffersOES(1, &viewRenderbuffer);
    ? ? ? ?
    ? ? ? ? glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    ? ? ? ? glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    ? ? ? ? [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer
    )self.layer];
    ? ? ? ? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
    ? ? ? ?
    ? ? ? ? glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    ? ? ? ? glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
    ? ? ? ?
    ? ? ? ? if ((useDepthBuffer) || (useStencilBuffer)) {
    ? ? ? ? ? ? if (useStencilBuffer) {
    ? ? ? ? ? ? ? ? /
    Apparently you need to pack stencil and depth into one buffer. /
    ? ? ? ? ? ? ? ? depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
    ? ? ? ? ? ? } else if (useDepthBuffer) {
    ? ? ? ? ? ? ? ? /
    iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES /
    ? ? ? ? ? ? ? ? depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
    ? ? ? ? ? ? }
    ? ? ? ? ? ?
    ? ? ? ? ? ? glGenRenderbuffersOES(1, &depthRenderbuffer);
    ? ? ? ? ? ? glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
    ? ? ? ? ? ? glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
    ? ? ? ? ? ? if (useDepthBuffer) {
    ? ? ? ? ? ? ? ? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    ? ? ? ? ? ? }
    ? ? ? ? ? ? if (useStencilBuffer) {
    ? ? ? ? ? ? ? ? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    ? ? ? ? ? ? }
    ? ? ? ? }
    ? ? ? ?
    ? ? ? ? if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
    ? ? ? ? ? ? return NO;
    ? ? ? ? }
    ? ? ? ? /
    end create buffers */
    ? ? ? ?
    ? ? ? ? self.autoresizingMask = 0;? // don’t allow autoresize, since we need to do some magic in -(void)updateFrame.
    ? ? ? ?
    ? ? ? ? [self startAnimation];
    ? ? }
    ? ? return self;
    }

  • (void)startAnimation
    {
    ? ? // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    ? ? // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
    ? ?
    ? ? displayLink = [NSClassFromString(@“CADisplayLink”) displayLinkWithTarget:self selector:@selector(doLoop:)];
    ? ? [displayLink setFrameInterval:animationFrameInterval];
    ? ? [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    ? ? [displayLink invalidate];
    ? ? displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    ? ? runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/ (http://www.ananseproductions.com/game-loops-on-ios/).

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
? ?// iOS uses a push event system instead of a pull event system
#ifdef WIN32
?? ?SDL_Event Event;
?? ?while (SDL_PollEvent(&Event))
?? ?{
?? ?? ?OnEvent(&Event);
?? ?}
#else
? ? /* Check for joystick state change */
? ? SDL_JoystickUpdate();
#endif // WIN32

? ?// do update stuff here

? ?// do render stuff here
? ?SDL_RenderClear(mRenderer);
? ?SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
? ?SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)


SDL mailing list
SDL at lists.libsdl.org (SDL at lists.libsdl.org)
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)

If you revert that patch, do you get a normal (non-black) screen and no
banner?On Sun, Jul 22, 2012 at 3:39 PM, stevo5800 wrote:

**
I got a black screen but the banner shows up

Sam Lantinga wrote:

David Ludwig discovered the issue with the game center being hidden, and
I put in an untested fix:http://hg.libsdl.org/SDL/rev/8f224d0762ab

Can you let me know if this works? I should be able to test iOS stuff
again in a week or so.

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 <> wrote:

Quote:

Sam that function works like a charm, I was able to use that function to
run my main loop then use the initialize stuff from BJ. I successfully
launched game centre in my app but now the issue is how to get the welcome
back message to pop up, or even any notification banner from game kit. If I
don’t render then I see the banner if not it draws over it. I got the idea
of checking for views but it seems to only show the SDL view. I base my
self of the SDL template included in the SDK. So I was wondering if there
was a way to to display this banner?

Thanks

Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to
Maelstrom.

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void
(callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation
callback, and then you have to return from main() to let the Cocoa event
loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
… do frame logic and rendering
}

int main(int argc, char *argv[])
{
… initialize game …

#if IPHONEOS
// Initialize the Game Center for scoring and matchmaking
InitGameCenter();

    // Set up the game to run in the window animation callback on iOS
    // so that Game Center and so forth works correctly.
    SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame,

0);
#else
while ( gRunning ) {
ShowFrame(0);
DelayFrame();
}
CleanUp();
#endif
return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:

Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to an

SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top of
the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are
processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c class
and implement as follows. (Header first)

Code:

#import
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import
#import
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == {
    
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into one

buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES,

depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets up
the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for every
2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using it) as
it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Yea I used it on an existing project switch back to my old SDL folder no black screen but banner behind

Sam Lantinga wrote:> If you revert that patch, do you get a normal (non-black) screen and no banner?

On Sun, Jul 22, 2012 at 3:39 PM, stevo5800 <@stevo5800 (@stevo5800)> wrote:

  I got a black screen but the banner shows up 




Sam Lantinga wrote:

David Ludwig discovered the issue with the game center being hidden, and I put in an untested fix:http://hg.libsdl.org/SDL/rev/8f224d0762ab (http://hg.libsdl.org/SDL/rev/8f224d0762ab)

Can you let me know if this works? ?I should be able to test iOS stuff again in a week or so.

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 <> wrote:

Quote:

   	Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks

Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom. 

I added a function to SDL to make this easier to hook up:
int?SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
? ? … do frame logic and rendering
}

int main(int argc, char *argv[])
{
? ?.. initialize game …

#if IPHONEOS
? ? ? ? // Initialize the Game Center for scoring and matchmaking
? ? ? ? InitGameCenter();

? ? ? ? // Set up the game to run in the window animation callback on iOS
? ? ? ? // so that Game Center and so forth works correctly.
? ? ? ? SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
? ? ? ? while ( gRunning ) {
? ? ? ? ? ? ? ? ShowFrame(0);
?? ? ? ? ? ? ? ?DelayFrame();
? ? ? ? }
? ? ? ? CleanUp();
#endif
? ? ? ? return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:

Quote:

   	The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.

(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
? ? return;
? ? /*
? ? ? ? When the user presses the ‘home’ button on the iPod
? ? ? ? the application exits – immediatly.

? ? ? ? Unlike in Mac OS X, it appears there is no way to cancel the termination.

? ? ? ? This doesn’t give the SDL user’s application time to respond to an SDL_Quit event.
? ? ? ? So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
? ? ? ? when the delegate receives the ApplicationWillTerminate message, we execute
? ? ? ? a longjmp statement to get back here, preventing an immediate exit.
? ? ?*/
? ? if (setjmp(jump_env()) == 0) {
? ? ? ? /
if we’re setting the jump, rather than jumping back */
? ? ? ? SInt32 result;
? ? ? ? do {
? ? ? ? ? ? result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
? ? ? ? } while (result == kCFRunLoopRunHandledSource);
? ? }
}

This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.

Code:

?int SystemEventCallback(SDL_Event* event)
?{
? ? ?MyEventHandler::instance().OnEvent(event);
? ? return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
? ?switch (aEvent->type)
? ? ? ?{
? ? case SDL_WINDOWEVENT:
? ? ? ? {
? ? ? ? ? ? switch (aEvent->window.event)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? case SDL_WINDOWEVENT_FOCUS_LOST:
? ? ? ? ? ? ? ? ? ? OnLostFocus();
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case SDL_WINDOWEVENT_FOCUS_GAINED:
? ? ? ? ? ? ? ? ? ? OnGainedFocus();
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? break;
? ? ? ? ? }
? ? ? ?}
}

Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 (http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11) to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)

Code:

#import
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

    Code:

#import “MYOpenGLView.h”
#import
#import
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    ? ? ? retainBacking:(BOOL)retained
    ? ? ? ? ? ? ? rBits:(int)rBits
    ? ? ? ? ? ? ? gBits:(int)gBits
    ? ? ? ? ? ? ? bBits:(int)bBits
    ? ? ? ? ? ? ? aBits:(int)aBits
    ? ? ? ? ? depthBits:(int)depthBits
    ? ? ? ? stencilBits:(int)stencilBits
    ? ? ? ?majorVersion:(int)majorVersion
    {
    ? ? depthBufferFormat = 0;
    ? ?
    ? ? if ((self = [super initWithFrame:frame])) {
    ? ? ? ? const BOOL useStencilBuffer = (stencilBits != 0);
    ? ? ? ? const BOOL useDepthBuffer = (depthBits != 0);
    ? ? ? ? NSString *colorFormat = nil;
    ? ? ? ?

? ? ? ? if (rBits == 8 && gBits == 8 && bBits == {
? ? ? ? ? ? /* if user specifically requests rbg888 or some color format higher than 16bpp /
? ? ? ? ? ? colorFormat = kEAGLColorFormatRGBA8;
? ? ? ? } else {
? ? ? ? ? ? /
default case (faster) /
? ? ? ? ? ? colorFormat = kEAGLColorFormatRGB565;
? ? ? ? }
? ? ? ?
? ? ? ? /
Get the layer */
? ? ? ? CAEAGLLayer eaglLayer = (CAEAGLLayer )self.layer;
? ? ? ?
? ? ? ? eaglLayer.opaque = YES;
? ? ? ? eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
? ? ? ?
? ? ? ? if (majorVersion > 1) {
? ? ? ? ? ? context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
? ? ? ? } else {
? ? ? ? ? ? context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
? ? ? ? }
? ? ? ? if (!context || ![EAGLContext setCurrentContext:context]) {
? ? ? ? ? ? [self release];
? ? ? ? ? ? SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
? ? ? ? ? ? return nil;
? ? ? ? }
? ? ? ?
? ? ? ? // !!! FIXME: use the screen this is on!
? ? ? ? /
Use the main screen scale (for retina display support) /
? ? ? ? if ([self respondsToSelector:@selector(contentScaleFactor)])
? ? ? ? ? ? self.contentScaleFactor = [UIScreen mainScreen].scale;
? ? ? ?
? ? ? ? /
create the buffers /
? ? ? ? glGenFramebuffersOES(1, &viewFramebuffer);
? ? ? ? glGenRenderbuffersOES(1, &viewRenderbuffer);
? ? ? ?
? ? ? ? glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
? ? ? ? glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
? ? ? ? [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer
)self.layer];
? ? ? ? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
? ? ? ?
? ? ? ? glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
? ? ? ? glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
? ? ? ?
? ? ? ? if ((useDepthBuffer) || (useStencilBuffer)) {
? ? ? ? ? ? if (useStencilBuffer) {
? ? ? ? ? ? ? ? /
Apparently you need to pack stencil and depth into one buffer. /
? ? ? ? ? ? ? ? depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
? ? ? ? ? ? } else if (useDepthBuffer) {
? ? ? ? ? ? ? ? /
iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES /
? ? ? ? ? ? ? ? depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
? ? ? ? ? ? }
? ? ? ? ? ?
? ? ? ? ? ? glGenRenderbuffersOES(1, &depthRenderbuffer);
? ? ? ? ? ? glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
? ? ? ? ? ? glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
? ? ? ? ? ? if (useDepthBuffer) {
? ? ? ? ? ? ? ? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
? ? ? ? ? ? }
? ? ? ? ? ? if (useStencilBuffer) {
? ? ? ? ? ? ? ? glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ?
? ? ? ? if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
? ? ? ? ? ? return NO;
? ? ? ? }
? ? ? ? /
end create buffers */
? ? ? ?
? ? ? ? self.autoresizingMask = 0;? // don’t allow autoresize, since we need to do some magic in -(void)updateFrame.
? ? ? ?
? ? ? ? [self startAnimation];
? ? }
? ? return self;
}

  • (void)startAnimation
    {
    ? ? // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    ? ? // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
    ? ?
    ? ? displayLink = [NSClassFromString(@“CADisplayLink”) displayLinkWithTarget:self selector:@selector(doLoop:)];
    ? ? [displayLink setFrameInterval:animationFrameInterval];
    ? ? [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    ? ? [displayLink invalidate];
    ? ? displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    ? ? runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/ (http://www.ananseproductions.com/game-loops-on-ios/).

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
? ?// iOS uses a push event system instead of a pull event system
#ifdef WIN32
?? ?SDL_Event Event;
?? ?while (SDL_PollEvent(&Event))
?? ?{
?? ?? ?OnEvent(&Event);
?? ?}
#else
? ? /* Check for joystick state change */
? ? SDL_JoystickUpdate();
#endif // WIN32

? ?// do update stuff here

? ?// do render stuff here
? ?SDL_RenderClear(mRenderer);
? ?SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
? ?SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)


SDL mailing list
SDL at lists.libsdl.org (SDL at lists.libsdl.org)
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org (http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org)

Hi all,

I did a similar fix to a much older version of SDL 1.3 for iOS, had a blank
screen on launch, and eventually found a fix. At the time, I was working
on a port of a commercial, Windows-based app to iOS. Early in the project,
the app would launch ok, but there’d be a blank screen. Once the app did
its first draw cycle, it’d go away. The fix ended up being to make SDL
display, on app launch, a “splash screen” view controller. SDL would use
the app’s launch image (Default.png) for content, along with a
UIActivityIndicator-based spinning wheel to show the user that things were
happening. When SDL was asked to update the screen for the first time, the
splash screen would be hidden.

I hope this helps,
– David L.On Mon, Jul 23, 2012 at 5:14 AM, stevo5800 wrote:

**
Yea I used it on an existing project switch back to my old SDL folder no
black screen but banner behind

Sam Lantinga wrote:

If you revert that patch, do you get a normal (non-black) screen and no
banner?

On Sun, Jul 22, 2012 at 3:39 PM, stevo5800 <> wrote:

Quote:

I got a black screen but the banner shows up

Sam Lantinga wrote:

David Ludwig discovered the issue with the game center being hidden, and I
put in an untested fix:http://hg.libsdl.org/SDL/rev/8f224d0762ab

Can you let me know if this works? I should be able to test iOS stuff
again in a week or so.

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 <> wrote:

Quote:

Sam that function works like a charm, I was able to use that function to
run my main loop then use the initialize stuff from BJ. I successfully
launched game centre in my app but now the issue is how to get the welcome
back message to pop up, or even any notification banner from game kit. If I
don’t render then I see the banner if not it draws over it. I got the idea
of checking for views but it seems to only show the SDL view. I base my
self of the SDL template included in the SDK. So I was wondering if there
was a way to to display this banner?

Thanks

Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to
Maelstrom.

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void
(callback)(void), void *callbackParam);

This will set up the given function to be called back on the animation
callback, and then you have to return from main() to let the Cocoa event
loop run.

e.g.

extern "C"
void ShowFrame(void*)
{
… do frame logic and rendering
}

int main(int argc, char *argv[])
{
… initialize game …

#if IPHONEOS
// Initialize the Game Center for scoring and matchmaking
InitGameCenter();

    // Set up the game to run in the window animation callback on iOS
    // so that Game Center and so forth works correctly.
    SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame,

0);
#else
while ( gRunning ) {
ShowFrame(0);
DelayFrame();
}
CleanUp();
#endif
return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:

Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a
pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows

Code:

void
UIKit_PumpEvents(_THIS)
{
return;
/*
When the user presses the ‘home’ button on the iPod
the application exits – immediatly.

    Unlike in Mac OS X, it appears there is no way to cancel the

termination.

    This doesn't give the SDL user's application time to respond to an

SDL_Quit event.
So what we do is that in the UIApplicationDelegate class
(SDLUIApplicationDelegate),
when the delegate receives the ApplicationWillTerminate message,
we execute
a longjmp statement to get back here, preventing an immediate exit.
*/
if (setjmp(jump_env()) == 0) {
/
if we’re setting the jump, rather than jumping back */
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while (result == kCFRunLoopRunHandledSource);
}
}

This stops SDL processing all the events ( I added a return at the top of
the function ). This fixes SDL crashing some times when other views are
laid over the top. The problem of needing the long jump is avoided as this
message will be processed when iOS sends the message and not during the
next update.

The next thing that needs to be done is to intercept the events as they
occur, fortunately this is an easy thing to do. Create a callback function
and inform SDL, like so. Always return 0, this will stop SDL from storing
the event.

Code:

int SystemEventCallback(SDL_Event* event)
{
MyEventHandler::instance().OnEvent(event);
return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);

The event handler looks something like this. (Remember that the events are
processed as they occur, so save results when needed)

Code:

void EventHandler::OnEvent(SDL_Event *aEvent)
{
switch (aEvent->type)
{
case SDL_WINDOWEVENT:
{
switch (aEvent->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
OnLostFocus();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
OnGainedFocus();
break;
}
break;
}
}
}

Not sure these events work I applied the patch
http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and
SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight
loop. It is time to change this to an event driven approach. First
SDL_uikitopenglview needs to be modified. Create a new objective c class
and implement as follows. (Header first)

Code:

#import
#import “./sdl/src/video/uikit/SDL_uikitopenglview.h”

@interface SDL_uikitopenglview (MYOpenGLView)

  • (void)startAnimation;

  • (void)stopAnimation;

  • (void)doLoop:(id)sender;
    @end

Code:

#import “MYOpenGLView.h”
#import
#import
#include “SDL.h”
// a file that will let me use c++ for SDL
#include “SystemCalls.h”

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function

  • (id)initWithFrame:(CGRect)frame
    retainBacking:(BOOL)retained
    rBits:(int)rBits
    gBits:(int)gBits
    bBits:(int)bBits
    aBits:(int)aBits
    depthBits:(int)depthBits
    stencilBits:(int)stencilBits
    majorVersion:(int)majorVersion
    {
    depthBufferFormat = 0;

    if ((self = [super initWithFrame:frame])) {
    const BOOL useStencilBuffer = (stencilBits != 0);
    const BOOL useDepthBuffer = (depthBits != 0);
    NSString *colorFormat = nil;

      if (rBits == 8 && gBits == 8 && bBits == {
          /* if user specifically requests rbg888 or some color format
    

higher than 16bpp /
colorFormat = kEAGLColorFormatRGBA8;
} else {
/
default case (faster) */
colorFormat = kEAGLColorFormatRGB565;
}

    /* Get the layer */
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary

dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:
retained], kEAGLDrawablePropertyRetainedBacking, colorFormat,
kEAGLDrawablePropertyColorFormat, nil];

    if (majorVersion > 1) {
        context = [[EAGLContext alloc] initWithAPI:

kEAGLRenderingAPIOpenGLES2];
} else {
context = [[EAGLContext alloc] initWithAPI:
kEAGLRenderingAPIOpenGLES1];
}
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
SDL_SetError(“OpenGL ES %d not supported”, majorVersion);
return nil;
}

    // !!! FIXME: use the screen this is on!
    /* Use the main screen scale (for retina display support) */
    if ([self respondsToSelector:@selector(contentScaleFactor)])
        self.contentScaleFactor = [UIScreen mainScreen].scale;

    /* create the buffers */
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES

fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,

GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if ((useDepthBuffer) || (useStencilBuffer)) {
        if (useStencilBuffer) {
            /* Apparently you need to pack stencil and depth into one

buffer. /
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
} else if (useDepthBuffer) {
/
iOS only has 24-bit depth buffers, even with
GL_DEPTH_COMPONENT16_OES */
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
}

        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES,

depthBufferFormat, backingWidth, backingHeight);
if (useDepthBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if (useStencilBuffer) {
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
}

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) !=

GL_FRAMEBUFFER_COMPLETE_OES) {
return NO;
}
/* end create buffers */

    self.autoresizingMask = 0;  // don't allow autoresize, since we

need to do some magic in -(void)updateFrame.

    [self startAnimation];
}
return self;

}

  • (void)startAnimation
    {
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against
    earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in
    -initWithCoder:.

    displayLink = [NSClassFromString(@“CADisplayLink”)
    displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop]
    forMode:NSDefaultRunLoopMode];
    }

  • (void)stopAnimation
    {
    [displayLink invalidate];
    displayLink = nil;
    }

  • (void)doLoop:(id)sender
    {
    runApplicationFrame();
    }
    @end

The initWithFrame function is a copy of the function in SDL with one
exception [self startAnimation];. This is the important part as it sets up
the way that we do a loop by callback. The start animation function
basically sets up the doLoop function to run every x number of frames. Set
this animationFrameInterval variable to 1 to run every frame, 2 for every
2nd frame etc. For more details (and other ways to do this)
http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and
call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.

Code:

void runApplicationFrame()
{
// iOS uses a push event system instead of a pull event system
#ifdef WIN32
SDL_Event Event;
while (SDL_PollEvent(&Event))
{
OnEvent(&Event);
}
#else
/* Check for joystick state change */
SDL_JoystickUpdate();
#endif // WIN32

// do update stuff here

// do render stuff here
SDL_RenderClear(mRenderer);
SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
SDL_RenderPresent(mRenderer);
}

I am assuming that SDL has already been setup, this can all happen as
usual. The important one is the SDL_JoystickUpdate (if you are using it) as
it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org