最近想学一下Mac系统的程序编写,觉得从辅助工具开始写起比较有兴趣学下去。
在App Store的免费游戏分类里有一个《大家来找碴豪华版》的游戏,因为几年前写过《QQ美女找茬》游戏的辅助,所以就决定写一个找碴的辅助工具了。
《QQ美女找茬》左右两幅图都是未修改过的原图,然后游戏把5个修改过的小图片绘制在右边的图片上面,这样就形成了5处不同的地方。
通过判断左右两幅图相同位置的点的颜色值是否相同,就可以知道该点是不是修改过的。如果把不同的点都替换为黄色的话,可以看到有5个很规则的小方块:
但是《大家来找碴豪华版》这个游戏比较复杂,首先图片5处不同的地方都是直接ps的,所以不会形成很规则的方块。
还有右边的图片经过一定的处理,左右两幅图相同位置的点的颜色值有所偏差,所以不能通过判断两个点的颜色值是否相等来区分,而是通过计算颜色的RBG值的方差是否大于某个值来区分。
一、遍历所有打开的窗口,通过游戏窗口名获取窗口id。
//初始化 - (id)initWithWindowName:(NSString *)windowName { if (self = [super init]) { self.windowName = windowName; self.windowId = [self windowId]; } return self; } //通过窗口名字获取窗口id - (CGWindowID)windowId { //获取屏幕上所有窗口的信息 CFArrayRef windowsRef = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); NSArray *windowInfos = (__bridge NSArray *)CGWindowListCreateDescriptionFromArray(windowsRef); NSUInteger count = windowInfos.count; //遍历窗口,找到名字相同的窗口,获取窗口id for (int i = 0; i < count; i++) { NSDictionary *windowInfo = windowInfos[i]; NSString *name = [windowInfo objectForKey:(NSString *)kCGWindowName]; if ([name isEqualToString:self.windowName]) { return (CGWindowID)CFArrayGetValueAtIndex(windowsRef, i); } } return 0; }
二、截取该窗口的图像。
- (void)captrueWindow { //通过窗口id获取窗口信息 CFArrayRef windowRef = CGWindowListCreate(kCGWindowListOptionIncludingWindow, self.windowId); NSArray *windowInfos = (__bridge NSArray *)(CGWindowListCreateDescriptionFromArray(windowRef)); NSDictionary *windowInfo = windowInfos[0]; //获取窗口坐标和大小 NSDictionary *bounds = [windowInfo objectForKey:(NSString *)kCGWindowBounds]; CGRectMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)(bounds), &_imageRect); //通过和大小创建图像 CGImageRef imgRef = CGWindowListCreateImageFromArray(_imageRect, windowRef, kCGWindowImageDefault); NSImage *image = [[NSImage alloc] initWithCGImage:imgRef size:NSZeroSize]; [image lockFocus]; self.bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, image.size.width, image.size.height)]; [image unlockFocus]; }
三、求两点颜色RGB值的方差。
float avgRed = (red1 + red2) / 2; float avgGreen = (green1 + green2) / 2; float avgBlue = (blue1 + blue2) / 2; float sRed = pow(red1 - avgRed, 2); float sGreen = pow(green1 - avgGreen, 2); float sBlue = pow(blue1 - avgBlue, 2); float s2 = sRed + sGreen + sBlue; if (s2 > 200) { //如果该点不同,则替换为红色 [self.leftBitmap setColor:[NSColor redColor] atX:i y:j]; } else { //否则降低该点红色的色值 NSColor *color = [NSColor colorWithCalibratedRed:red1*0.1 green:green1 blue:blue1 alpha:1]; [self.leftBitmap setColor:color atX:i y:j]; }
如果方差大于某个值(例如200),就说明两点的颜色不相近,则把该点的颜色替换为红色。否则就把该点的R值除以10以降低红色值,这样就不会干扰到红点了。结果如下:
四、自动点击。
要实现自动点击,就要找出5个红点连起来的区域。
我的做法是把图片分割成20*20=400个方块,创建一个400个元素的数组,统计每个方块里红点的数量存到数组里,然后按从多到少排序。
排序后数组的第一个元素就是有最多红点的,然后以这个格子所在的位置开始上下左右递归。如果相邻的格子里有红点,就说明它们是连在一起的区域,把它们存到一个临时数组,并把他们从大数组里移除。
递归结束后把临时数组里的元素的x坐标和y坐标分别进行排序,然后把最小的x值和最大的x值相加再除以2可以得出区域的横坐标中点,同理得出区域的纵坐标中点。
再让鼠标移动到这个中点的坐标点击就行了。
不知道是不是录像的原因,视频里辅助的窗口显示的颜色有问题,而实际看到是没问题的。
2013/09/01 10:46:06
2013/09/01 10:48:29
这个也能用在其他的上吧~!
2013/09/01 17:50:38
应该可以