直接贴代码:
#include <Windows.h> //全局函数声明 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE hInstance, int nShowCmd); void MyPaint(HDC hdc); BOOL Game_CleanUp(HWND hwnd);//在此函数中进行资源的清理 //****对战消息新增函数********************************* void MsgInsert(char* str); //****玩家怪物生命值判断函数************************* void CheckDie(int hp, bool player); #define WINDOW_WIDTH 640 //为窗口宽度定义的宏,以方便在此处修改窗口宽度 #define WINDOW_HEIGHT 480 //为窗口高度定义的宏,以方便在此处修改窗口高度 #define WINDOW_TITLE "游戏开发的梦想" //为窗口标题定义的宏 //定义结构 struct chr { int nHp; int fHp; int lv; int w; int kind; }; //全局变量 HBITMAP bg, sheep, girl, skill, slash, magic, recover, game; HDC hdc, mdc, bufdc; HWND hWnd; DWORD tPre, tNow; int pNum, f, txtNum; bool attack, over; chr player, monster; char text[5][100]; //--------------------------------------------WinMain() 入口函数----------------------------------------------- //应用程序的入口函数 //------------------------------------------------------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { MSG msg = { 0 };//定义并初始化msg MyRegisterClass(hInstance); if (!InitInstance(hInstance, nShowCmd)) { 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 >= 40)//相差0.04秒时再进行重绘操作 MyPaint(hdc); } } return msg.wParam; } //--------------------------------------------MyRegisterClass() 函数------------------------------------------- //注册窗口 //------------------------------------------------------------------------------------------------------------- ATOM MyRegisterClass(HINSTANCE hInstance) { //创建窗口第一步:开始设计一个完整的窗口类 WNDCLASSEX wndClass;//定义一个窗口类 wndClass.cbSize = sizeof(WNDCLASSEX);//设置结构体的字节数大小 wndClass.style = CS_HREDRAW | CS_VREDRAW;//设置窗口的样式 wndClass.lpfnWndProc = (WNDPROC)WndProc;//设置指向窗口过程函数的指针 wndClass.cbClsExtra = 0;//窗口类的附加内存,取0就可以了 wndClass.cbWndExtra = 0;//窗口的附加内存,依然取0就行了 wndClass.hInstance = hInstance;//指定包含窗口过程的程序的实例句柄 wndClass.hIcon = (HICON) ::LoadImage(NULL, "icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);//加载自定义ico图标 wndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);//指定窗口类的光标句柄 wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//指定一个灰色画刷句柄 wndClass.lpszMenuName = NULL;//用一个以空终止的字符串,指定菜单资源的名字. wndClass.lpszClassName = "GameClass";//指定窗口类的名称 //wndClass.hIconsm = NULL; //创建窗口第二步:注册窗口类 return RegisterClassEx(&wndClass);//设计完窗口后,需要对窗口类进行注册,这样才能创建该类型的窗口 } //--------------------------------------------InitInstance() 函数---------------------------------------------- //加载资源 //------------------------------------------------------------------------------------------------------------- BOOL InitInstance(HINSTANCE hInstance, int nShowCmd) { HBITMAP bmp; //创建窗口第三步:正式创建窗口 //创建窗口函数 hWnd = CreateWindow("GameClass", WINDOW_TITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } //创建窗口第四步:窗口的移动,显示和更新 MoveWindow(hWnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true);//调整窗口显示时的位置及窗口的大小 ShowWindow(hWnd, nShowCmd);//设定显示窗口时的状态 UpdateWindow(hWnd);//将窗口绘制于显示设备上 hdc = GetDC(hWnd); mdc = CreateCompatibleDC(hdc); bufdc = CreateCompatibleDC(hdc); //建立空白的位图 bmp = CreateCompatibleBitmap(hdc, 640, 480); SelectObject(mdc, bmp); //加载图片 bg = (HBITMAP)LoadImage(NULL, "bg.bmp", IMAGE_BITMAP, 640, 480, LR_LOADFROMFILE); sheep = (HBITMAP)LoadImage(NULL, "sheep.bmp", IMAGE_BITMAP, 133, 220, LR_LOADFROMFILE); girl = (HBITMAP)LoadImage(NULL, "girl.bmp", IMAGE_BITMAP, 480, 148, LR_LOADFROMFILE); skill = (HBITMAP)LoadImage(NULL, "skill.bmp", IMAGE_BITMAP, 74, 60, LR_LOADFROMFILE); slash = (HBITMAP)LoadImage(NULL, "slash.bmp", IMAGE_BITMAP, 196, 162, LR_LOADFROMFILE); magic = (HBITMAP)LoadImage(NULL, "magic.bmp", IMAGE_BITMAP, 200, 100, LR_LOADFROMFILE); recover = (HBITMAP)LoadImage(NULL, "recover.bmp", IMAGE_BITMAP, 300, 150, LR_LOADFROMFILE); game = (HBITMAP)LoadImage(NULL, "over.bmp", IMAGE_BITMAP, 289, 74, LR_LOADFROMFILE); player.nHp = player.fHp = 50; // player.lv = 2; // player.w = 4; // monster.nHp = monster.fHp = 100; // monster.lv = 1; // monster.w = 1; // txtNum = 0; MyPaint(hdc); return TRUE; } //--------------------------------------------MyPaint() 函数--------------------------------------------------- //绘制图形 //------------------------------------------------------------------------------------------------------------- void MyPaint(HDC hdc) { char str[100]; int i, damage; //贴上背景图 SelectObject(bufdc, bg); BitBlt(mdc, 0, 0, 640, 480, bufdc, 0, 0, SRCCOPY); //显示对战消息 for (i = 0; i<txtNum; i++) TextOut(mdc, 0, 360 + i * 18, text[i], strlen(text[i])); //贴上怪物图 if (monster.nHp>0) { SelectObject(bufdc, sheep); BitBlt(mdc, 70, 180, 133, 110, bufdc, 0, 110, SRCAND); BitBlt(mdc, 70, 180, 133, 110, bufdc, 0, 0, SRCPAINT); wsprintf(str, "%d / %d", monster.nHp, monster.fHp); TextOut(mdc, 100, 320, str, strlen(str)); } //帖上玩家图 if (player.nHp > 0) { SelectObject(bufdc, girl); BitBlt(mdc, 500, 200, 60, 74, bufdc, pNum * 60, 74, SRCAND); BitBlt(mdc, 500, 200, 60, 74, bufdc, pNum * 60, 0, SRCPAINT); wsprintf(str, "%d / %d", player.nHp, player.fHp); TextOut(mdc, 510, 320, str, strlen(str)); } if (over) //帖上游戏结束图标 { SelectObject(bufdc, game); BitBlt(mdc, 200, 200, 289, 37, bufdc, 0, 37, SRCAND); BitBlt(mdc, 200, 200, 289, 37, bufdc, 0, 0, SRCPAINT); } else if (!attack) //贴上攻击命令图标 { SelectObject(bufdc, skill); BitBlt(mdc, 500, 350, 74, 30, bufdc, 0, 30, SRCAND); BitBlt(mdc, 500, 350, 74, 30, bufdc, 0, 0, SRCPAINT); } else { f++; //第5—10个画面时显示玩家攻击图标 if (f >= 5 && f <= 10) { SelectObject(bufdc, slash); BitBlt(mdc, 100, 160, 98, 162, bufdc, 98, 0, SRCAND); BitBlt(mdc, 100, 160, 98, 162, bufdc, 0, 0, SRCPAINT); //第10个画面时计算怪物受伤害程度并加入消息 if (f == 10) { damage = rand() % 10 + player.lv*player.w; monster.nHp -= (int)damage; wsprintf(str, "玩家攻击...玩家对怪物造成了 %d 的伤害", damage); MsgInsert(str); CheckDie(monster.nHp, false); } } srand(tPre); //第15个画面时判断怪物进行哪项动作 if (f == 15) { if (monster.nHp > 20) //生命值大于20 { if (rand() % 10 != 1) monster.kind = 0; else monster.kind = 1; } else //生命值小于20 { switch (rand() % 5) { case 0: //普通攻击 monster.kind = 0; break; case 1: //施放攻击魔法 monster.kind = 1; break; case 2: //使尽全力攻击 monster.kind = 2; break; case 3: //补血 monster.kind = 3; break; case 4: //逃跑 monster.kind = 4; break; } } } //第26-30个画面时显示玩家攻击图标 if (f >= 26 && f <= 30) { switch (monster.kind) { case 0: //普通攻击 SelectObject(bufdc, slash); BitBlt(mdc, 480, 150, 98, 162, bufdc, 98, 0, SRCAND); BitBlt(mdc, 480, 150, 98, 162, bufdc, 0, 0, SRCPAINT); //第30个画面时计算玩家受伤害程度并加入显示消息 if (f == 30) { damage = rand() % 10 + monster.lv*monster.w; player.nHp -= (int)damage; wsprintf(str, "怪物攻击...怪物对玩家造成了 %d 的伤害", damage); MsgInsert(str); CheckDie(player.nHp, true); } break; case 1: //施放攻击魔法 SelectObject(bufdc, magic); BitBlt(mdc, 480, 190, 100, 100, bufdc, 100, 0, SRCAND); BitBlt(mdc, 480, 190, 100, 100, bufdc, 0, 0, SRCPAINT); //第30个画面时计算玩家受伤害程度并加入显示消息 if (f == 30) { damage = rand() % 10 + 3 * monster.w; player.nHp -= (int)damage; wsprintf(str, "怪物魔法攻击...怪物对玩家造成了 %d 的伤害", damage); MsgInsert(str); CheckDie(player.nHp, true); } break; case 2: //使尽全力攻击 SelectObject(bufdc, slash); BitBlt(mdc, 480, 150, 98, 162, bufdc, 98, 0, SRCAND); BitBlt(mdc, 480, 150, 98, 162, bufdc, 0, 0, SRCPAINT); //第30个画面时计算玩家受伤害程度并加入显示消息 if (f == 30) { damage = rand() % 10 + monster.lv*monster.w * 5; player.nHp -= (int)damage; wsprintf(str, "怪物全力攻击...怪物对玩家造成了 %d 的伤害", damage); MsgInsert(str); CheckDie(player.nHp, true); } break; case 3: //补血 SelectObject(bufdc, recover); BitBlt(mdc, 60, 160, 150, 150, bufdc, 150, 0, SRCAND); BitBlt(mdc, 60, 160, 150, 150, bufdc, 0, 0, SRCPAINT); //第30个画面时怪物恢复生命值并加入显示消息 if (f == 30) { monster.nHp += 30; wsprintf(str, "怪物魔法补血...恢复了 30 生命值", damage); MsgInsert(str); } break; case 4: //第30个画面时判断怪物是否逃跑成功 if (f == 30) { if (rand() % 3 == 1) //逃跑成功几率为1/3 { over = true; monster.nHp = 0; wsprintf(str, "怪物逃跑...逃跑成功"); MsgInsert(str); } else { wsprintf(str, "怪物逃跑...逃跑失败"); MsgInsert(str); } } break; } } if (f == 30) //回合结束 { attack = false; f = 0; } } BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY); tPre = GetTickCount(); pNum++; if (pNum == 8) pNum = 0; } //****对战消息新增函数********************************* void MsgInsert(char* str) { if (txtNum < 5) { wsprintf(text[txtNum], str); txtNum++; } else { for (int i = 0; i < txtNum; i++) wsprintf(text[i], text[i + 1]); wsprintf(text[4], str); } } //****玩家怪物生命值判断函数************************* void CheckDie(int hp, bool player) { char str[100]; if (hp <= 0) { over = true; if (player) { wsprintf(str, "你被怪物找败了..."); MsgInsert(str); } else { wsprintf(str, "怪物歼灭..."); MsgInsert(str); } } } //--------------------------------------------Game_CleanUp() 函数---------------------------------------------- //资源清理函数,在此函数中进行退出前的资源的清理工作 //------------------------------------------------------------------------------------------------------------- BOOL Game_CleanUp() { ClipCursor(NULL); //解除鼠标限制 DeleteDC(mdc); DeleteDC(bufdc); DeleteObject(bg); DeleteObject(sheep); DeleteObject(girl); DeleteObject(skill); DeleteObject(slash); DeleteObject(magic); DeleteObject(recover); DeleteObject(game); ReleaseDC(hWnd, hdc); return TRUE; } //--------------------------------------------WndProc() 窗口消息回调函数--------------------------------------- //窗口过程函数WndProc,对窗口消息进行处理 //------------------------------------------------------------------------------------------------------------- LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; int x, y; switch (message) { case WM_PAINT://窗口重绘消息 { hdc = BeginPaint(hwnd, &ps); MyPaint(hdc); EndPaint(hwnd, &ps); } break; case WM_LBUTTONDOWN://单击鼠标左键消息 { x = LOWORD(lParam);//取得鼠标X坐标 y = HIWORD(lParam);//取得鼠标Y坐标 if (x >= 500 && x <= 574 && y >= 350 && y <= 380) attack = true; } break; case WM_KEYDOWN://若是键盘按下消息 { if (wParam == VK_ESCAPE)//如果按下的键是ESC { if (MessageBox(hwnd, "退出?", "提示", MB_YESNO | MB_ICONQUESTION) == IDYES) DestroyWindow(hwnd);//销毁窗口,并发送一条WM_DESTROY消息 } } break; case WM_CLOSE://关闭按钮 { if (MessageBox(hwnd, "是否要退出?", "提示", MB_YESNO | MB_ICONQUESTION) == IDYES) DestroyWindow(hwnd);//销毁窗口,并发送一条WM_DESTROY消息 else return(0); } break; case WM_DESTROY://窗口结束消息 { //删除资源 Game_CleanUp(); PostQuitMessage(0);//向系统表明有个线程有终止的请求,用来响应WM_DESTROY消息 } break; default://若是上述case条件都不符合,则执行该default语句 { return DefWindowProc(hwnd, message, wParam, lParam);//调用默认的窗口过程 } } return 0;//正常退出 }