程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C#簡單游戲外掛制作(以Warcraft Ⅲ為例)

C#簡單游戲外掛制作(以Warcraft Ⅲ為例)

編輯:關於C語言

網上有很多游戲外掛制作的教程,大多是講針對大型網絡游戲的,主要包含一些抓包、反匯編、C++的知識綜合。事實也如此,常見的外掛都是使用VC++寫的,從來沒有過C#或者其他.Net語言編寫的外掛。

作為微軟.Net技術的忠實粉絲,這難免是一種遺憾。不過不要緊,下面流牛木馬就教大家兩招,包教包會,免收學費。

其實作為游戲外掛來說,主要就是三個功能:模擬鍵盤操作、模擬鼠標操作、修改內存數據。修改內存數據比較難,但模擬鼠標鍵盤的操作卻很簡單。很多流行游戲的外掛,都可以只通過模擬鼠標鍵盤來實現,例如:勁舞團、QQ音速、連連看、各類網頁游戲,以及各類大型網游中的自動打怪、自動吃藥等等。

Warcraft Ⅲ,學名魔獸爭霸之冰封王座,俗稱魔獸,簡稱war3,在最近六七年風靡全球。最近兩年,war3在中國又掀起了玩DOTA的新高潮。

本文制作DOTA游戲中的顯血、改鍵外掛為例,簡單地介紹如何使用C#語言制作游戲外掛。

最終界面如下:

本示例包含兩個功能:顯血;將Q鍵改為小鍵盤的7鍵。玩war3的同學都知道,這兩個功能對於war3(尤其是DOTA)相當重要。

首先簡單介紹一下,外掛程序模擬鍵盤的原理。

外掛程序與游戲程序是兩個不同的進程。外掛程序使用Windows提供的API找到游戲程序的進程,並設置鍵盤鉤子(什麼叫做鉤子?你不知道,但百度知道。)設置完鉤子後,我們再監控游戲進程中用戶的按鍵,並根據用戶需求進行處理,完成某些模擬鍵盤動作。

了解了這個過程之後,我們就可以開始整理思路了。完成外掛一共需要以下四個步驟:

一、聲明Windows API 中的函數和常量

  1. //鍵盤Hook結構函數  
  2. [StructLayout(LayoutKind.Sequential)]  
  3. public class KeyBoardHookStruct  
  4. {  
  5. public int vkCode;  
  6. public int scanCode;  
  7. public int flags;  
  8. public int time;  
  9. public int dwExtraInfo;  
  10. }  
  11. #region DllImport  
  12. //設置鉤子  
  13. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]  
  14. public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);  
  15. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]  
  16. //抽掉鉤子  
  17. public static extern bool UnhookWindowsHookEx(int idHook);  
  18. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]  
  19. //調用下一個鉤子  
  20. public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);  
  21. //取得模塊句柄   
  22. [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]  
  23. private static extern IntPtr GetModuleHandle(string lpModuleName);  
  24. //尋找目標進程窗口 [DllImport("USER32.DLL")]  
  25. public static extern IntPtr FindWindow(string lpClassName,  
  26. string lpWindowName);  
  27. //設置進程窗口到最前 [DllImport("USER32.DLL")]  
  28. public static extern bool SetForegroundWindow(IntPtr hWnd);  
  29. //模擬鍵盤事件 [DllImport("User32.dll")]  
  30. public static extern void keybd_event(Byte bVk, Byte bScan, Int32 dwFlags, Int32 dwExtraInfo);//釋放按鍵的常量  
  31. private const int KEYEVENTF_KEYUP =2;  

本例所使用的函數比較少,它們都在系統的USER32.dll裡,包括:設置和取消鉤子、調用下一個鉤子、導入進程、模擬鍵盤等等。我們依次導入它們。 這些函數的命名規范合理,幾乎只根據函數名就能知道其功能。 如果讀者對於其中的某些函數不熟悉,請自行搜索MSDN。

二、使用Windows API設置鉤子

有了以上Windows API函數的聲明,下一步就是設置鉤子了。

寥寥兩行代碼,但包含了相當豐富的內容。

  1. //委托  
  2. public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam); public void Hook_Start()  
  3. {  
  4. // 安裝鍵盤鉤子  
  5. if (hHook == 0)  
  6. {  
  7. KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);  
  8. hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardHookProcedure, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);  
  9. }  
  10. }  

先介紹一下設置鉤子的明星函數:SetWindowsHookEx 。它的參數說明如下。

SetWindowsHookEx(

idHook: Integer; {鉤子類型}

lpfn: TFNHookProc; {函數指針}

hmod: HINST; {包含鉤子函數的模塊(EXE、DLL)句柄; 一般是 HInstance; 如果是當前線程這裡可以是 0}

dwThreadId: DWord {關聯的線程; 可用 GetCurrentThreadId 獲取當前線程; 0 表示是系統級鉤子}

): HHOOK; {返回鉤子的句柄; 0 表示失敗} 

