c语言双缓冲区的实现csdn,<Win32_19>用双缓冲技术实现真正的平滑

这里使用微信中打飞机游戏的素材,先来做一个简单的例子(飞机平滑的移动)——也是我写这个打飞机游戏的第一步

下面通过代码的方式来讲解以下上面所说的几个步骤:

(1)首先获取客户区DC——hdc

hdc = BeginPaint(hwnd, &ps);

(2)获取关于hdc的内存兼容DC——hdcBuffer、获取关于hdc的兼容内存位图cptBmp并选入hdcBuffer中

//用于缓冲的内存DC

hdcBuffer = CreateCompatibleDC(hdc);

//创建内存兼容位图cptBmp

hdc = GetDC(hwnd);

cptBmp = CreateCompatibleBitmap(hdc, sClient.cx, sClient.cy);

ReleaseDC(hwnd, hdc);

//将内存位图选入缓冲内存DC中——以便可以绘制多个位图

SelectObject(hdcBuffer, cptBmp);

(3)一次性贴多个位图 , 那么还应该获取一个关于hdc的内存DC——hdcBmp , 将位图依次选入hdcBmp中,然后将位图从hdcBmp贴到hdcBuffer中

//用于贴位图的内存DC

hdcBmp = CreateCompatibleDC(hdc);

//将背景和飞机都先贴到内存缓冲DC hdcBuffer中(这是在内存中操作的)

for(i=0; i

{

SelectObject(hdcBmp, hBmp[i]);

if(i > 0)

{

//贴飞机(透明贴法,上次讲过)

TransparentBlt(hdcBuffer, sClient.cx * (i-1) / N, y - 128,

sBmp[i].cx, sBmp[i].cy / (SMALL + i-1),

hdcBmp, 0, 0, sBmp[i].cx, sBmp[i].cy / (SMALL + i-1), RGB(255, 255, 255));

}

else

{

//贴背景

BitBlt(hdcBuffer, 0, 0, sBmp[i].cx, sBmp[i].cy,

hdcBmp, 0, 0, SRCCOPY);

}

}

(4)最后将hdcBuffer(也就是内存中)中绘制好的位图贴到原客户区hdc中

//将内存缓冲DC hdcBuffer中所绘制的位图统一贴到客户区DC中(这是在显示屏上操作的)

BitBlt(hdc, 0, 0, sClient.cx, sClient.cy,

hdcBuffer, 0, 0, SRCCOPY);

以下是窗口回调函数的源代码:(内含详尽注释):

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

// 背景、飞机位图 内存兼容位图

static HBITMAPhBmp[N], cptBmp;

// 背景、飞机位图大小 客户区大小

static SIZEsBmp[N], sClient;

static inty;//飞机的y坐标

BITMAPbmp;

HINSTANCEhInstance;

HDChdc, hdcBmp, hdcBuffer;

PAINTSTRUCTps;

inti;

switch(message)

{

case WM_CREATE:

//加载背景以及飞机的位图

hInstance = ((LPCREATESTRUCT)lParam)->hInstance;

for(i=0; i

{

hBmp[i] = LoadBitmap(hInstance, MAKEINTRESOURCE(iBmpNames[i]));

GetObject(hBmp[i], sizeof(BITMAP), &bmp);

sBmp[i].cx= bmp.bmWidth;

sBmp[i].cy= bmp.bmHeight;

}

//设置定时器

SetTimer(hwnd, TIMER, 1, NULL);

return 0;

case WM_SIZE:

sClient.cx = LOWORD(lParam);

sClient.cy = HIWORD(lParam);

//创建内存兼容位图cptBmp

hdc = GetDC(hwnd);

cptBmp = CreateCompatibleBitmap(hdc, sClient.cx, sClient.cy);

ReleaseDC(hwnd, hdc);

return 0;

case WM_PAINT:

hdc = BeginPaint(hwnd, &ps);

//用于贴位图的内存DC

hdcBmp = CreateCompatibleDC(hdc);

//用于缓冲的内存DC

hdcBuffer = CreateCompatibleDC(hdc);

//将内存位图选入缓冲内存DC中——以便可以绘制多个位图

SelectObject(hdcBuffer, cptBmp);

//将背景和飞机都先贴到内存缓冲DC hdcBuffer中(这是在内存中操作的)

for(i=0; i

{

SelectObject(hdcBmp, hBmp[i]);

if(i > 0)

{

//贴飞机(透明贴法,上次讲过)

TransparentBlt(hdcBuffer, sClient.cx * (i-1) / N, y - 128,

sBmp[i].cx, sBmp[i].cy / (SMALL + i-1),

hdcBmp, 0, 0, sBmp[i].cx, sBmp[i].cy / (SMALL + i-1), RGB(255, 255, 255));

}

else

{

//贴背景

BitBlt(hdcBuffer, 0, 0, sBmp[i].cx, sBmp[i].cy,

hdcBmp, 0, 0, SRCCOPY);

}

}

//将内存缓冲DC hdcBuffer中所绘制的位图统一贴到客户区DC中(这是在显示屏上操作的)

BitBlt(hdc, 0, 0, sClient.cx, sClient.cy,

hdcBuffer, 0, 0, SRCCOPY);

//注意回收内存资源

DeleteDC(hdcBmp);

DeleteDC(hdcBuffer);

EndPaint(hwnd, &ps);

return 0;

//用定时器改变飞机的y坐标

case WM_TIMER:

//控制y坐标,使飞机在窗口中不断的移动

y = (y + 1) % (sClient.cy + 128);

InvalidateRect(hwnd, NULL, FALSE);//重绘

return 0;

case WM_DESTROY:

//回收资源

for(i=0; i

DeleteObject(hBmp[i]);

DeleteObject(cptBmp);

//销毁定时器

KillTimer(hwnd, TIMER);

PostQuitMessage(0);

return 0;

}

return DefWindowProc(hwnd, message, wParam, lParam);

}

最后来看看实现的效果:

0818b9ca8b590ca3270a3433284dd417.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值