sdl 1.2 到2.0 迁移指南

本文档详述了从SDL1.2迁移到SDL2.0的重要变更与新增功能,包括全3D硬件加速、多窗口支持、触摸及手势识别等,并提供了图形API的更新指导。

新功能概述

以下是 sdl 2.0 中最重要的新功能:
- 全3D 硬件加速
- 在各种配置文件中支持 opengl 3.0 + (核心、兼容性、调试、健壮等)
- 支持 opengl es
- 支持多个窗口
- 支持多显示器
- 支持多个音频设备
- 录音支持
- android 和 ios 支持
- Emscripten 和本地客户端支持
- 简单的2D 渲染 api, 可以使用 Direct3D, opengl, opengl es, 或软件渲染
- XInput 和 XAudio2 对 windows 的支持
- 原子操作
- 电源管理 (暴露电池剩余寿命等)
- 异型窗
- 32位音频 (int 和浮点)
- 简化游戏控制器 api (操纵杆 api 仍然在这里!)
- 触摸支持 (多点触控, 手势等)
- 更好的全屏支持
- 更好的键盘支持 (scancodes vs keycodes 等)。
- 消息框
- 剪贴板支持
- 在 sdl 之上构建健壮的 gui 工具包的 api
- 基本的拖放支持
- 正确的 unicode 输入和 ime 支持
- 强大的断言宏
- zlib 许可证而不是 lgpl。
- 1.2 的老烦恼都消失了
- 许多其他的事情!

从 sdl 1.2 移动到2.0

一些一般的真理

没有内置到 SDL2 的兼容层。如果 api 更改为 2.0, 我们已经改变或删除了旧的功能, 这是有意义的。如果将1.2 程序指向2.0 头, 它可能无法编译。这份文件将试图告诉你最重要的变化, 和那些最有可能绊倒你。

没有 SDL_main 嗯, 好了, 现在, 它做了什么, 它总是意味着: 是一小段代码, 隐藏主 () 和 winmain () 在 windows 上的区别。它没有初始化代码, 它是完全可选的。这意味着您可以不用它接管您的主线而使用 sdl, 这对于使用 sdl 的插件或用 sdl 模块编写脚本语言是很好的。所有的东西, 你想要的 1.2 SDL_main 是现在在 SDL_Init (), 它属于。

没有 sdl 降落伞了1.2 所谓的 SDL_INIT_NOPARACHUTE 是一个默认的和唯一的状态现在。这将导致问题, 如果不是主线程崩溃, 它会干扰应用程序设置自己的信号/异常处理程序。在缺点, 一些平台不清理全屏视频时, 崩溃。您应该安装自己的崩溃处理程序, 或调用 SDL_Quit () 在 atexit () 函数或诸如此类的事情, 如果这是一个关注。请注意, 在 unix 平台上, sdl 仍然捕获情报并将其映射到 SDL_QUIT 事件。

图形特性

使用新的视频 api 设置游戏

视频 api 是1.2 最引人注目的变化。由于 sdl 的 api 是在1990代末设计的, 因此需求发生了很大的变化。为了处理现代硬件和 os 功能, 我们几乎完全取代了旧的1.2 视频 api。

不要担心, 新的是相当伟大的, 一旦你明白什么是改变, 你会非常高兴的新功能, 它可以带到您的1.2 游戏。我们以后再讨论这些。

好消息是: 如果你的游戏使用 opengl, 你可能没有太多的事情要做: 把一些函数调用转换为 SDL2 等价的, 你就可以走了。

对于2D 图形, sdl 1.2 提供了一个称为 “曲面” 的概念, 它是像素的内存缓冲区。屏幕本身是一个 “表面”, 如果你在做2D 软件渲染, 我们提供了在曲面之间复制 (“blit”) 像素的函数, 必要时转换格式。你几乎总是在系统 ram 的 cpu, 而不是在 gpu 的视频内存。sdl 2.0 更改此项;您几乎总是现在得到硬件加速, 并且 api 已经更改以反映这一点。

如果你有一个2D 的游戏, 很可能你已经采取了三种方法之一渲染。我们会把它们都翻过去, 但首先, 让我们来谈谈介绍性的东西。

记得 SDL_SetVideoMode () 吗?完全消失了sdl 2.0 允许您拥有多个窗口, 因此旧功能不再有意义。

SDL_WM_SetCaption("My Game Window", "game");
SDL_Surface *screen = SDL_SetVideoMode(640, 480, 0, SDL_FULLSCREEN | SDL_OPENGL);

现在是这样的:

