燕良 2002年1月
http://www.diamondgarden.net/
前言 2
GDI基础 3
绘制一个位图(BITMAP)对象 3
常用像素格式 4
WINDOWS下的基本动画系统 4
动画驱动方式 4
播放动画 5
消除闪烁 6
透明色(COLOR KEY)处理 7
ALPHA混合 9
读取JPEG,GIF文件 10
子窗口管理 12
进阶技巧--使用DIB 14
像素操作 14
RLE压缩 15
参考 15
华山论键 15
其它类库 16
前言
说到实现游戏品质的动画,很多人会立刻想到DirectX,没错DirectDraw很强大,但是并不是必须用DirectDraw才行。动画后面的理论和技巧都是一样的,这和末端使用什么API没有太大关系(如果那API不是太~~慢的话)。就笔者实现的NewImage Lib的测试结果,内部所有像素数据的存储和运算都纯软件实现,最后一步输出到屏幕使用GDI的性能比DirectDraw低不到10%,在Window9X系统上要低20%左右,这对很多软件来说是绝对可以接受的。
现在应用程序界面越做越华丽,除了支持SKIN外,很多人都想在
程序中加入一些例如sprite动画这种原本用在游戏上的技术,因为这原因引入DirectX API,显然是不值得的(况且DX版本升级频繁,DX8中已经用DirectGraphic取代了DirectDraw)。本文将以笔者使用标准GDI函数实现的商业游戏为例,带你进入高品质2D动画编程领域,并且保证其设备无关性。
本文假设读者有C/C++语言知识,Windows编程基础,GDI基本概念。下面我将主要讲述我在过去工作中积累的经验和一些技巧,但是将不讲解以上基本概念。读者最好有MFC基础,本文给出的代码将主要使用MFC,但是其中的道理却不限于MFC。
GDI基础
绘制一个位图(Bitmap)对象
GDI的所有操作都是在DC(device context)上进行的,所以首先你应该有DC的概念,如果你对DC还不了解,现在就去翻一翻Windows编程的书吧。
首先我们要Load一个Bitmap对象,使用Win32 API可以写成这样:
file://从资源Load一个位图,如果从文件load的话,可以使用::LoadImage()
HBITMAP hbmp=::LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_MYBMP));
如果使用MFC可以这样写:
CBitmap bmp;
Bmp.LoadBitmap(IDB_MYBMP);
想把这个位图对象绘制到窗口上就要先得到窗口的DC,然后对这个DC操作。请留意创建MemoryDC的代码,后面会用到。
Win32 API的版本:
file://假设位图大小为100*100像素
file://假设hwnd是要绘制的窗口的HANDLE
HDC hwnddc=::GetDC(hwnd);
HDC memdc=::CreateCompatibleDC(hwnddc);
HBITMAP oldbmp=::SelectObject(memdc,hbmp);
::BitBlt(hwnddc,0,0,100,100,memdc,0,0,SRCCOPY);
if(oldbmp)
::SelectObject(memdc,oldbmp);
DeleteDC(memdc);
::ReleaseDC(hwnd,hwnddc);
MFC版本:
file://假设是在一个CWnd派生类的成员函数中
CClientDC dc(this);
CDC memdc;
memdc.CreateCompatibleDC(&dc);
CBitmap *oldbmp=memdc.SelectObject(&bmp);
dc.BitBlt(0,0,100,100,&memdc,0,0,SRCCOPY);
if(oldbmp)
memdc.SelectObject(oldbmp);
也可以这样:
CClientDC dc(this);
dc.DrawState(CPoint(0,0),CSize(100,100),&bmp,DST_BITMAP);
基本的代码就是这样,当然有更多的API可以用,这就要看你