65.9K
CodeProject 正在变化。 阅读更多。
Home

用 33 行代码创建一个简单的机器人创建器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2021 年 4 月 18 日

CPOL

5分钟阅读

viewsIcon

6383

downloadIcon

96

如何使用 Kotlin 仅用 33 行代码创建一个简单的机器人创建器

引言

我是一名软件工程师,对 Android 开发和编译器设计感兴趣,我喜欢玩一些角色扮演游戏,但其中一些游戏的设计就是让你尽可能多地花在游戏上,所以它们会给你一些重复而枯燥的任务,这些任务可能每天都有,例如收集一些物品等,所以我一直在寻找一个机器人创建器来自动化这些任务。

我找到了一个功能不错的机器人创建器,它有很多功能,比如控制鼠标、键盘、屏幕,通过一些辅助语句(如 if、loop 等)检查像素颜色。

但是要创建你的脚本,你需要添加一个带有 GUI 的命令列表,这意味着你可以像任何编程语言一样编写脚本,我讨厌这个主意,所以在尝试了这个程序之后,我有一个问题,我该如何设计一个像这样的,或者可能更好的呢?!

我开始搜索如何在 Java 中控制鼠标、屏幕、键盘,经过一些研究,我得到了很多答案,并发现了一个叫做 Robot 的很棒的 Java 类。

正如你在 Oracle 文档中看到的,Robot

“This class is used to generate native system input events for test automation, 
self-running demos, and other applications where control of the …”

它有很多有用的方法可以做我想要的事情,这时,我读了一些编译器设计书籍,并创建了许多玩具编程语言,并且在 JavaFX 框架方面也有丰富的经验,所以我觉得如果我将我在编译器设计、JavaFX 和 Robot 类方面的经验结合起来,创建我精彩的机器人创建器项目,那将是惊人的。

我开始创建一个脚本编程语言,包含鼠标、键盘、屏幕的关键字,然后我添加了对语句的支持,所以我添加了 ifwhilerepeat 语句,之后,我想让用户更容易地创建复杂的机器人,所以我添加了对变量、函数和内置函数支持,例如,我添加了一个名为 pixelColor 的内置函数来获取当前鼠标位置的像素值,完成这种语言后,就该轮到 JavaFX 发挥作用了,我为它创建了一个简单的编辑器,里面有一些按钮,比如运行、停止、重启等,这就是我称之为 SnapMacro 的结果。

在完成这个项目并在网络游戏中使用了它之后,我还用它为 LinkedIn 编写了一个机器人来添加好友,或者我可以用它来接受许多人的好友请求等等。

这就是 SnapMacro 背后的故事,顺便说一句,Snap 是我的脚本语言的名字,但文章并没有在此结束,目标不仅仅是讲述我的故事,而是向你展示如何用同样的概念在短短 33 行代码中创建一个简单的机器人创建器。

是的,正如你所见,它只需要 33 行代码!

我们不会创建一个脚本语言,也不会支持语句或变量,但我们将创建一个简单的机器人创建器,它支持鼠标和键盘命令。

那么,我们的小机器人创建器首先需要什么?基本上,我们将支持三种类型的命令,结果将是七个命令。

鼠标命令

mouse move x y
mouse press right | left
mouse release right | left
mouse wheel x

键盘命令

keyboard press x
keyboard release x

延迟命令

delay x

那么,让我们开始创建我们的机器人创建器,本文将使用 Kotlin 编程语言,但你也可以使用 Java,或者采用这个概念并使用你喜欢的编程语言,这无关紧要。

首先,我们将使用 Scanner 类从控制台读取用户输入,然后初始化一个 Robot 类的实例,并使用 when 来检查当前命令的类型。

fun main() {
    val scanner = Scanner(System.`in`)
    val robot = Robot()
    while (scanner.hasNext()) {
        when (scanner.next()) {
             "mouse" -> {}
             "keyboard" -> {}
             "delay" -> {}
        }
    }
}

现在,在每种类型中,我们需要支持一些命令,所以让我们从最小的开始,“delay”只有一个命令,就是 delay x,它以毫秒为单位接受一个整数时间,并使用 Robot 来进行延迟,所以代码将是这样的

"delay" -> robot.delay(scanner.nextInt())

现在让我们转向鼠标命令,它有四个命令:move、click 和 wheel。首先是“press”命令,它接受 right 或 left,我们将使用 when 来检查这一点,然后我们有“release”,它的结构与“press”完全相同,然后我们有“move”命令,它接受 x 和 y 值并将光标移动到该位置,所以我们需要为此命令扫描两个整数,之后,我们有“wheel”命令,它只需要一个正整数或负整数。

"mouse" -> when (scanner.next()) {
    "press" -> {
        when (scanner.next()) {
            "right" -> robot.mousePress(BUTTON3_DOWN_MASK)
            "left" -> robot.mousePress(BUTTON1_DOWN_MASK)
        }
    }
    "release" -> {
        when (scanner.next()) {
            "right" -> robot.mouseRelease(BUTTON3_DOWN_MASK)
            "left" -> robot.mouseRelease(BUTTON1_DOWN_MASK)
        }
    }
    "move" -> robot.mouseMove(scanner.nextInt(), scanner.nextInt())
    "wheel" -> robot.mouseWheel(scanner.nextInt())
}

现在,我们完成了鼠标命令,我们将继续处理键盘命令,它只有两个命令,“press”和“release”,它们接受字符码,但强迫用户像这样编写键码并不好,所以我们将读取一个字符并将其转换为键码,Robot 有一个很好的函数可以为我们完成这项工作,它叫做 getExtendedKeyCodeForChar,它接受 char 并返回整数键码,所以键盘命令部分将是这样的

"keyboard" -> {
    val action = scanner.next()
    val character = scanner.next()
    val key = KeyEvent.getExtendedKeyCodeForChar(character[0].toInt())
    when (action) {
        "press" -> robot.keyPress(key)
        "release" -> robot.keyRelease(key)
    }
}

现在,恭喜你,你有一个简单的机器人创建器,现在你可以像这样编写一个脚本

mouse point 500 500
mouse press left
delay 500
mouse release left
mouse wheel 100
keyboard press A
delay 500
keyboard release A
delay 500

它会正常工作的。:D

完整的代码大约是 33 行,如下所示

fun main() {
    val scanner = Scanner(System.`in`)
    val robot = Robot()
    while (scanner.hasNext()) {
        when (scanner.next()) {
            "mouse" -> when (scanner.next()) {
                "press" -> {
                    when (scanner.next()) {
                        "right" -> robot.mousePress(BUTTON3_DOWN_MASK)
                        "left" -> robot.mousePress(BUTTON1_DOWN_MASK)
                    }
                }
                "release" -> {
                    when (scanner.next()) {
                        "right" -> robot.mouseRelease(BUTTON3_DOWN_MASK)
                        "left" -> robot.mouseRelease(BUTTON1_DOWN_MASK)
                    }
                }
                "move" -> robot.mouseMove(scanner.nextInt(), scanner.nextInt())
                "wheel" -> robot.mouseWheel(scanner.nextInt())
            }
            "keyboard" -> {
                val action = scanner.next()
                val character = scanner.next()
                val key = KeyEvent.getExtendedKeyCodeForChar(character[0].toInt())
                when (action) {
                    "press" -> robot.keyPress(key)
                    "release" -> robot.keyRelease(key)
                }
            }
            "delay" -> robot.delay(scanner.nextInt())
        }
    }
}

如果你对这类项目感兴趣,你不应该止步于此,并尽可能地去改进它,如果你想将其转换为脚本语言,我推荐阅读这本书 Crafting Interpreter,它将教你如何创建编译器和解释器,你也可以存储命令并支持一些新命令,如 restart、exit 等。

感谢阅读,祝你编码愉快。😋

历史

  • 2021 年 4 月 18 日:初始版本
© . All rights reserved.