SDL_Window *screen = SDL_CreateWindow("My Game Window",
                          SDL_WINDOWPOS_UNDEFINED,
                          SDL_WINDOWPOS_UNDEFINED,
                          640, 480,
                          SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);

你可以看到这个地图非常接近1.2。不同的是, 你可以有多个窗口 (如果你想), 你可以控制他们更多。SDL_WM_SetCaption () 消失了, 因为我们希望允许每个窗口都有自己的标题 (以后可以用 SDL_SetWindowTitle () 来更改它), 我们希望让您指定一个窗口位置 (或者, 在这种情况下, 使用 SDL_WINDOWPOS_UNDEFINED, 因为我们不关心系统的位置。SDL_WINDOWPOS_CENTERED 也是一个不错的选择)。

允许用户为窗口指定显示的额外信贷: SDL2 还使您可以管理具有多个监视器的系统。不过现在不要担心这个

现在你的窗口又回到屏幕上了, 我们来谈谈策略吧。SDL2 仍然有 SDL_Surface, 但你想要的, 如果可能的话, 是新的 SDL_Texture。表面现在总是在系统 ram 中, 并且总是由 cpu 操作, 所以我们想离开那里。SDL2 有一个新的渲染 api。它的意思是使用简单的2D 游戏, 但最值得注意的是, 它的意思是把所有的软件渲染到视频 ram 和 gpu 上。即使你只是想用它来让你的软件渲染器的工作在屏幕上, 它带来了一些非常好的好处: 如果可能的话, 它会使用 opengl 或 Direct3D 幕后, 这意味着你会得到更快的 blits, 工作蒸汽覆盖, 并免费缩放。

程序看起来像这样。

SDL_SetVideoMode () 成为 SDL_CreateWindow (), 正如我们之前讨论过的。但是我们该如何解决这个决议呢?如果你的游戏是硬编码到 640x480, 例如, 你可能会运行到监视器, 不能做到这一点全屏分辨率, 在窗口模式, 您的游戏可能看起来像一个动画邮票上真正的高端显示器。在 SDL2 有一个更好的解决方案。

我们不再叫 SDL_ListModes () 了。有一个等价的 SDL2 (调用 SDL_GetDisplayMode () 在一个循环, SDL_GetNumDisplayModes () 时间), 但相反, 我们将使用一个新的功能称为 “全屏桌面”, 这告诉 sdl “给我整个屏幕, 不要改变决议。对于我们假设的640x480 游戏, 它可能看起来像这样:

SDL_Window *sdlWindow = SDL_CreateWindow(title,
                             SDL_WINDOWPOS_UNDEFINED,
                             SDL_WINDOWPOS_UNDEFINED,
                             0, 0,
                             SDL_WINDOW_FULLSCREEN_DESKTOP);

请注意, 我们没有指定640或480…fullscreen 桌面为您提供整个显示并忽略您指定的任何维度。游戏窗口应该立即出现, 而无需等待显示器点击到一个新的分辨率, 我们将使用 gpu 缩放到桌面大小, 这往往是更快, 更清洁的前瞻比如果 lcd 是假装一个较低的分辨率。额外的奖金: 没有一个你的背景窗口正在调整自己的现在。

现在我们需要一个渲染上下文。

SDL_Renderer *renderer = SDL_CreateRenderer(sdlWindow, -1, 0);

渲染器隐藏了我们如何在窗口中绘制的细节。这可能是使用 Direct3D, opengl, opengl es, 或软件表面幕后, 取决于系统提供;不管 sdl 选择什么, 您的代码都不会更改 (尽管欢迎您强制使用一种或另一种渲染器)。如果要尝试强制 sync-to-vblank 以减少撕裂, 可以使用 SDL_RENDERER_PRESENTVSYNC 代替零作为第三个参数。您不应该在这里创建带有 SDL_WINDOW_OPENGL 标志的窗口。如果 SDL_CreateRenderer () 决定要使用 opengl, 它将为您适当地更新窗口。

现在你明白了这是如何工作的, 你也可以在 SDL_CreateWindowAndRenderer () 的一个步骤中完成这一切, 如果你不想要任何花哨的东西:

SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &sdlWindow, &sdlRenderer);

假设这些函数没有失败 (总是检查空值), 您就可以开始绘制到屏幕上了。让我们开始把屏幕清除到黑色。

SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255);
SDL_RenderClear(sdlRenderer);
SDL_RenderPresent(sdlRenderer);

这样的工作, 你可能会认为;用黑色绘制 (r、g、b 全部为零, alpha 满), 清除整个窗口, 将清除的窗口放在屏幕上。这是正确的, 如果您使用 SDL_UpdateRect () 或 SDL_Flip () 来获取您的位到屏幕, 渲染 api 使用 SDL_RenderPresent ()。

