BLock Image Transfer, a computer graphics operation in which two bitmap patterns are combined
In computing, the Blit was a programmable bitmap graphics terminal designed by Rob Pike and Bart Locanthi Jr. of Bell Labs in 1982.
Steam,不知怎么翻譯,eg:Steam Big Picture Mode,Steam passes this configuration
a working Steam Overlay
原文地址 https://wiki.libsdl.org/MigrationGuide
簡介
經過多年的開發,SDL2.0版本終於發布了!
我們為它感到自豪,並且我們希望那些應用了SDL1.2的游戲能夠立刻升級到SDL2.0.也許這是個讓人感到氣餒的任務,這是一篇關於如何升級到新庫的簡單指導。我們想你會發現它並不是你想象的那樣難,很多時候, 你要么直接替換函數,要么在代碼中撤銷一些操作來處理1.2中的缺陷。
我們相信,你會為SDL2.0感到高興,新的特性和比SDL1.2更好的體驗。這篇文檔並不會嘗試包含所有SDL2中好的東西--有很多--僅僅是那些你為了能正確運行而必須去做的事情。一旦你升級完你的代碼,一定要檢查這些新的東西,你可能需要在你的程序中去增加這些新的東西。
新特性總覽
這里列舉出了SDL2.0中大部分重要的新屬性:
- 全3D硬件加速
- 支持OpenGL3.0+的多種配置(核心、兼容性、調試、魯棒性等)
- 支持OpenGL ES
- 支持多窗口
- 支持多顯示器
- 支持多音頻設備
- 安卓和IOS系統的支持
- 簡單的2D渲染API,它可以利用 Direct3D, OpenGL, OpenGL ES, 或者幕后的軟件渲染。
- 自適應於 Windows, Mac OS X 和Linux 操作系統
- Windows中支持XInput 和 XAudio2
- 原子操作
- 電源管理(顯示剩余電池的電量等)
- 適應形狀的窗口
- 32位音頻(整型和浮點型)
- 簡化的游戲控制器API(搖桿的API這里也有)
- 觸控支持(多點觸控、手勢識別等)
- 更好的全屏支持
- 更好的鍵盤支持(掃描碼與鍵碼等)
- 消息框
- 剪貼板支持
- 基本的拖放支持
- 正常的unicode輸入和輸入法的支持
- 一個很強大的assert宏
- 許可協議由LGPL變為zlib
- 很多1.2版本令人煩惱的東西移除了
- 許多其他的事情!
簡介頁面上有大量關於SDL特性的列表(包括老的1.2版的特性)
查看更多內容
SDL從1.2遷移到2.0
一些基本的事實
在SDL2中沒有添加不兼容層。如果一個API在2.0版中被改變了,那是因為我們更改或者移除舊的函數是有意義的。如果你1.2版的程序使用2.0版的頭部,它可能會編譯失敗。本文將會嘗試告訴你最重要的和那些最容易絆倒你的改變。
沒有SDL_main!好吧,還有就是它現在做的總是意味着:一小段代碼隱藏在windows系統中的main()和WinMain()之間。在它里面沒有任何初始化代碼,並且它完全是可選的。這就意味着,你能夠在不使用SDL_main代替主線程的情況下使用SDL,在插件中使用SDL是很棒的,或者在腳本語言中調用SDL模塊。1.2版SDL_main中的所有東西現在都在SDL_Init() 中了。
現在沒有SDL降落傘了。在1.2中的SDL_INIT_NOPARACHUTE現在是默認的,並且僅僅是個狀態值。這會引起一些問題,如果除了主線程之外地方崩潰了,它會干擾程序所建立的信號/異常處理。缺點:一些平台在崩潰的時候沒有很好的清理全屏。如果你關心這些事情,你應當建立自己的崩潰處理機制,或者在atexit()函數(或者其它類似的函數)中調用SDL_Quit()函數。注意在Unix平台,SDL仍然捕獲SIGNINT並且把它映射到SDL_QUIT事件上。
視頻部分
用新的視頻應用程序接口創建一個游戲
與1.2版本相比,視頻API發生了最明顯的變化。SDL的老的API是在上個世紀90年代后期設計的,而現在需求已經發生了很大的變化。為了配合當前的硬件和操作系統的特性,我們幾乎完全替換了1.2版本中老的視頻API。
放心各位,這個新的相當完美,一旦你理解了這些改變,你將會為這些可以加入你1.2版游戲中的新特性感到高興。這些我們稍后討論。
告訴你個好消息:如果你的游戲中使用了OpenGL,那么你可能將不需要做太多事情:將少數函數的調用形式改為SDL2的方式,你會非常順利的做完這些。
對於2D圖形,SDL1.2給出了一個稱為“surfaces”的概念(存儲像素的緩沖區)。屏幕就是一個“surfaces”,如果你做2D軟件渲染,我們提供了一個函數用來在surfaces之間進行像素復制(“blit”位塊傳輸),必要時進行一下格式轉換。以前你是讓CPU在系統內存上,而不是在GPU的顯存上運行。SDL2.0改變了這種狀況;現在你總能使用硬件加速,並且API因為這點也發生了改變。
如果你有一個2D游戲,你可以采用三種方法之一來渲染。我們都會介紹這些方法,但是首先,讓我們來談點入門的東西。
記得SDL_SetVideoMode()嗎?它已經完全移除了。SDL2.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。Surfaces仍然存在於系統內存中,並且也還是始終被CPU控制着,因此我們想離這個區域遠一些。SDL2有了一個新的用於渲染的API。它意味着可以被簡單的2D游戲所使用,但最主要的是,它意味着所有使用軟渲染的操作轉移到了顯存和GPU中。即使你只是想用它來使你的軟渲染器輸出到屏幕上,它同時也帶來了一些非常好的優點:如果可能的話,它會在幕后使用OpenGL或者Direct3D,這意味你將能得到更快的位塊傳輸、一個一直工作的Steam覆蓋層和自由的縮放。
設置如下所示。
正如我們前面討論過的SDL_SetVideoMode() 變成了SDL_CreateWindow()。但是我們應該設置什么樣的分辨率呢?如果你的游戲需要硬編碼到640x480,例如,在這種情況下你在顯示器上運行時可能不能將它全屏顯示,並且在窗口模式下,你的游戲可能看起來像是一張顯示在高端顯示器上的動態郵票。SDL2提供了一個很好的解決方案。
我們不再調用SDL_ListModes()。在SDL2中才在一個等效的方法(在循環中調用SDL_GetDisplayMode(),SDL_GetNumDisplayModes()次),但是我們將會使用一個名為“fullscreen desktop全屏桌面”的新特性,這會告訴SDL“給我整個屏幕並且不要改變分辨率”。對於我們假設的640x480的游戲,它可能看起來像這樣:
- SDL_Window *sdlWindow = SDL_CreateWindow(title,
- SDL_WINDOWPOS_UNDEFINED,
- SDL_WINDOWPOS_UNDEFINED,
- 0, 0,
- SDL_WINDOW_FULLSCREEN_DESKTOP);
注意,我們沒有指定640或者480……,全屏桌面帶給你的將是整個顯示區域並且它會忽略你指定的任何尺寸。游戲窗口應當立即被顯示,而不是等待顯示器去指定一個新的分辨率,我們會利用GPU去縮放到桌面的大小,這往往比液晶顯示器偽造一個低的分辨率更快、看起來更整潔。額外的好處是:現在你不用對窗口背景做什么,它將自動調整。
現在我們需要一個用於渲染的上下文。
- SDL_Renderer *renderer = SDL_CreateRenderer(sdlWindow, -1, 0);
渲染器隱藏了我們如何繪制到窗口上的細節。在幕后可能使用Direct3D, OpenGL, OpenGL ES,或者軟surfaces,這取決於系統提供了什么;無論SDL怎么選擇,你的代碼都不用改變什么(雖然你喜歡指定某種類型的渲染器)。如果你想嘗試強制同步到豎直方向的空白來減少拉伸感,你應當使用SDL_RENDERER_PRESENTVSYNC而不是0作為第三個參數去賦值。你不應當在創建窗口的時候使用SDL_WINDOW_OPENGL 標志位。如果SDL_CreateRenderer()自己決定要使用OpenGL,它會為你恰當的更新窗口。
現在你理解這是如何工作的了,如果你沒有什么別的想法了的話,你可以用SDL_CreateWindowAndRenderer()來一步完成這些設置。
- SDL_Window *sdlWindow;
- SDL_Renderer *sdlRenderer;
- SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &sdlWindow, &sdlRenderer);
假設這些函數沒有調用失敗(記得要檢查是否返回了NULL),你現在就可以在屏幕上繪制了。讓我們先從清理屏幕到黑屏狀態開始。
- SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255);
- SDL_RenderClear(sdlRenderer);
- SDL_RenderPresent(sdlRenderer);
如你所想;畫了黑色(R,G,B都為零,全透明),清理整個窗口,在屏幕上顯示出了清理好的窗口。就是這個樣子,如果你一直使用SDL_UpdateRect()或者SDL_Flip()來在屏幕上顯示你的bits,現在的渲染API變為了SDL_RenderPresent()。
一個更為一般的操作在這里設置。由於我們使用了SDL_WINDOW_FULLSCREEN_DESKTOP,我們實際上並不知道要在多大的屏幕上繪制。幸運的是,我們不需要知道。1.2版中的一個好處是你可以這樣寫“我想要一個 640x480的窗口,並且我不需要關心你是如何做到的”,即使這么做意味着在較大的分辨率下的中間窗口代表着你的應用程序。
在2.0版本中,用於渲染的API可以這個樣子……
- SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); //使縮放渲染看起來更平滑
- SDL_RenderSetLogicalSize(sdlRenderer, 640, 480);
……它會很好的為你完成這些事情。你可以改變邏輯渲染大小來實現各種效果,但是主要實現是這樣的:不是讓系統去適應你渲染的尺寸,而是我們讓你的渲染的尺寸去適應系統。在我的1920x1200顯示器上,這個應用程序認為它當前正在在跟一個640x480分辨率的顯示器交流,但是SDL使用GPU來放大它以使用全部的像素。需要注意的是640×480和1920x1200長寬比不一樣:SDL也注意到了這一點,盡可能的縮放並且信箱狀處理(letterboxing)不同。
現在,我們開始真正的繪制。
如果你的游戲只是想要將得到的完全渲染的幀畫面輸出到屏幕上
一種特殊的情況出現在以前的軟件在渲染游戲時:應用程序要繪制每個像素,並且最終將經過大位塊傳輸的像素有效的輸出到屏幕。舉個這樣游戲的例子:毀滅戰士、毀滅公爵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_SetVideoMode()中得到的SDL_Surface,或者申請一塊像素塊用於寫入。你最好在緩存中寫入的是RGBA格式的像素,但如果你需要通過一個轉換來得到這種格式也是可以的。
extern Uint32 *myPixels;//這么可能是 surface->pixels,或者通過malloc()申請得到的內存地址,或者其它的東東。
在幀的末尾,我們會像這樣更新紋理:
- 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() 則是將它輸出到屏幕上。
如果你的游戲想要傳送surfaces到屏幕上。
有一種情況,你的SDL1.2版的游戲從磁盤中加載了大量的圖片輸送到的大量的SDL_Surfaces中,嘗試將它們輸入到顯存中(使用SDL_HWSURFACE屬性)。只需加載一次,就可以一遍又一遍的在需要的時候blit它們,但在其他方面不用改變。一個簡單的2D平台游戲可以這么做。如果你認為你的界面是“游戲界面”,而不是緩沖區的像素,那么這僅僅是你的想法。
你可以創建自己的紋理(存在於GPU內存中的surfaces)就像我們做的那個大的紋理一樣。
- sdlTexture = SDL_CreateTexture(sdlRenderer,
- SDL_PIXELFORMAT_ARGB8888,
- SDL_TEXTUREACCESS_STATIC,
- myWidth, myHeight);
正如你所想得到的。我們使用SDL_TEXTUREACCESS_STATIC,是因為我們想一次就上傳完我們的像素而不是一次又一次。一個更方便的解決方案可能是:
- sdlTexture = SDL_CreateTextureFromSurface(sdlRenderer, mySurface);
利用這一句,你像往常一樣加載你的SDL_Surface,但是在最后時刻你創建了一個在你SDL_Surface之外的紋理。一旦你擁有了一個SDL_Texture,你就可以釋放掉原先的surface了。
從這一點上看,你的1.2版游戲有一大堆SDL_Surfaces,使用SDL_BlitSurface()傳輸到屏幕的surface,以組成最終的幀緩沖,並且最終調用SDL_Flip()來顯示到屏幕上。在SDL2.0下,你將擁有大量的SDL_Textures,通過調用SDL_RenderCopy()來將你的渲染器組成最終的幀緩沖,並最終通過調用SDL_RenderPresent()來顯示到屏幕上。就這么簡單。如果這些渲染器從不需要修改,你可能會發現你的幀率已經飆的比屋頂都高了。
如果你的游戲兩方面都要
如果你既想要blit surfaces又想要在幀緩沖中修改單個的像素。折返跑--從紋理中讀取數據---昂貴而痛苦;一般說來你想總是往一個方向推送數據。你可能是最好的了,在這種情況下,保持程序中的任何東西都不變,直到最后推送到屏幕上,因此我們組合了這兩種老技術。
好消息來了:1.2版中SDL_Surface 的大部分API仍然存在。下面是教你改變屏幕的surface:
- SDL_Surface *screen = SDL_SetVideoMode(640, 480, 32, 0);
... 變成這樣...
- //如果你對這些十六進制感到害怕,可以通過調用SDL_PixelFormatEnumToMasks()來找出相應的枚舉值
- SDL_Surface *screen = SDL_CreateRGBSurface(0, 640, 480, 32,
- 0x00FF000,
- 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()。設置一個紋理和一個former,並且前者的更新是由后者推動的。
渲染用的API還有很多其他特性。其中一些可能能夠替代你程序中代碼:縮放、划線等等。如果你閱讀這個章節是因為你的簡單需要超過了傳送surface,你可能會不再指定單個像素和將一切到移動到GPU中,這將會給你的程序一個顯著的性能提升並且可能極大的簡化你的代碼。
其他渲染器API的注意事項
你可以使用渲染器API做一些簡單的特效,而不用直接去操作像素。其中一些在1.2版的surfaces中也是可用的。
- 顏色alpha:SDL_Color現在有了第四個值,alpha分量。在你的1.2版代碼中SDL_Colors可能無法復制/設置該值(被命名了但沒使用)。在2.0版中,你可以了。
- Alpha混合:使用 SDL_SetSurfaceAlphaMod 和SDL_SetTextureAlphaMod來代替SDL_SetAlpha().Alpha-混合在surfaces中可以通過SDL_SetSurfaceBlendMode()來禁用,在紋理可以通過SDL_SetTextureBlendMode()來實現。
- 色鍵:當調用SDL_SetColorKey()時,你應該傳送SDL_TRUE而不是SDL_SRCCOLORKEY。
- 顏色幅度:一些渲染器現在支持一種全局的顏色變更(srcC = srcC * color),查看SDL_SetTextureColorMod()可以了解到詳情。
OpenGL
如果你直接使用了OpenGL,你的遷移將會相當簡單。在SDL_GL_CreateContext()后,更改SDL_SetVideoMode()為 SDL_CreateWindow(),更改SDL_GL_SwapBuffers()為SDL_GL_SwapWindow(window)。所有進入GL的調用都是一樣的。
如果你使用了SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, x),這個改了。現在調用SDL_GL_SetSwapInterval(x)函數,這樣你就可以在現有的GL上下文中改變這一點了。
需要注意的是SDL2.0使用OpenGL時可以切換窗口/全屏和背面而不會丟失GL的上下文(歡呼~~~)。對於這個使用SDL_SetWindowFullscreen()。
輸入
好消息是,SDL2.0已經可以用Unicode 輸入了。壞消息是,這需要在你的程序中做些小改動。
在1.2中,許多應用只關心美國英語是不是仍然調用SDL_EnableUNICODE(1),因為它對得到按鍵相關聯的字符非常有用。但是一旦你獲取英語之外的就會可能不正常,並且一旦你選擇的是亞洲語言會發現它根本就不工作。
事實證明,國際化是很難的。
SDL改變了這一點。SDL_EnableUNICODE()移除了,同樣的還有SDL_Keysym的unicode區域。你不再需要從SDL_KEYDOWN事件中獲取字符輸入。使用SDL_KEYDOWN,對待鍵盤就像是一個有着101個按鈕的搖桿一樣。文字輸入來自別的地方。
新的事件叫做SDL_TEXTINPUT。當有新的文本被用戶輸入時它就會被觸發。注意的是,這個文本可能來自按下按鍵,或者某種輸入法(這是一種輸入復雜的多字符文本的奇特方式)。這個事件返回了整個字符串,它可能是1個字符那么長,或者是多字符數據的多個碼點的數值。這個字符串使用的是UTF-8編碼。
如果你所關心的仍然是用戶是否按下了某個鍵,那么仍然是用SDL_KEYDOWN,但是從1.2版以來,我們分離這個系統為兩個部分:鍵碼和掃描碼。
掃描碼的目的是鍵布局無關。想象一下這種情形“用於按下了一個Q鍵,認為當前是在美國的QWERTY鍵盤上”不管這實際上是一個歐洲鍵盤或Dvorak鍵盤等等。掃描碼的鍵位置相同。
鍵碼是布局依賴的。想象一下這種情形“用戶在他的專有鍵盤上按下了一個標記為‘Q’的按鍵”。
舉個例子,如果你在美國的QWERTY鍵盤上按下了一個鍵那意味着按下了兩個大小寫正確的鍵,它將會報告一個掃描碼SDL_SCANCODE_S和一個鍵碼SDLK_S。在Dvorak 鍵盤上的相同鍵,將會報告一個掃描碼SDL_SCANCODE_S和一個鍵碼SDLK_O。
注意的是鍵碼和掃描碼目前都是32位,並且使用了一個非常寬的數字范圍。並沒有SDLK_LAST。如果你的程序有一個SDLK_LAST元素的查找表,用來在SDL關鍵字和你程序內部中的東西進行映射,那將不再可行。使用哈希表來代替。std::map就不錯。如果你映射掃描碼而不是鍵碼,你可以在數組邊界上使用SDL_NUM_SCANCODES。當前它的值是512。
SDLMod現在是SDL_Keymod,同時"META"鍵(“Windows”鍵)現在稱為”圖形用戶界面”鍵。
SDL_GetKeyState()現在更名為SDL_GetKeyboardState()。返回的數組現在通過SDL_SCANCODE_* values(見SDL_Scancode)而不是SDL_Keysym值進行索引。
現在,是關於鼠標輸入的部分。
第一個變化,很簡單,鼠標滾輪不再是一個按鈕。這個一個歷史錯誤,我們在SDL2.0版本中改正了它。查看SDL_MOUSEWHEEL事件。我們支持縱向和橫向的滾輪,在一些平台上會將兩個手指在觸控板上的滾動作為輪輸入。你將不會在鼠標滾輪上收到SDL_BUTTONDOWN事件,並且現在按鈕4和5是真正的鼠標按鈕了。
如果你的游戲只需要在一個方向上滾動鼠標,例如玩家在射擊類游戲中旋轉時沒有鼠標點擊屏幕邊緣和停止,你可能會隱藏鼠標光標並且獲取輸入:
- 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(stream, 0, len)。
搖桿
搖桿事件引入了SDL_JoystickID。這是因為SDL2.0能夠處理搖桿的插入與拔出,就像在你游戲時設備會插入和拔出一樣,所以1.2版本使用的那種在設備列表中索引的方法變的沒意義了,因為可用的設備列表變化了。
為SDL_Joystick*獲取SDL_JoystickID 的方法是調用:
- SDL_JoystickID myID = SDL_JoystickInstanceID(myOpenedStick);
並且搖桿事件與使用myID相比。如果不再因為搖桿而使用事件隊列,可以用SDL_JoystickGetAxis(),這個函數很友好,就像在SDL1.2中一樣。
你也應該檢查新游戲控制器的API,因為它很酷,也許你使用1.2的API敲了很多代碼,新的代碼將會精簡很多。你會在SDL_gamecontroller.h中發現,游戲控制器API與Steam大圖片模式整合的非常好:你會得到大部分控制器的自動配置,如果你想手動配置的話還會有一個漂亮的界面。在這兩種情況下,Stream傳遞這個配置到你的SDL應用中。
SDL2中已經不再支持Linux下舊的搖桿API了(/dev/input/js*)。SDL2.0僅僅支持搖桿較新的API(/dev/input/event*)。這些事件不能被正常用戶正常讀取,所以,即使搖桿插入了你也可能檢測不到什么。這些事使用者必須自己配置它們。
線程
移除了SDL_KillThread()。它既不安全又不可靠。最好的替代是設置一個標識來告訴線程它該退出了。線程應該以一定的頻率來檢查這個標識,然后”殺死”線程,調用SDL_WaitThread()來清理。
SDL_CreateThread() 現在需要獲取一個額外的參數,線程的名稱,它可以在調試的時候識別它,如果你不關心它,可以在你函數調用的時候塞入一個NULL。
CD
1.2版中的CD API完全移除了。沒有替代品。目前的狀況是你很可能不會再購買以光盤為載體的CD音樂了,更何況你可能根本沒買過光盤。你可以使用Ogg Vorbis或者其他的音頻文件格式的音樂,許多可以由SDL_mixer支持。
掛了的平台
我們移除了一些舊平台的支持,像是OS/2和Mac OS 9。當然我們可以輕松的列出大量仍然支持的平台:Windows (XP 及后續版本)、Linux、Mac OS X、iOS、 Android。在SDL的傳統中,還有一些邊緣的系統支持的並不是很完美,像是 Haiku和Sony PSP。我們將會給一些人發送增加某些平台支持的補丁,但是現在看起來是時候移到新平台並跟老朋友說再見了。
移動平台
多年以來,SDL1.2到iOS和Android的非官方端口已經存在了。現在SDL已經直接支持這些平台了,並且2.0的API更適合它們。這篇文檔中的大部分建議都很實用,但是也有值得注意的地方。
首先,有一些事件只適用於移動設備,或者說,適用於后iphone時代的移動設備操作系統操作。我們曾經嘗試將這些事件映射到現有的SDL事件中(例如“你的應用程序即將前往后台運行”可以認為是桌面窗口的失焦點),但是這有一個更迫切的關注點:大部分的事件需要立刻做出反應,並且如果程序不能給出反應,操作系統就會殺死你的程序。
因此,我們為一些Android和iOS的一些特定的細節增加了新的SDL事件,但是你應當建立一個SDL事件過濾器用於系統報告他們的時候捕獲他們,因為等到你的下一個SDL_PollEvent()循環的時候已經太晚了。
例如,SDL_APP_WILLENTERBACKGROUN,它是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;
- }
- // somewhere near startup...
- // this calls myEventFilter(data, event) as soon as event is generated.
- SDL_AddEventWatch(myEventFilter, data);
第二,現在有了真實的觸控事件,而不是試圖將其映射到鼠標輸入。你可以跟蹤觸摸軌跡,多個手指,甚至是復雜的手勢。你可能想使用這些操作。請參閱SDL_touch.h中的這些函數的列表,同時在SDL_events.h中查找SDL_Finger*。
當然也有其它的對移動設備友好的函數,像是SDL_StartTextInput(),將會顯示一個屏幕鍵盤。利用它們。
此外,也有 Android 和 iOS特定的函數,讓你來使用特定平台的特性但在通用API上不起作用。請參閱SDL_system.h來查看這些函數列表。
RWops
SDL_RWread()和SDL_RWwrite()現在變為了失敗返回0,而不是-1.
如果你實現自己的SDL_RWops,那么該函數的簽名就更改了。函數現在使用的是Sint64和size_t類型而不是int類型,所以他們能夠處理大文件。在許多情況下,你要做的僅僅是更新函數簽名並保持跟原先一樣的處理,但是一旦你遇到了這些限制,你可能會很高興有了一個解決方案。調用程序時應當會知道返回值已經改變了。
現在還有一種得到RWops大小的方法。這會讓RWops報告流的大小而不用使程序在末尾尋找0字節;換句話說,你可以報告流的總大小而不用搜索。對於那些不能這么做的流,你仍然可以返回-1。
附加庫
官方擴展庫SDL_image, SDL_ttf, SDL_mixer 和 SDL_net都有了對應SDL2.0的版本:SDL2_image, SDL2_ttf, SDL2_mixer 和 SDL2_net.你可能需要從mercurial源碼庫去下載這些最新修補程序。隨后,當然,你必須去鏈接像是 SDL2_image而不是SDL_image,然后編譯你的程序。
這些庫不會支持1.2以前的版本,並且與1.2的兼容很可能會在某個新版本后消息。
SDL_gfx從2.0.21版開始也能跟2.0編譯了(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 渲染:surfaces仍然存在,但是建議使用SDL_Surfaces代替,如果可能的話SDL_Textures和2D加速渲染器(SDL_CreateRenderer())一起使用
- SDL_VideoInfo:使用SDL_GetRendererInfo()/SDL_GetRenderDriverInfo()替換
- SDL_GetCurrentVideoDisplay():使用SDL_GetWindowDisplayIndex() 替換
- SDL_VIDEORESIZE事件:新的等價事件是SDL_WINDOWEVENT_RESIZE
其他的東東
在SDL2.0中有大量新的和有趣的功能,這在1.2版中是不能想象的。我們只是在試圖向你解釋將你的程序從1.2運行到2.0要做的事情,但是你應該去探索那些你常常期望的東西,到現在為止,還沒有這么做過。例如,每一次游戲結束的時候的會調用一個消息框函數,就像下面一樣:
- #if USING_SDL
- fprintf(stderr, "MSGBOX: %s\n%s\n", title, text); // oh well.
- #endif
現在有了SDL_ShowSimpleMessageBox()。不用客氣!
如果你跳過了前面部分,返回並且查看所有新功能的概述
轉自:http://blog.csdn.net/lanxiaziyi/article/details/24938981