痒痒鼠自动刷妖气封印

之前在玩痒痒鼠的时候,苦于刷副本比较累,于是写了自动刷妖气封印的代码。现在对痒痒鼠兴致缺缺,在整理电脑文件的时候就把代码整理上传到了 GitHub 上了。这里记录一下整个代码的结构和思路备忘。

目录结构

整个程序包含3个 Python 文件和两个目录,如下:

  • pic : 用于放置一些用来确定场景进行比较的图片
  • usr : 用于放置用户名的截图
  • baseFunction.py : 定义了一些鼠标的基本操作
  • order.py : 定义了按钮位置、尺寸大小等信息;每个副本的操作流程在此
  • yysgo.py : 程序入口

使用

  1. 在 usr 目录下添加一张游戏名称的截图(部分截图即可,需要 png 格式)。如下图 zhzz.png(我的游戏名称是“最后之作”) :

    zhzz

  2. 在命令行输入

    python yysgo.py user_name what_to_do times code

  • user_name : 你放在 usr 目录下的截图文件名,不包含格式后缀,如上面的应该是 zhzz

  • What_to_do : 需要刷的副本,使用拼音首字母。如鬼使黑的话就是 gsh

  • times : 需要刷的次数

  • code : 0~7 的数字,内容如下:

        接受房主 不当房主  
    有活动 无活动 有活动 无活动
     接受邀请  7
     不接受邀请  3

​ (其中的活动指的是痒痒鼠经常会有的一些鬼王活动,使得原本的「妖气封印」按钮下移一格)

eg. python yysgo.py zhzz gsh 100 6 表示刷100次鬼使黑,接受悬赏封印邀请,若原房主退出则接受房主,没有特殊活动

程序内容

整个程序的原理比较简单,就是模拟平时手动刷副本时的操作而已。

baseFunction.py

baseFunction.py 内定义了一些基本的鼠标操作,如:

  • 点击 :click(area, delay=0.5)
    • area :点击区域
    • delay :延时最大值(后面的 delay 皆是如此)
  • 拖拽 :drag(begin_area, end_area, delay=0.5, duraction=0.5)
    • begin_area :开始区域
    • end_eare :结束区域
    • duraction :拖拽最大时长
  • 寻找图片 :find_picture(file_location),返回 T/F
    • file_location :图片文件文字

以及基于这些操作的一些其他操作,如:

  • 滚动 :roll(block_nums, area, block_height, eps=2, delay=0.5, duraction=0.5)
    • block_nums :滚动格数,负数为从长往下拖拽一格,正数为从下往上
    • area :可以操作的列表区域
    • block_height :一格的高度
    • eps :误差
  • 检测邀请 :check_invatation(operation, pic, button_accept, button_decline)
    • operation :收到悬赏封印邀请的操作
    • pic :悬赏封印邀请的截图位置
    • button_accept :「接受」按钮区域
    • button_decline :「拒接」按钮区域
  • 检测房主 :check_roomowner(pic),返回 T/F
    • pic :成为房主时的标志图片(默认使用亮起的「开始战斗」按钮的截图作为已经成为房主的依据)
  • 检测等待状态 :check_searching(pic, button),无返回值,若不在匹配中,则点击「开始匹配」继续
    • pic :正在匹配的标志图片(默认使用亮起的「取消匹配」按钮的截图作为正在匹配中的依据)
  • 等待 :waiting(symbol, invatation_pic, invatation_operation, roomowner_pic, searching_pic, button_set)
    • symbol :进入战斗(「准备」按钮亮起)的标志图片
    • *_pic :上面三个检测的图片位置
    • invatation_operation :收到悬赏封印邀请的操作
    • button_set :按钮的位置的 list,[button_accept, button_decline, button_search]

注意

  • 图片的检测使用最原始的逐像素比对,因此若图片大小不对也会导致无法检测,这一点有兴趣的同志可以改进一下。在自行截图时要注意游戏的某些位置是动态的,或者的动态的底层上加一层半透明图片,这会导致图片检测失效。
  • 这里与时间相关的参数都是时间的最大值,程序执行时等待的对应时间都是从0到该「最大值」的随机数,以避免防作弊检测
  • 同理,这里所有的按钮的点击还有拖拽的操作,位置都是随机的。每一个 area(或 button) 都是 [[x1, y1], [x2, y2]] 的形式

order.py

order.py 定义了一些组合操作(即刷一个副本的完整操作,使用 baseFunction 的函数,也可以自行在此添加其他副本的操作),设置了一些有关按钮和相关检测区域位置坐标的参数。

副本操作示例(部分内容省略)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def guishihei(count, invitation_op, roomowner_op, user_name, activities=False):
# count : 刷该副本的次数
# *_op, activities : 对应上面表格
# user_name : 用户名(与上文一致,即截图的文件名)

while(count - index > 0):
pyautogui.moveTo(1, 1, 0.3) # 为防止鼠标的遮挡,每次需要匹配图片之前,将鼠标移动到左上角,后面不再出现这行代码

#### 执行副本组队的一连串操作
baseFunction.waiting(get_start_symbol(user_name), PIC_INVATATION, invitation_op, PIC_ROOMOWNER, PIC_IS_SEARCHING, button_set) # 若检测到 user_name.png 在屏幕中,则认为可以开始新一轮操作,否则继续等待
baseFunction.click(get_button(TEAM)) # 点击『组队』按钮
if activities:
baseFunction.roll(1, get_button(AREA[0]), block_height)
baseFunction.click(get_button(DEMON_SEAL)) # 点击『妖气封印』按钮,若有特殊活动,将列表下滚一格再点击
drag_area = [get_button(AREA[1][0]), get_button(AREA[1][1])] # 计算拖动区域
baseFunction.roll(8, drag_area, block_height_l2) # 下滚列表
baseFunction.click(get_button(GUI_SHI_HEI)) # 点击『鬼使黑』按钮
baseFunction.click(get_button(MATCH)) # 点击『自动匹配』
interupt = baseFunction.waiting(PIC_READY, PIC_INVATATION, invitation_op, PIC_ROOMOWNER, PIC_IS_SEARCHING, button_set) # 检测『准备』按钮是否出现

#### 特殊情况的处理
if interupt == 1: # 1 表示成为房主了(waiting()函数会每隔一段时间检测悬赏封印邀请和房间状态,正常状态返回 0)
if roomowner_op:
baseFunction.click(get_button(START)) # 若接受成为房主,则点击『开始战斗』按钮开始
if baseFunction.waiting(PIC_ROOMOWNER, PIC_INVATATION, invitation_op, PIC_ROOMOWNER, PIC_IS_SEARCHING, button_set) == 0: # 由于检测房主间隔时间较长,有可能执行到这里时其他玩家退出了,因此需要等待『开始战斗』按钮重新亮起
baseFunction.click(get_button(START))
baseFunction.waiting(PIC_READY, PIC_INVATATION, invitation_op, PIC_ROOMOWNER, PIC_IS_SEARCHING, button_set) # 等待『准备』按钮
else:
baseFunction.click(get_button(BACK)) # 若不接受房主,左上角返回,开始下一轮
countinue

#### 到这里准备按钮亮起,玩家已经进入副本并可以开始战斗了
baseFunction.click(get_button(PREPARE)) # 点击『准备』按钮

#### 战斗完成,点击任意位置退出
baseFunction.waiting(PIC_FINISH, PIC_INVATATION, invitation_op, PIC_ROOMOWNER, PIC_IS_SEARCHING, button_set)
baseFunction.click(get_button(FINISH))

部分参数设置(分辨率等参数不同,最好使用前重新测定坐标)

  • block_height_l1/l2 : 列表一格的高度,我在测量时 妖气封印的子列表(l2) 和其本身的列表(l1) 高度并不一样
  • BASE : 基准点,后面的所有坐标都是对此坐标的相对位置,采取窗口左上角坐标作为基准点
  • ACCEPT, DECLINE, BACK, START : (悬赏封印)接受/拒绝,返回,开始战斗 按钮的位置
  • MATCH, PREPARE, FINISH : 自动匹配,准备,完成(点击任意位置退出) 按钮的位置
  • TEAM, DEMON_SEAL : 组队(庭院界面),妖气封印 按钮的位置
  • AREA : 列表的区域,roll() 函数需要这个区域来确定拖动的界限,AREA[0]是点击组队后出现的列表(l1),AREA[1]是妖气封印下的子列表(l2)
  • PIC_*, USER_BASE : 各种图片位置,用户名截图目录

yysgo.py

程序入口,不用多说。

在 order.py 中添加新的操作后,需要在这里调用。

备注

  • 图片检测的速度不够快,这有时会导致一些意料之外的事发生
  • 逐一像素检测图片会导致以后若有改版,需要重新截图
  • order.py 中对特殊状况的处理似乎有一些错误,不过在实际使用中没有发生意外,就没有修改了
0%