这里还有一个一般的东西由于我们使用的是 SDL_WINDOW_FULLSCREEN_DESKTOP, 我们实际上并不知道有多少屏幕需要绘制。幸运的是, 我们不需要知道。1.2 的好东西之一是, 你可以说: “我想要一个640x480 窗口, 我不在乎你怎么做,” 即使得到它意味着在一个更大的分辨率代表您的应用程序的窗口。

对于 2.0, 渲染 api 允许你这样做..。

SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");  // make the scaled rendering look smoother.
SDL_RenderSetLogicalSize(sdlRenderer, 640, 480);

它会为你做正确的事。这是很好的, 您可以更改逻辑呈现大小以实现各种效果, 但主要用途是: 而不是试图使系统使用您的呈现大小, 我们现在可以使您的渲染大小与系统一起工作。在我的1920x1200 监视器上, 这个应用程序认为它现在正在与640x480 分辨率对话, 但是 sdl 正在使用 gpu 来扩展它以使用所有这些像素。请注意, 640x480 和1920x1200 的纵横比并不相同: sdl 也会处理这一问题, 尽可能多地扩展并 letterboxing 差异。

现在, 我们已经准备好开始绘制真正的。

如果你的游戏只是想得到完全渲染帧的屏幕

一个特殊的例子, 旧的教学示范渲染游戏: 应用程序要绘制每个像素本身, 并获得最后一组像素到屏幕上有效地在一个大 blit。像这样的一个游戏的例子是厄运或杜克公爵 3D或许多其他的。
为此, 您将需要一个单一的 SDL_Texture, 将代表屏幕。现在让我们为我们的640x480 游戏创建一个:

sdlTexture = SDL_CreateTexture(sdlRenderer,
                               SDL_PIXELFORMAT_ARGB8888,
                               SDL_TEXTUREACCESS_STREAMING,
                               640, 480);

这表示 gpu 上的纹理。战术是通过将像素上传到该纹理, 将纹理绘制到窗口, 并将此绘图翻转到屏幕上来完成每个帧。通过SDL_TEXTUREACCESS_STREAMING 告诉 sdl, 此纹理的内容将经常更改。
在你可能有一个 SDL_Surface 的屏幕, 你的应用程序提请, 然后调用SDL_Flip () 放在屏幕上。现在, 您可以创建一个 SDL_Surface, 它总是在 ram 中, 而不是使用您从 SDL_SetVideoMode () 中得到的, 或者只是 malloc () 要写入的一个像素块。理想情况下, 你写一个 rgba 像素的缓冲区, 但如果你需要做一个转换, 也没关系。

extern Uint32 *myPixels;  // maybe this is a surface->pixels, or a malloc()'d buffer, or whatever.

在框架的末尾, 我们要上传到这样的纹理:

SDL_UpdateTexture(sdlTexture, NULL, myPixels, 640 * sizeof (Uint32));

这将把你的像素上传到 gpu 内存。如果你想用肮脏的长方形来捣乱, 那么空可以是一个分区域, 但是现代的硬件可能会把整个帧吞下, 没有太大的麻烦。最后一个参数是音高–从一行开始到下一行的字节数–因为在这个例子中我们有一个线性的 rgba 缓冲区, 它只是640乘以 4 (r、g、b、a)。
现在把纹理带到屏幕上:

SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
SDL_RenderPresent(sdlRenderer);

就这样。SDL_RenderClear () 擦除现有的视频帧 (以防说, 蒸汽覆盖写在它的最后一帧), SDL_RenderCopy () 移动纹理的内容, 以视频帧 (并感谢 SDL_RenderSetLogicalSize (), 它将被缩放/居中, 如果显示器是 640x480), 和 SDL_RenderPresent () 把它放在屏幕上。

如果你的游戏想 blit 表面的屏幕

这种情况下, 你的 sdl 1.2 游戏加载一堆图形从磁盘到一堆 SDL_Surfaces, 可能试图让他们进入视频 ram 与 SDL_HWSURFACE。你加载这些一次, 你 blit 他们在必要的帧, 但否则他们永远不会改变。一个简单的2D 游戏可能会这样做。如果你倾向于认为你的表面是 “精灵”, 而不是像素的缓冲器, 那么这可能就是你。
您可以构建单独的纹理 (生活在 gpu 内存中的曲面), 就像我们为这一大纹理所做的那样:

sdlTexture = SDL_CreateTexture(sdlRenderer,
                               SDL_PIXELFORMAT_ARGB8888,
                               SDL_TEXTUREACCESS_STATIC,
                               myWidth, myHeight);

