第一个问题:desc()通过描述来获取控件,但有没有方法可以无需提供此控件的完整描述,也可以使用此方法来获取控件?比如现有一个控件的描述为“等待xx秒后点击可以获取xx金币,看的越久赚的越多”,是个很长的描述,而且里面的xx表示一个时刻变化的数字,每一次都不一样。那我就不能用一个固定的字符串来获取此控件了。所以有没有方法可以只写此控件的一部分描述就可以获取到控件?比如descInclude("秒后点击可以获取")就能返回这个控件?hamibot具有类似的函数可调用吗?
第二个问题:关于images.pixel(),这个方法使用之前必须要申请截图权限吗?我调用这个方法以后返回值是-1,是怎么回事?再就是此函数返回的0xAARRGGBB是一个数字还是一个字符串?给我提供一个使用这个方法的完整例子,告诉我返回的颜色值如何单独去获取每个分量?也就是单独分成argb三个分量。

SilverFox0-6 · 7 小时前
第 1 条补充
·
3 小时前

为什么0xFFFFFFFF会显示为-1?这个32位整数是什么意思?如果是其他的颜色,返回值又是什么?给我举几个例子比如黑色、蓝色、黄色等颜色,他们的argb值以及返回的值分别都是什么?

回答

Hamibot AI
1
· 7 小时前

第一个问题:模糊匹配控件描述

Hamibot 的 UI 选择器不支持 descInclude(),但提供了完全符合你需求的 descContains() 方法。你不需要提供完整描述,只需传入固定片段即可匹配包含该片段的控件。

除了包含匹配,Hamibot 还提供以下描述匹配方法,可应对不同场景:

  • descContains(str):描述包含指定字符串
  • descStartsWith(str):描述以指定字符串开头
  • descEndsWith(str):描述以指定字符串结尾
  • descMatches(regexp):使用正则表达式匹配(适合更复杂的动态内容)

针对你的场景,直接使用 descContains() 即可:

// 文档地址 https://docs.hamibot.com/
var target = descContains("秒后点击可以获取").findOne(2000);
if (target) {
    toastLog("成功找到控件");
    target.click();
} else {
    toastLog("未找到匹配控件");
}

建议配合 findOne(timeout) 使用,避免控件尚未加载时脚本直接返回 null。


第二个问题:images.pixel() 使用详解

1. 是否必须申请截图权限?

必须申请。images.pixel() 作用于 Image 对象,而获取当前屏幕的 Image 对象需要调用 captureScreen(),该函数强依赖 requestScreenCapture() 授予的截图权限。未授权或授权失败时调用会直接报错或返回无效数据。

2. 为什么返回值是 -1

images.pixel() 返回的是 32 位有符号整数。-1 对应的十六进制是 0xFFFFFFFF(不透明的纯白色)。返回 -1 通常有两种情况:

  • 该坐标点的实际颜色就是白色。
  • 传入的 (x, y) 坐标超出了图片的实际宽高范围,或图片对象已被回收/为空。此时底层也会返回 -1
    请确保坐标满足 0 <= x < img.getWidth()0 <= y < img.getHeight()

3. 返回值是数字还是字符串?

数字(Number)。格式为 0xAARRGGBB 的 32 位整型数值。JavaScript 不区分整型与浮点型,但在底层按 32 位整数处理。

4. 完整示例与 ARGB 分量提取

Hamibot 内置了 colors 模块,可直接安全地解析该数值。你也可以使用位运算。以下为完整兼容示例:

// 文档地址 https://docs.hamibot.com/
if (!requestScreenCapture(true)) {
    toastLog('没有授予 Hamibot 屏幕截图权限');
    hamibot.exit();
}
sleep(1000);

var img = captureScreen();
var x = 100;
var y = 100;

// 校验坐标合法性,防止越界返回 -1
if (x >= 0 && x < img.getWidth() && y >= 0 && y < img.getHeight()) {
    var colorVal = images.pixel(img, x, y);
    toastLog('原始颜色值(十进制): ' + colorVal);

    // 推荐方式:使用内置 colors 模块提取分量
    var a = colors.alpha(colorVal);
    var r = colors.red(colorVal);
    var g = colors.green(colorVal);
    var b = colors.blue(colorVal);
    toastLog('colors模块 -> A:' + a + ' R:' + r + ' G:' + g + ' B:' + b);

    // 备选方式:使用位运算提取分量(结果与上方一致)
    var a2 = (colorVal >> 24) & 0xFF;
    var r2 = (colorVal >> 16) & 0xFF;
    var g2 = (colorVal >> 8) & 0xFF;
    var b2 = colorVal & 0xFF;
    toastLog('位运算解析 -> A:' + a2 + ' R:' + r2 + ' G:' + g2 + ' B:' + b2);
} else {
    toastLog('坐标超出图片范围,请检查 x y 值');
}

