(Para sempre grátis, escaneie o código para participar)
Por LookOutTheBush
https://juejin.cn/post/7232253274056785957
Somente para aprendizado e intercâmbio, sem fins lucrativos
I. Visão geral
1.1 Efeito
Em geral, esse método é realizado por meio de reconhecimento de imagem, sem interferir no jogo, sem ler a memória e sem ser detectado com segurança.
1.2 Pré-requisito de conhecimento
Há uma variedade de armas de fogo diferentes no jogo. Diferentes armas de fogo têm diferentes recuos e diferentes taxas de disparo. A mesma arma de fogo, após a instalação de vários acessórios, o recuo também mudará.
O movimento ascendente do eixo y da arma de fogo é fixo e o eixo x é aleatório, então nosso programa move apenas o eixo y do mouse. Operação manual no jogo do eixo x.
1.3 Breve descrição do princípio de realização
Monitore o teclado e o mouse através do módulo pynput em python.
Ouça o botão esquerdo do mouse ser pressionado e comece a mover o mouse neste momento. Levante o botão esquerdo para parar de se mover. Monitore as teclas do teclado, como a tecla tab, abra a mochila neste momento, faça uma captura de tela e comece a identificar a coluna do equipamento.
Use o módulo pyautogui do python para fazer capturas de tela e você pode capturar a tela em um local especificado.
As imagens interceptadas são processadas através do módulo opencv do python.
Use o algoritmo SSIM para comparar a semelhança das imagens e obtenha as armas e acessórios na barra de equipamentos.
Manipule o movimento do mouse por meio do pydirectinput do python.
Dois, explicação detalhada
teclado de monitor pynput 2.1
import pynput.keyboard as keyboard
# 监听键盘
def listen_keybord():
listener = keyboard.Listener(on_press=onPressed, on_release=onRelease)
listener.start()
O ouvinte do pynput é um evento assíncrono, mas será bloqueado, portanto, se o evento de processamento do evento for muito longo, ele deverá ser processado de forma assíncrona.
2.2 Ouvindo eventos
A classe c_equipment foi criada para encapsular as informações da arma. O foco está no monitoramento da tecla tab, utilizando assíncrono para detectar informações do equipamento.
def onRelease(key):
try:
if '1' == key.char:
c_equipment.switch = 1 #主武器1
elif '2' == key.char:
c_equipment.switch = 2 #主武器2
elif '3' == key.char:
c_equipment.switch = 3 #手枪 switch=3的时候不压枪
elif '4' == key.char:
c_equipment.switch = 3 #刀具
elif '5' == key.char:
c_equipment.switch = 3 #手雷
except AttributeError:
if 'tab' == key.name: #tab键异步操作检测
asyncHandle()
elif 'num_lock' == key.name: #小键盘锁用来控制程序开关
changeOpen()
elif 'shift' == key.name:
c_contants.hold = False
2.3 captura de tela do pyautogui
Para detectar equipamentos, você deve primeiro fazer uma captura de tela ao abrir a barra de equipamentos.
pyautogui.screenshot(region=[x, y, w, h])
x,y representam as coordenadas respectivamente, w,h representam a largura e a altura. Após a interceptação, para comparar as imagens convenientemente, a imagem precisa ser binarizada e salva localmente.
O código completo é o seguinte:
import pyautogui
def adaptive_binarization(img):
#自适应二值化
maxval = 255
blockSize = 3
C = 5
img2 = cv2.adaptiveThreshold(img, maxval, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, blockSize, C)
return img2
# 屏幕截图
def shotCut(x, y, w, h):
im = pyautogui.screenshot(region=[x, y, w, h])
screen = cv2.cvtColor(numpy.asarray(im), cv2.COLOR_BGR2GRAY)
temp = adaptive_binarization(screen)
return temp
def saveScreen():
screen1 = shotCut(1780, 125, 614, 570)
cv2.imwrite("./resource/shotcut/screen.bmp", screen1)
![4021561a8f8f6df495b5c78c3da420a7.jpeg](https://img-blog.csdnimg.cn/img_convert/4021561a8f8f6df495b5c78c3da420a7.jpeg)
2.4 Preparação de materiais
Depois que a captura de tela é processada como acima, antes do reconhecimento do equipamento, precisamos preparar muitas imagens de material para comparação. Por exemplo: nome da arma, coronha, empunhadura, focinho
![b84d68fda4de582cf1f20264a301aeb6.jpeg](https://img-blog.csdnimg.cn/img_convert/b84d68fda4de582cf1f20264a301aeb6.jpeg)
Nome da arma:
![ec959c75606c3ef007e049f4786735fe.jpeg](https://img-blog.csdnimg.cn/img_convert/ec959c75606c3ef007e049f4786735fe.jpeg)
estoque de armas
![7386fea7067a4551d1c9919465687419.jpeg](https://img-blog.csdnimg.cn/img_convert/7386fea7067a4551d1c9919465687419.jpeg)
2.5 Cortar Imagem
Para facilitar a comparação de imagens, precisamos recortar a imagem capturada da coluna do equipamento em uma imagem do mesmo tamanho do material.
Por exemplo, queremos verificar o nome da arma um:
#读取之前的截屏
screen = cv2.imread("./resource/shotcut/screen.bmp", 0)
#裁剪出武器1名字
screenWepon1 = screen[0:40, 45:125]
#拿裁剪的图片和武器素材的目录作为入参,进行对比
w1Name = compareAndGetName(screenWepon1, "./resource/guns/")
2.6 Imagens de comparação
#对比图片获取名字
def compareAndGetName(screenImg, dir):
#获取目录下所有文件
content = os.listdir(dir)
name = 'none'
max = 0
#遍历文件
for fileName in content:
#使用opencv读取文件
curWepone = cv2.imread(dir + fileName, 0)
#使用SSIM算法拿到图片相似度
res = calculate_ssim(numpy.asarray(screenImg), numpy.asarray(curWepone))
#获取相似度最大的
if max < res and res > 0.5:
max = res
name = str(fileName)[:-4]
return name
Algoritmo SSIM:
def calculate_ssim(img1, img2):
if not img1.shape == img2.shape:
raise ValueError('Input images must have the same dimensions.')
if img1.ndim == 2:
return ssim(img1, img2)
elif img1.ndim == 3:
if img1.shape[2] == 3:
ssims = []
for i in range(3):
ssims.append(ssim(img1, img2))
return numpy.array(ssims).mean()
elif img1.shape[2] == 1:
return ssim(numpy.squeeze(img1), numpy.squeeze(img2))
else:
raise ValueError('Wrong input image dimensions.')
Neste ponto, podemos obter o nome da arma na posição 1 da barra de equipamento.
2.7 Operando o mouse
Depois de saber o nome da arma, da mesma forma, podemos obter os acessórios do equipamento. Em seguida, ouça os pressionamentos do botão esquerdo do mouse e comece a mover o mouse para baixo.
Vamos pegar a arma m762 como exemplo:
Taxa de tiro: 86, cada intervalo de bala 86 milissegundos
Recuo: [42, 36, 36, 36, 42, 43, 42, 43, 54, 55, 54, 55, 54, 55, 54, 55, 62, 62, 62, 62, 62, 62, 62, 62 ,62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 77, 78, 77, 78]
Indica a distância que precisa ser movida para baixo no eixo y depois que cada bala é disparada para neutralizar o recuo.
def moveMouse():
#从识别的数据中,再更具当前选择的武器,获取此刻的武器(比如按下1键,武器装备栏1为m762,那么此时武器就是m762)
curWepone = getCurrentWepone()
if (curWepone.name == 'none'):
return
#基础y轴补偿(没任何配件)
basic = curWepone.basic
#射速
speed = curWepone.speed
startTime = round(time.perf_counter(), 3) * 1000
for i in range(curWepone.maxBullets):
#是否可以开火,比如左键抬起,就中断。
if not canFire():
break
#系数,比如按住shift屏息,就需要再原来基础上乘1.33
holdK = 1.0
if c_contants.hold:
holdK = curWepone.hold
#乘以系数后实际的移动距离
moveSum = int(round(basic[i] * curWepone.k * holdK, 2))
while True:
if (moveSum > 10):
#移动鼠标
pydirectinput.move(xOffset=0, yOffset=10, relative=True)
moveSum -= 10
elif (moveSum > 0):
pydirectinput.move(xOffset=0, yOffset=moveSum, relative=True)
moveSum = 0
elapsed = (round(time.perf_counter(), 3) * 1000 - startTime)
if not canFire() or elapsed > (i + 1) * speed + 10:
break
time.sleep(0.01)
loop while no código:
Na verdade, depois que a primeira bala é disparada, precisamos apenas descer uma distância de 42 e, em seguida, calcular o tempo de espera (0,086 - o tempo para mover o mouse), disparar a segunda bala e assim por diante.
A função do loop while é evitar que a tela trema muito. Como a distância de 42 é movida diretamente, o jogo treme muito, então movemos o mouse várias vezes em um intervalo de 86 milissegundos.
A função sleep em python não é precisa, então temos que cronometrar nós mesmos para evitar perder o intervalo de tempo de cada marcador. Existe outra vantagem de ser impreciso, aleatório, e acontece que você não precisa impedir a detecção por conta própria.
3. A parte mais problemática
O recuo de cada arma é diferente, precisamos ir sozinhos ao campo de treinamento do jogo, ajustar as balas uma a uma e obter dados de compensação precisos.
Quatro, finalmente
Envie o código para gitee e comunique-se com os interessados.
https://gitee.com/lookoutthebush/PUBG
Finalmente, gostaria de recomendar nosso grupo de membros. Atualmente, existem investidores anjo de capital de risco, headhunters HR, Douyin big V, blogueiros emocionais, advogados, conselheiros psicológicos, vendas médicas, imóveis, seguros, professores de piano, operadores, consultoria de negócios , Estudantes de comércio eletrônico transfronteiriço, construção, analistas de dados na indústria da Internet, desenvolvimento de back-end, teste de python e outras indústrias se juntarão.
Atualmente, existem mais de 400 pessoas no planeta e 41 truques foram atualizados no conteúdo da coluna. Todos os dias, os planetas publicam suas próprias experiências. Você pode aprender por apenas um dólar:
Python: 44 lições do curso introdutório de python + 9 lições da coluna Django + casos práticos interessantes
chatgpt: iniciante, avançado, fun office, cursos avançados
Pintura de IA: fundamentos de Mj, entrada, avançado, jogabilidade de Xiaohongshu
Você também pode conhecer muitas pessoas legais!
Junte-se para enviar uma conta independente do ChatGPT
Envie também cursos em vídeo avançados do ChatGPT
O preço original é 99, e agora é grátis enviar membros do planeta
WeChat pressione e segure para experimentar o conteúdo
Se você não estiver satisfeito dentro de três dias, você pode reembolsar diretamente! ! !
推荐阅读:
入门: 最全的零基础学Python的问题 | 零基础学了8个月的Python | 实战项目 |学Python就是这条捷径
干货:爬取豆瓣短评,电影《后来的我们》 | 38年NBA最佳球员分析 | 从万众期待到口碑扑街!唐探3令人失望 | 笑看新倚天屠龙记 | 灯谜答题王 |用Python做个海量小姐姐素描图 |碟中谍这么火,我用机器学习做个迷你推荐系统电影
趣味:弹球游戏 | 九宫格 | 漂亮的花 | 两百行Python《天天酷跑》游戏!
AI: 会做诗的机器人 | 给图片上色 | 预测收入 | 碟中谍这么火,我用机器学习做个迷你推荐系统电影
小工具: Pdf转Word,轻松搞定表格和水印! | 一键把html网页保存为pdf!| 再见PDF提取收费! | 用90行代码打造最强PDF转换器,word、PPT、excel、markdown、html一键转换 | 制作一款钉钉低价机票提示器! |60行代码做了一个语音壁纸切换器天天看小姐姐!|