这是你所期望的我们使用 SDL_TEXTUREACCESS_STATIC, 因为我们要上传我们的像素一次, 而不是一遍又一遍。但更方便的解决方案可能是:

sdlTexture = SDL_CreateTextureFromSurface(sdlRenderer, mySurface);

使用这个, 你加载你的 SDL_Surface 像往常一样, 但在最后, 你做了一个纹理。一旦你有一个 SDL_Texture, 你可以释放原来的表面。
在这一点上, 你的1.2 游戏有一堆 SDL_Surfaces, 它会 SDL_BlitSurface () 到屏幕表面组成最后的帧, 并最终 SDL_Flip () 到屏幕。对于 sdl 2.0, 您有一堆 SDL_Textures, 您将 SDL_RenderCopy () 到渲染器以组成最终的帧, 并最终 SDL_RenderPresent () 到屏幕。就这么简单如果这些纹理不需要修改, 你可能会发现你的帧也刚刚经历了屋顶。

如果你的游戏想要做上面两个目的

如果要 blit 曲面并修改帧中的单个像素, 则情况会稍微复杂一些。往返行程–从纹理中读取数据–可能会令人痛苦地昂贵;通常情况下, 您希望始终将数据推向一个方向。在这种情况下, 你最好是把所有的东西都放在软件中, 直到最后的屏幕上, 所以我们将结合前两种技术。
好消息是: 1.2 SDL_Surface 的 api 大部分仍然存在。因此, 请更改屏幕表

SDL_Surface *screen = SDL_SetVideoMode(640, 480, 32, 0);

变为:

// if all this hex scares you, check out SDL_PixelFormatEnumToMasks()!
SDL_Surface *screen = SDL_CreateRGBSurface(0, 640, 480, 32,
                                        0x00FF0000,
                                        0x0000FF00,
                                        0x000000FF,
                                        0xFF000000);
SDL_Texture *sdlTexture = SDL_CreateTexture(sdlRenderer,
                                            SDL_PIXELFORMAT_ARGB8888,
                                            SDL_TEXTUREACCESS_STREAMING,
                                            640, 480);

…, 并继续传输的东西和调整像素像以前一样, 组成您的最终帧到这个 SDL_Surface。一旦您准备好在屏幕上获取这些像素, 就像在我们的第一个场景中那样做:

SDL_UpdateTexture(sdlTexture, NULL, screen->pixels, screen->pitch);
SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
SDL_RenderPresent(sdlRenderer);

请注意, 纹理创建可能使用既昂贵又有有限的资源: 不要每帧调用 SDL_CreateTextureFromSurface (),设置一个纹理和一个表面, 并从后者更新前者。
渲染 api 有更多的功能, 其中一些可以替换你的应用程序的代码: 缩放、线图等。如果您正在阅读本节, 因为您的需求超出了传输表面, 您可以停止戳单个像素并将所有内容移动到 gpu 上, 这将使您的程序大大提高速度, 并可能极大地简化您的代码。

其他渲染器 api 注释

您可以使用渲染 api 做一些简单的效果, 而不必直接进行像素操作。其中一些在1.2 表面上可用。
颜色 alpha: SDL_Color 现在包含第四, alpha 分量。处理 SDL_Colors 的1.2 代码可能不会复制/设置该值 (命名为 “未使用”)。在 2.0, 你应该。
alpha 混合: 使用 SDL_SetSurfaceAlphaMod 和 SDL_SetTextureAlphaMod 而不是 SDL_SetAlpha ()。通过 SDL_SetSurfaceBlendMode () 和纹理与 SDL_SetTextureBlendMode () 可以禁用表面上的 alpha 混合。
colorkey: 当打电话给 SDL_SetColorKey () 时, 你应该通过 SDL_TRUE 而不是 SDL_SRCCOLORKEY。
颜色调制: 某些器现在支持全局颜色更改 (民变 = 民变 * 颜色), 请检查 SDL_SetTextureColorMod () 以了解详细信息。

opengl

如果您已经直接使用了 opengl, 那么您的迁移非常简单。将您的 SDL_SetVideoMode () 调用更改为 SDL_CreateWindow (), 后跟 SDL_GL_CreateContext (), 并将您的 SDL_GL_SwapBuffers () 调用到 SDL_GL_SwapWindow (窗口)。所有到 gl 的实际调用都是完全相同的。

如果您使用的是 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, x), 这已经改变了。现在有一个 SDL_GL_SetSwapInterval (x) 调用, 因此您可以在现有的 gl 上下文上更改它。

