SDL 簡單入門學習


write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

討論新聞組及文件

概要

實際學習使用SDL創建窗體,並繪制圖形。

前言   

    今天想要做一個簡單的demo,由於一部分須要使用objective C,所以還須要跨平台,我才發現,我了解的東西還真沒有一個適合做這樣事情的,Cocos2D For IPhone只能在IPhone下跑,HGE只能在Windows下跑,Orx盡管可以跨平台,可是非常顯然,用於做簡單的demo太麻煩了,由於我須要的不過一個簡單的DrawBmp函數而已,Orx那種一使用就使用一套的做法不太適合,還能想到的就是OpenGL了,可是用OpenGL做跨平台應用全靠自己那就挺麻煩了,還是找個框架吧。
    事實上我有3個選擇,glut/free glut, SDL, GLFW。當中glut盡管在學習OpenGL的時候用過一些,可是由於該項目已經死了,我不想再為其投入很多其它的學習時間,了解到能夠看懂其代碼的水平(事實上使用也非常easy),已經夠了。SDL是非常多人推薦的選擇,我曾經找工作的時候,國內的一家公司居然直接提到過,說明其在國內也算是有人用了。我在那以后也看過SDL的API,感覺還算簡單,與HGE一樣,圖形顯示上,都是用了相似DirectDraw的抽象。(應該也是最通吃的抽象方式了)我對GLFW的感興趣是由於近期Orx的作者iarwain提到過,而且給予了非常高的評價,他說對GLFW的輕量級印象非常深刻,在最新的Orx版本號中,GLFW是Orx的默認插件,而且就iarwain的測試,比SDL快5%左右(盡管不算太多),最重要的是,GLFW的封裝都非常easy,以直接使用OpenGL為主,借這個契機,我也順面復習一下OpenGL,近期老是用庫,我都快忘了該怎么用了。
    兩相比較,我發現我不知道該用SDL還是GLFW,按我的習慣,兩個一起用先,嘗試一下再下結論。本文先看看SDL。

實際使用   

    事實上我的需求非常easy,創建窗體,在制定的地方畫圖。簡單的說也就是相似於CreateWindows和DrawBmp的兩個函數而已。

    SDL事實上真的算挺出名的了,也有人提到過,即使不真的准備使用SDL,可是想想一個庫,可以被移植到這么多平台,抽象封裝的方式和源碼起碼都值得研究研究。由於這個,我也略微看一下,盡管真的不打算長期SDL。SDL的協議是LGPL的(也有商業協議),還算可以接受。
    環境的搭建還算簡單,Windows版本號的SDL須要D3D SDK支持。
    簡單的參考了一下教程,顯示BMP圖片的過程還算簡單:
 1
 2 #include
 3 #include
 4 #include
 5 #include "SDL.h"
 6
 7 int  _tmain(int  argc, _TCHAR* argv[])
 8 {
 9   if  ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0  )
10   {
11     printf("Unable to initialize SDL: %s n " , SDL_GetError());
12
13     exit(1 );
14   }
15   atexit(SDL_Quit);
16
17   //Load image
18   SDL_Surface* picture = SDL_LoadBMP( "dragon.bmp"  );
19
20   SDL_Surface *screen = SDL_SetVideoMode(640 , 480 , 16 , SDL_DOUBLEBUF);
21   if  ( screen == NULL  )
22   {
23     printf("Unable to set video mode: %s n " , SDL_GetError());
24
25     exit(1 );
26   }
27
28   //Apply image to screen
29   SDL_BlitSurface( picture, NULL , screen, NULL  );
30
31   //Update Screen
32   SDL_Flip( screen );
33
34   //Pause
35   SDL_Delay( 2000  );
36
37   //Free the loaded image
38   SDL_FreeSurface( picture );
39
40     return  1 ;
41 }


這里,能夠看到,SDL沒有管理主循環,同一時候我沒有使用自己的主循環,那得牽涉到SDL的事件系統,所以,這個演示里,用了SDL_Delay,才干看到圖片的顯示。這里的顯示沒有指定大小,沒有指定alpha值,所以圖片原大顯示。SDL_BlitSurface 函數的使用非常像Windows API的相應函數。其它也沒有什么好說的,看凝視及函數名就知道在干什么了。

然后,通過下述方式來設置想要的透明色(在沒有alpha通道的bmp中,也僅僅能使用這樣蹩腳的color key方式了)
1
2   Uint32 colorKey = SDL_MapRGB(picture->format, 0xFF , 0xFF , 0xFF );
3   SDL_SetColorKey(picture, SDL_SRCCOLORKEY, colorKey);

當中0xFF,0xFF,0xFF各自是想要設定的顏色的R,G,B,這里都是0xFF,那就是白色了。
於是,原圖:




在黑色背景下,周圍的白色都透明了,顯示出下列的效果:


