【问题标题】:How should I use SDL2 iOS Application Events?我应该如何使用 SDL2 iOS 应用程序事件?
【发布时间】:2013-09-01 22:51:48
【问题描述】:

我目前正在使用 SDL2 库和 C 来编写一个 iPhone 应用程序,并且大部分情况下进展顺利。不幸的是,文档在某些方面似乎相当薄弱,尤其是 iOS 特定的功能。我是使用 SDL2 的新手,这让事情变得非常困难。到目前为止,一切都奏效了,但我被一个问题难住了。 SDL2 定义了六种专门用于移动应用程序的事件类型。 README-ios.txt 文件描述了它们并像这样使用它们:

int HandleAppEvents(void *userdata, SDL_Event *event)
{
    switch (event->type)
    {
    case SDL_APP_TERMINATING:
        /* Terminate the app.
           Shut everything down before returning from this function.
        */
        return 0;
    case SDL_APP_LOWMEMORY:
        /* You will get this when your app is paused and iOS wants more memory.
           Release as much memory as possible.
        */
        return 0;
    case SDL_APP_WILLENTERBACKGROUND:
        /* Prepare your app to go into the background.  Stop loops, etc.
           This gets called when the user hits the home button, or gets a call.
        */
        return 0;
    case SDL_APP_DIDENTERBACKGROUND:
        /* This will get called if the user accepted whatever sent your app to the background.
           If the user got a phone call and canceled it, you'll instead get an    SDL_APP_DIDENTERFOREGROUND event and restart your loops.
           When you get this, you have 5 seconds to save all your state or the app will be terminated.
           Your app is NOT active at this point.
        */
        return 0;
    case SDL_APP_WILLENTERFOREGROUND:
       /* This call happens when your app is coming back to the foreground.
           Restore all your state here.
       */
        return 0;
    case SDL_APP_DIDENTERFOREGROUND:
        /* Restart your loops here.
           Your app is interactive and getting CPU again.
        */
        return 0;
    default:
        /* No special processing, add it to the event queue */
        return 1;
    }
}

int main(int argc, char *argv[])
{
    SDL_SetEventFilter(HandleAppEvents, NULL);

    //... run your main loop

    return 0;
}

我有几个关于这段代码的问题。

SDL_SetEventFilter() 有什么作用?我阅读了 SDL Wiki 页面,它似乎特别模糊。

在实践中,HandleAppEvents() 函数是如何工作的?例如,如果我有这样的代码:

int main(int argc, char* argv[])
{
    //Initialize SDL, etc...
    SDL_SetEventFilter(HandleAppEvents, NULL);


    //I've got some SDL_Textures and windows and things...
    SDL_Window* my_window;
    SDL_Renderer* windowrend;
    SDL_Texture* tex1, tex2, tex3;

    //Primitive game loop
    while(game_is_running){
        handle_input();
        do_logic();
        update_screen();
    }

    destroy_all_my_data();
    SDL_Quit();
    return 0;
}

例如,当我收到 SDL_APP_WILLENTERBACKGROUND 时,应该在 HandleAppEvents() 或 main() 中放置什么样的代码来破坏内存或停止我的游戏循环?

假设 tex2 是可消耗的,如果应用收到 SDL_APP_LOWMEMORY,则可以将其删除。我如何从 HandleAppEvents() 中删除 tex2 而不会弄乱其他数据?

userdata 指针中有什么?

当我的应用程序进入后台时,我应该将我的纹理转换为表面,并将它们作为 bmps 保存在 ../tmp/ 目录中,还是当应用程序回到前台时它们仍然在内存中?

我希望我的令人困惑的问题有某种意义。如果有地方我可以找到 SDL2 的完整文档,我会很高兴知道。

感谢观看!

【问题讨论】:

    标签: ios c sdl-2


    【解决方案1】:

    SDL_SetEventFilter 是一种“领先”SDL 事件队列的方法。您基本上会在收到事件后将它们放入队列中,而在 iOS 情况下,您必须立即对它们做出反应。

    这背后的技术原因是,对于这类消息,iOS 使用一系列回调,SDL 会为您接收并包装这些回调,以使跨平台体验尽可能无缝,但事实仍然是 iOS 仍然期望您在从回调返回之前对它们采取行动。

    因此,例如,如果我们只是将系统内存不足的消息放在队列中,而不是通过此机制将其直接传递给应用程序,那么在该事件通过队列之前您什么都不做,您对其进行投票等,iOS 可以强制关闭您的应用,因为它的行为不符合预期。

    当应用程序进入后台时,您无需保存纹理。 iOS 会为您执行此操作,如果它没有足够的内存来执行此操作,它只会杀死您的应用程序(您永远不会丢失 GL ES/ES2 上下文,这可能会在某些 Android 设备上发生)。

    userdata 指针将包含您作为第二个参数传递给 SDL_SetEventFilter 的数据,因此如果您使用 SDL_SetEventFilter(HandleAppEvents, NULL),userdata 将为 NULL。

    在 SDL_APP_WILLENTERBACKGROUND 上,如果我没记错的话,你不需要做任何事情。我有一段时间没有启动我的 iOS 应用程序,但我认为 SDL 会自行处理其所有内部状态(包括阻塞事件循环然后重新启动它)。您必须自己处理的事件是 SDL_APP_LOWMEMORY 和 SDL_APP_TERMINATING,但您如何处理是特定于应用程序的(删除纹理、空闲内存等,它特别超出了 SDL)

    【讨论】:

    • +1 提供非常丰富的答案。如果你有时间的话,我真的很想看看一些能说明你的意思的代码!
    • 我不认为代码示例适用于这种情况,因为您问的主要是“哲学”问题,并且代码在应用程序特定部分(SDL_APP_LOWMEMORY 等)中有用。但我没有一个例子可以给出,它可能涉及释放资源并跟踪它们以在需要时重新创建它们。但是,如果您想澄清答案,请走开!
    • 好的,我明白你的意思了。稍后我将用代码更新问题,希望通过您的反馈我能更好地理解该主题。
    【解决方案2】:

    正如this thread 显示的那样,您必须在 SDL_APP_WILLENTERBACKGROUND 上停止游戏循环并在 SDL_APP_WILLENTERFOREGROUND 上恢复它以避免崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-03
      • 2019-10-10
      • 1970-01-01
      相关资源
      最近更新 更多