请注意, sdl 2.0 可以在不丢失 gl 上下文的情况下切换窗口/全屏并返回 opengl 窗口 (万岁!为此, 请使用 SDL_SetWindowFullscreen ()。

输入

好消息是, sdl 2.0 已使 unicode 输入可用。坏消息是, 它将对您的应用程序进行一些细微的更改。
在1.2 中, 许多只关心我们英语的应用程序仍然被称为 SDL_EnableUNICODE (1), 因为获取与按键关联的字符是很有用的。一旦你学到了英语, 这就不管用了, 一旦你得到了亚洲语言, 它就完全没有作用了。
事实证明, i18n 是很难的。

sdl 更改了此项。SDL_EnableUNICODE () 消失了, SDL_Keysym 的 unicode 字段也是如此。您不再从 SDL_KEYDOWN 事件中获取字符输入。使用 SDL_KEYDOWN 来处理键盘像一个101按钮游戏杆现在。文本输入来自其他地方。
新的事件是 SDL_TEXTINPUT。只要用户输入了新的文本, 就会触发此操作。请注意, 此文本可能来自按键, 也可能来自某种 ime (这是一种输入复杂的多文本的奇特方式)。此事件返回整个字符串, 可能是一个 char 长, 或者是多个代码的多数据。此字符串始终 UTF-8 编码。
如果你所关心的是用户是否按了某个键, 那仍然是 SDL_KEYDOWN, 但是我们已经把这个系统分成了1.2 个部分: keycodes 和 scancodes。

Scancodes 的意思是与布局无关。认为这是 “用户按下 q 键, 因为它会在美国 qwerty 键盘”, 无论这是实际上是一个欧洲键盘或伏都键盘或任何。扫描始终是相同的关键位置。

Keycodes 的意思是布局依赖。将其视为 “用户按下在特定键盘上标记为” q “的键。

例如, 如果按下钥匙, 这是美式qwerty 键盘上的大写锁的两个键, 它将报告扫描的 SDL_SCANCODE_S 和号码的 SDLK_S。在伏地键盘上的同一键, 将报告扫描的 SDL_SCANCODE_S 和号码的 SDLK_O。

请注意, keycodes 和 scancodes 现在都是32位, 并且使用的数字范围很广。没有 SDLK_LAST 了如果您的程序有一个 SDLK_LAST 元素的查找表, 要在 sdl 密钥和您的应用程序内部需要的任何内容之间进行映射, 则不再可行。请改用哈希表。std:: 地图会做。如果您要映射 scancodes 而不是 keycodes, 则有 SDL_NUM_SCANCODES, 您可以使用数组边界。现在是512

SDLMod 现在是 SDL_Keymod, 其 “元” 键 (“windows” 键) 现在被称为 “gui” 键。

SDL_GetKeyState () 已重命名为 SDL_GetKeyboardState ()。返回的数组现在应由 SDL_SCANCODE_ * 值 (请参见 SDL_SCANCODE) 而不是 SDL_Keysym 值进行索引。

现在, 对于鼠标输入。

第一个变化, 仅仅是足够的, 是滚轮不再是一个按钮。这是一个错误的历史, 我们更正了它在 sdl 2.0。寻找 SDL_MOUSEWHEEL 事件。我们支持垂直和水平的车轮, 和一些平台可以处理双手指滚动的触摸板作为车轮输入, 太。您将不再接收鼠标滚轮的 SDL_BUTTONDOWN 事件, 并且按钮4和5现在是真正的鼠标按钮。

如果你的游戏需要永远滚动鼠标在一个方向, 例如, 让一个球员在 fps 旋转周围没有鼠标击中屏幕边缘和停止, 你可能隐藏了鼠标光标和抓取输入:

SDL_ShowCursor(0);
SDL_WM_GrabInput(SDL_GRAB_ON);

在 SDL2, 这种方法的作用略有不同。你叫..。

SDL_SetRelativeMouseMode(SDL_TRUE);

其余的则由 sdl 来做。

事件

SDL_PushEvent () 现在返回1成功, 而不是0。
事件掩码现在使用范围指定:

SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN));

成为:

SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONDOWN);

音频

音频的好消息是, 有一个例外, 它完全向后兼容1.2。如果您想要这些新功能, 它们可供您使用, 但您可能只是编译并运行而没有它们。

这是一个非常重要的例外: 音频回调不再以完全初始化的缓冲区开始。在所有情况下都必须完全写入缓冲区。如果你没有足够的音频, 你的回调应该写沉默。如果你不这样做, 你会听到重复的音频, 或者可能是音频损坏。如果要恢复无条件初始化缓冲区的旧行为, 只需在回调开始时放置一个 SDL_memset (流、0、len)。

