|
这些日子,QQ游戏外挂是风光了一阵.俄罗斯方块,连连看,对对碰这些游戏的外挂层出不穷。其实这一类外挂的原理大体都是一样的。下面我就以QQ游戏对对碰外挂作为例子阐述一下QQ外挂的制作原理。
观察QQ游戏对对碰的游戏界面及游戏规则,发现玩家是在固定的一个游戏区内寻找复合要求的方块然后点击两次鼠标消去方块从而达到得分的目的。因此,我们可以通过模拟人的观察,和鼠标点击来实现外挂自动消除方块,完成全局。
取得可消方块(模拟人观察):要判断哪个方块可以消,我们可以通过获取方块某点的颜色来判断方块的类型,然后建立方块矩阵,然后在矩阵中选择出适合消去的方块。关于取颜色,我们用到几个API函数 GetPixel、GetDC、ReleaseDC。(详细的介绍请参考MSDN或各种API相关资料)
模拟鼠标击:在此我们使用 mouse_event
来模拟鼠标的移动,点击,弹起。个人认为用postmessage是更好的,在此使用mouse_event只是为了阐述简单。
下面是VB实现代码(带详细注释):
查看代码 1 '模块中 2 '*************模块:modMain****************** 3 '作者:Cyril 4 'Email:terry6394@126.com 5 'Web: http://www.sguca.com/other 6 '书写日期:2004.10.23 7 '编辑日期:2002.10.23 8 '转载请保留此信息 9 '版权所有(a)Cyril 405 工作室 10 '******************************************** 11 Option Explicit 12 13 'API声明 14 Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long 15 Public Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long 16 Private Declare Function ScreenToClient Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long 17 Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long) 18 Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long 19 Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long 20 Private Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long 21 Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long 22 Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long 23 Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long 24 25 'API类型定义 26 Private Type POINTAPI 27 x As Long 28 y As Long 29 End Type 30 Private Type RECT 31 Left As Long 32 Top As Long 33 Right As Long 34 Bottom As Long 35 End Type 36 37 '方块类型定义 38 Public Enum BOX_TYPE 39 Ox = 0 40 Dog = 1 41 Panda = 2 42 Chicken = 3 43 Cat = 4 44 Frog = 5 45 Monkey = 6 46 End Enum 47 48 '自定义方块数据类型x,y位方块坐标,type为方块类型. 49 '在Easy对对碰1.5版中还加如了一些其他属性,例如是否带道具属性. 50 Public Type BOX 51 x As Integer 52 y As Integer 53 type As BOX_TYPE 54 End Type 55 56 'Api常量 57 58 '鼠标事件常量 59 Private Const MOUSEEVENTF_LEFTDOWN = &H2 60 Private Const MOUSEEVENTF_LEFTUP = &H4 61 Private Const MOUSEEVENTF_MOVE = &H1 62 Private Const MOUSEEVENTF_ABSOLUTE = &H8000 63 64 Public Const HWND_TOPMOST = -1 65 Public Const SWP_NOSIZE = &H1 66 Public Const SWP_NOMOVE = &H2 67 '自定义常量 68 '游戏区左上角坐标 69 Const GAME_LEFT As Integer = 176 70 Const GAME_TOP As Integer = 102 71 '每个方块的长宽 72 Const BOX_WIDTH As Integer = 48 73 Const BOX_HEIGHT As Integer = 48 74 75 '游戏窗口句柄 76 Public g_WindowHwnd As Long 77 '方块矩阵 (8*8) 78 Public boxs(7, 7) As BOX 79 80 '**********过程名:getBoxs****************** 81 '作者:Cyril 82 '书写日期:2004.10.23 83 '编辑日期:2002.10.23 84 '目的:获取当前场景 , 建立方块矩阵 85 '方法:getBoxs 86 '应用于:MainMod模块 87 '******************************************** 88 Public Function getBoxs() 89 Dim i As Integer '矩阵行 90 Dim j As Integer '矩阵列 91 Dim color1 As Long '颜色 (22,22)处 92 Dim color2 As Long '颜色 (22,17)处 93 94 For i = 0 To 7 95 For j = 0 To 7 96 With boxs(i, j) 97 .x = GAME_LEFT + 22 + BOX_WIDTH * j 98 .y = GAME_TOP + 22 + BOX_HEIGHT * i 99 '取每个方块坐标(22,22)和(22,17)位置的颜色 100 color1 = getColor(.x, .y) 101 color2 = getColor(.x, .y - 5) 102 '用两点颜色确定一个方块类型. 103 If color1 = 16777215 And color2 = 16777215 Then .type = Panda 104 If color1 = 2097151 And color2 = 1353909 Then .type = Chicken 105 If color1 = 4473924 And color2 = 14209230 Then .type = Dog 106 If color1 = 13828048 And color2 = 3862322 Then .type = Frog 107 If color1 = 8623264 And color2 = 5805536 Then .type = Monkey 108 If color1 = 10921638 And color2 = 9408399 Then .type = Cat 109 If color1 = 15398649 And color2 = 1655140 Then .type = Ox 110 End With 111 Next j 112 Next i 113 End Function 114 115 '为了方便理解,这里用了一种比较简单的算法 -- 穷举法.(这也是Easy对对碰最初版本的算法). 116 '其主要思想是列举16种消除方块的可能。一旦有匹配的情况出现,则马上执行鼠标点击动作. 117 '如果你要使你的外挂更强大,就必须采更优秀的算法. 118 119 '**********过程名:killBox****************** 120 '作者:Cyril 121 '书写日期:2004.10.23 122 '编辑日期:2002.10.23 123 '目的:消去一个方块 124 '方法:killBox 125 '说明:无 126 '返回值:无 127 '应用于:MainMod模块 128 '******************************************** 129 Public Function killBox() 130 Dim i As Integer 131 Dim j As Integer 132 getBoxs 133 134 ' : 135 ' | 情况 136 137 For i = 0 To 4 138 For j = 0 To 7 139 If boxs(i, j).type = boxs(i + 2, j).type And boxs(i, j).type = boxs(i + 3, j).type Then 140 mouseClick boxs(i, j).x, boxs(i, j).y 141 mouseClick boxs(i + 1, j).x, boxs(i + 1, j).y 142 Exit Function 143 End If 144 Next j 145 Next i 146 147 '_ 148 ' | 情况 149 150 For i = 0 To 5 151 For j = 0 To 6 152 If boxs(i, j).type = boxs(i + 2, j + 1).type And boxs(i, j).type = boxs(i + 1, j + 1).type Then 153 mouseClick boxs(i, j).x, boxs(i, j).y 154 mouseClick boxs(i, j + 1).x, boxs(i, j + 1).y 155 Exit Function 156 End If 157 Next j 158 Next i 159 160 ' _ 161 '| 情况 162 163 For i = 0 To 5 164 For j = 1 To 7 165 If boxs(i, j).type = boxs(i + 2, j - 1).type And boxs(i, j).type = boxs(i + 1, j - 1).type Then 166 mouseClick boxs(i, j).x, boxs(i, j).y 167 mouseClick boxs(i, j - 1).x, boxs(i, j - 1).y 168 Exit Function 169 End If 170 Next j 171 Next i 172 173 '| 174 ': 情况 175 For i = 3 To 7 176 For j = 0 To 7 177 If boxs(i, j).type = boxs(i - 2, j).type And boxs(i, j).type = boxs(i - 3, j).type Then 178 mouseClick boxs(i, j).x, boxs(i, j).y 179 mouseClick boxs(i - 1, j).x, boxs(i - 1, j).y 180 Exit Function 181 End If 182 Next j 183 Next i 184 185 '_ | 情况 186 For i = 2 To 7 187 For j = 0 To 6 188 If boxs(i, j).type = boxs(i - 1, j + 1).type And boxs(i, j).type = boxs(i - 2, j + 1).type Then 189 mouseClick boxs(i, j).x, boxs(i, j).y 190 mouseClick boxs(i, j + 1).x, boxs(i, j + 1).y 191 Exit Function 192 End If 193 Next j 194 Next i 195 196 '| _ 情况 197 For i = 2 To 7 198 For j = 1 To 7 199 If boxs(i, j).type = boxs(i - 1, j - 1).type And boxs(i, j).type = boxs(i - 2, j - 1).type Then 200 mouseClick boxs(i, j).x, boxs(i, j).y 201 mouseClick boxs(i, j - 1).x, boxs(i, j - 1).y 202 Exit Function 203 End If 204 Next j 205 Next i 206 207 '_-- 情况 208 For i = 1 To 7 209 For j = 0 To 5 210 211 If boxs(i, j).type = boxs(i - 1, j + 2).type And boxs(i, j).type = boxs(i - 1, j + 1).type Then 212 mouseClick boxs(i, j).x, boxs(i, j).y 213 mouseClick boxs(i - 1, j).x, boxs(i - 1, j).y 214 Exit Function 215 End If 216 Next j 217 Next i 218 219 '-_ _ 情况 220 For i = 0 To 6 221 For j = 0 To 5 222 223 If boxs(i, j).type = boxs(i + 1, j + 2).type And boxs(i, j).type = boxs(i + 1, j + 1).type Then 224 mouseClick boxs(i, j).x, boxs(i, j).y 225 mouseClick boxs(i + 1, j).x, boxs(i + 1, j).y 226 Exit Function 227 End If 228 Next j 229 Next i 230 231 ' -_- 情况 232 For i = 1 To 7 233 For j = 1 To 6 234 235 If boxs(i, j).type = boxs(i - 1, j - 1).type And boxs(i, j).type = boxs(i - 1, j + 1).type Then 236 mouseClick boxs(i, j).x, boxs(i, j).y 237 mouseClick boxs(i - 1, j).x, boxs(i - 1, j).y 238 Exit Function 239 End If 240 Next j 241 Next i 242 ' _-_ 情况 243 For i = 0 To 6 244 For j = 1 To 6 245 246 If boxs(i, j).type = boxs(i + 1, j - 1).type And boxs(i, j).type = boxs(i + 1, j + 1).type Then 247 mouseClick boxs(i, j).x, boxs(i, j).y 248 mouseClick boxs(i + 1, j).x, boxs(i + 1, j).y 249 Exit Function 250 End If 251 Next j 252 Next i 253 254 '|< 情况 255 256 For i = 1 To 6 257 For j = 1 To 7 258 259 If boxs(i, j).type = boxs(i + 1, j - 1).type And boxs(i, j).type = boxs(i - 1, j - 1).type Then 260 mouseClick boxs(i, j).x, boxs(i, j).y 261 mouseClick boxs(i, j - 1).x, boxs(i, j - 1).y 262 Exit Function 263 End If 264 Next j 265 266 Next i 267 '>| 情况 268 For i = 1 To 6 269 For j = 0 To 6 270 271 If boxs(i, j).type = boxs(i + 1, j + 1).type And boxs(i, j).type = boxs(i - 1, j + 1).type Then 272 mouseClick boxs(i, j).x, boxs(i, j).y 273 mouseClick boxs(i, j + 1).x, boxs(i, j + 1).y 274 Exit Function 275 End If 276 Next j 277 Next i 278 '--_ 情况 279 280 For i = 1 To 7 281 For j = 2 To 7 282 283 If boxs(i, j).type = boxs(i - 1, j - 2).type And boxs(i, j).type = boxs(i - 1, j - 1).type Then 284 mouseClick boxs(i, j).x, boxs(i, j).y 285 mouseClick boxs(i - 1, j).x, boxs(i - 1, j).y 286 Exit Function 287 End If 288 Next j 289 Next i 290 '-- - 情况 291 For i = 0 To 7 292 For j = 3 To 7 293 294 If boxs(i, j).type = boxs(i, j - 2).type And boxs(i, j).type = boxs(i, j - 3).type Then 295 mouseClick boxs(i, j).x, boxs(i, j).y 296 mouseClick boxs(i, j - 1).x, boxs(i, j - 1).y 297 Exit Function 298 End If 299 Next j 300 Next i 301 '_ _- 情况 302 For i = 0 To 6 303 For j = 2 To 7 304 305 If boxs(i, j).type = boxs(i + 1, j - 2).type And boxs(i, j).type = boxs(i + 1, j - 1).type Then 306 mouseClick boxs(i, j).x, boxs(i, j).y 307 mouseClick boxs(i + 1, j).x, boxs(i + 1, j).y 308 Exit Function 309 End If 310 Next j 311 Next i 312 313 '- -- 情况 314 For i = 0 To 7 315 For j = 0 To 4 316 317 If boxs(i, j).type = boxs(i, j + 2).type And boxs(i, j).type = boxs(i, j + 3).type Then 318 mouseClick boxs(i, j).x, boxs(i, j).y 319 mouseClick boxs(i, j + 1).x, boxs(i, j + 1).y 320 Exit Function 321 End If 322 Next j 323 Next i 324 325 End Function 326 327 '这里的鼠标模拟用了鼠标事件.你也可以用sendmessage来实现. 328 329 '**********过程名:mouseClick****************** 330 '作者:Cyril 331 '书写日期:2004.10.23 332 '编辑日期:2002.10.23 333 '目的:模拟鼠标单击 334 '方法:mouseClick(ByVal x As Long, ByVal y As Long) 335 '说明:x -- 方块相对游戏窗口的X; y -- 方块相对游戏窗口的Y; 336 '返回值:无 337 '应用于:MainMod模块 338 '******************************************** 339 Public Sub mouseClick(ByVal x As Long, ByVal y As Long) 340 Dim po As POINTAPI 'po点击前鼠标位置 341 Dim kX As Long '方块的绝对X坐标 342 Dim kY As Long '方块的绝对Y坐标 343 Dim winRECT As RECT '游戏窗口的RECT 344 345 '获得游戏窗口的RECT 346 GetWindowRect g_WindowHwnd, winRECT 347 '绝对坐标 = 游戏窗口左上角坐标 + 游戏中的相对坐标 348 kX = winRECT.Left + x 349 kY = winRECT.Top + y 350 '获得鼠标点击前位置 351 GetCursorPos po 352 '模拟鼠标移动 353 mouse_event MOUSEEVENTF_MOVE Or MOUSEEVENTF_ABSOLUTE, kX * 65535 / 1024, kY * 65535 / 768, 0&, 0& 354 '模拟鼠标按下弹起 355 mouse_event MOUSEEVENTF_LEFTDOWN Or MOUSEEVENTF_LEFTUP Or MOUSEEVENTF_ABSOLUTE, 0, 0, 0&, 0& 356 '点击后返回原先位置 357 SetCursorPos po.x, po.y 358 End Sub 359 360 '**********过程名:getColor****************** 361 '作者:Cyril 362 '书写日期:2004.10.23 363 '编辑日期:2002.10.23 364 '目的:取游戏中某点颜色 365 '方法:getColor(ByVal newX As Long, ByVal newY As Long) As Long 366 '说明:newX -- 要取颜色的点的X; newY -- 要取颜色的点的Y;(X,Y均相对于游戏窗口) 367 '返回值:Long 368 '应用于:MainMod模块 369 '******************************************** 370 Public Function getColor(ByVal newX As Long, ByVal newY As Long) As Long 371 Dim windowDC As Long 372 '获取游戏场景 373 windowDC = GetDC(g_WindowHwnd) 374 '取场景中 (newX,newY)坐标的颜色 375 getColor = GetPixel(windowDC, newX, newY) 376 '释放场景(不要漏掉此项) 377 ReleaseDC g_WindowHwnd, windowDC 378 End Function 379 380 381 382 '====在窗体中========在窗体中========在窗体中=== 383 Option Explicit 384 '################################################################## 385 '## 过程名称:Command5_Click 386 '## 参数: 无 387 '################################################################## 388 Private Sub Command5_Click() 389 Command6.Enabled = Not Command6.Enabled 390 Command5.Enabled = Not Command5.Enabled 391 Timer1.Enabled = True 392 End Sub 393 394 '################################################################## 395 '## 过程名称:Command6_Click 396 '## 参数: 无 397 '################################################################## 398 Private Sub Command6_Click() 399 Timer1.Enabled = False 400 Command6.Enabled = Not Command6.Enabled 401 Command5.Enabled = Not Command5.Enabled 402 End Sub 403 404 '################################################################## 405 '## 过程名称:Form_Load 406 '## 参数: 无 407 '################################################################## 408 Private Sub Form_Load() 409 g_WindowHwnd = FindWindow(vbNullString, "对对碰") 410 '窗口总在前 411 SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE 412 End Sub 413 414 '################################################################## 415 '## 过程名称:Label2_Click 416 '## 参数: 无 417 '################################################################## 418 Private Sub Label2_Click() 419 End Sub 420 421 '################################################################## 422 '## 过程名称:Timer1_Timer 423 '## 参数: 无 424 '################################################################## 425 Private Sub Timer1_Timer() 426 killBox 427 End Sub 428 429
以上代码相对简单,只实现了对对碰外挂的基本功能。其他的一些功能(如自动使用道具,自动开始)还需要读者自己去扩充。不过只要你理解了取颜色,模拟鼠标动作的话,这些已经不是难题了。:)
另:感谢CONAN的帮助,感谢卢培培的帮助。
|