解决方案

Python如何实现简单DNF脚本

seo靠我 2023-09-23 21:16:22

效果

https://v.qq.com/x/page/m09169jorj0.html?vuid24=UQ4gZ9NuNjFsyWtJ%2FXiQNw%3D%3D&ptag=2_7.3.6.19976_SEO靠我copy

前言

在此声明,本博客仅作学习交流使用,不可用于任何商业途径,对产生的任何影响,本人概不负责。如有侵权,请联系删除。

本文参考自https://blog.csdn.net/chijiandi/arSEO靠我ticle/details/85276661#_1

       玩了好几年dnf,虽然脱坑了,正好有个兴趣,就做了一个简陋的脚本。代码水平有限,正在努力学习中。

使用环境

语言:python

工具:pycharm

实现

键盘SEO靠我模拟

win10使用键盘模拟时,开启测试模式。

     bcdedit /set testsigning on

图像分析

1.定位怪物和门的坐标

首先需要定位人物和怪物,本文修改了npk文件,怪物大小设置25*25,颜SEO靠我色为纯色。通过找色块找到位置。

author = Yanxiangversion = 1.0date = 10/06/2019import cv2import numpy as npimport timSEO靠我edef detective(img_path,flag):kernel_4 = np.ones((4, 4), np.uint8) # 4x4的卷积核def separate_color_yelloSEO靠我w(hsv):# 怪物颜色提取lower_hsv = np.array([0, 0, 255]) # 提取颜色的低值..high_hsv = np.array([0, 0, 255]) # 提取颜色的SEO靠我高值mask = cv2.inRange(hsv, lowerb=lower_hsv, upperb=high_hsv)print("怪物坐标提取完成")return maskdef separateSEO靠我_color_door(hsv):# 门颜色提取lower_hsv = np.array([120, 255, 255]) # 提取颜色的低值high_hsv = np.array([120, 255SEO靠我, 255]) # 提取颜色的高值mask = cv2.inRange(hsv, lowerb=lower_hsv, upperb=high_hsv)print("门的坐标提取完成")return mSEO靠我askdef erocode_dilate(mask):erosion = cv2.erode(mask, kernel_4, iterations=1)erosion = cv2.erode(eroSEO靠我sion, kernel_4, iterations=1)dilation = cv2.dilate(erosion, kernel_4, iterations=1)dilation = cv2.diSEO靠我late(dilation, kernel_4, iterations=1)return dilation# flag = 0 表示找到怪物的平均坐标# flag = 1 表示找到人物坐标def coSEO靠我ntours(dilation, flag):# target是把原图中的非目标颜色区域去掉剩下的图像target = cv2.bitwise_and(Img, Img, mask=dilation)SEO靠我# 将滤波后的图像变成二值图像放在binary中ret, binary = cv2.threshold(dilation, 127, 255, cv2.THRESH_BINARY)# 在binary中SEO靠我发现轮廓,轮廓按照面积从小到大排列img_contours, contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2SEO靠我.CHAIN_APPROX_SIMPLE)p = 0inumber = 1# 新建数组存放所有怪物 X,Y坐标的中心值monster_x = []monster_Y = []# pos_x =0# pSEO靠我os_y =0if(len(contours)!=0):for i in contours: # 遍历所有的轮廓x, y, w, h = cv2.boundingRect(i) # 将轮廓分解为识别对SEO靠我象的左上角坐标和宽、高if w * h > 100:if flag == 0:p += 1print(第 %d 个怪物的底中的位置为 % (p), x + w / 2, y + h )monster_SEO靠我x.append(x + w / 2)monster_Y.append(y + h )return monster_x,monster_Yif flag == 2:p += 1print(第 %d 个SEO靠我的中心像素位置为 % (p), x + w / 2, y + h / 2)pos_xx = xpos_yy = yreturn pos_xx,pos_yyelse:if flag == 0:returSEO靠我n monster_x,monster_Yif flag == 2:return 0,0Img = cv2.imread(img_path)#读入一幅图像if Img is not None:#判断图SEO靠我片是否读入HSV = cv2.cvtColor(Img, cv2.COLOR_BGR2HSV)#把BGR图像转换为HSV格式# 提取颜色if flag==0:mask_yellow = separatSEO靠我e_color_yellow(HSV)dilation_yellow = erocode_dilate(mask_yellow)pos_x,pos_y = contours(dilation_yellSEO靠我ow,flag)return pos_x,pos_yelif flag==2:mask_door = separate_color_door(HSV)dilation_red = erocode_diSEO靠我late(mask_door)pos_x,pos_y = contours(dilation_red,flag)return pos_x,pos_y

