首页 技术 正文
技术 2022年11月20日
0 收藏 433 点赞 5,023 浏览 7707 个字



本系列文章由@二货梦想家张程 所写,转载请注明出处。

作者:ZeeCoder  微博链接:http://weibo.com/zc463717263

我的邮箱:michealfloyd@126.com   欢迎大家发邮件来和我交流编程心得

you are what you read!与大家共勉!

————————————————-分割线:ZeeCoder——————————————–

这篇笔记是在【Visual C++】游戏编程学习笔记之七:键盘输入消息的基础上添加了鼠标输入消息,也算完成一个2D游戏的demo(很糙的demo)—剑侠客扔飞镖。

废话就不多说,由于利用到了鼠标输入消息,那么先来讲讲鼠标相关函数的知识。

一、获取鼠标外的消息:

函数原型:

HWND SetCapture( HWND hWnd);  //设定获取窗口外的鼠标消息BOOL ReleaseCapture( VOID );  //释放获取窗口外的鼠标消息

如果调用了SetCapture()函数,并输入要取得鼠标消息的窗口代号,那么便可以取得鼠标在窗口外的所发出的消息。与之相对应使用的是ReleaseCapture()用于释放窗口外鼠标消息的函数。

二、设定鼠标光标位置

为了防止游戏开始时鼠标出现在不该出现的位置,在程序初始化的时候通常要预先设定好鼠标光标的位置,那么我们就需要用到:

 //设定光标位置   pt.x = 300;   pt.y = 300;   ClientToScreen(hWnd , &pt);//将pt的坐标转换成屏幕坐标   SetCursorPos(pt.x , pt.y);//设定鼠标光标的初始位置

由于SetCursorPos()需要设定的是相对于屏幕左上角的屏幕坐标,所以需要先利用ClientToScreen()将需要设定的坐标值转换成屏幕坐标。

三、显示或隐藏鼠标光标

int ShowCursor(BOOL true&FALSE); //隐藏或显示鼠标光标

四、限制鼠标光标移动区域

在游戏过程中为了避免鼠标移到窗口外造成游戏bug,,往往需要限制鼠标只能在窗口内移动。

//限制光标移动区域   GetClientRect(hWnd , (LPRECT)&rect);//获取窗口的四个顶点坐标   lt.x = rect.left;//矩形窗口右上点x坐标   lt.y = rect.top;//矩形窗口右上点y坐标   rb.x = rect.right;//矩形窗口左下点x坐标   rb.y = rect.bottom;//矩形窗口左下点y坐标   ClientToScreen(hWnd , &lt);//转换成屏幕坐标   ClientToScreen(hWnd , &rb);   rect.left = lt.x;   rect.top = lt.y;   rect.right = rb.x;   rect.bottom = rb.y;   ClipCursor(&rect);//限制鼠标光标移动位置

五、关于鼠标函数的相关知识就介绍到这了,下面看整个demo是怎么实现的。

游戏说明:【↑】【↓】【←】【→】控制人物 行走

鼠标左键控制角色扔流星镖。

