亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? 第11小節.txt

?? 游戲編程起源...中文版
?? TXT
?? 第 1 頁 / 共 2 頁
字號:
   
  
 傻馬亂踢  譯   
 
 
  
游戲編程起源(初學者)ⅩⅠ
 
 

★ DirectDraw的位圖化圖形

☆ 簡介

終于,你已經掌握了制作一個完整游戲的基礎知識了,只不過你現在還只能使用GDI。今天,我們就學習使用DirectX來執行每一件你以前用GDI完成的工作,以及一些關于DirectX其它的東東。具體內容是:裝載(調用)位圖,使用位塊傳輸,填充表面,使用剪裁板、顏色鍵等拷貝位圖。
你可以在不了解前一章內容的基礎上學習本章,但象素格式是很重要的,我將經常直接或間接的提到它,所以你至少應該看看上一章關于象素格式的部分!^_^ 另外,我假設你已經本系列的第一、二、三、四章,并且擁有一個DirectX SDK游戲開發平臺。準備好了嗎?發動引擎吧,女士們、先生們!

☆ 裝載位圖

不管你信不信,你的確已經知道了把位圖裝載到DirectDraw表面的大部分知識。怎么會這樣呢?Well,在Windows GDI下裝載位圖同在DirectDraw下極其相似,只是有一點點不同。輕輕的回憶一下,我們曾經使用LoadImage()函數得到位圖的句柄,然后把位圖選入到內存設備上下文中,最后利用BitBlt()函數把圖形從內存設備上下文中拷貝到顯示設備上下文中,設備上下文可以用GetDC()函數得到。如果這個承擔顯示任務的就是DirectDraw表面(現在我們就是要用它),我們就可以針對性的得到DirectDraw表面的設備上下文!感謝上帝,IDirectDrawSurface7接口提供了一個極其簡單的函數來得到這個設備上下文:

HRESULT GetDC(HDC FAR *lphDC);

該函數的返回類型同所有DirectDraw函數的返回類型相同。如果函數調用成功,參數就是一個HDC類型的設備上下文的指針,很簡單吧!本章就是從把一個位圖裝載到DirectDraw表面講起的。千萬要記住使用完了表面設備上下文后,你一定要釋放它哦!你可能已經想到了,用表面接口函數ReleaseDC()完成:
HRESULT ReleaseDC(HDC hDC);
你不用回頭去看關于GDI部分的位圖調用,我將把適合于DirectDraw的位圖調用展現給你。唯一不同的是:不是直接把設備上下文作為一個參數,而是用一個DirectDraw表面指針取代了它,然后函數從表面得到設備上下文,用它來拷貝圖形,最終釋放設備上下文。(可能這里我說的有些混亂,但你看一下下面的程序代碼就都明白了^_^):

int LoadBitmapResource(LPDIRECTDRAWSURFACE7 lpdds, int xDest, int yDest, int nResID)
{
    HDC hSrcDC; // source DC - memory device context
    HDC hDestDC; // destination DC - surface device context
    HBITMAP hbitmap; // handle to the bitmap resource
    BITMAP bmp; // structure for bitmap info
    int nHeight, nWidth; // bitmap dimensions

    // first load the bitmap resource
    if ((hbitmap = (HBITMAP)LoadImage(hinstance, MAKEINTRESOURCE(nResID), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION)) == NULL)
        return(FALSE);

    // create a DC for the bitmap to use
    if ((hSrcDC = CreateCompatibleDC(NULL)) == NULL)
        return(FALSE);

    // select the bitmap into the DC
    if (SelectObject(hSrcDC, hbitmap) == NULL)
    {
        DeleteDC(hSrcDC);
        return(FALSE);
    }

    // get image dimensions
    if (GetObject(hbitmap, sizeof(BITMAP), &bmp) == 0)
    {
        DeleteDC(hSrcDC);
        return(FALSE);
    }

    nWidth = bmp.bmWidth;
    nHeight = bmp.bmHeight;

    // retrieve surface DC
    if (FAILED(lpdds->GetDC(&hDestDC)))
    {
        DeleteDC(hSrcDC);
        return(FALSE);
    }

    // copy image from one DC to the other
    if (BitBlt(hDestDC, xDest, yDest, nWidth, nHeight, hSrcDC, 0, 0, SRCCOPY) == NULL)
    {
        lpdds->ReleaseDC(hDestDC);
        DeleteDC(hSrcDC);
        return(FALSE);
    }

    // kill the device contexts
    lpdds->ReleaseDC(hDestDC);
    DeleteDC(hSrcDC);

    // return success
    return(TRUE);
}