2.定位人的坐标

和上面差不多,不贴了。还有另外一种方SEO靠我法定位的人物。

3.窗口定位与模拟键盘

首先将屏幕置于最前窗口。

class setf():def __init__(self):self.gamename = 地下城与勇士self.shell = winSEO靠我32com.client.Dispatch("WScript.Shell")self.dll = CDLL("user32.dll")def setfocus(self):# pid = self.gSEO靠我et_pid_for_pname(self.gamename)# if pid:# print(222)# for hwnd in self.get_hwnds_for_pid(pid):# 获得窗口SEO靠我句柄hwnd = win32gui.FindWindow(None, "地下城与勇士")# 将dnf窗口保持焦点self.shell.SendKeys(%)self.dll.LockSetForegrSEO靠我oundWindow(2)if self.dll.IsIconic(hwnd):win32gui.SendMessage(hwnd, win32con.WM_SYSCOMMAND, win32con.SEO靠我SC_RESTORE, 0)self.dll.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 0, 0, 0, 0,win32con.SWP_NOSIZE | wiSEO靠我n32con.SWP_NOMOVE)self.dll.SetForegroundWindow(hwnd)self.dll.SetActiveWindow(hwnd)

移动 参考模拟按键

完整的按键模拟方法SEO靠我包引用自网络。

import rabird.winio import time import atexit# KeyBoard Commands # CoSEO靠我mmand port KBC_KEY_CMD = 0x64 # Data port KBC_KEY_DATA = 0x60__winio = NonedSEO靠我ef __get_winio():global __winioif __winio is None:__winio = rabird.winio.WinIO()def __clear_winio():SEO靠我global __winio__winio = Noneatexit.register(__clear_winio)return __winiodef wait_for_buffer_empty():SEO靠我Wait keyboard buffer emptywinio = __get_winio()dwRegVal = 0x02while (dwRegVal & 0x02):dwRegVal = winSEO靠我io.get_port_byte(KBC_KEY_CMD)def key_down(scancode):winio = __get_winio()wait_for_buffer_empty();winSEO靠我io.set_port_byte(KBC_KEY_CMD, 0xd2);wait_for_buffer_empty();winio.set_port_byte(KBC_KEY_DATA, scancoSEO靠我de)def SPkey_down(scancode):winio = __get_winio()wait_for_buffer_empty();winio.set_port_byte(KBC_KEYSEO靠我_CMD, 0xd2);wait_for_buffer_empty();winio.set_port_byte(KBC_KEY_DATA, 0xe0)wait_for_buffer_empty();wSEO靠我inio.set_port_byte(KBC_KEY_CMD, 0xd2);wait_for_buffer_empty();winio.set_port_byte(KBC_KEY_DATA, scanSEO靠我code)def key_up(scancode):winio = __get_winio()wait_for_buffer_empty();winio.set_port_byte( KBC_KEY_SEO靠我CMD, 0xd2);wait_for_buffer_empty();winio.set_port_byte( KBC_KEY_DATA, scancode | 0x80);def SPkey_up(SEO靠我scancode):winio = __get_winio()wait_for_buffer_empty();winio.set_port_byte(KBC_KEY_CMD, 0xd2);wait_fSEO靠我or_buffer_empty();winio.set_port_byte(KBC_KEY_DATA, 0xe0)wait_for_buffer_empty();winio.set_port_byteSEO靠我(KBC_KEY_CMD, 0xd2);wait_for_buffer_empty();winio.set_port_byte(KBC_KEY_DATA, scancode | 0x80)def moSEO靠我use_down():winio = __get_winio()wait_for_buffer_empty();winio.set_port_byte(KBC_KEY_CMD, 0xd3);wait_SEO靠我for_buffer_empty();winio.set_port_dword(KBC_KEY_DATA, 0x09)def mouse_up():winio = __get_winio()wait_SEO靠我for_buffer_empty();winio.set_port_byte(KBC_KEY_CMD, 0xd3);wait_for_buffer_empty();winio.set_port_dwoSEO靠我rd(KBC_KEY_DATA, 0x08)def key_press(scancode, press_time = 0.05):key_down( scancode )time.sleep( preSEO靠我ss_time )key_up( scancode )time.sleep(0.05)def SPkey_press(scancode, press_time = 0.05):SPkey_down( SEO靠我scancode )time.sleep( press_time )SPkey_up( scancode )time.sleep(press_time)def mouse_clicked(clickeSEO靠我d_time = 0.05):mouse_down()time.sleep( clicked_time )mouse_up()time.sleep( clicked_time )

https://bloSEO靠我g.csdn.net/qq_37232329/article/details/79926440

上面的链接为扫描码