摇杆

游戏杆事件现在指的是 SDL_JoystickID。这是因为 sdl 2.0 可以处理控制杆的进出 , 因为在游戏的生命周期中 , 设备入并拉出 , 因此 , 1 . 2 使用的设备列表中的索引将毫无意义 , 因为可用的设备列表会发生更改。

要获得您打开的 SDL_Joystick * 的 SDL_JoystickID, 请致电:

SDL_JoystickID myID = SDL_JoystickInstanceID(myOpenedStick);

并且比较操纵杆事件,哪个领域反对 myid。如果您没有使用事件队列的游戏杆, SDL_JoystickGetAxis () 和朋友的工作就像 sdl 1.2。
你也应该检查出新的游戏控制器 api, 因为它很酷, 也许你做了很多踢踏舞与 1.2 api, 这一新的代码将解决更干净。你可以在 SDL_gamecontroller 找到它。游戏控制器 api 真的很好地结合了蒸汽大图片模式: 你得到了大多数控制器的自动配置, 以及一个不错的 ui, 如果你必须手动配置它。无论是哪种情况, 蒸汽都将此配置传递给您的 sdl 应用程序。
支持旧的操纵杆 api (/开发/输入/js ) 为 linux 已经从 SDL2 下降。SDL2 只支持新的事件 api (/开发/输入/事件 ) 的操纵杆。对于普通用户帐户, 这些事件通常是不可读的, 因此即使操纵杆插入, 也可能没有检测到。这是最终用户必须为自己配置的东西。

线程

SDL_KillThread () 不见了。这是从来没有安全或可靠的。最好的替换是设置一个标志, 告知线程应该退出。该线程应该检查标志与一些频率, 然后 “杀死” 线程调用 SDL_WaitThread () 清理。
SDL_CreateThread () 现在需要一个额外的参数, 这个线程的名称可以由调试器用来识别它。如果你不关心, 只是在你的函数调用额外的空。

音频光盘

1.2 cd api 完全消失了。没有替代品在这一点上, 如果您正在传送光盘, 那么您就不会将您的音乐作为 cd 音频曲目传送到光盘上。您可以使用 ogg vorbis 或其他一些音频文件格式的音乐, 其中许多是由 SDL_mixer 提供的。

死去的平台

我们撕开了一堆旧平台, 比如 OS/2 和 mac os 9。更容易列出我们仍然支持的部分: windows (xp 和更高版本)、linux、mac os x、ios、android。在 sdl 的传统中, 还有其他人在外围工作, 但却没有得到大力支持, 比如俳句和索尼 psp。我们将添加任何平台, 有人发送补丁, 但它似乎是时间向一些老朋友告别时, 移动到新的版本。

移动平台

多年来, sdl 1.2 的非官方扩展一直是 ios 和 android。sdl 现在直接支持这些平台, 而 2.0 api 更适合它们。您在本文档其他地方得到的大多数建议都适用, 但还有其他一些值得注意的事项。

首先, 有些事件只适用于移动设备, 或者更好地说, 适用于移动设备操作系统在 post-iPhone 的世界中运行的方式。我们最初尝试将这些项目映射到现有的 sdl 事件 (如 “您的应用程序正在进入后台” 被视为桌面窗口失去焦点), 但还有一个更紧迫的问题: 这些事件中的大多数需要立即响应, 如果应用程序没有给出一个, 操作系统将会杀死您的应用程序。

因此, 我们已经为一些 android 和 ios 的具体细节添加了新的 sdl 事件, 但是您应该设置一个 sdl 事件过滤器, 以便在操作系统报告它们时立即捕获它们, 因为等待您的下一个 SDL_PollEvent () 循环将为时已晚。

例如, 有 SDL_APP_WILLENTERBACKGROUND, 这是 ios 的 applicationWillResignActive (), 如果您在这个事件到达后绘制到屏幕上, ios 将终止您的进程。所以你要立即抓住这个:

int SDLCALL myEventFilter(void *userdata, SDL_Event * event)
{
    if (event->type == SDL_APP_WILLENTERBACKGROUND) {
        // free up resources, DON'T DRAW ANY MORE until you're in the foreground again!
    }
    // etc
    return 1;
}

在初创公司附近..。

这将在生成事件后立即调用 myEventFilter (数据、事件)。
SDL_AddEventWatch (myEventFilter, 数据);
第二, 现在有真正的触摸事件, 而不是试图映射到鼠标输入。您可以跟踪触摸, 多个手指, 甚至复杂的手势。你可能想用那些有关这些函数的列表, 请参阅 SDL_touch h. SDL_Finger SDL_events。

