玩過電腦游戲的同學(xué)對于外掛肯定不陌生,但是你在用外掛的時候有沒有想過如何做一個外掛呢耕漱?:算色!
我打開了4399小游戲網(wǎng),點(diǎn)開了一個不知名的游戲螟够,唔灾梦,做壽司的,有材料在一邊妓笙,客人過來后說出他們的要求若河,你按照菜單做好端給他便好~
首先要聲明,這里的游戲外掛的概念寞宫,和那些大型網(wǎng)游里的外掛可不同萧福,不能自動打怪,不能喝藥不能躲避GM…… 那做這個外掛有啥用辈赋?問的好鲫忍,沒用,除了可以浪費(fèi)你一點(diǎn)時間炭庙,提高一下編程技術(shù)饲窿,增加一點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)的做外掛的基礎(chǔ)以外,毫無用處焕蹄,如果您是以制作一個驚天地泣鬼神不開則已一開立刻超神的外掛為目標(biāo)過來的話逾雄,恐怕要讓您失望了,請及早繞道腻脏。我的目的很簡單鸦泳,就是自動玩這款小游戲而已。
1. 工具的準(zhǔn)備
需要安裝autopy和PIL以及pywin32包永品。
autopy是一個自動化操作的python庫做鹰,可以模擬一些鼠標(biāo)、鍵盤事件鼎姐,還能對屏幕進(jìn)行訪問钾麸,本來我想用win32api來模擬輸入事件的,發(fā)現(xiàn)這個用起來比較簡單炕桨,最厲害的是它是跨平臺的饭尝,請搜索安裝。
PIL那是大名鼎鼎了献宫,Python圖像處理的No.1钥平,下面會說明用它來做什么。
pywin32其實(shí)不是必須的姊途,但是為了方便(鼠標(biāo)它在自己動著呢涉瘾,如何結(jié)束它呢)知态,還是建議安裝一下,哦對了立叛,我是在win平臺上做的负敏,外掛大概只有windows用戶需要吧?
截屏和圖像處理工具
截屏是獲取游戲圖像以供分析游戲提示囚巴,其實(shí)沒有專門的工具直接Print Screen粘貼到圖像處理工具里也可以原在。我用的是PicPick,相當(dāng)好用彤叉,而且個人用戶是免費(fèi)的。而圖像處理則是為了獲取各種信息的村怪,我們要用它得到點(diǎn)菜圖像后保存起來秽浇,供外掛分析判斷。我用的是PhotoShop… 不要告訴Adobe甚负,其實(shí)PicPick中自帶的圖像編輯器也足夠了柬焕,只要能查看圖像坐標(biāo)和剪貼圖片就好了,只不過我習(xí)慣PS了~
看這個游戲梭域,有8種菜斑举,每種菜都有固定的做法,顧客一旦坐下來病涨,頭頂上就會有一個圖片富玷,看圖片就知道他想要點(diǎn)什么菜,點(diǎn)擊左邊原料區(qū)域既穆,然后點(diǎn)擊一下……不知道叫什么赎懦,像個竹簡一樣的東西,菜就做完了幻工,然后把做好的食物拖拽到客戶面前就好了励两。
顧客頭上顯示圖片的位置是固定的,總共也只有四個位置囊颅,我們可以逐一分析当悔,而原料的位置也是固定的,每種菜的做法更是清清楚楚踢代,這樣一來我們完全可以判斷盲憎,程序可以很好的幫我們做出一份一份的佳肴并奉上,于是錢滾滾的來:)
2.移動鼠標(biāo)
這個命令會讓鼠標(biāo)迅速移動到指定屏幕坐標(biāo)奸鬓,你知道什么是屏幕坐標(biāo)的吧焙畔,左上角是(0,0),然后向右向下遞增串远,所以1024×768屏幕的右下角坐標(biāo)是……你猜對了宏多,是(1023,767)儿惫。
不過有些不幸的,如果你實(shí)際用一下這個命令伸但,然后用autopy.mouse.get_pos()獲得一下當(dāng)前坐標(biāo)肾请,發(fā)現(xiàn)它并不在(100,100)上,而是更小一些更胖,比如我的機(jī)器上是(97,99)铛铁,和分辨率有關(guān)。這個移動是用戶了和windows中mouse_event函數(shù)却妨,若不清楚api的饵逐,知道這回事就好了,就是這個坐標(biāo)不是很精確的彪标。像我一樣很好奇的倍权,可以去讀一下autopy的源碼,我發(fā)現(xiàn)他計算絕對坐標(biāo)算法有問題:
這里先做除法再做乘法捞烟,學(xué)過一點(diǎn)計算方法的就應(yīng)該知道對于整數(shù)運(yùn)算薄声,應(yīng)該先乘再除的,否則就會產(chǎn)生比較大的誤差题画,如果他寫成:
就會準(zhǔn)多了默辨,雖然理論上會慢一點(diǎn)點(diǎn),不過我也懶得改代碼重新編譯了苍息,差幾個像素缩幸,這里對我們影響不大~咱要吸取教訓(xùn)呀。
3.點(diǎn)擊鼠標(biāo)
這個比較簡單档叔,不過記得這里的操作都是非常非匙婪郏快的,有可能游戲還沒反應(yīng)過來呢衙四,你就完成了铃肯,于是失敗了…… 所以必要的時候,請sleep一小會兒传蹈。
4.鍵盤操作
我們這次沒用到鍵盤押逼,所以我就不說了。
怎么做惦界?分析顧客頭上的圖像就可以挑格,來,從獲取圖像開始吧~
打開你鐘愛的圖像編輯器沾歪,開始丈量吧~ 我們得知道圖像在屏幕的具體位置漂彤,可以用標(biāo)尺量出來,本來直接量也是可以的,但是我這里使用了畫面左上角的位置(也就是點(diǎn)1)來當(dāng)做參考位置挫望,這樣一旦畫面有變動立润,我們只需要修改一個點(diǎn)坐標(biāo)就好了,否則每一個點(diǎn)都需要重新寫一遍可不是一件快樂的事情媳板。
看最左邊的顧客頭像上面的圖像桑腮,我們需要兩個點(diǎn)才可確定這個范圍,分別是圖像的左上角和右下角蛉幸,也就是點(diǎn)2和點(diǎn)3,破讨。后面還有三個顧客的位置,只需要簡單的加上一個增量就好了奕纫,for循環(huán)就是為此而生提陶!
同樣的,我們原料的位置若锁,“竹席”的位置等等搁骑,都可以用這種方法獲得。注意獲得的都是相對游戲畫面左上角的相對位置又固。至于抓圖的方法,PIL的ImageGrab就很好用煤率,autopy也可以抓圖仰冠,為什么不用,我下面就會說到蝶糯。
5.分析圖像
我們這個外掛里相當(dāng)有難度的一個問題出現(xiàn)了洋只,如何知道我們獲得的圖像到底是哪一個菜?對人眼……甚至狗眼來說昼捍,這都是一個相當(dāng)easy的問題识虚,“一看就知道”!對的妒茬,這就是人比機(jī)器高明的地方担锤,我們做起來很簡單的事情,電腦卻傻傻分不清楚乍钻。
autopy圖像局限
如果你看過autopy的api肛循,會發(fā)現(xiàn)它有一個bitmap包,里面有find_bitmap方法银择,就是在一個大圖像里尋找樣品小圖像的多糠。聰明的你一定可以想到,我們可以截下整個游戲畫面浩考,然后準(zhǔn)備所有的菜的小圖像用這個方法一找就明白哪個菜被叫到了夹孔。
確實(shí),一開始我也有這樣做的沖動,不過立刻就放棄了……這個方法查找圖像搭伤,速度先不說只怎,它有個條件是“精確匹配”,圖像上有一個像素的RGB值差了1闷畸,它就查不出來了尝盼。
我們知道flash是矢量繪圖,它把一個點(diǎn)陣圖片顯示在屏幕上是經(jīng)過了縮放的佑菩,這里變數(shù)就很大盾沫,理論上相同的輸入相同的算法得出的結(jié)果肯定是一致的,但是因?yàn)槔L圖背景等的關(guān)系殿漠,總會有一點(diǎn)點(diǎn)的差距赴精,就是這點(diǎn)差距使得這個美妙的函數(shù)不可使用了……
好吧,不能用也是好事绞幌,否則我怎么引出我們高明的圖像分析算法呢蕾哟?
相似圖像查找原理
相信你一定用過Google的“按圖搜圖”功能,如果沒有莲蜘,你就落伍啦谭确,快去試試!當(dāng)你輸入一張圖片時票渠,它會把與這張圖相似的圖像都給你呈現(xiàn)出來逐哈,所以當(dāng)你找到一張中意的圖想做壁紙又覺得太小的時候,基本可以用這個方法找到合適的~
我們就要利用和這個相似的原理來判斷用戶的點(diǎn)餐问顷,當(dāng)然我們的算法不可能和Google那般復(fù)雜昂秃,,我直接給出實(shí)現(xiàn):
因?yàn)檫@是類的一個方法杜窄,所以有個self參數(shù)肠骆,無視它。這里的img應(yīng)該傳入一個Image對象塞耕,可以使讀入圖像文件后的結(jié)果蚀腿,也可以是截屏后的結(jié)果。而縮放的尺寸(18,13)是我根據(jù)實(shí)際情況定的荷科,因?yàn)轭櫩皖^像上的菜的圖像基本就是這個比例唯咬。事實(shí)證明這個比例還是挺重要的,因?yàn)槲覀兊牟擞悬c(diǎn)兒相似畏浆,如果比例不合適壓縮后就失真了胆胰,容易誤判(我之前就吃虧了)。
得到一個圖片的“指紋”后刻获,我們就可以與標(biāo)準(zhǔn)的圖片指紋比較蜀涨,怎么比較呢,應(yīng)該使用“漢明距離”,也就是兩個字符串對應(yīng)位置的不同字符的個數(shù)厚柳。實(shí)現(xiàn)也很簡單……
好了氧枣,我們可以用準(zhǔn)備好的標(biāo)準(zhǔn)圖像,然后預(yù)先讀取計算特征碼存儲起來别垮,然后再截圖與它們比較就好了便监,距離最小的那個就是對應(yīng)的菜,代碼如下:
這里有一個50的初始距離碳想,如果截取圖像與任何菜單相比都大于50烧董,說明什么?
說明現(xiàn)在那個位置的圖像不是菜胧奔,也就是說顧客還沒坐那位置上呢逊移,或者我們把游戲最小化了(老板來了),這樣處理很重要龙填,免得它隨意找一個最相近但又完全不搭邊的菜進(jìn)行處理胳泉。
6.自動做菜
這個問題很簡單,我們只需要把菜單的原料記錄在案岩遗,然后點(diǎn)擊相應(yīng)位置便可扇商,我把它寫成了一個類來調(diào)用:
這是本外掛中最沒技術(shù)含量的一個類了,請原諒我沒有寫注釋和doc宿礁,因?yàn)槎己芎唵吻鳎嘈拍愣谩?/p>