#include "stdafx.h"#include "MyGame.h"#define MAX_LOADSTRING 100#define SPEED 6  //定义跑动速度//自定义结构体struct Mydart{int x , y ;bool exist;};//定义全局变量HINSTANCE hInst;// current instanceTCHAR szTitle[MAX_LOADSTRING];// The title bar textTCHAR szWindowClass[MAX_LOADSTRING];// the main window class nameHDC hdc , mdc , bufdc;HWND hWnd;HBITMAP bg , Walker[8] , dart;DWORD tNow , tPre ;int dir , char_x = 0 , char_y = 0;//char_x,char_y为人物贴图坐标int num , dart_num;//人物跑动图中的编号int mouse_x , mouse_y;int dcount = 0 ;Mydart mydart[20];// Forward declarations of functions included in this code module:ATOMMyRegisterClass(HINSTANCE hInstance);BOOLInitInstance(HINSTANCE, int);LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);//定义自定义函数void MyPaint(HDC hdc);//***************************主函数**********************************int APIENTRY _tWinMain(HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPTSTR    lpCmdLine,                     int       nCmdShow){UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here.MSG msg;// Initialize global stringsLoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_MYGAME, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// Perform application initialization:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}// Main message loop:GetMessage(&msg,NULL,NULL,NULL);  //初始化msgwhile (msg.message != WM_QUIT){if ( PeekMessage( &msg , NULL ,0 ,0 ,PM_REMOVE))//PM_REMOVE消息从队列里除掉{TranslateMessage(&msg);DispatchMessage(&msg);}else{tNow = GetTickCount();//获取当前时间if (tNow - tPre >= 100)//实现游戏循环{MyPaint(hdc);//循环贴图}}}return (int) msg.wParam;}//***************************窗口类函数**********************************ATOM MyRegisterClass(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= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAME));wcex.hCursor= LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName= MAKEINTRESOURCE(IDC_MYGAME);wcex.lpszClassName= szWindowClass;wcex.hIconSm= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));return RegisterClassEx(&wcex);}//***************************初始化函数**********************************BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){   TCHAR filename[20];   POINT pt , lt , rb ;   RECT rect;   HBITMAP bmp;   memset(filename , 0 ,sizeof(TCHAR)*20);   int i ;    hInst = hInstance; // Store instance handle in our global variable   hWnd = CreateWindow(_T("MyGame"), _T("Game"), WS_OVERLAPPEDWINDOW,      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);   if (!hWnd)   {      return FALSE;   }   MoveWindow(hWnd , 10 , 10 , 1100 ,700 ,true);   ShowWindow(hWnd, nCmdShow);   UpdateWindow(hWnd);   hdc = GetDC(hWnd);   mdc = CreateCompatibleDC(hdc);   bufdc = CreateCompatibleDC(hdc);   bmp = CreateCompatibleBitmap(hdc , 1100 , 720);   SelectObject(mdc , bmp);   //载入4方向跑动和站立图   for ( i = 0 ; i <= 7 ;i++)   {   _stprintf_s(filename , TEXT("%d.bmp") , i);   Walker[i] = (HBITMAP)LoadImage(NULL , filename , IMAGE_BITMAP , 536 ,182, LR_LOADFROMFILE);   }   //载入背景图   bg = (HBITMAP)LoadImage(NULL , _T("res.bmp") , IMAGE_BITMAP ,  1100 ,720 , LR_LOADFROMFILE);   dart = (HBITMAP)LoadImage(NULL , _T("dart.bmp") , IMAGE_BITMAP , 100 , 96 , LR_LOADFROMFILE);   //初始化各变量   char_x = 300;   char_y = 300;   //设定光标位置   pt.x = 300;   pt.y = 300;   ClientToScreen(hWnd , &pt);   SetCursorPos(pt.x , pt.y);   //隐藏鼠标光标   //ShowCursor(FALSE);   //限制光标移动区域   GetClientRect(hWnd , (LPRECT)&rect);//获取窗口的四个顶点坐标   lt.x = rect.left;//矩形窗口右上点x坐标   lt.y = rect.top;//矩形窗口右上点y坐标   rb.x = rect.right;//矩形窗口左下点x坐标   rb.y = rect.bottom;//矩形窗口左下点y坐标   ClientToScreen(hWnd , &lt);//转换成屏幕坐标   ClientToScreen(hWnd , &rb);   rect.left = lt.x;   rect.top = lt.y;   rect.right = rb.x;   rect.bottom = rb.y;   ClipCursor(&rect);//限制鼠标光标移动位置   num = 0 ;   dart_num = 0 ;   //调用自定义绘图程序   MyPaint(hdc);   return TRUE;}//***************************消息响应函数**********************************//按下【↑】【↓】【←】【→】使人物跑动//按下鼠标左键使人物跑动到指定位置LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){POINT cursor;switch (message){case WM_KEYDOWN:switch (wParam){case VK_ESCAPE://按下【ESC】键退出PostQuitMessage(0);break;case VK_UP: //按下【↑】键char_y -= SPEED ;if (char_y <=0){char_y = 0;}dir = 3;break;case VK_DOWN://按下【↓】键char_y += SPEED;if (char_y >= 720){char_y = 720;}dir = 0;break;case VK_LEFT://按下【←】键char_x -= SPEED;if (char_x <= 0){char_x =0;}dir = 1;break;case VK_RIGHT://按下【→】键char_x += SPEED;if (char_x >= 1100){char_x = 1100;}dir = 2;break;}break;case WM_KEYUP:switch (wParam){case VK_UP: //弹起【↑】键dir = 7;break;case VK_DOWN://弹起【↓】键dir = 4;break;case VK_LEFT://弹起【←】键dir = 5;break;case VK_RIGHT://弹起【→】键dir = 6;break;}break;case WM_LBUTTONDOWN:int i ;for (i = 0 ; i < 20 ; i++){if (!mydart[i].exist){switch (dir){case 0:case 4://人物面朝下mydart[i].x = char_x + 33;mydart[i].y = char_y + 91;break;case 1:case 5://人物面朝左mydart[i].x = char_x ;mydart[i].y = char_y + 20;break;case 2:case 6://人物面朝右mydart[i].x = char_x + 30;mydart[i].y = char_y + 20;break;case 7:case 3://人物面朝上mydart[i].x = char_x + 33;mydart[i].y = char_y ;break;}mydart[i].exist = true;dcount++;break;}}case WM_MOUSEMOVE:mouse_x = LOWORD(lParam);if (mouse_x > 1100){mouse_x = 1100;}mouse_y = HIWORD(lParam);if (mouse_y > 720){mouse_y = 720;}break;case WM_DESTROY:DeleteDC(mdc);DeleteDC(bufdc);for ( i = 0 ; i < 8 ; i++){DeleteObject(Walker[i]);}DeleteObject(bg);ReleaseDC(hWnd , hdc);PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;}void MyPaint(HDC hdc){int i = 0;TCHAR str[20] ;memset(str , 0 ,sizeof(TCHAR)*20);//贴背景图SelectObject(bufdc , bg);BitBlt(mdc , 0 , 0 , 1100 , 720 , bufdc , 0 , 0 ,SRCCOPY);//贴人物行走或站立SelectObject(bufdc , Walker[dir]);BitBlt(mdc , char_x , char_y , 67 , 91 , bufdc , num*67 , 91 , SRCAND);BitBlt(mdc , char_x , char_y , 67 , 91 , bufdc , num*67 , 0 , SRCPAINT);//贴飞镖SelectObject(bufdc , dart);if (dcount != 0){for (i = 0 ; i < 20 ; i++){if (mydart[i].exist){BitBlt(mdc , mydart[i].x , mydart[i].y , 50 , 48 , bufdc , dart_num*50 , 48 , SRCAND);BitBlt(mdc , mydart[i].x , mydart[i].y , 50 , 48 , bufdc , dart_num*50 , 0 , SRCPAINT);switch (dir){case 0:case 4://人物面朝下mydart[i].y += 20;if (mydart[i].y > 720){dcount-- ;mydart[i].exist = false;}break;case 1:case 5://人物面朝左mydart[i].x -= 20;if (mydart[i].x < 0){dcount-- ;mydart[i].exist = false;}break;case 2:case 6://人物面朝右mydart[i].x += 20;if (mydart[i].x > 1100){dcount-- ;mydart[i].exist = false;}break;case 3:case 7://人物面朝上mydart[i].y -= 20;if (mydart[i].y < 0){dcount-- ;mydart[i].exist = false;}break;}}}}//显示鼠标坐标TextOut(mdc , 10 , 10 ,_T("鼠标坐标:"),strlen("鼠标坐标") );_stprintf_s(str , TEXT("X坐标 :%d   ") , mouse_x);TextOut(mdc , 10 , 30 , str , _tcslen(str));_stprintf_s(str , TEXT("Y坐标 :%d   ") ,mouse_y);TextOut(mdc , 10 , 50 , str , _tcslen(str));//将最后的画面显示在窗口上BitBlt(hdc , 0 ,0 , 1100 , 720 ,mdc , 0 , 0 ,SRCCOPY);//获取当前时间tPre = GetTickCount();//动作分解图的图号+1num++;if (num == 8){num = 0;}dart_num++;if (dart_num == 2){dart_num = 0;}}

六、游戏效果图

游戏编程学习笔记八就写到这了,游戏的具体效果请自行下载源码后运行。

写完代码看到效果图后,我想我是不是毁了剑侠客~~代码中还存在很多bug,做的不算完美。希望在后续的学习中能够有更好的办法修改和完善。

—end!

笔记八的配套代码已上传,欢迎下载:【visual C++】游戏编程笔记八配套代码

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,105
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,582
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,429
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,200
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,836
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,919