//windows.h文件中包含应用程序中所需的数据类型和数据结构的定义 #include#include #include #include #include "menu_4.h" #include //TransparentBlt需要导入以下头文件 #pragma comment(lib,"Msimg32.lib") #include HBITMAP hBm_Dir[24]; //人物动作 HBITMAP hBm_bg; //背景图 HBITMAP hBm_dia; //弹出对话的图片 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow) { HWND hwnd; MSG Msg; WNDCLASS wndclass; /* 关于为啥在WINMAIN里面载入位图 是因为LoadBitmap需要传入HInstance参数 当然在WinProc里载入也是可以的 就需要设一个全局的HInstance变量 所以为了方便还是在WINmain里载入 */ //载入动作图 hBm_Dir[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_L1)); hBm_Dir[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_L2)); hBm_Dir[2] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_L3)); hBm_Dir[3] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_R1)); hBm_Dir[4] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_R2)); hBm_Dir[5] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_R3)); hBm_Dir[6] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_U1)); hBm_Dir[7] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_U2)); hBm_Dir[8] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_U3)); hBm_Dir[9] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_D1)); hBm_Dir[10] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_D2)); hBm_Dir[11] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_D3)); hBm_Dir[12] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RD1)); hBm_Dir[13] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RD2)); hBm_Dir[14] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RD3)); hBm_Dir[15] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RU1)); hBm_Dir[16] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RU2)); hBm_Dir[17] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RU3)); hBm_Dir[18] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LD1)); hBm_Dir[19] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LD2)); hBm_Dir[20] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LD3)); hBm_Dir[21] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LU1)); hBm_Dir[22] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LU2)); hBm_Dir[23] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LU3)); //载入背景图 hBm_bg = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_BG)); //载入对话图 hBm_dia = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_DIA)); char lpszClassName[] = "窗口"; char lpszTitle[] = "[Vic.]模仿_上古神器2"; //窗口标题名 //窗口类的定义 wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //载入rs文件 wndclass.lpszMenuName = "menu4" ; wndclass.lpszClassName = lpszClassName; if (!RegisterClass(&wndclass)) { MessageBeep (0); return FALSE; } //创建窗口 hwnd = CreateWindow( lpszClassName, lpszTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, //窗口左上角坐标为默认值 640, //窗口宽度 510, //窗口的髙 NULL, NULL, hInstance, NULL ); ShowWindow( hwnd, nCmdShow); UpdateWindow(hwnd); while( GetMessage(&Msg, NULL, 0, 0)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } //窗口函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // hdc_old和 hBmp是用于双缓冲,如果不懂双缓冲是啥,可以看看我的博客 HDC hDC, hdc_old; HBITMAP hBmp; // 用于与hDC绑定的位图hDC与hBmp(人物,背景,对话) static HDC hdcmem_ch, hdcmem_bg, hdcmem_dia; static BITMAP bm_ch, bm_bg, bm_dia; RECT rect; PAINTSTRUCT ps; //j是用来 static int i, j = 0; static int mx, my; //记录鼠标的位置 static int toX = 0, toY = 0; //记录鼠标点击时的位置 static int beforeX, beforeY; //记录鼠标点击之前的坐标 //设置全局标记(上下左右,左上下,右上下,鼠标点击移动,对话) static bool isLeft = false, isRight = false, isUp = false, isDown = false, isOut = false; static bool isMoving = false, isDia = false; static bool isLeDown = false, isRiDown = false, isRiUp = false, isLeUp = false; /* state代表的时加载哪种类型的位图 0:抬右手 1:抬左手 2:静止 这个主要是因为我的人物动作位图每个方位都分解为3张 之后我将它们按这样的顺序命名与载入了 */ static int state = 2; /* dir代表的是方位标记 按照载入顺序进行标记 L,R,U,D, RD,RU,LD,LU */ static int dir = 0; char str[100]; static int x = 12, y = 204; //人物的初始位置坐标 static int keep; //用于切换方向位图 static int pre_dir = dir; //用于记录两次按键是否同一方向 switch(message) { case WM_KEYDOWN: //对话状态,键盘将无法使用 if (!isDia) { isMoving = false; //将用鼠标移动的标记打成false InvalidateRect(hWnd, NULL,1);//刷新 } return 0; case WM_MOUSEMOVE: //对话状态,不需要记录鼠标的位置 if (!isDia) { mx = LOWORD(lParam); my = HIWORD(lParam); InvalidateRect(hWnd, NULL,1); } return 0; case WM_LBUTTONDOWN: //对话状态,如果用鼠标左键点击则解除对话状态 if (isDia) { isDia = false; x -= 10;//将人物位置后退一点以免重复触发 } //其他状态,鼠标点击代表移动 else { j = 0; beforeX = x, beforeY = y; //记录点击之前人物的位置 if (state == 2) state = 0; //将人物重置为静止状态先 toX = mx-bm_ch.bmWidth, toY = my-bm_ch.bmHeight; //将点击位置作为人物的落脚点(右下角) //设置边界 if (toX >= 430) toX = 430; if (toX <= 20) toX = 20; if (toY >= 239) toY = 239; if (toY <= 179) toY = 179; isMoving = true;//将鼠标移动状态置真 //重置方向标记 isLeft = isRight = isUp = isDown = false; isLeDown = isRiDown = isLeUp = isRiUp = false; //判断人物方向 if (mx <= x && my <= y) isLeUp = true, dir = 7; else if (mx <= x && my >= y+bm_ch.bmHeight) isLeDown = true, dir = 6; else if (mx >= x+bm_ch.bmWidth && my >= y+bm_ch.bmHeight) isRiDown = true, dir = 4; else if (my <= y && mx >= x+bm_ch.bmWidth) isRiUp = true, dir = 5; else if (my <= y) isUp = true, dir = 2; else if (my >= y+bm_ch.bmHeight) isDown = true, dir = 3; else if (mx <= x) isLeft = true, dir = 0; else if (mx >= x+bm_ch.bmWidth) isRight = true, dir = 1; } InvalidateRect(hWnd, NULL,1); return 0; case WM_CHAR: //对话状态,键盘将无法使用 if (!isDia) { // 判断运动方位 if ((HIWORD(GetAsyncKeyState('W')) || HIWORD(GetAsyncKeyState('w'))) && (HIWORD(GetAsyncKeyState('D')) || HIWORD(GetAsyncKeyState('d')))) { //将静止状态转换为行动状态 if (state == 2) state = 0; isRiUp = true, dir = 5; } else if ((HIWORD(GetAsyncKeyState('W')) || HIWORD(GetAsyncKeyState('w'))) && (HIWORD(GetAsyncKeyState('A')) || HIWORD(GetAsyncKeyState('a')))) { if (state == 2) state = 0; isLeUp = true, dir = 7; } else if ((HIWORD(GetAsyncKeyState('s')) || HIWORD(GetAsyncKeyState('S'))) && (HIWORD(GetAsyncKeyState('D')) || HIWORD(GetAsyncKeyState('d')))) { if (state == 2) state = 0; isRiDown = true, dir = 4; } else if ((HIWORD(GetAsyncKeyState('S')) || HIWORD(GetAsyncKeyState('s'))) && (HIWORD(GetAsyncKeyState('A')) || HIWORD(GetAsyncKeyState('a')))) { if (state == 2) state = 0; isLeDown = true, dir = 6; } else if (HIWORD(GetAsyncKeyState('A')) || HIWORD(GetAsyncKeyState('a'))) { if (state == 2) state = 0; isLeft = true, dir = 0; } else if (HIWORD(GetAsyncKeyState('D')) || HIWORD(GetAsyncKeyState('d'))) { if (state == 2) state = 0; isRight = true, dir = 1; } else if(HIWORD(GetAsyncKeyState('W')) || HIWORD(GetAsyncKeyState('w'))) { if (state == 2) state = 0; isUp = true, dir = 2; } else if(HIWORD(GetAsyncKeyState('s')) || HIWORD(GetAsyncKeyState('S'))) { if (state == 2) state = 0; isDown = true, dir = 3; } } InvalidateRect(hWnd, NULL, 1); return 0; case WM_KEYUP: //方向键抬起的时候换为静止状态 if (!isDia) state = 2; InvalidateRect(hWnd, NULL, 1); return 0; case WM_ERASEBKGND: return 1; case WM_CREATE: //创建位图hDC hDC=GetDC(hWnd); hdcmem_ch=CreateCompatibleDC(hDC); hdcmem_dia=CreateCompatibleDC(hDC); hdcmem_bg=CreateCompatibleDC(hDC); ReleaseDC(hWnd, hDC); return 0; case WM_PAINT: //双缓冲绑定 hdc_old = BeginPaint(hWnd, &ps); hDC = CreateCompatibleDC(hdc_old); GetClientRect(hWnd,&rect); hBmp = CreateCompatibleBitmap(hdc_old,rect.right,rect.bottom); SelectObject(hDC,hBmp); SelectObject(hdcmem_ch, hBm_Dir[dir*3+state]); //判断是否对话状态 if (!isDia) { SelectObject(hdcmem_bg, hBm_bg); GetObject(hBm_bg, sizeof(BITMAP), &bm_bg); } else { SelectObject(hdcmem_dia, hBm_dia); GetObject(hBm_dia, sizeof(BITMAP), &bm_dia); } //绑定动作位图 GetObject(hBm_Dir[dir*3+state], sizeof(BITMAP), &bm_ch); //如果持续在一个方向上就使keep增加 //if (pre_dir == dir) keep++; //如果不在一个方向上就将keep初始话 //else pre_dir = dir, keep = 0; //如果键盘走动 if (!isMoving) { if (isLeUp) { //限制边界 if (x >= 20) x -= 3; if (y >= 179) y -= 3; if (keep >=5) { if (state == 0) state = 1; else if (state == 1) state = 0; keep = 0; } } else if (isRiUp) { if (x <= 430) x += 3; if (y >= 179) y -= 3; if (keep >= 5) { if (state == 0) state = 1; else if (state == 1) state = 0; keep = 0; } } else if (isLeDown) { if (y <= 239) y += 3; if (x >= 20) x -= 3; if (keep >= 5) { if (state == 0) state = 1; else if (state == 1) state = 0; keep = 0; } } else if (isRiDown) { if (y <= 239) y += 3; if (x <= 430) x += 3; if (keep >= 5) { if (state == 0) state = 1; else if (state == 1) state = 0; keep = 0; } } else if (isLeft) { if (x >= 20) x -= 5; if (keep >= 5) { if (state == 0) state = 1; else if (state == 1) state = 0; keep = 0; } } else if (isRight) { if (x <= 430) x += 5; if (keep >= 5) { if (state == 0) state = 1; else if (state == 1) state = 0; keep = 0; } } else if (isUp) { if (y >= 179) y -= 5; if (keep >= 5) { if (state == 0) state = 1; else if (state == 1) state = 0; keep = 0; } } else if (isDown) { if (y <= 239) y += 5; if (keep >= 5) { if (state == 0) state = 1; else if (state == 1) state = 0; keep = 0; } } //将方向置空 isLeft = isRight = isUp = isDown = false; isLeDown = isRiDown = isLeUp = isRiUp = false; } //如果鼠标点击 else { Sleep(10); //j代表 j++; int di = sqrt((toY-beforeY)*(toY-beforeY)+(toX-beforeX)*(toX-beforeX))/3; x = beforeX + (toX-beforeX)*j/di, y = beforeY + (toY-beforeY)*j/di; if (j == di) isMoving = false, state = 2; if (keep >= 10) { if (state == 0) state = 1; else if (state == 1) state = 0; keep = 0; } InvalidateRect(hWnd, NULL, 1); } //如果到了那个位置就弹出对话 if (x >= 430) isDia = true; //加载对话图片 if (isDia) BitBlt(hDC, 0, 0, bm_dia.bmWidth, bm_dia.bmHeight,hdcmem_dia,0,0,SRCCOPY); //加载背景图片 else BitBlt(hDC, 0, 0, bm_bg.bmWidth, bm_bg.bmHeight,hdcmem_bg,0,0,SRCCOPY); //加载人物图片 //sprintf(str," %d %d", x, y); //DrawText(hDC, str, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); TransparentBlt(hDC, x, y, bm_ch.bmWidth, bm_ch.bmHeight, hdcmem_ch, 0, 0, bm_ch.bmWidth, bm_ch.bmHeight, RGB(255,255,255)); BitBlt(hdc_old,0,0,rect.right,rect.bottom,hDC,0,0,SRCCOPY); DeleteObject(hBmp); DeleteDC(hDC); ReleaseDC(hWnd, hDC); //释放 EndPaint(hWnd, &ps); //结束缓制 return 0; case WM_DESTROY: //将位图释放 for (i = 0; i < 24; i++) DeleteObject(hBm_Dir[i]); DeleteObject(hBm_bg); DeleteObject(hBm_dia); PostQuitMessage(0); //调用 PostQuitMessage 发出 WM_QUIT 消息 return 0; default: return DefWindowProc(hWnd, message, wParam, lParam); //默认时采用系统消息默认处理函数 } }