SDL 1.3 Behavior on iOS

来源:互联网 发布:ubuntu 解压缩命令 编辑:程序博客网 时间:2024/05/23 12:02

SDL 1.3 works on iOS and it's easy to get started. Unfortunately the docs are not too clear however on how to respond to some of the iOS features and so on. This here should hopefully help you a little bit.

Switching OpenGL ES Modes

Starting with the 3GS your phone supports both OpenGL ES 1.0 and OpenGL ES 2.0. Because these two are completely different systems you need to decide which to use. There are two important things here. First of all the functions available at compile time are different for these two standards. To cope with that, SDL provides you with two headers to chose from:SDL_opengles.h and SDL_opengles2.h. You need to include the one you want to use yourself.

On top of that, the device will boot up in OpenGL ES 1.0 mode currently, so if you want OpenGL ES 2.0 you need to tell SDL to give you such a context:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);m_win = SDL_CreateWindow(0, 0, 0, screen_width, screen_height,                         SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

The Statusbar

On iOS your application will have a status bar on top that shows the carrier and battery levels. For games you often want the extra 12 pixel from the top and have this bar hidden. All you need to do to hide the status bar is passing SDL_WINDOW_BORDERLESS as additional flag to theSDL_CreateWindow function call:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);m_win = SDL_CreateWindow(0, 0, 0, screen_width, screen_height,                         SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS |                         SDL_WINDOW_SHOWN);

Respond to Rotation

If you want to respond to rotation events of the phone you will need to pass theSDL_WINDOW_RESIZABLE flag to SDL_CreateWindow. Whenever the device is rotated, SDL will switch width and height and fire an SDL_WINDOWEVENT with the window.event flag set toSDL_WINDOWEVENT_RESIZED:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);m_win = SDL_CreateWindow(0, 0, 0, screen_width, screen_height,                         SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE |                         SDL_WINDOW_SHOWN);

Here is how you could respond to such an event:

SDL_Event event;while (SDL_PollEvent(&event)) {    if (event.type == SDL_WINDOWEVENT &&        event.window.event == SDL_WINDOWEVENT_RESIZED)        update_opengl_viewport();    else        handle_event(event);}

Retina Display and Display Sizes

The iPad supports multiple screens and the iPhone 4 has a much higher screen resolution than older devices. So how can you deal with that? SDL provides a function calledSDL_GetNumDisplayModes that in combination with SDL_GetDisplayMode will tell you the supported display modes for a given screen. The screen “0” is the builtin one. On an iPhone 4 it will spit out the high resolution, on an iPhone 3GS or iPad it will just return a lower resolution. SDL automatically configures the phone in a way that it will scale to a full screen resolution for you if the size does not match. That way you can configure the app to have a context o 320x480 and it will upscale to the retina resolution automatically.

Here is how SDL_GetNumDisplayModes works:

int screen = 0;int modes = SDL_GetNumDisplayModes(screen);for (int i = 0; i < modes; i++) {    SDL_DisplayMode mode;    SDL_GetDisplayMode(screen, i, &mode);    printf("%dx%d\n", mode.w, mode.h);}

Touch Events

Generally the events on the touchscreen are emitted as mouse events so you can just use that if you like. For extra control you might however want to use the dedicated touch API. It reports things differently and you will be notified about the indivdual finger motions.

There are three events to look out for: SDL_FINGERDOWNSDL_FINGERUP, andSDL_FINGERMOTION. All of them carry the event data in the tfinger attribute on the event. The interesting fields are these:

  • touchId — the identifier of the touch device. There is just one touch device on iOS, but you will need this information to get the touch state.
  • fingerId — the ID of the finger. More below.
  • xydxdy — the position information in its own scale. This is not the pixel scale, you will have to calculate this yourself. dx and dy are only available for SDL_FINGERMOTION.
  • pressure — the pressure applied, this is also needs to be normalized yourself to make use of this.

