May 20, 2015

製作艦隊收藏(艦これ)外掛 (三) 外掛的使用者介面、快速補給




目錄



(零) 聲明

此程式僅為個人學習 Python 的實作練習,並藉由此遊戲來分析與驗證網路傳輸行為,所有程式及文章僅為程式學習目的,架設於 Bitbucket 的私人 repository 中,無任何公開、散佈或任何營利行為,
不正ツール使用は規約違反です。お辞め頂けますようお願い申し上げます。 – 艦これ開発/運営 公式ツイート
本人不鼓勵也不贊同於艦これ使用任何形式的外掛或任何不正的工具,使用此類工具違反 艦これ 的 利用規約,並可能導致帳號被永久刪除。
The program was built for Python learning purpose only. Both the source codes and the program are stored in Bitbucket’s private repository. They are not disclosed to anyone in any form. Using such programs violates kancolle’s Terms of Use and may result in a permanent account ban.

(一) 外掛本體 / Shell

0. 影片展示、說明


在 Youtube 可選擇 HD 高畫質。

1. Shell


我們希望外掛「能像 Unix 一樣透過指令操作遊戲」,於是我用 Python 寫了一個類似 Shell 的程式,負責接收使用者輸入的指令,解析指令後自動執行相對應的動作。
一個最基本的 Shell 架構如下:
def main():
    # init something
    # ...

    while True:
        _user_input = raw_input(u.append_color('電:ご命令を','green') + ">")

        if is_handled_by_predefined_func(_user_input) is True:
            continue

        check_command(_user_input)
Shell 基本流程如下:
  • 接收使用者指令。
  • 視需求對指令做預處理。(例如自動將空白指令視為某特殊指令。)
  • Parse 預處理後的使用者指令。
  • 執行指令對應之動作,或無動作。

2. 頁面與按鈕位置

在上一篇文章中,我們寫了一個 javascript 遮罩來協助抓取滑鼠點擊的座標位置,利用該工具我們可以快速建立起一個頁面與按鈕座標對應的資料結構。

我採用 Associative array 來實作,第一個 hash key 為「頁面」,第二個 hash key 為「此頁面的按鈕」,value 則為訊息指令種類座標位置所組成的 tuple。
指令種類紀錄不同類型的指令,例如有些指令會切換頁面,此時就需要修改環境變數等等。
善用 Sublime Text 的快捷鍵,配上上述 javascript,20分鐘內就能建立完遊戲所有可互動的座標。
有人可能會認為「這些座標都是絕對位置,若瀏覽器或遊戲頁面一移動,這些位置不就全部都跑掉了?」
這個憂慮是多餘的,就算頁面移動了也沒關係,遊戲畫面上的元件彼此之間「相對位置」不會變動,只要透過 sikuli (之後會說明) 抓出遊戲左上角的頂點,點擊前再自動在所有座標補上 offset 即可。

3. 模擬滑鼠、鍵盤之 Pyhton Module

我們有了 Shell 來接收使用者指令,也有了頁面與按鈕座標的資料,接下來就只差可以用 Python 來模擬滑鼠、鍵盤的 Module 了。
今年三月我寫了這篇文章:在 OSX 10.10.2 Yosemite 上安裝 PyUserInput (python 2.7.8)
其實我當初就是在寫這個艦これ外掛,我使用 PyUserInput 來控制滑鼠鍵盤,安裝方法如上,使用方法請參照 github 說明。
滑鼠點擊鍵盤輸入的方法應該很容易找到,複合按鍵滑鼠滾輪則可能要進 github 程式碼內稍微查看一下 API 的定義,再推敲該怎麼使用,整體而言也不難。

4. 撥放音效

網路上可以找到很多 讓 Python撥放聲音的套件,但我在外掛裡加入語音等只是為了好玩而已,沒有必要為了撥放聲音特別裝東西。
我選擇用最簡單的方法,使用 subprocess 去呼叫 OSX 的 afplay,但如果跟 Shell 使用同一個 Thread 的話,撥放聲音時會 block 住 Shell,因此需使用 Multithread 的方式來呼叫。
class AudioThread(threading.Thread):
    def __init__(self, audio_path):
        threading.Thread.__init__(self)
        self.audio_path = audio_path
    def run(self):
        subprocess.call(['afplay', self.audio_path])

def play_audio(audio_path):
    audio_thread = AudioThread(audio_path)
    audio_thread.start()

play_audio('kcAudio/nanodesu.mp3')
艦娘語音的音源取自 艦これv

5. 其他資源

不一定會用到但可能有幫助的提示:
  • 在 Unix/OSX terminal 顯示顏色
  • time.sleep() 短暫睡眠。
  • datetime.datetime.now() 取得時間日期。
  • .format() 協助排版。
  • _k.press_key('Alt')_k.tap_key('tab')_k.release_key('Alt') 等於模擬 alt + tab
  • 這篇文章:Python and the Mac Clipboard 或許有幫助,但程式碼要做修改。

(二) 快速補給 / 每日補給

0. 影片展示、說明


在 Youtube 可選擇 HD 高畫質。

1. 使用 Shell 下指令補給


如同上述提到的,我們已經建立了指令與點擊位置的對照表(上圖),故只需要輸入 f1, all, matome 就能透過指令補給 第一艦隊所有艦娘彈藥與燃料
其他頁面(編成、維修、工廠、戰鬥等)也可用類似的方式操作,之後就不再解釋。

2. 使用 Script 進行每日補給

接下來介紹一個比較特殊的東西,我把它稱作 Script,也就是「一連串的指令」。
剛剛提到的 Shell 指令都是一個口令一個動作,譬如 f1, all, matome 就是三個口令三個動作。
但是每次出擊回來一定要補給,因此這個三個動作幾乎一定會連著做。所以我們希望能夠「一個口令三個動作」,譬如 f1 all 就連續執行 f1, all, matome
f1 daily 則是自動執行「艦隊酒保祭り!」這個任務。
艦隊酒保祭り!各艦に延べ15回以上の補給を実施しよう!
1 人ずつ燃料と弾薬を別々に補給すれば 1 艦隊 6 隻編成で 12 回分まで一度にカウントを稼げる - -艦これ- 攻略 Wiki
我將這些「一個口令多個動作」的腳本從 Shell 抽出來,另外放在一個叫做 Scripts 的資料夾內。

之後會陸續介紹的功能,像是:
  • 快速更換使用者指定之艦娘
  • 快速更換使用者自訂之艦隊編成
  • 自動維修
  • 快速建造
  • 自動練等
..等等也都是獨立於 Shell 的 Scripts。
這些 Scripts 在程式架構上是各個獨立的 module,但都可以透過 Shell 直接呼叫執行。

(三) 延伸閱讀

VoiceTube 看影片學英文