请注意, sdl 还会将简单的触摸图映射成鼠标事件 (将鼠标事件的 “” 字段设置为 SDL_TOUCH_MOUSEID), 这意味着, 如果你不关心更复杂的触摸界面, 你现有的桌面应用程序可能仍然在手机上的框中工作, 用户用手指戳屏幕。这样: 移动感知应用程序应该忽略 SDL_TOUCH_MOUSEID 事件, 但仍然尊重 “真正的” 鼠标事件除了触摸事件-一些移动设备支持 usb 和蓝牙小鼠, 毕竟!–但是当你在 SDL2 上运行时, 当你开始擦亮你的应用程序时, 这是一个更深层次的考虑。

还有其他一些移动友好的功能, 如 SDL_StartTextInput (), 这将显示 on-screen 键盘。利用它们。

此外, 还有 android 和 ios 的特定功能, 让您能够访问在通用 api 中没有意义的平台特定功能。有关这些函数的列表, 请参阅 SDL_system. h。

rwops

SDL_RWread () 和 SDL_RWwrite () 现在返回0错误而不是-1。

如果您编写了自己的 SDL_RWops 实现, 则函数签名已更改。函数现在使用 Sint64 和 size_t 而不是 int, 这样他们就可以处理大文件。在许多情况下, 您可以只更新您的功能签名, 并继续像以前一样工作, 但如果您遇到了这些限制, 您可能会很高兴有一个解决方案。调用应用程序应该知道返回值已更改。

还有一个大小的方法来 RWops, 现在。它被称为 SDL_RWsize ()。这可以让 RWops 报告流的大小, 而不必使应用程序从末尾到零字节;换言之, 您可以报告无法查找的流的总大小。对于那些甚至不能这样做的流, 你仍然可以返回-1。

附加库

SDL_image、SDL_ttf、SDL_mixer 和 SDL_net 的官方扩展有一个专用于 sdl 2.0 的版本: SDL2_image、SDL2_ttf、SDL2_mixer 和 SDL2_net。您可能需要从善变的存储库中下载最新的修补程序。随后, 当然, 你将不得不链接, 如 SDL2_image, 而不是 SDL_image, 编译你的程序。

这些库将不支持1.2 向前迈进, 与1.2 的任何兼容性可能会在某些时候从较新版本中消失。

SDL_gfx 也可以编译与2.0 从 2.0.21 (2010年5月) 开始。

某些重命名或替换的内容的摘要

一个简短的作弊表, 其中一些旧的功能和其他的东西去:

  • SDL_SetVideoMode (): 使用 SDL_CreateWindow (), 而不是 (与SDL_CreateRenderer (), 如果你想做经典的2D 渲染, 而不是 opengl)
  • SDL_ListModes (): 使用 SDL_GetDisplayMode ()/SDL_GetNumDisplayModes () 代替
  • SDL_UpdateRect ()/SDL_Flip (): 使用 SDL_RenderPresent () 代替
  • SDL_Surface/2D 渲染: 表面仍然存在, 但建议您在可能的情况下使用2D 加速渲染器 (SDL_CreateRenderer (), 而不是使用 SDL_Surfaces)
  • SDL_VideoInfo: 使用 SDL_GetRendererInfo ()/SDL_GetRenderDriverInfo () 代替
  • SDL_GetCurrentVideoDisplay (): 使用 SDL_GetWindowDisplayIndex () 代替
  • SDL_VIDEORESIZE 事件: 新的等价 sdl_windowevent_resized

其他的东西

在 sdl 2.0 中有大量新的和有趣的功能, 1.2 的人甚至做梦也没想到。我们只是试图解释你可能要做什么, 让你的1.2 程序运行在2.0 这里, 但你应该探索的文件, 你可能一直希望的东西, 直到现在, 没有。例如, 我所移植的每一个游戏都以一个消息框函数的结尾为例:

#if USING_SDL
fprintf(stderr, "MSGBOX: %s\n%s\n", title, text);   // oh well.
#endif

现在有 SDL_ShowSimpleMessageBox ()。不客气!

如果你跳过前面, 回去看看所有的新功能在概述!

