三国杀钓鱼自动化

三国杀钓鱼脚本

前言

本来是想做必杀的,但是后来测试了大约400钓发现纯靠连点没有漏掉的鱼,所以必杀功能就舍弃了。
我pyinstaller打包后运行.exe居然黑屏了???可能是多进程报错处理没写好,反正还是用vscode运行python吧。这样最起码可以保证不死机。

环境配置

python 3.12.7

Visual Studio Code 任何版本

雷电模拟器9

Win11 23H2

雷电模拟器安装

通过官网https://www.ldmnq.com下载。这个没啥好说的,没有网络问题,直接下一步下一步就行了。
说一下问题我运行vivo端的游戏商店或者三国杀时,发现不能使用。最后查阅信息有一个解决方法是将模拟器的手机型号设置为除了vivo以外的任意一款手机型号。

python 安装

通过官网https://www.python.org/downloads/release/python-3127找到下面Windows installer (64-bit)下载。

链接为https://www.python.org/ftp/python/3.12.7/python-3.12.7-amd64.exe,可以点击此处直接下载

之后,安装python,安装步骤这里不是重点。推荐一位bilibili的up主的视频,根据他的安装即可,后面会讲。

Visual Studio Code 安装

通过官网https://code.visualstudio.com找到Download for Windows下载即可。

同样安装步骤,后面会讲。

如何安装?

https://www.bilibili.com/video/BV1w7411N7Ti这个up主的BV1w7411N7Ti视频可以很好的讲解。记得Visual Studio Code 需要加插件,别忘了看文档安装一下。

脚本

脚本代码-python

这是一段python代码,复制到文本文件更改后缀名为py,即可运行。也可以继续观看B站up的视频稍微学习一点点怎么运行代码。

python 复制代码
from PIL import ImageGrab
import multiprocessing
import pygetwindow
import pyautogui
import keyboard
import numpy
import json
import time

class CustomError(Exception):
    def __init__(self,message):
        self.message=message
class Fishing():
    standWidth=1962
    standHeight=1115
    def __init__(self,window):
        self.window= window 
        self.left=window.left
        self.top=window.top
        self.jsonDir="./position.json"
        self.config=None
        self.GameInit()
    def WindowJudge(self,window):
        return (window.width,window.height)==(Fishing.standWidth,Fishing.standHeight)
    def GameInit(self):
        if not self.WindowJudge(self.window):
            raise CustomError("window size is not match!")
        else:
            self.config=dict(json.loads(self.__read(self.jsonDir)))
    def Click(self,position):
        pyautogui.click(self.left+position[0],self.top+position[1])
    def DragTo(self,position,speed):
        pyautogui.dragTo(self.left+position[0],self.top+position[1],speed,button="left")
    def __read(self,file):
        f=open(file,'r',encoding="utf-8")
        res=f.read()
        f.close()
        return res
def StateFishing(CodeRun):
    while CodeRun.value:#不可更改!
        if keyboard.is_pressed('esc'):
            CodeRun.value=False
            exit(0)

def FishingRun(codeRun,runTime,slow,stink,again,queue,queueNumber):
    window = pygetwindow.getWindowsWithTitle('雷电模拟器')[0]
    fishingGame=Fishing(window)
    queueNumber.value=0
    queue.put((window.left,window.top))
    queue.put(fishingGame.config['slowColor'])
    queue.put(fishingGame.config['WatchRange'])
    time.sleep(0.1)
    queueNumber.value=1
    queue.put((window.left,window.top))
    queue.put(fishingGame.config['stinkColor'])
    queue.put(fishingGame.config['stinkOffset'])
    queue.put(fishingGame.config['StinkyRange'])
    time.sleep(0.1)
    queueNumber.value=2
    queue.put((window.left,window.top))
    queue.put(fishingGame.config['againColor'])
    queue.put(fishingGame.config['AgainRange'])
    time.sleep(0.1)
    queueNumber.value=3
    queue.put((window.left,window.top))
    queue.put(fishingGame.config['energyColor'])
    queue.put(fishingGame.config['EnergyRange'])
    time.sleep(0.1)
    while runTime>0 and codeRun.value:
        runTime-=1
        print("剩余%d次垂钓"%runTime)
        time.sleep(0.5)
        fishingGame.Click(fishingGame.config['beginButton'])
        time.sleep(0.5)
        fishingGame.DragTo(fishingGame.config['dragToPosition'],0.3)
        time.sleep(5.3)
        startTime=time.time()
        while not stink.value and codeRun:
            if time.time()-startTime>2:
                break
        fishingGame.Click(fishingGame.config['liftingPosition'])
        stink.value=False
        while codeRun.value:
            if slow.value :
                fishingGame.Click(fishingGame.config['fishingButton'])
            if again.value:
                fishingGame.Click(fishingGame.config['againButton'])
                break
    codeRun.value=False
    exit(0)
