键盘控制小人的行动。windows
运行结果:数组
源代码:函数
#include <windows.h> #include <tchar.h> //使用swprintf_s函数所需的头文件 #pragma comment(lib, "winmm.lib") //调用PlaySound函数所需库文件t #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define WINDOW_TITLE L"【游戏程序设计】键盘交互" HINSTANCE hInst; HDC hdc, mdc, bufdc; HBITMAP hBackGround, g_hSprite[4]; //声明位图数组用来存储人物位图 DWORD g_tNow, g_tPre; //两个变量记录时间,g_tPre记录上一次绘图的时间,g_tNow记录这次准备绘图的时间 int g_iNum, g_iX, g_iY; //g_iNum用来记录图号,g_iX,g_iY分别表示贴图的横纵坐标 int g_iDirection; //人物移动方向,0,1,2,3表明人物上下左右方向的移动 HWND hwnd; int MyWindowClass(HINSTANCE); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void MyDraw(HWND); /***************************************************************************************************************** 在不一样的应用程序中,在此处添加相关的全局变量 ******************************************************************************************************************/ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPreInstace, LPSTR lpCmdLine, int nCmdShow) { MyWindowClass(hInstance); PlaySound(L"sound.wav", NULL, SND_FILENAME| SND_ASYNC| SND_LOOP); //循环播放背景音乐 if(!InitInstance(hInstance, nCmdShow)) return FALSE; MSG msg = {0}; while(msg.message != WM_QUIT) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { g_tNow = GetTickCount(); //获取系统时间 if(g_tNow - g_tPre >= 100) { MyDraw(hwnd); g_tPre = GetTickCount(); //记录这次绘图时间 } } } return 0; } int MyWindowClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"gamebase"; wcex.hIconSm = NULL; return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; hwnd = CreateWindow(L"gamebase", WINDOW_TITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL); if(!hwnd) return FALSE; MoveWindow(hwnd, 10, 10, WINDOW_WIDTH, WINDOW_HEIGHT, true); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); hdc = GetDC(hwnd); mdc = CreateCompatibleDC(hdc); bufdc = CreateCompatibleDC(hdc); //首先在内存dc中建立一张图为背景图,用以从bufdc中映射图片,此不可省略 HBITMAP bmp = CreateCompatibleBitmap(hdc, WINDOW_WIDTH, WINDOW_HEIGHT); SelectObject(mdc, bmp); //设定人物贴图初始位置和移动方向 g_iX = 150; g_iY = 350; g_iDirection = 3; g_iNum = 0; //加载各类跑动图及背景图,这里以0,1,2,3来表明人物的上下左右移动 wchar_t filename[20]; for(int i = 0; i != 4; ++i) { swprintf_s(filename, L"go%d.bmp", i); g_hSprite[i] = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 480, 216, LR_LOADFROMFILE); } hBackGround = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, WINDOW_WIDTH, WINDOW_HEIGHT, LR_LOADFROMFILE); return TRUE; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; switch(message) { case WM_KEYDOWN: //按下键盘消息 switch(wParam) //判断按键的虚拟键码 { case VK_ESCAPE: //按下【Esc】键 DestroyWindow(hwnd); break; case VK_UP: //按下【上】键 g_iY -= 10; if(g_iY < 0) g_iY = 0; g_iDirection = 0; break; case VK_DOWN: //按下【下】键 g_iY += 10; if(g_iY > WINDOW_HEIGHT - 140) g_iY = WINDOW_HEIGHT - 140; g_iDirection = 1; break; case VK_LEFT: //按下【左】键 g_iX -= 10; if(g_iX < 0) g_iX = 0; g_iDirection = 2; break; case VK_RIGHT: //按下【右】键 g_iX += 10; if(g_iX > WINDOW_WIDTH - 75) g_iX = WINDOW_WIDTH - 75; g_iDirection = 3; break; } break; /************************************************************************************************************** 在退出程序前,每每在此处删除建立的相关资源 ***************************************************************************************************************/ case WM_DESTROY: for(int i = 0; i != 4; ++i) DeleteObject(g_hSprite[i]); DeleteObject(hBackGround); DeleteDC(mdc); DeleteDC(bufdc); ReleaseDC(hwnd, hdc); PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; } /*************************************************************************************************************** 在函数MyDraw()中进行相关绘制工做 ****************************************************************************************************************/ void MyDraw(HWND hwnd) { //先在mdc中贴上背景图 //不可直接映射到mdc上,由于以前的位图无法被覆盖 SelectObject(bufdc, hBackGround); BitBlt(mdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, bufdc, 0, 0, SRCCOPY); //按照目前的移动方向取出对应人物的连续走动图,并肯定截取人物图的宽度与高度 SelectObject(bufdc, g_hSprite[g_iDirection]); BitBlt(mdc, g_iX, g_iY, 60, 108, bufdc, g_iNum*60, 108, SRCAND); BitBlt(mdc, g_iX, g_iY, 60, 108, bufdc, g_iNum*60, 0, SRCPAINT); //将最后的画面显示在窗口中 BitBlt(hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, mdc, 0, 0, SRCCOPY); ++g_iNum; //下一张位图 if(g_iNum == 8) g_iNum = 0; }