2010-11-20 85 views
7

有很多Flash遊戲會讓你做重複的動作。一個例子是FarmVille或獲得在線撲克遊戲的統計數據。如何構建在線Flash遊戲的機器人?

什麼是在屏幕上看到的東西,機器人的算法和點擊鼠標之間創建接口的最佳方式。

所以基本上,當我在臉書上玩得克薩斯撲克,如果我得到AA,我希望機器人點擊全押。如果我沒有得到AA我想摺疊。這只是一個例子,而不是實際的策略。或者另一個例子是farmville中的路由任務。

所以基本上。它必須抓取屏幕的圖片。識別模式並將其轉換爲算法的輸入。輸出算法會點擊其他一些(可能是相同的)模式。

有什麼建議嗎?

+0

這裏有一個類似的帖子http://stackoverflow.com/questions/1964529/online-trading-bot其中有一個建立一個撲克機器人鏈接http://www.codingthewheel.com/archives/how-i-built-a-working-poker-bot。顯然我想做類似的smtn,但我很好奇這些天有沒有更好的工具。儘管查看發送和接收的數據更容易,但查看屏幕並使計算機移動鼠標更爲普遍。 – 2010-11-20 19:07:50

+0

看起來像這可能也是一種方式來做到這一點http://www.mjtnet.com/blog/2006/10/11/see-the-screen-with-image-recognition/ – 2010-11-20 20:09:53

回答

3

我有建立一個簡單的基於計算機視覺的在線紙牌遊戲機器人的經驗。

我使用了一個名爲autopy的跨平臺python庫來處理自動鼠標點擊和鍵盤輸入。機器人捕獲屏幕每0.5秒,然後將捕獲的屏幕轉換爲一個numpy陣列進行分析。 Python具有良好的圖像處理(PIL,OpenCV python綁定)和機器學習實用程序(scikit-learn)。對於簡單的圖像模式識別,bot提取圖像區域上的像素亮度的平均值以作出決定。對於複雜的,正在使用OpenCV模板匹配和SVM分類器。

服務器第一次發現我的機器人,所以我想有些服務器端有機器人檢測。在添加了更多的隨機性和靈活的決策制定之後,機器人已經繞過了服務器端機器人檢測。

所有帶我一個星期六,我喜歡星期天。

4

在嘗試解析屏幕圖像併產生鼠標點擊(這將非常困難)之前,首先看看瀏覽器和服務器之間遊戲實際發送/接收的數據。像平常一樣與遊戲互動,並使用類似WireShark的東西來捕獲數據包,看看它是否可以自動執行。

這是不可能的(因爲他們明確希望人們做你想做的事情),但它可能與服務器的通信只是簡單的請求與參數。 (我知道很久以前,MySpace遊戲就是這種情況,例如Dragon Wars和Mafia Wars。)

如果數據是你可以解析和理解的東西,那麼你可以完全跳過Flash界面,只需寫下你的擁有。

+0

wireshark聽起來不錯。我會研究這一點。但我也很好奇,如果我可以通過屏幕進行交互,因爲它更通用,並且可能會節省時間,試圖找出發送的值。 – 2010-11-20 19:12:15

+1

@kirill_igum:可能存在用於將數據以鼠標/鍵盤輸入的形式發送到屏幕的庫。例如,WatiN是一個體面的.NET庫,用於與瀏覽器進行交互(HTML元素,對於Flash來說不是很多,儘管可能有其他的)。但是,從屏幕讀取數據將非常困難。即使這是可能的(可行可能是一個更準確的詞),我不認爲它會像你期望的那樣通用。 – David 2010-11-20 19:19:23

+0

如果你知道你在找什麼,我不會跟隨它如何變得困難。例如:我午餐的程序需要Flash遊戲或瀏覽器或屏幕的屏幕截圖。將其轉換爲矩陣,其中每個元素都是表示顏色的數字。一個代碼將匹配一個來自我的庫的子矩陣(預先存儲的模式,我正在尋找)。如果匹配,代碼將輸出模式的位置。所以當我想要使用它時,我只需要輸入我正在尋找的模式。如果他們改變了。我將不得不手動改變他們 – 2010-11-20 19:32:30

1

我製作了很多使用c#和一個簡單的webBrowser控件的機器人。 但是,通常我會嘗試自動化元素上的「單擊」功能,而不使用實際模擬遊標並調用點擊。