上面這段代碼被設計成從資源調用位圖,但你可以很容易就把它修改成從外部文件調用位圖,或者更理想的是,首先你從資源調用位圖,如果失敗,再試圖從外部文件調用位圖。從外部調用,需要記住的是調用LoadImage()函數時加上LR_LOADFROMFILE標志。最美妙的事情是,函數BitBlt()自動完成象素格式的轉換。舉例說,當我們把24-bit的位圖放入內存設備上下文,再把它傳送(拷貝)到16-bit色彩深度的表面,所有的顏色將得到正確的顯示,不用顧忌象素格式是555還是565,很方便吧,哦?
如果你要控制位圖傳遞的實際過程,而不是使用BitBlt()這樣簡單的函數,你有兩個選擇。第一個,你可以修改這個函數,需要利用BITMAP結構的bmBits成員,它是一個組成圖象的位的LPVOID指針變量。第二種方法,如果你真的想控制圖象的調用過程,你可以自己編寫函數,思路是使用標準的I/O函數來打開圖象文件,然后讀取它。要這樣做,你需要了解位圖文件的結構。我們將不涉及這種函數的編寫,因為目前的對我們來說已經足夠了,但我還是要為你將來的大展鴻圖做一點點鋪墊。^_^

☆ 位圖格式

令人高興的是,要自己寫一個調用位圖的函數,有一個Win32結構的位圖頭文件可以利用。讀取這個頭文件的信息,用fread()這樣簡單的函數就可以了。所有的位圖文件都有這樣一個頭文件,它包含了位圖的全部信息。BITMAPFILEHEADER就是這個頭文件結構的名字,下面是它的原形:

typedef struct tagBITMAPFILEHEADER { // bmfh
    WORD bfType;         // file type - must be "BM" for bitmap
    DWORD bfSize;        // size in bytes of the bitmap file
    WORD bfReserved1;    // must be zero
    WORD bfReserved2;    // must be zero
    DWORD bfOffBits;     // offset in bytes from the BITMAPFILEHEADER
                         // structure to the bitmap bits
} BITMAPFILEHEADER;

我就不詳細介紹這些成員了,因為注釋里已經說得很清楚了,只要使用fread()讀取它們就可以了。注意要檢測bfType成員是否等于字符“BM”,若是,說明你正在處理一個有效的位圖。在此之后,有另一個頭文件需要讀取,它包含位圖的尺寸、壓縮類型等圖象信息。以下是它的結構:

typedef struct tagBITMAPINFOHEADER{ // bmih
    DWORD biSize;         // number of bytes required by the structure
    LONG biWidth;         // width of the image in pixels
    LONG biHeight;        // height of the image in pixels
    WORD biPlanes;        // number of planes for target device - must be 1
    WORD biBitCount;      // bits per pixel - 1, 4, 8, 16, 24, or 32
    DWORD biCompression;  // type of compression - BI_RGB for uncompressed
    DWORD biSizeImage;    // size in bytes of the image
    LONG biXPelsPerMeter; // horizontal resolution in pixels per meter
    LONG biYPelsPerMeter; // vertical resolution in pixels per meter
    DWORD biClrUsed;      // number of colors used
    DWORD biClrImportant; // number of colors that are important
} BITMAPINFOHEADER;

只有幾個成員需要解說一下。第一個,注意壓縮格式。大多數的位圖你都需要做解壓縮的操作。最普通的位圖壓縮格式是run-length編碼(RLE),但只能應用于4-bit或8-bit圖象,在此情況時,成員biCompression將分別是BI_RLE4和BI_RLE8,我們就不討論這種壓縮格式了,但它真的很簡單,很容易理解,你如果要了解它是不會有任何麻煩的。^_^
第二個,對于高色彩的位圖,biClrUsed和biClrImportant這兩個成員通常設置為0,所以不用太在意它們。對于BI_RGB這種未壓縮格式的位圖,成員biSizeImage也將被設置為0。最后,針對我們的目的,其它的結構成員都不是很重要的,我們只需要注意位圖的長、寬和色彩的深度(biWidth、biHeight、biBitCount)。
讀取完了這些頭文件的信息后,如果位圖是8-bit或者以下色彩深度的(也就是調色板模式),調色板的信息會緊跟在這些信息之后。也許出乎你的意料,調色板的信息不是存儲在PALETTEENTRY結構中,而是在RGBQUAD結構中。RGBQUAD結構如下:

typedef struct tagRGBQUAD { // rgbq
    BYTE rgbBlue;
    BYTE rgbGreen;
    BYTE rgbRed;
    BYTE rgbReserved;
} RGBQUAD;

不要問我為什么紅、綠、藍以倒序方式排列,事實就是這樣!讀取RGBQUAD中的數據,把數據傳遞給DirectDraw調色板的數組。記得要把每個PALETTEENTRY的peFlag設置成PC_NOCOLLAPSE。
之后呢(調色板信息不一定存在,因為高彩模式下就沒有),你將發現圖象位(image bits),你可能會想到建立一個指針,在內存中分配足夠的空間來控制這些圖象位數據,然后讀取它們。對極了,我正要這樣干。假設把存儲在BITMAPINFOHEADER結構中的信息頭文件稱作info,你的圖象位指針稱作fptr,實施的代碼如下:

