传奇新服网,新开变态传奇网站,最新中微变传奇网站
当前位置:网站首页 > 轻变传奇 > 正文

雷电模拟器传奇挂机脚本编写

作者:admin发布时间:2022-01-14分类:轻变传奇浏览:229评论:9


导读:找到模拟器窗口设置模拟器大小该流程使用的是参考代码中原封不动的函数这段我仅仅能看懂把两个分开的方法合并成一个嵌套方法并做一些简单的变量修改要是让我全部重构还是有些许困难():#为要...

雷电模拟器传奇挂机脚本编写

找到模拟器窗口设置模拟器大小

该流程使用的是参考代码中原封不动的函数这段我仅仅能看懂把两个分开的方法合并成一个嵌套方法并做一些简单的变量修改要是让我全部重构还是有些许困难

():#为要被修改的窗口(hwnd,):#去掉下面这句就所有都输出了但是我不需要那么多(hwnd)(hwnd)(hwnd)(GetWindowText(hwnd))globaltitlesEnumWindows(foo,0)lt[tfortintitlesift]lt.sort()fortinlt:#print(t)if(t.find(OrderWindow.getName()))0:hwndwin32gui.FindWindow(None,t)print(hwnd)win32gui.SetWindowPos(\hwnd,win32con.HWND_TOPMOST,\OrderWindow.getLeftTop()[0],OrderWindow.getLeftTop()[1],\OrderWindow.getWidth(),OrderWindow.getHeight(),\win32con.SWP_SHOWWINDOW)#修改窗口属性核心代码print(OrderWindow.getLeftTop()[0],OrderWindow.getLeftTop()[1],\OrderWindow.getWidth(),OrderWindow.getHeight())hwndwin32gui.FindWindow(None,t)print(hwnd)sizewin32gui.GetWindowRect(hwnd)print(size)returnsize

在这一环节中会出现一些重要的问题窗口名应该叫什么窗口应该设置多大

这些问题源于用户使用的安卓模拟器并不都是同一款。比如我自己用的是mumu模拟器而我朋友使用的则是雷电模拟器因此可以先拿这两款模拟器进行比较。

此为mumu模拟器的标题名“明日方舟-星云引擎

此为雷电模拟器的标题名“雷电模拟器”

两款模拟器的标题名都不相同且没有共同点因此理所当然会想到让用户自己去设置这个窗口名。而如果通过程序输入来获取标题名那便会让用户每次使用程序都要输入一次窗口名因此也理所当然会想到使用文本IO操作来读取用户自定义的窗口名。

然后再考虑一下窗口大小的细节。

以上为雷电模拟器和mumu模拟器窗口大小相同时的状态1024x588

其中雷电模拟器实际游戏画面大小为981x553

而mumu模拟器实际游戏画面大小为888x499

由此可见由于各个模拟器布局方式的不同即使将窗口设置为同一大小实际的游戏画面大小也并不相同。然而pyauto的图像识别功能只能识别到和保存图片大小完全一致的图片这便要求运行游戏时的游戏画面大小必须和编程时截取游戏按钮图片时的游戏画面大小完全一致。而对与这一点我所能想到的解决方法便是由编程人员我自己或者用户自行确认和记录当游戏画面大小为981x553时所用模拟器的窗口大小。不过和窗口名的思路一致文件读取操作必不可少。因此对配置文件的读取、异常处理、给用户的编辑配置文件方法说明都要安排上。

defFileInit(OrderWindow):whileTrue:try:fopen(set.txt,r,encodingutf-8)print(已打开文件)breakexcept:print(读取文件失败已创建新文件set.txt)fopen(set.txt,w)f.close()print(配置写入说明)print(第一行模拟器进程名)print(第二行游戏窗口宽度x)print(第三行游戏窗口高度y)print(注程序默认读取utf-8编码txt文件)input(请填入配置信息保存后回车继续)try:OrderWindow.setName(f.readline().strip())print(读取窗口名成功)OrderWindow.setLeftTop(0,0)OrderWindow.setWidth(int(f.readline()))print(读取窗口宽度x成功)OrderWindow.setHeight(int(f.readline()))print(读取窗口高度y成功)f.close()except:input(读取文件数据失败可能因为文件内容缺少或不匹配请检查文件内容,回车后结束程序)exit(0)print(窗口名OrderWindow.getName())print(宽度,OrderWindow.getWidth(),,高度,OrderWindow.getHeight())

展示菜单不必多说。

