2010-11-20 68 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())); 
}