UCHAR* buffer = (UCHAR*)malloc(info.biSizeImage);
fread(buffer, sizeof(UCHAR), info.biSizeImage, fptr);

要記住,在一些情況下,biSizeImage的值可能為0,所以有必要在上面的代碼運行前檢測它一下。如果它被設置為0,你將不得不計算圖象由多少個象素構成,每個象素需要多少個字節。
寫你自己的位圖調用函數,并非什么難事兒。但你覺得不需要,就用我們開始介紹的方法好了。這個話題告一段落,下面讓我們看看DirectDraw的精華:使用位塊傳輸。

☆ 使用位塊傳輸

位塊傳輸是顯示卡操控位圖數據的一部分,你同樣可以用它來進行顏色填充。就像我們過一會兒看到的,隨著硬件的性能提高,會有很多經典的技巧。DirectX有權使用硬件的加速功能,但要記住,如果DirectX使用的加速功能不被機器硬件支持,將自動啟用硬件仿真層(HEL),但這也并非萬無一失,因為有些功能靠硬件仿真層是無法實現的(否則誰還買3D加速卡^_^),所以你需要檢測你的函數是否調用成功。
GDI位塊傳輸可以在DirectDraw編程中使用,而且有時也的確是這樣做的。然而DirectDraw具有其自身的位塊傳輸函數,它們通常更加適合于編程環境,而且比GDI的相應的函數執行得更快。DirectDraw位塊傳輸函數名為Blt()和BltFast(),都是有IDirectDrawSurface7接口提供的。兩者不同處是BltFast()不處理剪切、放縮等其它Blt()做的有趣的事情。如果在硬件仿真層上,BltFast()要比Blt()快10%左右,但如果有硬件加速卡支持(硬件加速卡主要就是為位塊傳輸服務的),二者的速度就差不多了,而且現在大多數的機器都有硬件加速卡,所以我總是使用Blt()。讓我們仔細看看這個神奇的東東:

HRESULT Blt(
    LPRECT lpDestRect,
    LPDIRECTDRAWSURFACE7 lpDDSrcSurface,
    LPRECT lpSrcRect,
    DWORD dwFlags,
    LPDDBLTFX lpDDBltFx
);