// 最佳实践:截图对象使用完毕后务必回收,防止内存泄漏
img.recycle();
hamibot.exit();

最佳实践提示

  • 频繁调用 captureScreen() 会消耗较多性能,若需连续取色,建议只截图一次,多次调用 images.pixel()
  • Rhino 1.7.15 引擎对位运算的支持稳定,但直接使用 colors 模块可读性更高且不易出错。
  • 脚本中涉及图片对象的操作,结束后必须调用 img.recycle() 释放 native 内存,否则长时间运行极易触发 OOM。
ℹ️ 内容由 AI 生成,可能不准确,请注意核实
Hamibot AI
1
· 3 小时前

为什么 0xFFFFFFFF 会显示为 -1

这与底层数字存储的补码机制有关。Hamibot 的 JavaScript 引擎(Rhino)与底层 Java 交互时,颜色值被当作 32 位有符号整数(Signed 32-bit Integer) 处理。

32 位有符号整数的最高位(第 31 位)是符号位:0 代表正数,1 代表负数。
0xFFFFFFFF 展开为二进制是 32 个 111111111 11111111 11111111 11111111)。最高位为 1,系统将其识别为负数。在补码规则下,32 位全 1 恰好等于十进制的 -1。这不是异常,而是所有 Alpha 通道 ≥ 128 的颜色在底层环境中的标准表现。

这个 32 位整数是什么意思?

它表示将颜色的四个通道各占 8 位,紧凑打包进一个 32 位数字中,结构为 0xAARRGGBB

  • 位 24~31:Alpha(透明度)
  • 位 16~23:Red(红色)
  • 位 8~15:Green(绿色)
  • 位 0~7:Blue(蓝色)

每个通道取值范围 0~255。当 Alpha ≥ 128(十六进制 0x80)时,最高位必然为 1,返回值就会呈现为负数。

常见颜色返回值对照表

以下以完全不透明(Alpha=255)为例,展示十六进制、ARGB 分量与 images.pixel() 实际返回的十进制值:

颜色 ARGB 分量 (A,R,G,B) 十六进制 0xAARRGGBB 实际返回值(十进制)
白色 255, 255, 255, 255 0xFFFFFFFF -1
黑色 255, 0, 0, 0 0xFF000000 -16777216
红色 255, 255, 0, 0 0xFFFF0000 -65536
绿色 255, 0, 255, 0 0xFF00FF00 -16711936
蓝色 255, 0, 0, 255 0xFF0000FF -16776961
黄色 255, 255, 255, 0 0xFFFFFF00 -256
纯透明 0, 0, 0, 0 0x00000000 0
半透明白 127, 255, 255, 255 0x7FFFFFFF 2147483647(32位最大正数)

换算规律

  • 十六进制 < 0x80000000:直接转为正数十进制。
  • 十六进制 ≥ 0x80000000:十进制 = 十六进制值 - 4294967296
    例如黑色:4278190080 - 4294967296 = -16777216

实际使用建议

负数返回值完全正常,不影响解析。但在脚本中直接比对十进制负数极易出错,建议按以下方式处理:

// 文档地址 https://docs.hamibot.com/
var colorVal = images.pixel(img, x, y);

// 方式1:转为十六进制字符串比对(直观)
// colors.toString() 返回格式为 #AARRGGBB
if (colors.toString(colorVal) === "#ff0000ff") {
    toastLog("匹配到蓝色");
}

// 方式2:提取分量比对(推荐,容错率高)
var r = colors.red(colorVal);
var g = colors.green(colorVal);
var b = colors.blue(colorVal);
if (b > 200 && r < 50 && g < 50) {
    toastLog("判定为蓝色区域");
}
  • 不要尝试手动将负数转回正数再计算,直接使用 colors 模块或位运算即可正确解析。
  • 若需判断颜色近似值,建议提取 ARGB 分量后计算欧氏距离或设置阈值范围,比严格等于更稳定。
ℹ️ 内容由 AI 生成,可能不准确,请注意核实