内容概要:本文研究了一种应用于太阳能发电系统的多级逆变器,旨在通过采用正弦脉宽调制(SPWM)技术有效降低输出电压的总谐波失真(THD),从而提升电能质量。研究基于Simulink平台构建了完整的仿真模型,系统地实现了SPWM信号生成、驱动逻辑控制以及多电平输出波形合成等关键环节,验证了该多级逆变器在不同运行工况下具备优异的动态响应能力和稳定性。仿真结果表明,所设计的逆变器能够输出接近理想正弦波的电压波形,显著抑制高次谐波,满足可再生能源并网对电能质量的严苛要求,体现出多级逆变拓扑在光伏发电系统中的技术先进性与工程应用价值。; 适合人群:电气工程、自动化、新能源科学与工程及相关专业的本科生、研究生,以及从事光伏逆变器设计、电力电子变换技术和可再生能源并网系统研发的工程技术人员。; 使用场景及目标:①深入理解多级逆变器的工作原理及其在太阳能发电系统中的关键作用;②掌握SPWM调制技术的理论基础与实现方法,并分析其对改善THD的核心机制;③借助Simulink仿真平台开展电力电子电路的建模、参数调试与性能评估,服务于课程设计、毕业设计、科研课题或实际工程项目开发。; 阅读建议:建议读者结合提供的Simulink仿真模型进行同步操作与验证,细致调整调制比、载波频率等关键参数,观察其对输出波形和THD指标的影响,以深化对系统动态特性的理解,并尝试优化控制策略以进一步提升系统性能。
VCF 生成器 Lite v6.0.0:批量导入与功能拓展 VCF 生成器 Lite v6.0.0 正式版已发布,此次更新带来了批量导入手机通讯录这一重要功能,极大地方便了用户整理和管理联系人信息。同时,新增了多项功能,如翻译所有 CLI 内容,让不同语言背景的用户都能更好地使用;verbose 模式新增更多日志信息,有助于用户更详细地了解操作过程。 此外,还添加了多地区号码格式支持,包括中国港澳台地区电话号码格式,满足了不同地区用户的需求。当未捕获异常时,系统会自动保存错误日志,并引导用户反馈给开发者,这体现了产品团队对用户体验 的重视,有助于及时发现和解决问题。 修复痛点:引号清理与进度条显示问题 在修复方面,此次更新解决了引号清理功能在包含换行符时的错误行为,以及自 `v4.3.0` 版本以来的进度条显示问题。这些问题虽然看似微小,但却影响了用户的使用体验,修复后能让用户更加顺畅地使用 VCF 生成器 Lite。 代码与文档重构:提升可维护性与易用性 在变更方面,将翻译框架迁移到 gettext,提升了 `LANGUAGE` 环境变量 优先级,方便用户根据自己的语言偏好进行设置。在 AI 的指导下重构项目,使得各层次职责更加清晰,代码更加模块化,可维护性更高,这为产品的后续发展奠定了良好的基础。 同时,按 Diataxis 框架重构用户文档,按开发生命周期 重组开发者文档,让用户和开发者都能更方便地获取所需信息,提高了产品的易用性。 编辑观点:VCF 生成器 Lite v6.0.0 的更新在功能、修复和代码文档方面都有显著提升,满足了用户的实际需求,增强了产品的竞争力,未来有望在市场上取得更好的成绩。
内容概要:本文围绕2026年高教社杯全国大学生数学建模竞赛B题“无线电干扰源的快速自动定位与清除”展开,提供完整的数学建模方案、配套代码实现与论文撰写资源。内容涵盖问题分析、模型构建、算法设计与仿真验证全过程,并延伸至多类相关科研方向的Matlab/Simulink仿真实例,如无人机路径规划、微电网优化调度、信号处理、电力系统无功优化、时频冲突消解等,充分展示复杂工程问题的建模与求解方法。资源通过百度网盘及微信公众号“荔枝科研社”免费共享,旨在为参赛学生与科研人员提供系统性技术支持与创新启发。; 适合人群:全国大学生数学建模竞赛参赛者,具备一定数学建模、编程基础(尤其是Matlab/Simulink)的本科生与研究生,以及从事智能优化、通信工程、电力系统、信号处理、路径规划等相关领域研究的科研人员。; 使用场景及目标:①辅助完成数学建模竞赛中关于无线电干扰源定位与清除等问题的建模、编程与论文撰写;②获取多种科研课题的高质量代码实现与论文参考范例,提升科研效率与创新能力;③学习先进优化算法(如GWO、WOA、NSGA-III等)在复杂系统优化中的应用方法;④借鉴多学科交叉问题的建模思路与仿真技术。; 其他说明:所有资源均可通过提供的百度网盘链接及公众号免费获取,建议用户按照目录结构系统性地浏览与学习,结合代码运行与论文阅读进行实践,以深入掌握建模范式与算法实现细节,充分发挥资源的学习价值与科研参考价值。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值