由于Blt()所擁有的最后一個參數,使其能做很多特殊的事兒。該參數配有一個標志常量列表,我將會向你介紹其中最有用的幾個。另外,注意在把位圖從一個表面向另一個表面傳遞時,你應該調用目的表面的Blt(),不是源表面的。好了嗎?以下是函數的參數說明:

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
日韩一区和二区| 国产成人鲁色资源国产91色综| 五月天视频一区| 久久99蜜桃精品| av在线播放不卡| 欧美日韩国产首页| 久久久国产精华| 亚洲一区二区3| 国产呦萝稀缺另类资源| 97se亚洲国产综合自在线| 正在播放亚洲一区| 国产精品久久久久一区二区三区共| 亚洲一区二区精品3399| 国产一区二区三区综合| 欧美亚洲国产怡红院影院| 精品久久99ma| 亚洲一区二区三区在线播放| 久久99精品国产麻豆不卡| 97久久精品人人爽人人爽蜜臀| 91精品国产综合久久久蜜臀粉嫩 | 极品尤物av久久免费看| 波多野结衣在线一区| 这里是久久伊人| 中文字幕一区二区三区在线观看| 日韩电影在线一区| 色婷婷久久久综合中文字幕| 欧美videofree性高清杂交| 亚洲天堂av一区| 韩国三级中文字幕hd久久精品| 欧美最猛黑人xxxxx猛交| 久久久精品国产免费观看同学| 午夜日韩在线电影| av影院午夜一区| 久久久三级国产网站| 午夜精品一区二区三区免费视频 | 久久午夜色播影院免费高清| 一区二区三区在线观看动漫| 狠狠色丁香九九婷婷综合五月| 在线观看不卡一区| 国产精品国产三级国产普通话蜜臀 | 国产做a爰片久久毛片| 欧美熟乱第一页| 亚洲天堂福利av| 成人av集中营| 久久综合久色欧美综合狠狠| 午夜精品福利一区二区三区av| 91网址在线看| 亚洲欧洲日韩在线| 国产成人综合在线| www久久久久| 久久精品国产99国产| 欧美日韩国产综合一区二区| 亚洲欧美偷拍三级| 成人h精品动漫一区二区三区| 欧美电影免费观看高清完整版在线 | 高潮精品一区videoshd| 欧美成人一区二区三区在线观看| 亚洲国产精品一区二区久久| 99久久伊人久久99| 国产精品情趣视频| 成人午夜又粗又硬又大| 26uuu成人网一区二区三区| 久久激情五月激情| 日韩精品专区在线| 日韩av二区在线播放| 欧美日韩大陆一区二区| 偷拍一区二区三区四区| 69久久99精品久久久久婷婷| 天堂资源在线中文精品| 欧美午夜免费电影| 视频一区欧美日韩| 91精品国产欧美一区二区成人 | 91麻豆精品91久久久久久清纯| 亚洲h在线观看| 欧美日本在线观看| 日韩av在线发布| 精品久久久久久亚洲综合网| 久久99精品久久只有精品| 久久亚洲一区二区三区明星换脸| 久久国产生活片100| 精品奇米国产一区二区三区| 激情综合五月婷婷| 国产性色一区二区| 成人精品在线视频观看| 中文字幕在线一区| 91国产丝袜在线播放| 亚洲高清免费视频| 欧美电视剧在线观看完整版| 激情综合色丁香一区二区| 久久久蜜臀国产一区二区| 成人久久18免费网站麻豆 | 91成人在线免费观看| 亚洲午夜一区二区| 欧美一区二区福利视频| 黑人巨大精品欧美一区| 国产精品美女久久久久aⅴ国产馆| 91在线观看成人| 亚洲不卡av一区二区三区| 日韩欧美国产综合在线一区二区三区| 极品销魂美女一区二区三区| 欧美极品美女视频| 在线亚洲免费视频| 蜜乳av一区二区| 国产嫩草影院久久久久| 色综合婷婷久久| 全部av―极品视觉盛宴亚洲| 久久欧美一区二区| 色欧美片视频在线观看在线视频| 日韩精品欧美成人高清一区二区| 精品精品国产高清a毛片牛牛| 波多野结衣中文字幕一区二区三区| 亚洲影院免费观看| 久久综合狠狠综合| 欧美在线看片a免费观看| 麻豆精品一二三| 亚洲欧洲在线观看av| 日韩三级免费观看| 成人免费视频视频在线观看免费| 一区二区三区在线看| 久久综合999| 欧美色精品天天在线观看视频| 美女mm1313爽爽久久久蜜臀| 国产精品污www在线观看| 777色狠狠一区二区三区| 成人午夜电影网站| 日本怡春院一区二区| 亚洲欧洲精品天堂一级| 日韩一区二区三区视频| 99国产精品国产精品久久| 青青草一区二区三区| 亚洲精选视频在线| 国产拍欧美日韩视频二区| 欧美日本在线看| caoporn国产精品| 久久99最新地址| 性做久久久久久免费观看欧美| 国产亚洲成av人在线观看导航 | 日韩av电影天堂| 亚洲人成网站影音先锋播放| 欧美一区二区观看视频| 日本乱码高清不卡字幕| 国产大陆精品国产| 久久精品国产免费看久久精品| 一个色在线综合| 亚洲欧洲精品一区二区三区| 2020国产精品自拍| 91麻豆精品国产91久久久久久久久| 色网站国产精品| 不卡的av中国片| 国产福利精品一区二区| 青娱乐精品视频在线| 亚洲福利一二三区| 亚洲天天做日日做天天谢日日欢 | 成人午夜免费av| 国模冰冰炮一区二区| 天天做天天摸天天爽国产一区| 亚洲三级在线看| 中文字幕亚洲一区二区va在线| 精品sm在线观看| 欧美www视频| 欧美刺激午夜性久久久久久久| 欧美美女激情18p| 欧美综合色免费| 一本大道av伊人久久综合| 成人国产一区二区三区精品| 精品一区二区三区久久久| 日日夜夜精品视频免费| 一区二区三区日韩| 亚洲你懂的在线视频| 亚洲欧美自拍偷拍色图| 欧美激情一区在线| 久久久久99精品国产片| 日韩精品专区在线影院重磅| 日韩一卡二卡三卡四卡| 69精品人人人人| 日韩亚洲电影在线| 日韩一级片在线观看| 日韩一级视频免费观看在线| 欧美一区二区观看视频| 欧美一区二区国产| 精品免费视频一区二区| 久久这里只精品最新地址| 久久久久久亚洲综合影院红桃| 2019国产精品| 国产日韩精品一区二区三区在线| 久久青草欧美一区二区三区| 久久久99免费| 亚洲国产精品激情在线观看| 国产精品拍天天在线| 中文字幕日本乱码精品影院| 亚洲三级在线看| 亚洲大片精品永久免费| 日本不卡1234视频| 国产一区二区三区国产| 成人免费视频一区| 一本大道av伊人久久综合| 欧美中文字幕一区二区三区| 欧美高清dvd| 久久婷婷成人综合色| 成人欧美一区二区三区|