例子:

webBrowser1.Document.GetElementById("elementid").InvokeMember("Click"); 

我覺得這更容易比實際模擬光標,但是模擬光標也可以實現相對容易,這裏的代碼,我通常使用:

//Example of how to use it: 
    Point controlLoc = this.PointToScreen(webbrowser1.Location); 
    controlLoc.X = controlLoc.X + webbrowser1.Document.GetElementById("elementid").OffsetRectangle.Left; 
    controlLoc.Y = controlLoc.Y + webbrowser1.Document.GetElementById("elementid").OffsetRectangle.Top; 
    Cursor.Position = controlLoc; 
    MouseSimulator.ClickLeftMouseButton(); 

public class MouseSimulator 
{ 
[DllImport("user32.dll", SetLastError = true)] 
static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); 

[StructLayout(LayoutKind.Sequential)] 
struct INPUT 
{ 
    public SendInputEventType type; 
    public MouseKeybdhardwareInputUnion mkhi; 
} 
[StructLayout(LayoutKind.Explicit)] 
struct MouseKeybdhardwareInputUnion 
{ 
    [FieldOffset(0)] 
    public MouseInputData mi; 

    [FieldOffset(0)] 
    public KEYBDINPUT ki; 

    [FieldOffset(0)] 
    public HARDWAREINPUT hi; 
} 
[StructLayout(LayoutKind.Sequential)] 
struct KEYBDINPUT 
{ 
    public ushort wVk; 
    public ushort wScan; 
    public uint dwFlags; 
    public uint time; 
    public IntPtr dwExtraInfo; 
} 
[StructLayout(LayoutKind.Sequential)] 
struct HARDWAREINPUT 
{ 
    public int uMsg; 
    public short wParamL; 
    public short wParamH; 
} 
struct MouseInputData 
{ 
    public int dx; 
    public int dy; 
    public uint mouseData; 
    public MouseEventFlags dwFlags; 
    public uint time; 
    public IntPtr dwExtraInfo; 
} 
[Flags] 
enum MouseEventFlags : uint 
{ 
    MOUSEEVENTF_MOVE = 0x0001, 
    MOUSEEVENTF_LEFTDOWN = 0x0002, 
    MOUSEEVENTF_LEFTUP = 0x0004, 
    MOUSEEVENTF_RIGHTDOWN = 0x0008, 
    MOUSEEVENTF_RIGHTUP = 0x0010, 
    MOUSEEVENTF_MIDDLEDOWN = 0x0020, 
    MOUSEEVENTF_MIDDLEUP = 0x0040, 
    MOUSEEVENTF_XDOWN = 0x0080, 
    MOUSEEVENTF_XUP = 0x0100, 
    MOUSEEVENTF_WHEEL = 0x0800, 
    MOUSEEVENTF_VIRTUALDESK = 0x4000, 
    MOUSEEVENTF_ABSOLUTE = 0x8000 
} 
enum SendInputEventType : int 
{ 
    InputMouse, 
    InputKeyboard, 
    InputHardware 
} 

public static void ClickLeftMouseButton() 
{ 

    INPUT mouseDownInput = new INPUT(); 
    mouseDownInput.type = SendInputEventType.InputMouse; 
    mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN; 
    SendInput(1, ref mouseDownInput, Marshal.SizeOf(new INPUT())); 

    INPUT mouseUpInput = new INPUT(); 
    mouseUpInput.type = SendInputEventType.InputMouse; 
    mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP; 
    SendInput(1, ref mouseUpInput, Marshal.SizeOf(new INPUT())); 
} 

這將左鍵單擊加載的webBrowser控件中名爲「elementid」的任何元素。請注意,可以很容易地實現其他MouseEventFlags:

下面是右鍵單擊一個例子:

public static void ClickRightMouseButton() 
{ 
    INPUT mouseDownInput = new INPUT(); 
    mouseDownInput.type = SendInputEventType.InputMouse; 
    mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTDOWN; 
    SendInput(1, ref mouseDownInput, Marshal.SizeOf(new INPUT())); 

    INPUT mouseUpInput = new INPUT(); 
    mouseUpInput.type = SendInputEventType.InputMouse; 
    mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTUP; 
    SendInput(1, ref mouseUpInput, Marshal.SizeOf(new INPUT())); 
}