Visual C++游戏编程基础之多背景循环动画,


一、基本思路

1.现在有三张背景图:天空和草地、山峦、房屋;

2.天空在最远处,其次是草地和山峦(因为山峦在草地上),最后是房屋;

3.背景的循环速度是天空最慢、然后是山峦、最后是草地和房屋;

4.恐龙让它原地跑动,以num记录图号,每次到末尾号,再从第0号开始;

二、背景循环贴图

1.以天空为例,设x0表示背景图从左向右滚动右边需要切割的宽度,初值为0;

2.设背景图宽度640,裁剪的右边区域的左上角坐标为:(640-x0,0),把该区域贴到mdc以(0,0)为起点的坐标区域上;

3.然后把天空图剩下的部分贴到mdc中以(x0,0)为起点的坐标上;

4.假设每次x0增加5,每次贴图就实现了背景图的移动,直到x=640时,再重新设为0;

5.需要注意,山峦和房屋除了实现循环外,还要进行透明处理;

三、代码如下


#include "stdafx.h"

HINSTANCE hInst;
HBITMAP dra,bg[3];
HDC		hdc,mdc,bufdc;
HWND	hWnd;
DWORD	tPre,tNow;
int		x0=0,x1=0,x2=0,num=0;//x0、x1、x2三张背景图由左向右移动时所要切割的宽度;num表示图号

ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
void				MyPaint(HDC hdc);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	MSG msg;

	MyRegisterClass(hInstance);

	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

    while( msg.message!=WM_QUIT )
    {
        if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
		else
		{
			tNow = GetTickCount();
			if(tNow-tPre >= 100)
				MyPaint(hdc);
		}
    }

	return msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= NULL;
	wcex.hCursor		= NULL;
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= "canvas";
	wcex.hIconSm		= NULL;

	return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HBITMAP bmp;
	hInst = hInstance;

	hWnd = CreateWindow("canvas", "绘图窗口" , WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

	if (!hWnd)
	{
		return FALSE;
	}

	MoveWindow(hWnd,10,10,640,520,true);
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	hdc = GetDC(hWnd);
	mdc = CreateCompatibleDC(hdc);
	bufdc = CreateCompatibleDC(hdc);

	bmp = CreateCompatibleBitmap(hdc,640,480);
	SelectObject(mdc,bmp);

	bg[0] = (HBITMAP)LoadImage(NULL,"bg0.bmp",IMAGE_BITMAP,640,480,LR_LOADFROMFILE);
	bg[1] = (HBITMAP)LoadImage(NULL,"bg1.bmp",IMAGE_BITMAP,640,600,LR_LOADFROMFILE);
	bg[2] = (HBITMAP)LoadImage(NULL,"bg2.bmp",IMAGE_BITMAP,640,600,LR_LOADFROMFILE);
	dra = (HBITMAP)LoadImage(NULL,"dra.bmp",IMAGE_BITMAP,760,198,LR_LOADFROMFILE);

	MyPaint(hdc);

	return TRUE;
}


void MyPaint(HDC hdc)
{
	//贴上天空背景图
	SelectObject(bufdc,bg[0]);
	BitBlt(mdc,0,0,x0,300,bufdc,640-x0,0,SRCCOPY);
	BitBlt(mdc,x0,0,640-x0,300,bufdc,0,0,SRCCOPY);

	//贴上草地图
	BitBlt(mdc,0,300,x2,180,bufdc,640-x2,300,SRCCOPY);
	BitBlt(mdc,x2,300,640-x2,180,bufdc,0,300,SRCCOPY);

    //贴上山峦并透明
	SelectObject(bufdc,bg[1]);
	BitBlt(mdc,0,0,x1,300,bufdc,640-x1,300,SRCAND);
	BitBlt(mdc,x1,0,640-x1,300,bufdc,0,300,SRCAND);
	BitBlt(mdc,0,0,x1,300,bufdc,640-x1,0,SRCPAINT);
	BitBlt(mdc,x1,0,640-x1,300,bufdc,0,0,SRCPAINT);

	//贴上房屋并透明
	SelectObject(bufdc,bg[2]);
	BitBlt(mdc,0,250,x2,300,bufdc,640-x2,300,SRCAND);
	BitBlt(mdc,x2,250,640-x2,300,bufdc,0,300,SRCAND);
	BitBlt(mdc,0,250,x2,300,bufdc,640-x2,0,SRCPAINT);
	BitBlt(mdc,x2,250,640-x2,300,bufdc,0,0,SRCPAINT);

	SelectObject(bufdc,dra);
	BitBlt(mdc,250,350,95,99,bufdc,num*95,99,SRCAND);
	BitBlt(mdc,250,350,95,99,bufdc,num*95,0,SRCPAINT);

	BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY);

	tPre = GetTickCount();

	//控制各个背景图的循环速度
	x0 += 5;		
	if(x0==640)
		x0 = 0;

	x1 += 8;		
	if(x1==640)
		x1 = 0;

	x2 += 16;		
	if(x2==640)
		x2 = 0;

	num++;			
	if(num == 8)
		num = 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_DESTROY:					
			DeleteDC(mdc);
			DeleteDC(bufdc);
			DeleteObject(bg[0]);
			DeleteObject(bg[1]);
			DeleteObject(bg[2]);
			DeleteObject(dra);
			ReleaseDC(hWnd,hdc);
			PostQuitMessage(0);
			break;
		default:							
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

四、效果

相关内容

    暂无相关文章