So how can you convert from the values in x and y to actually useful values? For this you need the actual SDL_Touch struct of the device which you can get with the SDL_GetTouch function which returns a pointer to the touch struct. This struct will tell you the resolution of x and y and of the pressure.

  • SDL_Touch->xres — resolution in X direction
  • SDL_Touch->yres — resolution in Y direction
  • SDL_Touch->pressures — resolution of the pressure values
  • SDL_Touch->num_fingers — number of fingers currently down on the device.
  • SDL_Touch->fingers — an array with the IDs of all fingers down.

The following core normalizes the touch values into the range 0-1. You can multiply this with the screen resolution to get actual pixel values back. As the touch device has a higher resolution than the actual screen you don't want to do this when using the touchscreen as joystick replacement.

if (evt.type == SDL_FINGERDOWN) {    SDL_Touch *state = SDL_GetTouch(evt.tfinger.touchId);    float x = (float)evt.tfinger.x / state->xres;    float y = (float)evt.tfinger.y / state->yres;    printf("%f/%f\n", x, y);}

Generally speaking you really want to use the regular mouse events if all you want to do is to select things on the screen and the touch API if you want to work with gestures. At the point where you work with gestures you need to have an actual phone hooked up as the simulator cannot be used to do that.

Special note on the finger IDs. These things are identifiers that are very short living. They are removed the moment the finger is removed from the surface which has two effects: first of all fingers can go away, be prepared for that and secondly the SDL_FINGERUP event will no longer be able to access the finger.

What is the finger in SDL speak? With SDL_GetFinger you can get the state of the finger for further processing:

SDL_Touch *state = SDL_GetTouch(evt.tfinger.touchId);if (!state)    return;SDL_Finger *finger = SDL_GetFinger(state, evt.tfinger.fingerId);if (!finger)    return;

What does the finger struct expose?

  • SDL_Finger->x / y / pressure — pretty much the same thing you also have in the event itself.
  • SDL_Finger->xdelta / ydelta — delta since the last finger motion.
  • SDL_Finger->last_x / last_y / last_pressure — the old values for the coordinates or pressure levels.

As you can see from the examples above: SDL_Finger and SDL_Touch are memory managed by SDL itself, so you shouldn't tamper with it. Also consider it read only.

CMake and Info.plist

This one is a bonus if you are using CMake. CMake will automatically create an Info.plist file for you so you don't have to worry about that. But if you want to extend it, you will need to specify a different template for this file. Just add this to your CMakeLists.txt:

set_target_properties(YourTarget PROPERTIES    MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in    XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer")

And then provide an Info.plist.in file like this:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"  "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict>    <key>CFBundleDevelopmentRegion</key>    <string>English</string>    <key>CFBundleExecutable</key>    <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>    <key>CFBundleGetInfoString</key>    <string>${MACOSX_BUNDLE_INFO_STRING}</string>    <key>CFBundleIdentifier</key>    <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>    <key>CFBundleInfoDictionaryVersion</key>    <string>6.0</string>    <key>CFBundleLongVersionString</key>    <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>    <key>CFBundleName</key>    <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>    <key>CFBundlePackageType</key>    <string>APPL</string>    <key>CFBundleShortVersionString</key>    <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>    <key>CFBundleSignature</key>    <string>????</string>    <key>CFBundleVersion</key>    <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>    <key>CSResourcesFileMapped</key>    <true/>    <key>NSHumanReadableCopyright</key>    <string>${MACOSX_BUNDLE_COPYRIGHT}</string>    <!-- custom stuff here -->    <key>UIStatusBarHidden</key>    <true/></dict></plist>

The file above overrides the UIStatusBarHidden value which will hide the status bar during startup of the application. There is a lot more that can be customized in the Info.plist file, just refer to the apple documentation for more information.


转贴:http://immersedcode.org/2011/4/27/sdl-ios-behavior/

原创粉丝点击