//windows.h文件中包含应用程序中所需的数据类型和数据结构的定义
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "menu_4.h"
#include <math.h>
//TransparentBlt需要导入以下头文件
#pragma comment(lib,"Msimg32.lib")
#include <wingdi.h>
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 isDia = false, isMoving = 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; //用于记录两次按键是否同一方向
//int di;
switch(message)
{
case WM_CHAR:
return 0;
case WM_KEYUP:
return 0;
case WM_KEYDOWN:
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;
isMoving = true;
beforeX = x, beforeY = y; //记录点击之前人物的位置
if (state == 2) state = 0; //将人物重置为静止状态先
toX = mx-bm_ch.bmWidth/2, toY = my-bm_ch.bmHeight*4/5; //将点击位置作为人物的落脚点(右下角)
//设置边界
if (toX >= 430) toX = 430;
if (toX <= 20) toX = 20;
if (toY >= 239) toY = 239;
if (toY <= 179) toY = 179;
//判断人物方向
if (mx <= x && my <= y) dir = 7;
else if (mx <= x && my >= y+bm_ch.bmHeight) dir = 6;
else if (mx >= x+bm_ch.bmWidth && my >= y+bm_ch.bmHeight) dir = 4;
else if (my <= y && mx >= x+bm_ch.bmWidth) dir = 5;
else if (my <= y) dir = 2;
else if (my >= y+bm_ch.bmHeight) dir = 3;
else if (mx <= x) dir = 0;
else if (mx >= x+bm_ch.bmWidth) dir = 1;
}
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)
{
Sleep(10);
//j代表
j+=100;
int di = 100*(abs(toX-beforeX)+abs(toY-beforeY));
di /= 3;
if (di)
x = beforeX + (toX-beforeX)*j/di, y = beforeY + (toY-beforeY)*j/di;
if (j >= di) state = 2, isMoving = false;
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); //默认时采用系统消息默认处理函数
}
}