def WatchSpeed(codeRun,slow,queue,queueNumber):
    while queueNumber.value!=0:
        pass
    window=queue.get()
    slowColor=queue.get()
    watchRange=queue.get()
    left,top=watchRange["position1"]
    right,down=watchRange["position2"]
    while codeRun.value:
        screenshot =numpy.array( ImageGrab.grab(bbox=(window[0]+left, window[1]+top, window[0]+right, window[1]+down)))
        screenshotShape=screenshot.shape
        cnt=0
        for i in range(screenshotShape[0]):
            for j in range(screenshotShape[1]):
                temp=screenshot[i][j]
                if ((int(temp[0])-slowColor[0])**2+(int(temp[1])-slowColor[1])**2+(int(temp[2])-slowColor[2])**2)**0.5>5:
                    cnt+=1
        slow.value= cnt/(screenshotShape[0]*screenshotShape[1])<0.6
    exit(0)
def WatchStinky(codeRun,stink,queue,queueNumber):
    while queueNumber.value!=1:
        pass
    window=queue.get()
    stinkColor=queue.get()
    stinkOffset=queue.get()
    watchRange=queue.get()
    left,top=watchRange["position1"]
    right,down=watchRange["position2"]
    top+=stinkOffset
    down+=stinkOffset
    while codeRun.value:
        screenshot =numpy.array( ImageGrab.grab(bbox=(window[0]+left, window[1]+top, window[0]+right, window[1]+down)))
        screenshotShape=screenshot.shape
        cnt=0
        for i in range(screenshotShape[0]):
            for j in range(screenshotShape[1]):
                temp=screenshot[i][j]
                if ((int(temp[0])-stinkColor[0])**2+(int(temp[1])-stinkColor[1])**2+(int(temp[2])-stinkColor[2])**2)**0.5<50:
                    cnt+=1
        stink.value= cnt/(screenshotShape[0]*screenshotShape[1])>0.1
    exit(0)

def WatchAgain(codeRun,again,queue,queueNumber):
    while queueNumber.value!=2:
        pass
    window=queue.get()
    againColor=queue.get()
    watchRange=queue.get()
    left,top=watchRange["position1"]
    right,down=watchRange["position2"]
    while codeRun.value:
        screenshot =numpy.array( ImageGrab.grab(bbox=(window[0]+left, window[1]+top, window[0]+right, window[1]+down)))
        screenshotShape=screenshot.shape
        cnt=0
        for i in range(screenshotShape[0]):
            for j in range(screenshotShape[1]):
                temp=screenshot[i][j]
                if ((int(temp[0])-againColor[0])**2+(int(temp[1])-againColor[1])**2+(int(temp[2])-againColor[2])**2)**0.5<50:
                    cnt+=1
        again.value= cnt/(screenshotShape[0]*screenshotShape[1])>0.8
    exit(0)
def WatchEnergy(codeRun,energy,queue,queueNumber):
    while queueNumber.value!=3:
        pass
    window=queue.get()
    energyColor=queue.get()
    watchRange=queue.get()
    left,top=watchRange["position1"]
    right,down=watchRange["position2"]
    while codeRun.value:
        screenshot =numpy.array( ImageGrab.grab(bbox=(window[0]+left, window[1]+top, window[0]+right, window[1]+down)))
        screenshotShape=screenshot.shape
        cnt=0
        for i in range(screenshotShape[0]):
            for j in range(screenshotShape[1]):
                temp=screenshot[i][j]
                if ((int(temp[0])-energyColor[0])**2+(int(temp[1])-energyColor[1])**2+(int(temp[2])-energyColor[2])**2)**0.5<50:
                    cnt+=1
        energy.value= cnt/(screenshotShape[0]*screenshotShape[1])>0.8
if __name__ == '__main__':
    runTime=999# 运行次数
    codeRun = multiprocessing.Value('b', True)
    queueNumber = multiprocessing.Value('i', -1)
    slow = multiprocessing.Value('b', True)
    stink= multiprocessing.Value('b', True)
    again= multiprocessing.Value('b', False)
    queue=multiprocessing.Queue(20)
    processList=[]
    processList.append(multiprocessing.Process(target=StateFishing, args=(codeRun,)))
    processList.append(multiprocessing.Process(target=FishingRun, args=(codeRun,runTime,slow,stink,again,queue,queueNumber)))
    processList.append(multiprocessing.Process(target=WatchSpeed,args=(codeRun,slow,queue,queueNumber)))
    processList.append(multiprocessing.Process(target=WatchStinky,args=(codeRun,stink,queue,queueNumber)))
    processList.append(multiprocessing.Process(target=WatchAgain,args=(codeRun,again,queue,queueNumber)))
    for each in processList:
        each.start()
    for each in processList:
        each.join()

脚本代码-json

此处需要创建在你的上述python脚本文件的同一目录下,命名为position.json,注意扩展名为json。此处由于电脑性能不同需要手动调节一下stinkOffset,负号代表检测区间向上方偏移像素。由于本脚本设计原理是通过监控并对进程通信实现的,所以由于电脑性能问题需要平移一定距离以留充足反应。如果刺鱼点太靠上,数值应当由-32适当调大,如果太靠下应当由-32适当调小。防呆小tips:-40比-32小。

json 复制代码
{
    "stinkOffset":-32,
    "beginButton":[1625,880],
    "dragToPosition":[1625,630],
    "liftingPosition":[1625,880],
    "fishingButton":[1625,880],
    "againButton":[1420,950],
    "WatchRange":{
        "position1":[1195,135],
        "position2":[1305,140]
    },
    "AgainRange":{
        "position1":[1250,920],
        "position2":[1290,960]
    },
    "StinkyRange":{
        "position1":[626,530],
        "position2":[629,600]
    },
    "EnergyRange":
    {
        "position1":[1366,189],
        "position2":[1367,209]
    },
    "stinkColor":[239,199,107],
    "slowColor":[99,77,66],
    "againColor":[255, 199, 99],
    "energyColor":[255,170,90]
}

安装库

复制下面的命令,在命令框中输入即可自动安装清华镜像下的依赖库。如果不会安装,还是去看一下上文B站up的视频,会有讲解pip指令的教程,这里也只是需要知道在哪里输入就可以了。或者去搜一下别人的文档,只要能确定在那里输入就可以。

cmd 复制代码
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple keyboard pillow pyautogui pygetwindow numpy

说明

  1. 脚本是针对雷电模拟器做的适配,因此最好不要换模拟器,而且甚至版本都不要变。
  2. 窗口分辨率设置为平板版 > 1920x1080(dpi 280)。代码中做了窗口检测,而且需要做到像素匹配。这里代码中像素匹配是1962x1115,设置分辨率后应该就是这个尺寸,不要缩放,如果缩放了,改成其他分辨率后再改回来。
  3. 再runTime中输入此次运行次数,如果不写就会按照我的代码默认参数999次去运行下去了。且换鱼饵是要重开的。
  4. 脚本是模拟鼠标操作,所以不要让任何可能影响点击的操作置于模拟器前,运行脚本时模拟器必须处于显示的状态,而不是最小化。
  5. 可以按下esc退出,如果前10秒左右按下,其他功能会终止,由于代码中的延迟语句的缘故,代码整体会等一会才能终止。10秒左右之后,可以立即终止。
  6. 运行时要先进入开始垂钓的界面中运行脚本。
  7. 本脚本中所有用到的位置信息全部存放在position.json中,可以根据自己的需求进行更改。但是需要注意的是分辨率的更改可能会引起操作、监控位置以及阈值信息的改变,需要手动测试。

By-Round Moon

后继

这个脚本没有对其他电脑做过测试,我的电脑比较好的OMEN,所以运行流畅,但是我的脚本是基于监控信息加进程通信实现的,有可能不同电脑性能不一样导致无法运行,而且刺鱼操作需要调试,但是基本无妨。

另外最近脚本交易盛行,有可能会被他人使用,这里标识一下我的创作日期是2024年10月19日晚22点,为了完成2024年的1024任务所以等到1024当天再发布。本脚本完全开源,欢迎大家交流,且未经本人允许禁止转载。

相关推荐
databook4 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar5 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户8356290780516 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_6 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机12 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机13 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机13 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机13 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i14 小时前
drf初步梳理
python·django
每日AI新事件14 小时前
python的异步函数
python