4.人物移动

从上面得知人物、怪物、门的坐标,可以移动。在移动之前,先计算移动速度。

主要代SEO靠我码如下:

def moveTo(monsters_x,monsters_y,person_x,person_y,flag = 0): flag = 1 时,为 人物 向 门口 移动flag = 0 时,SEO靠我为 人物 向 怪物 移动 , 距离怪物 80 个像素时 , 释放技能if(flag==0):# 释放技能的位置,在怪物前方60像素skill_pos = 60else:skill_pos = 0# 1SEO靠我 怪物 在 人物 的 右上if((person_x - monsters_x)<0 and (person_y - monsters_y) >0):if(monsters_x - person_x <SEO靠我skill_pos):print(距离右边怪物挺近,直接往上移动)key_press(0x34)key_press(0x25, abs(person_y - monsters_y) / y_speedSEO靠我)else:move_time = abs(monsters_x - person_x - skill_pos) / x_speed - abs(person_y - monsters_y) / y_SEO靠我speedif (move_time > 0):print(跑啊跑,往右上移动)key_press(0x34)key_down(0x34)time.sleep(0.1)key_press(0x25, SEO靠我abs(person_y - monsters_y) / y_speed)time.sleep(move_time)key_up(0xb4)else:print(不值得跑,先往右,后往上)key_prSEO靠我ess(0x34)key_press(0x34, abs(monsters_x -skill_pos- person_x) / x_speed)key_press(0x25, abs(person_ySEO靠我 - monsters_y) / y_speed)

5.释放技能

剑魂的技冷却时间,释放技能时间。此方法计算的是可用的技能。可以继续优化,如:加入技能释放范围;或者按照一定顺序计算冷却时间最短的技能。

liSEO靠我st_to_time = [0,0,0,0,0,0,0,0,0,0,0] list_skill = [q, e, w, d,t,y,a,s,f,g,h] list_skSEO靠我ill_cooling = [ 6.8, 9.6, 32, 9, 37, 103, 22, 0, 17.5,36, 120] skill_release_time = [ 0.5, 0SEO靠我.5, 3, 0.5, 0.5, 7, 5, 0.3, 1, 1.5, 2] list_key = [0x10,0x12,0x11,0x20,0x14,0x15,0x1e,0x1f,0SEO靠我x21,0x22,0x23] def rel_skill(skill,ini_time):for i in list_skill:while(skill==i):list_to_timSEO靠我e[list_skill.index(i)] = ini_time + list_skill_cooling[list_skill.index(i)] + skill_release_time[lisSEO靠我t_skill.index(i)]f = open(data.txt,w)for j in range(len(list_skill)):f.write(str(list_to_time[j])+\nSEO靠我)f.close()key_press(list_key[list_skill.index(i)])time.sleep(skill_release_time[list_skill.index(i)]SEO靠我+0.8)breakreturn

屏幕快照

截图

import win32gui,win32ui,win32con,win32api from key import * deSEO靠我f window_capture(filename,flag = 0):hwnd = win32gui.FindWindow(None, "地下城与勇士")# 根据窗口句柄获取窗口的设备上下文DC(DSEO靠我ivice Context)hwndDC = win32gui.GetWindowDC(hwnd)win32gui.SetForegroundWindow(hwnd)# 根据窗口的DC获取mfcDCmSEO靠我fcDC = win32ui.CreateDCFromHandle(hwndDC)# mfcDC创建可兼容的DCWsaveDC = mfcDC.CreateCompatibleDC()# 创建bigmSEO靠我ap准备保存图片saveBitMap = win32ui.CreateBitmap()# 获取监控器信息left, top, right, bottom = win32gui.GetWindowRecSEO靠我t(hwnd)width = right - leftheight = bottom - topsaveBitMap.CreateCompatibleBitmap(mfcDC, width, heigSEO靠我ht)# 高度saveDC,将截图保存到saveBitmap中saveDC.SelectObject(saveBitMap)# 截取从左上角(0,0)长宽为(w,h)的图片if flag==0:savSEO靠我eDC.BitBlt((0, 0), (width, height), mfcDC, (0, 0), win32con.SRCCOPY)saveBitMap.SaveBitmapFile(saveDCSEO靠我, filename)else:saveDC.BitBlt((720, 795), (75, 60), mfcDC, (0, 0), win32con.SRCCOPY)saveBitMap.SaveBSEO靠我itmapFile(saveDC, ./pos.png)return width, height

结语

水平有限,花了5天时间修改npk文件,10几天写代码。初学python,我所会的就只是一些基础以及一SEO靠我丁点制作思路,没有后续的成品,谢谢。

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2