defMenu():EmergencySanitySwitchFalse#碎药开关初始化AnnihilationSwitchFalse#剿灭开关初始化whileTrue:Mode-1#模式选择初始化print(1.肝任意关卡)print(2.肝剿灭)ifEmergencySanitySwitchTrue:print(3.自动消耗药剂开关:True选择则关闭)ifEmergencySanitySwitchFalse:print(3.自动消耗药剂开关:False选择则开启)Modeeval(input(请选择模式(输入Q或q退出程序):))ifMode1:AnnihilationSwitchFalse#剿灭开关关闭SetWork(EmergencySanitySwitch,AnnihilationSwitch,999)#设置并开始运行程序核心内容os.system(cls)ifMode2:AnnihilationSwitchTrue#剿灭开关打开AnnihilationCountint(input(请选择执行剿灭次数:))SetWork(EmergencySanitySwitch,AnnihilationSwitch,AnnihilationCount)#设置并开始运行程序核心内容os.system(cls)ifMode3:ifEmergencySanitySwitchTrue:EmergencySanitySwitchFalseelse:EmergencySanitySwitchTrueos.system(cls)ifModeQorModeq:break

程序菜单

3.由流程图可以看见程序在设置信息都获取完毕后便会开始正式工作。此处使用模块化的函数来实现每一个流程。

使用pyautogui.moveTo()时需要注意如果将鼠标移动到屏幕的边界可能会引发FailSafeException异常

PyAutoGUIfail-safetriggeredfrommousemovingtoacornerofthescreen.

百度上说添加pyautogui.FAILSAFETrue即可解决但我的解决方案是不把鼠标移到边界移动到不影响识别的位置就够了。

由于游戏中出现等级提升的机会过于稀少因此并没有机会来测试对“LevelUp”图标进行识别的代码是否存在bug。

#用于处理Start按钮判断的流程模块defReadyStart():Start_GArea(Start_G,FilePathpicture\\Start_G_798,514,158,37.jpg)Start_BArea(Start_B,FilePathpicture\\Start_B_798,514,158,37.jpg)PRTS_OFFArea(PRTS_OFF,FilePathpicture\\PRTS_OFF_802,471,155,34.jpg)PRTS_ONArea(PRTS_ON,FilePathpicture\\PRTS_ON_802,471,155,34.jpg)PRTS_LOCKArea(PRTS_LOCK,FilePathpicture\\PRTS_LOCK_802,471,155,34.jpg)whilePRTS_ON.Find()False:#如果代理未开启ifPRTS_OFF.Find()True:#如果代理可以被开启print(\r检测到未开启代理,自动开启代理)PRTS_OFF.Click()pyautogui.moveTo(11,55)ifPRTS_LOCK.Find()True:#如果代理不能被开启input(检测到该关卡自动代理未解锁按下回车键六秒后重试)time.sleep(6)whileStart_G.Click()FalseandStart_B.Click()False:#确认代理开启点击蓝色Start_Gtime.sleep(6)#如果没找到就一直循环pyautogui.moveTo(11,55)#防止鼠标在检测区域影响判断time.sleep(10)#找到点击后等待#用于处理MissionStart按钮判断的流程模块defReadyMissionStart():MissionStartArea(MissionStart,FilePathpicture\\MissionStart_795,314,105,216.jpg)whileMissionStart.Find()False:#没有找到就多找几次print(\r请确认红色开始行动按键在预定范围,6秒后将重试)time.sleep(6)whileMissionStart.Click()!False:#找到了并且点击了如果后面找不到就算点击成功time.sleep(6)#用于处理MissionResults界面判断的流程模块defReadyMissionResults():GetEXPArea(GetEXP,FilePathpicture\\GetEXP_396,453,66,47.jpg)ResultsArea(Results,FilePathpicture\\Results_254,427,40,20.jpg)LevelUpArea(LevelUp,FilePathpicture\\LevelUp_814,272,164,95.jpg)whileGetEXP.Find()False:LevelUp.Click()#如果没有找到经验结算寻找并点击经验提升有则点击不需要返回值time.sleep(15)#每隔15秒检测一次pyautogui.moveTo(11,55)else:Results.Click()#点击随意位置return#用于处理剿灭Results界面判断的流程模块defReadyAnnilationResults():GetEXPArea(GetEXP,FilePathpicture\\GetEXP_396,453,66,47.jpg)AnnihilationOverArea(AnnihilationOver,FilePathpicture\\AnnihilationOver_84,338,101,41.jpg)LevelUpArea(LevelUp,FilePathpicture\\LevelUp_814,272,164,95.jpg)whileAnnihilationOver.Find()False:time.sleep(15)#每隔15秒检测一次pyautogui.moveTo(11,55)else:pointAnnihilationOver.Click()time.sleep(6)whileGetEXP.Find()False:LevelUp.Click()#如果没有找到经验结算寻找并点击经验提升有则点击不需要返回值time.sleep(15)#每隔15秒检测一次pyautogui.moveTo(11,55)else:pyautogui.click(point)#由于剿灭没有不透明标识符因此只能保存刚刚点过的坐标再点一次print(点击,point)return

使用函数将上面的几个流程串联起来。

