按键精灵 安卓脚本开发:游戏实战之自动切换账号辅助工具
给大家带来的是一个H5小游戏的自动换号
这也是常见的游戏自动化功能
可以看到这是游戏登录了的一个状态,就先从怎么退出游戏再到怎么去登录游戏吧
这个游戏的个人中心是一个悬浮框,单纯的想去找图找色可能是比较麻烦的,因为它这个是不固定位置的,而且容易被背景干扰到
像这种悬浮框多数是由元素界面组成的,可以通过抓取这个元素去定位它,这样不管它在哪个位置,都能精准的点击到它
话不多说,直接开干,先打开按键助手的抓抓工具,把这个游戏界面的元素抓取一下看看
经过抓取可以确认到这个悬浮球的元素,然后需要用到一个专门针对元素使用的插件去帮助更好更快的编写代码
这个元素插件叫 "ElementEx.luae" 是采用Lua编写的一个加密插件
下面用导入插件命令来引用这个插件
Import "ElementEx.luae"
找到这个插件的查找元素功能 "ElementEx.Find(匹配模式[,下标,查找超时])"一共有三个参数,目前只需要关注第一个匹配模式
这个匹配模式根据插件介绍是有两种模式的,一种是键值对,一种是table表
//匹配模式1:一个属性对应一个值,不能落单,支持多个属性,所有命令的匹配模式均使用以下格式
Dim 元素 = ElementEx.Find("text","按键精灵","desc","按键精灵","class","xxxx","desc","xxxxx")//匹配模式2:table表
Dim 元素 = ElementEx.Find({"text":"按键精灵","desc":"按键精灵","class":"xxxx","desc":"xxxxx"})
使用那一种都是可以的,这里就采用第一种
先定义一个变量[悬浮球]来存放游戏悬浮球的元素内容
Dim 悬浮球 = ElementEx.Find("class","android.widget.LinearLayout","pkg","com.ylwl.res.common","focused",False,"long-clickable",False,"clickable",False,"checkable",False,"checked",False)
然后判断一下返回的值是不是已经找到了这个悬浮球
If 悬浮球 ThenTracePrint "找到了悬浮球~"
End If
根据实际的调试结果,已经是调试输出找到了悬浮球,但是现在还不确定是不是找正确了,采用元素点击让它多点几次看看
DoDelay 1000TracePrint "点击悬浮球 = " & CStr(ElementEx.Click(悬浮球))
Loop
现在出新问题了,游戏的个人中心出现了它还在点这个悬浮球,那就要做一个判断
在出现用户中心的情况下,要停止点击悬浮球,先把游戏的个人中心打开,抓取一下界面元素
然后定义一个变量[我的界面模式]来存放游戏的个人中心的元素
Dim 我的界面模式 = {"text":"我的","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}DoDelay 1000If ElementEx.Find(我的界面模式) ThenTracePrint "打开我的界面 = " & CStr(True)Exit DoElseTracePrint "点击悬浮球 = " & CStr(ElementEx.Click(悬浮球))End If
Loop
现在已经能顺利打开了游戏个人中心,接下来也是抓取需要点击的元素,这里就不再细说了,开干
Dim 我的界面模式 = {"text":"我的","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Dim 切换账号模式 = {"text":"切换账号","class":"android.widget.Button","pkg":"com.ylwl.res.common"}
Dim 确认切换账号 = {"text":"确认切换账号","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Dim 确定 = {"text":"确定","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
现在代码多了起来,就需要把代码封装成功能,这样阅读代码也方便,后期也更好的维护
有些同学可能就要提问了,老师你函数里面有Do Loop 万一游戏闪退了怎么办?
这是一个好问题,那就需要在死循环的代码里带上限制条件
一种是,如果出现了问题,我就重启你
一种是,如果出现了问题,我就退出你
Dim 游戏包名 = "com.tianmu.webshell.dldl.tmjh.xuanzang431"
Function 切换账号()切换账号 = FalseDim 我的界面模式 = {"text":"我的","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}Dim 切换账号模式 = {"text":"切换账号","class":"android.widget.Button","pkg":"com.ylwl.res.common"}Dim 确认切换账号 = {"text":"确认切换账号","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}Dim 确定 = {"text":"确定","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}If Sys.AppIsFront(游戏包名) = True ThenIf 打开礼包中心() = True ThenDoDelay 200If ElementEx.Find(切换账号模式) ThenTracePrint "点击切换账号模式 = " & CStr(ElementEx.Click(切换账号模式))ElseIf ElementEx.Find(我的界面模式) ThenTracePrint "点击我的界面模式 = " & CStr(ElementEx.Click(我的界面模式))End IfDelay 1000End IfIf ElementEx.Find(确认切换账号) ThenTracePrint "是否在确认切换账号页面 = " & CStr(True)If ElementEx.Click(确定) ThenTracePrint "点击确认按钮 = " & CStr(True)切换账号 = TrueExit FunctionDelay 1000End IfEnd IfIf Sys.AppIsFront(游戏包名) <> True ThenExit DoEnd IfLoopElseTracePrint "打开账号界面 = " & CStr(False)End IfElse
TracePrint "应用是否在前台 = " & CStr(False)End If
End FunctionFunction 打开礼包中心()打开礼包中心 = FalseDim 悬浮球 = ElementEx.Find("class","android.widget.LinearLayout","pkg","com.ylwl.res.common","focused",False,"long-clickable",False,"clickable",False,"checkable",False,"checked",False)Dim 我的界面模式 = {"text":"我的","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}DoDelay 200If Sys.AppIsFront(游戏包名) <> True ThenTracePrint "应用是否在前台 = " & CStr(False)Exit DoEnd IfIf ElementEx.Find(我的界面模式) ThenTracePrint "打开我的界面 = " & CStr(True)打开礼包中心 = TrueExit FunctionElseTracePrint "点击悬浮球 = " & CStr(ElementEx.Click(悬浮球))Delay 1000End IfLoop
End Function
现在来看一下实际的测试效果吧!
TracePrint "是否退出账号 = " & CStr(切换账号())
可可以看到,我们已经退出了游戏账号,那我们继续开始编写登录的函数吧
登录需要注意的点
1.编辑框里面的账号是旧的账号还是新的账号?
2.编辑框的密码元素text全是??????不好判断?
3.什么时候才合适点击登录按钮?
先把需要的元素数据取出来
Dim 登录界面 = {"text":"仅对年满18周岁成年人提供游戏服务","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Dim 登录按钮 = {"text":"登录","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Dim 账号输入框未输入 = {"res":"com.ylwl.res.common:id/mixsdk_login_et_account","class":"android.widget.EditText","pkg":"com.ylwl.res.common"}
Dim 密码输入框未输入 = {"res":"com.ylwl.res.common:id/mixsdk_login_et_passwd","class":"android.widget.EditText","pkg":"com.ylwl.res.common"}
经过实际的测试,发现账号输入了密码框可以通过元素text来确定这个账号是不是输入的账号
Dim 账号输入框已输入 = {"text":账号,"res":"com.ylwl.res.common:id/mixsdk_login_et_account","class":"android.widget.EditText"}
但是密码的text?????并不能找到,那我们就换一个思路,先清空输入框,确定是空的输入框再输入密码,确定账号密码都输入了,就点击登录按钮
Dim 密码输入框已输入 = {"text":"请输入密码","res":"com.ylwl.res.common:id/mixsdk_login_et_passwd","class":"android.widget.EditText"}
接下来就是逻辑方面,思路是先判断账号输入框的账号是否符合,然后清空密码框,并且确定了就输入密码,两个步骤都做完了就可以点击登录了
Dim 账号是否输入 = False, 密码是否输入 = False
If ElementEx.Find(登录界面) ThenTracePrint "是否在登录界面 = " & CStr(True)If 账号是否输入 = False ThenIf ElementEx.Find(账号输入框已输入) Then账号是否输入 = TrueElseIf ElementEx.Find(账号输入框未输入) ThenTracePrint "点击账号输入框 = " & CStr(ElementEx.Click(账号输入框未输入))Call 清空输入框()Delay 200InputText 账号Delay 500End IfEnd IfEnd IfIf 密码是否输入 = False ThenIf ElementEx.Find(密码输入框已输入) ThenInputText 密码Delay 500密码是否输入 = TrueElseIf ElementEx.Find(密码输入框未输入) ThenTracePrint "点击密码输入框 = " & CStr(ElementEx.Click(密码输入框未输入))Call 清空输入框()KeyPress "del"Delay 200End IfEnd IfEnd IfIf 账号是否输入 = True And 密码是否输入 = True ThenIf ElementEx.Find(登录按钮) ThenTracePrint "点击登录按钮 = " & CStr(ElementEx.Click(登录按钮))Delay 1000End IfEnd If
End If
Sub 清空输入框()
For 10
Keypress "PageUp"
Next
Keydown 114
keydown 60
For 10
Keydown "PageDown"
Next
Keyup 114
Keyup 60
Keyup "PageDown"
End Sub
点击登录之后,有一个登录中的状态,我们也把它写出来,这样方便客户观看脚本的运行状态
Dim 登录中 = {"textC":"登录中","class":"android.widget.TextView"}
If ElementEx.Find(登录中) ThenTracePrint "正在登录中……"
End If
登录完了游戏还有悬浮球的公告
Dim 公告 = {"text":"公告","class":"android.widget.TextView"}
Dim 公告关闭按钮 = {"res":"com.ylwl.res.common:id/mixsdk_img_right","class":"android.widget.ImageView","pkg":"com.ylwl.res.common"}
If ElementEx.Find(公告关闭按钮) ThenTracePrint "是否登录成功 = " & CStr(True)TracePrint "点击公告关闭按钮 = " & CStr(ElementEx.Click(公告关闭按钮))
End If
关闭了悬浮球的公告再出来一个游戏公告,由于游戏公告已经不属于元素,所以我们用到了图色插件
这里请出我们的GK插件
Import "GK.luae"If GK.Full(308,1199,415,1232, "Attachment:公告_点击返回.png", 0.9, True) ThenTracePrint "公告页面点击返回 = " & CStr(True)Delay 200
End If
If GK.Full(623,43,709,902, "Attachment:公告_点击关闭.png", 0.9, True) ThenTracePrint "公告页面点击关闭 = " & CStr(True)Delay 200
End If
If GK.Full(289,904,435,947, "Attachment:进入游戏.png", 0.9, True) ThenTracePrint "点击进入游戏 = " & CStr(True)Delay 200
End If
If GK.Full(261,1180,350,1270, "Attachment:主界面_背包.png", 0.9) ThenTracePrint "进入游戏 = " & CStr(True)Delay 200
End If
到进去游戏界面看到背包我们就判断登录成功了,接下来把零碎的代码用函数封装起来,最终代码如下~
Import "ElementEx.luae"
Import "GK.luae"
Dim 游戏包名 = "com.tianmu.webshell.dldl.tmjh.xuanzang431"
'到进去游戏界面看到背包我们就判断登录成功了,接下来把零碎的代码用函数封装起来
Function 登录(账号, 密码)
登录 = False
Dim 账号是否输入 = False, 密码是否输入 = False
Dim 登录界面 = {"text":"仅对年满18周岁成年人提供游戏服务","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Dim 登录按钮 = {"text":"登录","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Dim 账号输入框未输入 = {"res":"com.ylwl.res.common:id/mixsdk_login_et_account","class":"android.widget.EditText","pkg":"com.ylwl.res.common"}
Dim 密码输入框未输入 = {"res":"com.ylwl.res.common:id/mixsdk_login_et_passwd","class":"android.widget.EditText","pkg":"com.ylwl.res.common"}
Dim 账号输入框已输入 = {"text":账号,"res":"com.ylwl.res.common:id/mixsdk_login_et_account","class":"android.widget.EditText"}
Dim 密码输入框已输入 = {"text":"请输入密码","res":"com.ylwl.res.common:id/mixsdk_login_et_passwd","class":"android.widget.EditText"}
Dim 登录中 = {"textC":"登录中","class":"android.widget.TextView"}
Dim 公告 = {"text":"公告","class":"android.widget.TextView"}
Dim 公告关闭按钮 = {"res":"com.ylwl.res.common:id/mixsdk_img_right","class":"android.widget.ImageView","pkg":"com.ylwl.res.common"}
If Sys.AppIsFront(游戏包名) = True Then
Do
Delay 200
If ElementEx.Find(登录界面) Then
TracePrint "是否在登录界面 = " & CStr(True)
If 账号是否输入 = False Then
If ElementEx.Find(账号输入框已输入) Then
账号是否输入 = True
Else
If ElementEx.Find(账号输入框未输入) Then
TracePrint "点击账号输入框 = " & CStr(ElementEx.Click(账号输入框未输入))
Call 清空输入框()
Delay 200
InputText 账号
Delay 500
End If
End If
End If
If 密码是否输入 = False Then
If ElementEx.Find(密码输入框已输入) Then
InputText 密码
Delay 500
密码是否输入 = True
Else
If ElementEx.Find(密码输入框未输入) Then
TracePrint "点击密码输入框 = " & CStr(ElementEx.Click(密码输入框未输入))
Call 清空输入框()
KeyPress "del"
Delay 200
End If
End If
End If
If 账号是否输入 = True And 密码是否输入 = True Then
If ElementEx.Find(登录按钮) Then
TracePrint "点击登录按钮 = " & CStr(ElementEx.Click(登录按钮))
Delay 1000
End If
End If
End If
If ElementEx.Find(登录中) Then
TracePrint "正在登录中……"
End If
If ElementEx.Find(公告关闭按钮) Then
TracePrint "是否登录成功 = " & CStr(True)
TracePrint "点击公告关闭按钮 = " & CStr(ElementEx.Click(公告关闭按钮))
End If
If GK.Full(308,1199,415,1232, "Attachment:公告_点击返回.png", 0.9, True) Then
TracePrint "公告页面点击返回 = " & CStr(True)
Delay 200
End If
If GK.Full(623,43,709,902, "Attachment:公告_点击关闭.png", 0.9, True) Then
TracePrint "公告页面点击关闭 = " & CStr(True)
Delay 200
End If
If GK.Full(289,904,435,947, "Attachment:进入游戏.png", 0.9, True) Then
TracePrint "点击进入游戏 = " & CStr(True)
Delay 200
End If
If GK.Full(261,1180,350,1270, "Attachment:主界面_背包.png", 0.9) Then
TracePrint "进入游戏 = " & CStr(True)
登录 = True
Delay 200
Exit Function
End If
Loop
Else
TracePrint "应用是否在前台 = " & CStr(False)
End If
End Function
Function 切换账号()
切换账号 = False
Dim 我的界面模式 = {"text":"我的","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Dim 切换账号模式 = {"text":"切换账号","class":"android.widget.Button","pkg":"com.ylwl.res.common"}
Dim 确认切换账号 = {"text":"确认切换账号","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Dim 确定 = {"text":"确定","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
If Sys.AppIsFront(游戏包名) = True Then
If 打开礼包中心() = True Then
Do
Delay 200
If ElementEx.Find(切换账号模式) Then
TracePrint "点击切换账号模式 = " & CStr(ElementEx.Click(切换账号模式))
Else
If ElementEx.Find(我的界面模式) Then
TracePrint "点击我的界面模式 = " & CStr(ElementEx.Click(我的界面模式))
End If
Delay 1000
End If
If ElementEx.Find(确认切换账号) Then
TracePrint "是否在确认切换账号页面 = " & CStr(True)
If ElementEx.Click(确定) Then
TracePrint "点击确认按钮 = " & CStr(True)
切换账号 = True
Exit Function
Delay 1000
End If
End If
Loop
Else
TracePrint "打开账号界面 = " & CStr(False)
End If
Else
TracePrint "应用是否在前台 = " & CStr(False)
End If
End Function
Function 打开礼包中心()
打开礼包中心 = False
Dim 悬浮球 = ElementEx.Find("class","android.widget.LinearLayout","pkg","com.ylwl.res.common","focused",False,"long-clickable",False,"clickable",False,"checkable",False,"checked",False)
Dim 我的界面模式 = {"text":"我的","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Dim 登录界面 = {"text":"仅对年满18周岁成年人提供游戏服务","class":"android.widget.TextView","pkg":"com.ylwl.res.common"}
Do
Delay 200
If Sys.AppIsFront(游戏包名) <> True Then
TracePrint "应用是否在前台 = " & CStr(False)
Exit Do
End If
If ElementEx.Find(登录界面) Then
TracePrint "打开礼包中心错误,处于未登录状态~"
Exit Function
End If
If ElementEx.Find(我的界面模式) Then
TracePrint "打开我的界面 = " & CStr(True)
打开礼包中心 = True
Exit Function
Else
TracePrint "点击悬浮球 = " & CStr(ElementEx.Click(悬浮球))
Delay 1000
End If
Loop
End Function
Sub 清空输入框()
For 10
Keypress "
ageUp"
Next
Keydown 114
keydown 60
For 10
Keydown "
ageDown"
Next
Keyup 114
Keyup 60
Keyup "
ageDown"
End Sub
TracePrint "是否退出账号 = " & CStr(切换账号())
Delay 5000
Call 登录("账号", "密码")