請注意lpfn這個參數。上面的解釋是“函數指針”。在C#中,是不能直接使用指針的,更不要說函數指針了。我們可以采用C#中的委托(delegate)來實現函數指針的功能。

於是乎,在上面的代碼中,我們定義了一個處理鍵盤消息函數的委托KeyBoardHookProcedure = new HookPro(KeyBoardHookProc),並將它作為參數傳入SetWindowsHookEx 內。KeyBoardHookProc就是被委托的具體函數。

三、監控用戶操作

設置好鉤子後,我們可以在被委托的函數中寫入監控用戶操作與模擬鍵盤的代碼。

  1. public static int KeyBoardHookProc(int nCode, IntPtr wParam, IntPtr lParam)  
  2. {  
  3. //監控用戶鍵盤輸入 KeyBoardHookStruct input = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));  
  4. //截獲Home 鍵 if (input.vkCode == (int)Keys.Home)  
  5. {  
  6. //此處寫入其他操作邏輯 }  
  7. // 繼續執行下一個鉤子程序  
  8. return CallNextHookEx(hHook, nCode, wParam, lParam);  
  9. }  

四、根據用戶需要模擬鍵盤操作

顯血功能:玩war3的都知道,war3自帶的顯血快捷鍵有3個。Alt鍵是顯示所有單位生命,[ 鍵顯示友方單位生命,] 鍵顯示地方單位生命。外掛需要做的事情僅僅是模擬一直按著某個鍵不松手而已。由於Alt鍵與其他很多鍵構成組合鍵,故我們不能模擬長按Alt,否則會影響正常游戲。我們的解決方案應該是模擬長按 [ 鍵和 ] 鍵。代碼如下:

  1. //獲得魔獸程序的句柄  
  2. IntPtr wcHandle = FindWindow(null, "Warcraft III");  
  3. //如果鉤子有效  
  4. if (wcHandle != IntPtr.Zero)  
  5. {  
  6. //設置游戲窗口到最前  
  7. SetForegroundWindow(wcHandle); byte VK_NUM1 = 219; //鍵盤上 [ 鍵的代碼。按[可顯示友方單位生命值。  
  8. byte VK_NUM2 = 221; // 鍵盤上] 鍵的代碼。按]可顯示敵方單位生命值。  
  9. keybd_event(VK_NUM1, 0, 0, 0); //長按[  
  10. keybd_event(VK_NUM2, 0, 0, 0); //長按] }  

改鍵: 小鍵盤(Numpad)上的快捷鍵很不方便按,所以很多玩家喜歡把小鍵盤上的鍵改到左邊的字母鍵盤。玩DOTA的同學都知道,沒有任何英雄的技能使用"Q”這個快捷鍵(召喚師有一種球是"Q"(不是技能))。於是我們把小鍵盤上的7鍵改到Q上,也不會造成任何沖突。方法也很簡單:如果監控到用戶按"Q”鍵,則像游戲進程發送小鍵盤上的"7"鍵。代碼如下:

  1. //如果用戶按了Q鍵  
  2. if (input.vkCode == (int)Keys.Q)  
  3. {  
  4. //獲得魔獸程序的句柄  
  5. IntPtr wcHandle = FindWindow(null, "Warcraft III");  
  6. //如果鉤子有效  
  7. if (wcHandle != IntPtr.Zero)  
  8. {  
  9. //設置游戲窗口到最前  
  10. SetForegroundWindow(wcHandle);  
  11. byte VK_Q = (byte)Keys.NumPad7;  
  12. keybd_event(VK_Q, 0, 0, 0);//按下小鍵盤7  
  13. keybd_event(VK_Q, 0, KEYEVENTF_KEYUP, 0); //松開小鍵盤7  
  14. }  
  15. return 1;  

好了,到這裡就把模擬鍵盤的外掛介紹完了。模擬鼠標與之非常類似,請用戶自行揣摩。本文僅做拋磚引玉,歡迎感興趣的朋友來流牛木馬的博客進行討論。

附件:外掛成品下載(運行需要.Net 2.0以上環境)

參考文獻:《精通.Net互操作》。感謝作者黃際洲、崔曉源的贈書,我終於學以致用了一回~ :)

原文鏈接: http://www.elivn.com

【編輯推薦】

  1. C#編程刪除系統自帶游戲
  2. C#圖片處理的3種高級實用方法
  3. 淺談C#中標准Dispose模式的實現
  4. 淺談C++調用C#的DLL程序方法
【責任編輯:QiHappy TEL:(010)68476606】
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved