一、需求描述
- 游戏中的一些状态(如血量蓝量等)需要时刻注意
- 因为反射弧长,反应不过来,导致常常被自己菜死,从而另辟蹊径[doge]
二、可行性分析
1. 基础知识
请看第一期。
2. PixelGetColor
点击链接 标签 即可查看官方API,要是看不懂,请往下看:
PixelGetColor, OutputVar, X, Y [, Mode]
参数介绍
OutputVar
:可以理解成函数的返回值,是一个十六进制的BGR颜色变量X, Y
:你想要获取像素的坐标Mode
:Alt
:如果获取不到颜色,就可以尝试这个方法,不过缺点就是稍微慢10%Slow
:可在全屏中获取颜色,大约慢三倍RGB
:用这个mode,才会返回通用的RGB顺序的值
错误处理
- 如果遇到问题无法识别的,ErrorLevel会变为1,正常情况下是0。
备注
- 函数运行时,只会获取屏幕上显示的该点像素颜色,如果窗口堆叠,它并不会获取到下面窗口的像素颜色。
- 概括一下,就是:所见即所得。
- 如果发现识别不准确,一定要尝试
mode
为Alt
或者Slow
。
举例
PixelGetColor, color, 10, 10, RGB
msgbox % color
3. RGB转HSV
这个不是ahk提供的功能,是我觉得HSV能够更好地判断颜色状态。
RGB
前面就提到过一次RGB,可能初学者会有点懵,这里详细介绍一下:
- RGB是一个颜色标准,它可以表示一个颜色。
- 拆分一下不难发现:R(Red 红色)、G(Green 绿色)、B(Blue 蓝色)。不难发现,其本质就是:通过不同比例的红绿蓝三种基本色彩,可以调出所有颜色。
- 每个原色的范围都是0-255。且会以16进制表示。PS:如果不了解16进制的同学,可以自行搜索,这里不再赘述。
- 那么也就是说无论怎样,每个原色都可以通过两个字符表示,那么一个颜色就可以用六个字符表示。这,就是RGB。
- 通常地,我们会习惯在六个字符前加上一个
#
,如#FFFF00
。上述例子可以简写成#FF0
,不过这不是重点,了解便可。
HSV
HSV是对颜色进行另一种维度的划分方式。分析维度分别为:色调(H),饱和度(S),明度(V)。
色调H
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。
饱和度S
取值范围为0%~100%,值越大,颜色越饱和。
明度V
取值范围为0%(黑)到100%(白)。
为什么要从RGB转HSV
- 从上面的介绍中我们不难发现,HSV更符合人眼观察,如:颜色的明暗可以直观地体现在明度V上。
- 反观RGB,同一个颜色的明暗变化,在数值上是很难去寻找规律的。
- 因此,就本篇监测血(蓝)量而言,用HSV是更容易判断的,下一节我会详细带大家了解转换算法。
4. RGB转HSV算法(AHK实现)
声明:这里的算法并非我原创(害,我哪有这本事,只是站在巨人的肩上罢了)
如果只想实现功能的同学,直接复制粘贴下面的代码即可,没必要了解算法的含义;有兴趣的同学可以自行研究,欢迎探讨。
RGB2HSV(color) {
; 提取rgb,转成10进制
rgb := SubStr(color, 3, 6)
r := toBase("0x"+SubStr(rgb, 1 , 2), 10)
g := toBase("0x"+SubStr(rgb, 3 , 2), 10)
b := toBase("0x"+SubStr(rgb, 5 , 2), 10)
; 转hsv
cMax := max(r,g,b)
cMin := min(r,g,b)
dlta := cMax - cMin
; MsgBox %r%, %g%, %b%, %cMax%, %cMin%, %dlta%
if (dlta != 0 && cMax == r) {
h := (g - b) / dlta
} else if (dlta != 0 && cMax == g) {
h := (b - r) / dlta + 2
} else if (dlta != 0 && cMax == b) {
h := (r - g) / dlta + 4
}
h := h * 60
if (h < 0) {
h := h + 360
}
if (cMax != 0) {
s := dlta / cMax
}
v := cMax / 255
; MsgBox %h%, %s%, %v%
; 这里得到三个值,我只返回了对我有用的v
; 如果需要在别处使用,请自行修改
return v
}
toBase(n, b) {
return (n < b ? "" : ToBase(n//b,b)) . ((d:=Mod(n,b)) < 10 ? d : Chr(d+55))
}
max(a, b, c) {
return (a>=b && a>=c) ? a : (b>=a && b>=c) ? b : c
}
min(a, b, c) {
return (a<=b && a<=c) ? a : (b<=a && b<=c) ? b : c
}
经过测试,监测一个位置的颜色:
- 有血的时候,v会很大,即明度大;
- 无血的时候,v会很小,即明度小。
所以,我们只需判断颜色的明度大于某个值,就可以知道是否有血了。
三、落地实现
俗话说天上飞的理念,对应着落地跑的实现
话不多说,开始实操!lesson2.ahk