• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 126,  comments - 73,  trackbacks - 0

              下文從使用SDL的編程函數(shù)開始,介紹了如何使用SDL在屏幕上進行象素繪制的基本知識,并給出了一個簡單的例子。

              如果要在VC中用SDL庫,必須在源文件頭部包含以下頭文件:

            #include “SDL.h”

              初始化SDL是通過SDL_Init()函數(shù)來實現(xiàn)的。如果初始化失敗,函數(shù)返回值為0。函數(shù)只接受初始化對象作為參數(shù)。如果要初始化視頻屏幕,傳入常數(shù)SDL_INIT_VIDEO作為參數(shù);初始化音頻,傳入常數(shù)SDL_INIT_AUDIO;如果同時初始化視頻和音頻,傳入SDL_INIT_VIDEO|SDL_INIT_AUDIO。其它還有一些量可以傳入作為參數(shù)的(如果同時傳入多個量要使用|將它們隔開):

            SDL_INIT_TIMER
            SDL_INIT_AUDIO
            SDL_INIT_VIDEO
            SDL_INIT_CDROM
            SDL_INIT_JOYSTICK
            SDL_INIT_NOPARACHUATE
            SDL_INIT_EVENTTHREAD
            SDL_INIT_EVERYTHING

              如果我們要初始化,可以使用如下語句:

            if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 )
            {
             printf(“Unable to init SDL: %s\n”, SDL_GetError());
             return 1;
            }

              如果初始化失敗,則函數(shù)SDL_GetError()返回關(guān)于錯誤的一個字符串提示信息。

              當(dāng)從你的C++語句返回時,記住使用SDL_Quit()進行程序的清理工作,否則就會出現(xiàn)奇怪的現(xiàn)象。可以使用如下語句進行描述:

            atexit(SDL_Quit);

              這樣的話就不需要在main函數(shù)中每個return語句前加入SDL_Quit()了。

              在SDL中你可以擁有多個surface,每件物體都是一個surface。你可以在一個surface上進行繪圖或者在其他surface上繪制另外一個surface。程序中一個surface的表示即為指向結(jié)構(gòu)SDL_Surface的指針。如果要獲得一個surface只要如下定義:

            SDL_Surface *screen;

              如果需要對screen所指向的surface上進行繪圖,你可以使用函數(shù)SDL_SetVideoMode()來設(shè)置屏幕分辨率:

            screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);

              前三個參數(shù)分別為屏幕寬度,高度和屏幕上的每象素包含的位數(shù)(bits per pixel, BPP)。如果填入0則SDL自動選擇最合適的BPP。第四個參數(shù)用來給出某些特殊標(biāo)志位。如果要在屏幕上進行圖形繪制就必須使用SDL_HWSURFACE或者SDL_SWSURFACE。以下給出了一個你可以指定的標(biāo)志位:

              SDL_SWSURFACE:在系統(tǒng)內(nèi)存中創(chuàng)建視頻Surface

              SDL_HWSURFACE:在視頻內(nèi)存中創(chuàng)建視頻Surface

              SDL_ASYNCBLIT:允許在顯示surface上使用異步更新。在單CPU機器上會變慢,但在SMP系統(tǒng)上會有顯著的性能提升。

              SDL_ANYFORMAT:一般的,如果指定位數(shù)的bpp不可用,那么SDL就會模擬使用陰影surface。如果傳入SDL_ANYFORMAT就會阻止這樣做,并且不管色深強制使用視頻surface。

              SDL_HWPALETTE:給予SDL特許的畫盤的訪問權(quán),使用這個標(biāo)志位就不需要總是使用SDL_SetColors或者SDL_SetPalette來獲取所需的顏色。

              SDL_DOUBLEBUF:允許硬件雙緩沖;只是和SDL_HWSURFACE一起使用時比較有用。調(diào)用SDL_Flip將會flip整個緩沖并且更新屏幕。所有的繪制將會在當(dāng)前未顯示的surface上發(fā)生。如果雙緩沖被允許,那么SDL_Flip將會對整個屏幕進行SDL_UpdateRect操作。

              SDL_FULLSCREEN:SDL將會嘗試使用全屏模式。如果硬件分辨率的調(diào)整由于某種情況無法完成,那么下一個稍高的分辨率將會被使用,并且顯示窗口將會處于一個黑色背景的中央。

              SDL_OPENGL:創(chuàng)建一個OPENGL rendering context。使用前必須已經(jīng)使用SDL_GL_SetAttribute對OpenGL視頻屬性進行設(shè)置。

              SDL_OPENGLBLIT: 和上一個選項一樣創(chuàng)建一個 OPENGL rendering context, 但是允許使用正常的blitting操作。

              SDL_RESIZABLE; 創(chuàng)建一個可伸縮大小的窗口。當(dāng)用戶調(diào)整窗口大小時,將會觸發(fā)一個SDL_VIDEORESIZE事件,SDL_SetVideoMode將會使用新大小作為參數(shù)再次被調(diào)用。

              SDL_NOFRAME: 如果可以的話,SDL_NOFRAME將會創(chuàng)建出一個沒有標(biāo)題欄和邊界修飾的窗口,全屏方式自動設(shè)置此標(biāo)志位。

              建議使用SDL_HWSURFACE | SDL_DOUBLEBUF,如果出現(xiàn)錯誤可以嘗試使用SDL_SWSURFACE。

              SDL_SetVideoMode如果操作成功,則返回一個指向SDL_Surface的指針,否則的話返回NULL。可以使用如下語句檢查發(fā)生的錯誤:

            If ( screen == NULL )
            {
             printf(“Unable to set 640x480 video: %s\n”, SDL_GetError());
             return 1;
            }

              以上介紹了如何對SDL進行初始化,下面可以開始繪制了。但是還有一些需要注意的關(guān)鍵地方,首先是一些SDL使用的容易讓人產(chǎn)生迷惑的數(shù)據(jù)類型:

            Uint8 – 相當(dāng)于unsigned char
            Uint16 – 16位(2字節(jié)) unsigned integer
            Uint32 – 32位(4字節(jié)) unsigned integer
            Uint64 - 64位(8字節(jié)) unsigned integer
            Sint8 – 相當(dāng)于signed char
            Sint16 – 16位(2字節(jié)) signed integer
            Sint32 – 32位(4字節(jié)) signed integer
            Sint64 - 64位(8字節(jié)) signed integer

              還有,有的時候如果初始化出現(xiàn)錯誤,沒必要完全退出。例如當(dāng)初始化了SDL_INIT_VIDEO而沒有初始化SDL_INIT_AUDIO,那么你可以繼續(xù)這個錯誤只是沒有音頻而已。要檢查是否音頻初始化是否成功,可以使用SDL_WasInit()函數(shù)來檢查。下面是一個例子:

            Uint32 init = SDL_WasInit(SDL_INIT_AUDIO);
            If (init & SDL_INIT_AUDIO)
            {
             sound = 1;
            } else {
             sound = 0;
            }

              你可以在程序初始化的某些地方加入以上語句。

              以下是SDL介紹中進行象素繪制的語句,可以暫時不需要完全了解其中的意思:

            void DrawPixel(SDL_Surface *screen, int x, int y, Uint8 R, Uint8 G, Uint8 B)
            {
             Uint32 color = SDL_MapRGB(screen->format, R, G, B);
             switch (screen->format->BytesPerPixel)
             {
              case 1: // Assuming 8-bpp
              {
               Uint8 *bufp;
               bufp = (Uint8 *)screen->pixels + y*screen->pitch + x;
               *bufp = color;
              }
              break;
              case 2: // Probably 15-bpp or 16-bpp
              {
               Uint16 *bufp;
               bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x;
               *bufp = color;
              }
              break;
              case 3: // Slow 24-bpp mode, usually not used
              {
               Uint8 *bufp;
               bufp = (Uint8 *)screen->pixels + y*screen->pitch + x * 3;
               if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
               {
                bufp[0] = color;
                bufp[1] = color >> 8;
                bufp[2] = color >> 16;
               } else{
                bufp[2] = color;
                bufp[1] = color >> 8;
                bufp[0] = color >> 16;
               }
              }
              break;
              case 4: // Probably 32-bpp
              {
               Uint32 *bufp;
               bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x;
               *bufp = color;
              }
              break;
             }
            }

              通過這個函數(shù),可以傳遞給surface要繪制的點的(x,y)坐標(biāo)和RGB值。
            ?  同時,由于繪制的屏幕不能同時接受兩個函數(shù)的同時操作,我們需要其他兩個輔助函數(shù),用于在繪制前對屏幕進行鎖定,以及在繪制完成之后解除鎖定。這兩個工作一般由SDL_MUSTLOK(SDL_Surface *screen)和SDL_UnlockSurface(SDL_Surface *screen)完成。使用如下兩個自定義的函數(shù)會更加簡單:

            void Slock(SDL_Surface *screen)
            {
             if ( SDL_MUSTLOCK(screen) )
             {
              if ( SDL_LockSurface(screen) < 0 )
              {
               return;
              }
             }
            }
            void Sulock(SDL_Surface *screen)
            {
             if ( SDL_MUSTLOCK(screen) )
             {
              SDL_UnlockSurface(screen);
             }
            }

              這樣,我們可以得到一個簡單的主程序框架如下:

            #include <stdio.h>
            #include <stdlib.h>
            #include "SDL.h"

            // The functions are not shown to save space
            void DrawPixel(SDL_Surface *screen, int x, int y, Uint8 R, Uint8 G, Uint8 B);
            void Slock(SDL_Surface *screen);
            void Sulock(SDL_Surface *screen);

            int main(int argc, char *argv[])
            {
             if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 )
             {
              printf("Unable to init SDL: %s\n", SDL_GetError());
              exit(1);
             }
             atexit(SDL_Quit);
             SDL_Surface *screen;
             screen=SDL_SetVideoMode(640,480,32,SDL_HWSURFACE|SDL_DOUBLEBUF);
             if ( screen == NULL )
             {
              printf("Unable to set 640x480 video: %s\n", SDL_GetError());
              exit(1);
             }

             // DRAWING GOES HERE
             return 0;
            }

              如果對該程序進行編譯運行,那么只能得到一閃而過的一個黑色的窗口。我們需要對窗口進行繪制,并且對基本的鍵盤鼠標(biāo)事件進行處理。

              繪制的基本原理是,先在緩沖區(qū)繪制,再一次性將緩沖區(qū)繪制到屏幕上。這樣比起一次一個象素點在屏幕上繪圖的方式效率更高,速度更快,也不易出錯。首先使用循環(huán)在screen所指向的surface(緩沖區(qū))上繪制,然后調(diào)用SDL_Flip函數(shù)將screen surface繪制到真實電腦屏幕上。SDL_Flip函數(shù)的作用是:在支持雙緩沖(double-buffering)的硬件上,建立flip并返回。硬件將等待vertical retrace,然后在下一個視頻surface blit或者執(zhí)行鎖定返回前交換視頻緩沖區(qū)。如果硬件不支持雙緩沖,那么等同于調(diào)用SDL_UpdateRect(screen, 0, 0, 0, 0),即對整個screen的繪制區(qū)域進行刷新。

            void DrawScene(SDL_Surface *screen)
            {
             Slock(screen);
             for(int x=0;x<640;x++)
             {
              for(int y=0;y<480;y++)
              {
               DrawPixel(screen, x,y,y/2,y/2,x/3);
              }
             }
             Sulock(screen);
             SDL_Flip(screen);
            }

              在SDL中對采用結(jié)構(gòu)SDL_Event來描述事件,并采用輪詢的機制對事件進行處理,程序中使用一個SDL_Event的實例(Instance)來檢查事件的發(fā)生:

            SDL_Event event;

              輪詢采用while循環(huán)來檢查:

            while ( SDL_PollEvent(&event))
            {
             if ( event.type == SDL_QUIT)
             {
              //code here….
             }
             if ( event.type == SDL_KEYDOWN)
             {
              //code here….
             }
             //…..
            }

              事件輪詢完畢之后,調(diào)用DrawScene(sreen)進行一次繪制。?

            ?????????本例中的源代碼如下:

            #include <stdio.h>
            #include <stdlib.h>
            #include "SDL.h"

            void Slock(SDL_Surface *screen)
            {
             if ( SDL_MUSTLOCK(screen) )
             {
              if ( SDL_LockSurface(screen) < 0 )
              {
               return;
              }
             }
            }
            void Sulock(SDL_Surface *screen)
            {
             if ( SDL_MUSTLOCK(screen) )
             {
              SDL_UnlockSurface(screen);
             }
            }
            void DrawPixel(SDL_Surface *screen, int x, int y,
            Uint8 R, Uint8 G, Uint8 B)
            {
             Uint32 color = SDL_MapRGB(screen->format, R, G, B);
             switch (screen->format->BytesPerPixel)
             {
              case 1: // Assuming 8-bpp
              {
               Uint8 *bufp;
               bufp = (Uint8 *)screen->pixels + y*screen->pitch + x;
               *bufp = color;
              }
              break;
              case 2: // Probably 15-bpp or 16-bpp
              {
               Uint16 *bufp;
               bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x;
               *bufp = color;
              }
              break;
              case 3: // Slow 24-bpp mode, usually not used
              {
               Uint8 *bufp;
               bufp = (Uint8 *)screen->pixels + y*screen->pitch + x * 3;
               if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
               {
                bufp[0] = color;
                bufp[1] = color >> 8;
                bufp[2] = color >> 16;
               } else {
                bufp[2] = color;
                bufp[1] = color >> 8;
                bufp[0] = color >> 16;
               }
              }
              break;
              case 4: // Probably 32-bpp
              {
               Uint32 *bufp;
               bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x;
               *bufp = color;
              }
              break;
             }
            }
            void DrawScene(SDL_Surface *screen)
            {
             Slock(screen);
             for(int x=0;x<640;x++)
             {
              for(int y=0;y<480;y++)
              {
               DrawPixel(screen, x,y,y/2,y/2,x/3);
              }
             }
             Sulock(screen);
             SDL_Flip(screen);
            }

            int main(int argc, char *argv[])
            {
             if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 )
             {
              printf("Unable to init SDL: %s\n", SDL_GetError());
              exit(1);
             }
             atexit(SDL_Quit);
             SDL_Surface *screen;
             screen=SDL_SetVideoMode(640,480,32,SDL_HWSURFACE|SDL_DOUBLEBUF);
             if ( screen == NULL )
             {
              printf("Unable to set 640x480 video: %s\n", SDL_GetError());
              exit(1);
             }
             int done=0;
             while(done == 0)
             {
              SDL_Event event;
              while ( SDL_PollEvent(&event) )
              {
               if ( event.type == SDL_QUIT ) { done = 1; }
               if ( event.type == SDL_KEYDOWN )
               {
                if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }
               }
              }
              DrawScene(screen);
             }
             return 0;
            }

              程序運行結(jié)果如下:


            posted on 2010-08-11 13:54 我風(fēng) 閱讀(1222) 評論(0)  編輯 收藏 引用 所屬分類: SDL
            <2010年11月>
            31123456
            78910111213
            14151617181920
            21222324252627
            2829301234
            567891011

            常用鏈接

            留言簿(12)

            隨筆分類

            隨筆檔案

            文章檔案

            相冊

            收藏夾

            C++

            MyFavorite

            搜索

            •  

            積分與排名

            • 積分 - 326062
            • 排名 - 75

            最新評論

            閱讀排行榜

            評論排行榜

            99久久精品国产一区二区三区| 久久涩综合| 久久丫精品国产亚洲av不卡| 久久精品国产亚洲AV电影| 国产精品女同久久久久电影院| 国内精品久久久久影院网站| 亚洲中文久久精品无码| 99久久国产亚洲高清观看2024| 久久久久黑人强伦姧人妻| 久久综合综合久久97色| 久久久久无码精品国产不卡| 草草久久久无码国产专区| 国产精品久久久久久久久鸭 | 欧美亚洲国产精品久久蜜芽| 久久婷婷色综合一区二区| 日韩精品久久久久久免费| 久久一区二区三区99| 狠狠狠色丁香婷婷综合久久五月 | 久久综合亚洲色HEZYO国产| 精品人妻久久久久久888| 久久婷婷色综合一区二区| 久久久无码精品午夜| 久久精品国产99国产精偷| 亚洲色大成网站WWW久久九九| 久久久精品视频免费观看| 久久精品国产一区二区三区日韩| 久久人人爽人人爽人人av东京热| 久久久久一本毛久久久| 97久久精品人人澡人人爽| 久久精品国产精品青草| 无码国内精品久久人妻蜜桃| 亚洲AV乱码久久精品蜜桃| 亚洲婷婷国产精品电影人久久| 伊人久久五月天| 蜜臀av性久久久久蜜臀aⅴ| 亚洲精品国产字幕久久不卡| 一级做a爰片久久毛片看看 | 无码久久精品国产亚洲Av影片 | 久久夜色精品国产欧美乱| 伊人色综合久久天天人手人婷| 久久久久人妻一区二区三区|