如何构建在线Flash游戏的机器人?
有很多Flash游戏会让你做重复的动作。一个例子是FarmVille或获得在线扑克游戏的统计数据。如何构建在线Flash游戏的机器人?
什么是在屏幕上看到的东西,机器人的算法和点击鼠标之间创建接口的最佳方式。
所以基本上,当我在脸书上玩得克萨斯扑克,如果我得到AA,我希望机器人点击全押。如果我没有得到AA我想折叠。这只是一个例子,而不是实际的策略。或者另一个例子是farmville中的路由任务。
所以基本上。它必须抓取屏幕的图片。识别模式并将其转换为算法的输入。输出算法会点击其他一些(可能是相同的)模式。
有什么建议吗?
我有建立一个简单的基于计算机视觉的在线纸牌游戏机器人的经验。
我使用了一个名为autopy的跨平台python库来处理自动鼠标点击和键盘输入。机器人捕获屏幕每0.5秒,然后将捕获的屏幕转换为一个numpy阵列进行分析。 Python具有良好的图像处理(PIL,OpenCV python绑定)和机器学习实用程序(scikit-learn)。对于简单的图像模式识别,bot提取图像区域上的像素亮度的平均值以作出决定。对于复杂的,正在使用OpenCV模板匹配和SVM分类器。
服务器第一次发现我的机器人,所以我想有些服务器端有机器人检测。在添加了更多的随机性和灵活的决策制定之后,机器人已经绕过了服务器端机器人检测。
所有带我一个星期六,我喜欢星期天。
在尝试解析屏幕图像并产生鼠标点击(这将非常困难)之前,首先看看浏览器和服务器之间游戏实际发送/接收的数据。像平常一样与游戏互动,并使用类似WireShark的东西来捕获数据包,看看它是否可以自动执行。
这是不可能的(因为他们明确不希望人们做你想做的事情),但它可能与服务器的通信只是简单的请求与参数。 (我知道很久以前,MySpace游戏就是这种情况,例如Dragon Wars和Mafia Wars。)
如果数据是你可以解析和理解的东西,那么你可以完全跳过Flash界面,只需写下你的拥有。
wireshark听起来不错。我会研究这一点。但我也很好奇,如果我可以通过屏幕进行交互,因为它更通用,并且可能会节省时间,试图找出发送的值。 – 2010-11-20 19:12:15
@kirill_igum:可能存在用于将数据以鼠标/键盘输入的形式发送到屏幕的库。例如,WatiN是一个体面的.NET库,用于与浏览器进行交互(HTML元素,对于Flash来说不是很多,尽管可能有其他的)。但是,从屏幕读取数据将非常困难。即使这是可能的(可行可能是一个更准确的词),我不认为它会像你期望的那样通用。 – David 2010-11-20 19:19:23
如果你知道你在找什么,我不会跟随它如何变得困难。例如:我午餐的程序需要Flash游戏或浏览器或屏幕的屏幕截图。将其转换为矩阵,其中每个元素都是表示颜色的数字。一个代码将匹配一个来自我的库的子矩阵(预先存储的模式,我正在寻找)。如果匹配,代码将输出模式的位置。所以当我想要使用它时,我只需要输入我正在寻找的模式。如果他们改变了。我将不得不手动改变他们 – 2010-11-20 19:32:30
我制作了很多使用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()));
}
这里有一个类似的帖子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
看起来像这可能也是一种方式来做到这一点http://www.mjtnet.com/blog/2006/10/11/see-the-screen-with-image-recognition/ – 2010-11-20 20:09:53