說實話,用SDL的API還算比較簡單,使用的時候有點感覺時空穿越,有點回到當年學習使用Win32 API來做相似事情的時候。接口的概念都差點兒相同,或許SDL的優勢比起當年的Win32 API僅在於速度和跨平台了。
顯示兩個圖僅僅須要再blit一次就可以:
  //Apply image to screen
  SDL_BlitSurface( picture, NULL , screen, NULL  );

  SDL_Rect dest;
  dest.x = picture->w;
  dest.y = 0 ;

  //Apply image to screen again and move it to right
  SDL_BlitSurface( picture, NULL , screen, &dest );

然后,增加SDL對主循環的控制。

  // main loop
  bool  running = true ;
  while  (running) {
    //Update Screen
    SDL_Flip( screen );

    // delay, 50 for simple
    SDL_Delay( 50  );

    //While there's an event to handle
    SDL_Event event;
    while ( SDL_PollEvent( &event ) ) {
      if  (event.type == SDL_QUIT) {
        running = false ;
      }
    }
  }

SDL_PollEvent用於輪詢SDL的事件。
於是,如今SDL創建的窗體能夠被拖動,也能夠點擊關閉了。
想說的是,SDL真的非常easy,我看教程的時候基本上僅僅須要看源碼就可以,就能了解大部分的意思。

    以下到關鍵的部分了,PNG的顯示,我看到,盡管SDL本身只支持BMP,可是已經有人做了一個名叫SDL_Image的庫,能夠支持其它格式。(考驗一個開源庫好不好,有沒有良好的第3方支持是非常重要的方面,SDL這方面明顯非常不錯)於是,我們就不用直接使用libpng了,個人不是非常喜歡libpng的接口。。。。。
    不知道是不是秉承了SDL簡單的優良傳統,SDL_Image的使用也很easy,編譯好后,將里面的動態庫(由於須要支持PNG,所以有libpng和zlib的動態庫)都復制到執行文件夾里面,然后包括"SDL_image.h"就能夠了。從bmp到png的距離僅僅有幾行代碼。。。。。從我發現SDL_Image到真的載入顯示PNG圖片,也就過了不到10分鍾。。。。
所有源碼:

#include
#include
#include
#include "SDL.h"
#include "SDL_image.h"
int  _tmain(int  argc, _TCHAR* argv[])
{
  if  ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0  )
  {
    printf("Unable to initialize SDL: %s n " , SDL_GetError());

    exit(1 );
  }
  if  (IMG_Init(IMG_INIT_PNG) == 0  ) {
    printf("Unable to initialize SDL_image" );

    exit(1 );
  }
  atexit(SDL_Quit);

  //Load image
  //SDL_Surface* picture = SDL_LoadBMP( "dragon.bmp" );
  SDL_Surface* picture = IMG_Load("dragon.png" );

  SDL_Surface *screen = SDL_SetVideoMode(640 , 480 , 16 , SDL_DOUBLEBUF);
  if  ( screen == NULL  )
  {
    printf("Unable to set video mode: %s n " , SDL_GetError());

    exit(1 );
  }

  // because we use png with alpha now
  //Uint32 colorKey = SDL_MapRGB(picture->format, 0xFF, 0xFF, 0xFF);
  //SDL_SetColorKey(picture, SDL_SRCCOLORKEY, colorKey);

  //Apply image to screen
  SDL_BlitSurface( picture, NULL , screen, NULL  );

  SDL_Rect dest;
  dest.x = picture->w;
  dest.y = 0 ;

  //Apply image to screen again and move it to right
  SDL_BlitSurface( picture, NULL , screen, &dest );

  // main loop
  bool  running = true ;
  while  (running) {
    //Update Screen
    SDL_Flip( screen );

    // delay, 50 for simple
    SDL_Delay( 50  );

    //While there's an event to handle
    SDL_Event event;
    while ( SDL_PollEvent( &event ) ) {
      if  (event.type == SDL_QUIT) {
        running = false ;
      }
    }
  }

  //Free the loaded image
  SDL_FreeSurface( picture );

    return  1 ;
}

只唯獨幾行改動,在代碼中看的非常清楚。

 

小結

    簡單,還是簡單,這是我學習SDL的最大感受,API設計的簡單,相關概念也簡單,SDL無愧於Simple DirectMedia Layer中的Simple一次。要想真的從OpenGL學習起,然后調用libpng來載入PNG圖像並顯示,你得看到紅寶書的第十幾章,直到紋理貼圖的學習后你才干做到,可是,在SDL中做這些事情實在是太簡單了。即使與當年的Win32 API相比,也少了非常多Windows特定的消息循環原理等東西的學習,創建窗體的API比較起來,就會感覺MS那一幫人都是廢物,設計的窗體創建API,居然須要用幾十行的代碼去創建一個窗體,還須要注冊窗體類。。。。。。。。。。。其實,僅僅須要一行代碼。。。。。。

    一般來說,一個比較流行的開源庫都是比較好的,由於好,才流行,由於流行而變的更好,當中,最最重要的關鍵在於,使用要簡單,太復雜難用的庫,不管設計的多么靜止,都非常難吸引到使用者,也就難以進入這個良性的循環,不得不說,SDL在這方面,做的是非常好了。

 

 

原創文章作者保留版權 轉載請注明原作者 並給出鏈接

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM