灵魂潮汐自动钓鱼脚本(基于按键精灵,适用于MuMu模拟器)

话不多说先上代码,后面有一些注意事项也请仔细阅读。

脚本代码

Dim hwnd
Dim LTX, LTY, RBX, RBY, screenWidth, screenHeight
Dim position, playing

Sub locate_screen
	hwnd = find_hwnd("MuMu模拟器12", "nemudisplay")
	screenRect = Plugin.Window.GetClientRect(hwnd)
	LTX = split(screenRect, "|")(0)
	LTY = split(screenRect, "|")(1)
	RBX = split(screenRect, "|")(2)
	RBY = split(screenRect, "|")(3)
	screenWidth = RBX - LTX
	screenHeight = RBY - LTY
End Sub

Sub start_fishing
	MoveTo LTX + (CInt(screenWidth) * 9 / 10), LTY + (CInt(screenHeight) * 2 / 3)
	LeftClick 1
	Delay 500
	MoveTo LTX + (CInt(screenWidth) / 2), LTY + (CInt(screenHeight) * 9 / 10)
	LeftClick 1
	playing = 1
End Sub

Call locate_screen

Function find_hwnd(fatherTitle, title)
	fatherHwnd = Plugin.Window.Find(0, fatherTitle)
	If fatherTitle = title Then 
		find_hwnd = fatherHwnd
	Else 
		tempHwnd = 0
		While tempHwnd = 0
			tempHwnd = Plugin.Window.FindEx(fatherHwnd, 0, 0, title)
			If tempHwnd = 0 Then 
				fatherHwnd = Plugin.Window.FindEx(fatherHwnd, 0, 0, 0)
			End If
		Wend
	End If
	find_hwnd = tempHwnd
End Function

While True
	Call start_fishing
	
	Delay 4000
	
	While playing = 1
		tempx1 = CInt(LTX) + CInt(screenWidth) * 8 / 30
		tempx2 = CInt(LTX) + CInt(screenWidth) * 22 / 30
		tempy = CInt(LTY) + CInt(screenHeight) * 4.2 / 17
		
		iNum1 = Plugin.Color.GetBlockRange(tempx1, tempy, tempx2, tempy, "ADCB10", 1)
        iNum2 = Plugin.Color.GetBlockRange(tempx1, tempy, tempx2, tempy, "FFFFFF", 1)
        iNum3 = Plugin.Color.GetBlockRange(tempx1, tempy, tempx2, tempy, "6361FF", 1)
	
        fishX = CInt(split(split(iNum2, "|")(0), ",")(0))
		
        rightLimit = CInt(split(split(iNum1, "|")(0), ",")(0))

        If rightLimit <> CInt(-1)  Then 
        	tempBlock = split(iNum1, "|")
        	leftLimit = split(tempBlock(UBound(tempBlock)), ",")(0)
        Else 
        	rightLimit = split(split(iNum3, "|")(0), ",")(0)
        	tempBlock = split(iNum3, "|")
        	leftLimit = split(tempBlock(UBound(tempBlock)), ",")(0)
        End If
        
        position = (CInt(leftLimit) + CInt(RightLimit)) / 2
		
        If position < fishX Then 
        	LeftDown 1
        Else 
        	LeftUp 1
        End If
        
        If fishX = - 1  Then 
        	playing = 0
        	Delay 3000
        	LeftClick 1
        End If
	Wend
Wend

在按键精灵中新建脚本,将上述代码复制粘贴保存后即可运行。运行前,请在MuMu模拟器12中打开灵魂潮汐并进入到家园的钓鱼界面。准备好足够多的鱼竿和鱼饵之后,在按键精灵中点击启动即可。脚本会不断自动钓鱼,直到鱼竿或鱼饵耗尽为止。另外根据我的测试,在鱼竿和鱼饵充足的前提下,脚本每小时可产出5000~6000的硬币,搬空商店仅需每月15000硬币(不包括工坊券),因此我并不认为需要额外添加自动购买鱼竿和鱼饵的功能,也请各位人偶师大人合理安排凝炼石的投入。

根据我的测试,按键精灵2014并不能用后台点击的方式操作游戏,因此只能做成前台脚本。开启脚本之前请将可能遮住模拟器界面的窗口关闭或拖到一边,开启脚本后尽量不要动鼠标。我推荐如下图的窗口安排,既可以欣赏萨塔妮娅大人的人间真实时刻又可以刷硬币,

 下面讲解一下脚本的结构。

结构分析

第一步,寻找游戏窗口,并读取窗口位置、窗口宽度、窗口高度等信息;

子程序locate_screen调用find_hwnd函数找到灵魂潮汐游戏所在的子窗口。

据观察,游戏所在的子窗口与其父窗口的关系如图:

 我们事先知道了最高级的父窗口标题为“MuMu模拟器12”,目标窗口标题为“nemudisplay”。于是编写函数,通过递归查找的方式一层一层深入窗口的父子关系,直到找到目标窗口并获取其句柄。

你也许已经发现了,游戏的窗口其实固定在第三层,因此调用三次FindEx方法就可以实现同样的功能,我为什么要写那么一大坨东西,来预防并不存在的普遍性问题呢?事实上,我一开始认为我可以尝试做一个遍历树的算法,但是后来发现自己的技术力不够,只能写成这种样子了。唉好吧,我承认我就是菜,菜所以想多练。好了别说了别说了我这就去学数据结构。

GetClientRect方法接受一个句柄作为输入,返回句柄对应的窗口的左上角、左下角坐标,用“|”分开,利用split方法将其分开并记录到LTX等变量中。

第二步,分析钓鱼过程,确定程序主要结构

根据游戏的规则,一个完整的钓鱼过程包括以下步骤:

  1. 点击“钓鱼”按钮
  2. 点击“开始钓鱼”按钮
  3. 等待游戏内动画结束
  4. 钓鱼。
  5. 等待成功钓鱼动画结束
  6. 跳出结算画面
  7. 回到1

 

其中钓鱼过程中,屏幕上方会跳出一个长条,一个代表鱼的标志沿着长条随机左右运动。玩家操纵一条线段,只要鱼标志处在线段之内,线段便呈现绿色,且下方代表钓鱼进度的进度条前进。反之,若鱼在线段之外,线段呈现红色,且进度条倒退。当进度条达到100%时,钓鱼成功。

前两次点击可以使用LeftClick 1命令模拟。主要的难点是找到按钮的位置。

等待可以用Delay命令对应

钓鱼过程,需要检测鱼的位置,线段的位置,并对二者的关系进行判断,根据判断的结果模拟玩家的操作。

脚本需要判断钓鱼是否成功,成功后离开结算界面,再重新开始。

那么下面开始编写脚本代码。

第三步,开始钓鱼

start_fishing子程序承担了第1、第2步。使用MoveTo方法将光标移动到对应的按钮上,点击即可。

Sub start_fishing
	MoveTo LTX + (CInt(screenWidth) * 9 / 10), LTY + (CInt(screenHeight) * 2 / 3)
	LeftClick 1
	Delay 500
	MoveTo LTX + (CInt(screenWidth) / 2), LTY + (CInt(screenHeight) * 9 / 10)
	LeftClick 1
	playing = 1
End Sub

在这里需要注意一点,游戏每个操作之后都需要一定的时间播放包装动画,因此中间暂停了500毫秒让程序有一点反应时间。

另外,程序通过playing的值确定此时是否进入了钓鱼阶段。在这里初始化其为1,表示开始钓鱼。

该子程序执行结束后游戏会播放一段时长3~4秒的动画,因此随后暂停4000毫秒。即第3步。

接下来进入第4步钓鱼。start_fishing的初始化此时并不需要进行,因此钓鱼过程被放入一个新的while循环中,用playing决定是否结束循环。

tempx1 = CInt(LTX) + CInt(screenWidth) * 8 / 30
tempx2 = CInt(LTX) + CInt(screenWidth) * 22 / 30
tempy = CInt(LTY) + CInt(screenHeight) * 4.2 / 17

tempx1、tempx2、tempy确定了钓鱼长条的左右端点。

在这里值得一提的是,我一开始是通过hard_coding的方式,即加减数值来调整位置的。我很快发现这样编写的程序一旦游戏窗口进行了缩放就有可能失效,因此采用了比例。那些数字是一个一个试出来的,先用尺子量一下确定大概的数值,然后反复调试增减数值。

		iNum1 = Plugin.Color.GetBlockRange(tempx1, tempy, tempx2, tempy, "ADCB10", 1)
        iNum2 = Plugin.Color.GetBlockRange(tempx1, tempy, tempx2, tempy, "FFFFFF", 1)
        iNum3 = Plugin.Color.GetBlockRange(tempx1, tempy, tempx2, tempy, "6361FF", 1)
	
        fishX = CInt(split(split(iNum2, "|")(0), ",")(0))
		
        rightLimit = CInt(split(split(iNum1, "|")(0), ",")(0))

        If rightLimit <> CInt(-1)  Then 
        	tempBlock = split(iNum1, "|")
        	leftLimit = split(tempBlock(UBound(tempBlock)), ",")(0)
        Else 
        	rightLimit = split(split(iNum3, "|")(0), ",")(0)
        	tempBlock = split(iNum3, "|")
        	leftLimit = split(tempBlock(UBound(tempBlock)), ",")(0)
        End If
        
        position = (CInt(leftLimit) + CInt(RightLimit)) / 2

GetBlockRange方法可以读取特定区域内的颜色块,并返回颜色块的坐标。坐标内部XY用“,”隔开,若有多个坐标则用“|”分开。iNum1读取绿色,iNum2读取白色,iNum3读取红色。

注意到钓鱼条中只有鱼身上有白色,且左右分散的宽度明显小于玩家操作的线段长度,直接用读取到的第一个坐标的X分量作为鱼的位置。

默认读取绿色的坐标,如果没有绿色,GetBlockRange方法会返回-1,此时转到iNum3即可。由于需要得到线段的左右坐标,又注意到GetBlockRange方法返回的坐标X从大到小分布,故使用tempBlock作为中间量读取左侧坐标。注意这里不能使用hard_coding的方法,因为iNum1和iNum3的长度是不固定的。

position是线段中点的X坐标,此脚本以position作为与鱼比较的对象。

        If position < fishX Then 
        	LeftDown 1
        Else 
        	LeftUp 1
        End If

根据游戏规则,按住鼠标则线段右移,松开鼠标则线段左移,故如上模拟玩家动作。

        If fishX = - 1  Then 
        	playing = 0
        	Delay 3000
        	LeftClick 1
        End If

上面已经说过,只有鱼身上有白色色块。当脚本检测不到白色色块时,说明游戏已经跳出了结算画面,钓鱼结束,故令playing为0跳出while循环。等待动画播放完毕即可单击退出,然后开始新一轮的钓鱼。

最后用一个无限循环将整个钓鱼过程包起来即可。

补充:想在其他模拟器上运行 ?

由于此脚本在提取游戏画面时使用的是游戏本身的画面,因此如果想要让此脚本运行在MuMu模拟器以外的平台,并不需要对代码进行过多的修改。您只需要:

  1. 打开模拟器,进入游戏。同时打开按键精灵。
  2. 单击脚本进入脚本编辑界面,选择“源文件”,使用按键精灵上方工具栏中的“抓抓”功能,选择句柄选项卡,将准星拖到游戏画面后松开
  3. “当前窗口”区域中有一个“标题”输入框,将输入框中的内容复制,取代脚本代码中第6行的nemudisplay,注意双引号不能去掉。
  4. 将准星拖动到模拟器左上角后松开,同样将“标题”输入框中的内容复制,取代第6行“MuMu模拟器12”

此时你已经完成了所需的修改,保存脚本,启动即可!

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值