#将ReadyStart()、ReadyMissionStart()、ReadyMissionResults()、ReadyAnnilationResults()串联起来添加药剂、源石判断处理defStartWork(EmergencySanitySwitch,AnnihilationSwitch,AnnilationCount):#剿灭用计次,用True标记系统暂停False标记系统结束CancelArea(Cancel,FilePathpicture\\Cancel_583,462,33,33.jpg)ConfirmArea(Confirm,FilePathpicture\\Confirm_820,462,33,33.jpg)UseEmergencySanityArea(UseEmergencySanity,FilePathpicture\\UseEmergencySanity_468,94,267,90.jpg)UseOriginiteArea(UseOriginite,FilePathpicture\\UseOriginite_468,133,308,378.jpg)#1:正常返回等待下次循环2理智不足等待30分钟后循环3达成目标不再循环ReadyStart()#win32api.SetCursorPos([0,0])ifUseOriginite.Find():#出现嗑源石提示Cancel.Click()#点击取消没有可选动作print(\r检测到碎石界面,系统暂停将在30分钟(5点理智)后继续,)return2,AnnilationCountifUseEmergencySanity.Find():#出现嗑药提示ifEmergencySanitySwitchTrue:print(允许自动消耗药剂,将消耗一次药剂)Confirm.Click()#允许嗑药点击确认time.sleep(6)ReadyStart()#回到了蓝色行动页面需要再点一次蓝色开始行动else:Cancel.Click()#不允许嗑药点击取消print(未允许自动消耗药剂,系统暂停将在30分钟(5点理智)后继续)return2,AnnilationCountReadyMissionStart()ifAnnihilationSwitchTrue:ReadyAnnilationResults()#剿灭结束画面AnnilationCountAnnilationCount-1print(剿灭剩余次数,AnnilationCount,次)ifAnnilationCount0:input(剿灭次数已达到指定次数请回车继续)return3,AnnilationCountelse:ReadyMissionResults()#普通结束画面time.sleep(6)#确保完全退回结算界面return1,AnnilationCount

一次StartWork为执行一次关卡使用SetWork对多次StartWork进行管理。

因为方舟每日凌晨4点进行刷新如果上一次执行关卡在3点而将要在4点执行下一次关卡则停止程序等待用户手动处理游戏刷新领签到、基建换班之类的由于我凌晨三四点还醒着的机会不多这部分也基本没有进行测试。

#管理StartWork的大循环defSetWork(EmergencySanitySwitch,AnnihilationSwitch,AnnilationCount):print(将在凌晨4点自动停止工作)input(请手动转到关卡的蓝色\开始行动\界面后回车)os.system(cls)StartWorkSign1Timedatetime.datetime.now()BeforeTimeTimewhile(Time.hour!4orBeforeTime.hour!3):##上一次执行和这次执行不能跨过4点,且执行不返回3BeforeTimeTimeStartWorkSign,AnnilationCountStartWork(EmergencySanitySwitch,AnnihilationSwitch,AnnilationCount)Timedatetime.datetime.now()print(当前时间:,Time.year,Time.month,Time.day,Time.hour,Time.minute,Time.second,sep-)ifStartWorkSign1:continueifStartWorkSign2:BeforeTimeTimeSleepTimes30*60#休眠的秒数whileSleepTimes0:print(剩余时间,int(SleepTimes/60),分,int(SleepTimes%60),秒,end\r)SleepTimesSleepTimes-1time.sleep(1)print(计时结束开始重启正在检查当前时间)Timedatetime.datetime.now()ifStartWorkSign3:print(模式已结束)input(回车刷新以上记录)breakTimedatetime.datetime.now()

最后将所有的函数串联在main函数里。由于程序会修改窗口名与配置文件中窗口名相同的窗口因此如果程序窗口的名字与配置文件冲突了程序有可能会修改自己的窗口而不是模拟器的窗口因此程序窗口名必须独一无二。

if__name____main__:os.system(title没⇝有⇝力↝量↺)OrderWindowArea()FileInit(OrderWindow)SelfWindowArea(没⇝有⇝力↝量↺,OrderWindow.getRightDown()[0],OrderWindow.getLeftTop()[1],300,300)titlesset()setWindowsSize(OrderWindow)#****617,496setWindowsSize(SelfWindow)Menu()

结尾

本文章只是记录自己对程序复盘的思路并未发布图片素材因此源程序并不可用。如果有人需要可在评论区留言我会把代码和图片打包传到云盘。

当前程序最大的缺点便是不能跨夜运行不过我确实想不到有什么方案能够让程序自动帮我安排基建。虽然用这个程序能让我一整天不需要去肝方舟但如果我外出家里没有人电脑开一整天说不定会引发安全事故。因此下一步打算尝试在Android平台编写一套方舟脚本。希望到我学会Android开发前还没有对明日方舟和鹰角失去兴趣。最后说一句yjfm。

标签:传奇挂机脚本编写


已有9位网友发表了看法:

欢迎 发表评论: