教你写页游自动化Python脚本,取色,大漠识别和后台点击
off999 2024-10-21 06:52 32 浏览 0 评论
本教程为新手学习python教程
废话少说,下面开始python教程
我们先用tkinter搭建好脚本的基本界面
私信小编01即可获取大量Python学习资源
import tkinter as tk#[size=3]首先导入tkinter,需要事先用pip安装进python里(方法自行百度)[/size]
def init_window():
global cs,wd
wd = tk.Tk()
cs = tk.Canvas(wd,
width = 800,
height = 500,
bg = 'white')
wd.minsize(800, 500) # 最小尺寸
wd.maxsize(800, 500)#最大尺寸,使最大化失效
wd.title('DDTHelper')
pic = tk.PhotoImage(file="pic.png")#设置背景图片,最好是800*500和png格式的
cs.create_image(400,250,image = pic)
cs.pack()
bt = tk.Button(wd,
text='初始化',
bg=('white'),
font=('微软雅黑',20),
width=155,
height=48,
command=BT_onCreat)
bt.pack()
cs.create_window(530,70,
width=155,
height=48,
window=bt)
wd.mainloop()
def BT_onCreat():
print("初始化。。。")
#入口,这行代码需要一直都待在脚本的最底下
#设置字典
hwnd_title = dict()
init_window()(不过在图片上叠加控件其实有更好的方案,使控件的背景为透明的,但是那篇文章的代码运行不来)
运行效果
现在我们为点击 初始化 按钮添加一些事项
让他在被点击的时候识别当前的游戏窗口
(因为我用的是36jb大厅登录的游戏,抓取句柄的时候可以根据他的title来区别游戏窗口)
这里我偷了个懒,利用该登录器游戏窗口的title来获取
更改上面的导入库和 BT_onCreat()方法
import win32com.client as wc,win32gui as wg,threading as xc,time,tkinter as tk,win32api as wa,win32con as wn#需要事先用pip安装pywin32插件进python里(方法自行百度)
def init_window():
global cs,wd
wd = tk.Tk()
cs = tk.Canvas(wd,
width = 800,
height = 500,
bg = 'white')
wd.minsize(800, 500) # 最小尺寸
wd.maxsize(800, 500)#最大尺寸,使最大化失效
wd.title('DDTHelper')
pic = tk.PhotoImage(file="pic.png")#设置背景图片,最好是800*500和png格式的
cs.create_image(400,250,image = pic)
cs.pack()
bt = tk.Button(wd,
text='初始化',
bg=('white'),
font=('微软雅黑',20),
width=155,
height=48,
command=BT_onCreat)
bt.pack()
cs.create_window(530,70,
width=155,
height=48,
window=bt)
wd.mainloop()
def BT_onCreat():
global is_run,Znum,t1,t2,t3
Znum = 0#当前已经登陆的游戏账号数量
wg.EnumWindows(get_all_hwnd, 0)
for h,t in hwnd_title.items():
if "4399" in t:#根据title里包含的 4399 来提取游戏窗口
hwnd = t.split("|")[3]
name = t.split("|")[2]
print("账号:" + name + "句柄:" + hwnd)
Znum = Znum + 1
hwnd = int(hwnd)#将句柄转化为int,因为句柄是从标题获取的string,导致了类型错误,我就是被这个坑了好久。。
if Znum==1:#为每一个游戏界面创建一个单独的操作线程,为了方便用global传递,没有用exec。
t1 = xc.Thread(target=Con,args=(hwnd,name,Znum))
elif Znum==2:
t2 = xc.Thread(target=Con,args=(hwnd,name,Znum))
elif Znum==3:
t3 = xc.Thread(target=Con,args=(hwnd,name,Znum))
init_control(Znum,name)
#下面再添加几个方法进去
#获取句柄用的
def get_all_hwnd(hwnd,mouse):
if wg.IsWindow(hwnd) and wg.IsWindowEnabled(hwnd) and wg.IsWindowVisible(hwnd):
hwnd_title.update({hwnd:wg.GetWindowText(hwnd)})
#为每一个线程创建一个对应的控件来控制线程的运行
def init_control(Znum,name):
global cs,wd,v1,v2,v3,tx1,t2,tx2,t3,tx3,txn1,txn2,txn3
if Znum==1:
v1=tk.IntVar()
tx1=tk.StringVar()
txn1=tk.StringVar()
elif Znum==2:
v2=tk.IntVar()
tx2=tk.StringVar()
txn2=tk.StringVar()
elif Znum==3:
v3=tk.IntVar()
tx3=tk.StringVar()
txn3=tk.StringVar()
exec('tx{}.set("未运行")'.format(Znum))
exec('lb{} = tk.Label(wd,text="{}",bg=("#ffffff"),font=("微软雅黑",20))'.format(Znum,name))
exec('lbn{} = tk.Label(wd,textvariable=txn{},bg=("#ffffff"),font=("微软雅黑",10))'.format(Znum,Znum))
exec('cb{} = tk.Checkbutton(wd,textvariable=tx{},bg=("#ffffff"),font=("微软雅黑",10),variable = v{}, height=5,width = 0,command=BT_onRun{})'.format(Znum,Znum,Znum,Znum))
exec('cb{}.pack()'.format(Znum))
exec('lb{}.pack()'.format(Znum))
exec('lbn{}.pack()'.format(Znum))
Ytmp=Znum*100
Ytmp=Ytmp+70
exec('cs.create_window(630,{},width=0,height=0,window=lb{})'.format(Ytmp,Znum))
Ytmp=Ytmp+40
exec('cs.create_window(630,{},width=35,height=25,window=lbn{})'.format(Ytmp,Znum))
exec('cs.create_window(710,{},width=70,height=25,window=cb{})'.format(Ytmp,Znum))
#线程方法
def Con(hwnd,name,xc):
print("启动成功")
#多选框点击事件
def BT_onRun1():
global v1,tx1,t1,ct1
if v1.get()==1:#判断是否被选中
ct1=0
tx1.set('正运行')
t1.start()
else:
ct1=1#用来控制线程终止
tx1.set('未运行')
def BT_onRun2():
global v2,tx2,ct2
if v2.get()==1:#判断是否被选中
ct2=0
tx2.set('正运行')
t2.start()
else:
ct2 = 1
tx2.set('未运行')
def BT_onRun3():
global v3,tx3,ct3
if v3.get()==1:#判断是否被选中
ct3=0
tx3.set('正运行')
t3.start()
else:
ct3=1
tx3.set('未运行')
#入口,这行代码需要一直都待在脚本的最底下
#设置字典
hwnd_title = dict()
init_window()运行后,点击初始化的效果
可以看到,当只有一个游戏窗口的时候,脚本就自动识别出了该游戏窗口。(目前最多识别3个,且不能二次点击初始化,否则会报错。听说用exce动态封装线程时可以用dict来接收,而目前二次识别也有了大致方案)
并在勾选 未运行 旁边的 框框 时,运行对应的线程。
接下来就要到脚本的线程模块了,而有过py基础的人都知道,py的线程是没有stopThread的
但我们将要实现如何控制脚本执行游戏操作的线程,让它收放自如
下面教程开始
因为接下来的脚本是精简过的,和上次帖子略有不同,以这次帖子为准
我们先像上个帖子一样搭建好一个界面的代码,以此作为平台
import win32com.client as wc,win32gui as wg,threading as xc,time,tkinter as tk,win32api as wa,win32con as wn,multiprocessing as jc
def init_window():
global cs,wd
wd = tk.Tk()
cs = tk.Canvas(wd,
width = 800,
height = 500,
bg = 'white')
wd.minsize(800, 500) # 最小尺寸
wd.maxsize(800, 500)
wd.title('DDTHelper')
pic = tk.PhotoImage(file="pic.png")
cs.create_image(400,250,image = pic)
cs.pack()
bt = tk.Button(wd,
text='初始化',
bg=('white'),
font=('微软雅黑',20),
width=155,
height=48,
command=BT_onCreat)
bt.pack()
cs.create_window(530,70,
width=155,
height=48,
window=bt)
wd.mainloop()
def init_control(Znum,name):
global v1,v2,v3,tx1,t2,tx2,t3,tx3,txn1,txn2,txn3
if Znum==1:
v1=tk.IntVar()
tx1=tk.StringVar()
#txn1=tk.StringVar()
elif Znum==2:
v2=tk.IntVar()
tx2=tk.StringVar()
#txn2=tk.StringVar()
elif Znum==3:
v3=tk.IntVar()
tx3=tk.StringVar()
#txn3=tk.StringVar()
exec('tx{}.set("未运行")'.format(Znum))
exec('lb{} = tk.Label(wd,text="{}",bg=("#ffffff"),font=("微软雅黑",20))'.format(Znum,name))
#exec('lbn{} = tk.Label(wd,textvariable=txn{},bg=("#ffffff"),font=("微软雅黑",10))'.format(Znum,Znum))
exec('cb{} = tk.Checkbutton(wd,textvariable=tx{},bg=("#ffffff"),font=("微软雅黑",10),variable = v{}, height=5,width = 0,command=BT_onRun{})'.format(Znum,Znum,Znum,Znum))
exec('cb{}.pack()'.format(Znum))
exec('lb{}.pack()'.format(Znum))
#exec('lbn{}.pack()'.format(Znum))
Ytmp=Znum*100
Ytmp=Ytmp+70
exec('cs.create_window(630,{},width=0,height=0,window=lb{})'.format(Ytmp,Znum))
Ytmp=Ytmp+40
#exec('cs.create_window(630,{},width=35,height=25,window=lbn{})'.format(Ytmp,Znum))
exec('cs.create_window(710,{},width=70,height=25,window=cb{})'.format(Ytmp,Znum))
def BT_onCreat():
global Znum,D1,D2,D3,conT
Znum = 0
wg.EnumWindows(get_all_hwnd, 0)
conT=jc.Manager().Array("i",[3,0,0,0])#用来控制进程
#lock = jc.Lock()#用来给进程运行顺序排序,防止显示错乱,打包成exe时可以去除(如果出现错误 windos 什么的就改成lock = jc.Manager.Lock() 这样就可以了,或者删掉Manager)
#lock不稳定,弃用
for h,t in hwnd_title.items():
if "4399" in t:
hwnd = t.split("|")[3]
name = t.split("|")[2]
print("账号:" + name + "句柄:" + hwnd)
Znum = Znum + 1
hwnd = int(hwnd)
init_control(Znum,name)
if Znum==1:
D1 = jc.Manager().Array("i",[1,hwnd])
elif Znum==2:
D2 = jc.Manager().Array("i",[2,hwnd])
elif Znum==3:
D3 = jc.Manager().Array("i",[3,hwnd])
def get_all_hwnd(hwnd,mouse):
if wg.IsWindow(hwnd) and wg.IsWindowEnabled(hwnd) and wg.IsWindowVisible(hwnd):
hwnd_title.update({hwnd:wg.GetWindowText(hwnd)})
def Con(data,conT):
#l.acquire()#锁
#try:
print("运行成功")
#finally:
#l.release()
def onRunMan(Znum):
if onRunMan2(Znum) == 1:
conT[Znum]=0
exec('p{} = jc.Process(target=Con,args=(D{},conT))'.format(Znum,Znum))
exec('p{}.daemon=True'.format(Znum))
exec('tx{}.set("运行中")'.format(Znum))
exec('p{}.start()'.format(Znum))
else:
conT[Znum]=1
exec('tx{}.set("未运行")'.format(Znum))
def onRunMan2(Znum):
if Znum ==1:
return v1.get()
elif Znum == 2:
return v2.get()
elif Znum ==3:
return v3.get()
def BT_onRun1():
onRunMan(1)
def BT_onRun2():
onRunMan(2)
def BT_onRun3():
onRunMan(3)
if __name__ == '__main__':
hwnd_title = dict()
init_window()成功识别后,我们勾上运行的钩子
成功的话会在终端显示 成功运行
这次我在onCreat方法里封装需要发送给进程的数据
然后在onRunMain中动态拼装进程并启动它
再让产生的子进程来生成守护线程,让守护线程去操控游戏
然后子进程循环检测我们是不是发出了停止命令,如果线程检测到我们发出了停止的命令
自身的代码就执行完了,然后带动他产生的守护线程也被kill掉了。
这样就可以实现多线程的随时停止了
代码还巧妙借用了exec指令的“特性”:输出变量只能在该方法内可见,一旦该方法被重启,变量就没了
也就是说,如果我们直接用 p1 = jc.Process(target=Con,args=(D1,conT))来产生进程
那么在进程结束后,需要用 del p1来清除掉进程的“尸体”,然后再重新创建它
设置的Con方法代码,让它会自己生产守护线程
def Con(hwnd,Znum,conT,l):
#设置守护线程
time.sleep(1)
exec('t{} = xc.Thread(target=RunMain,args=(hwnd,Znum))'.format(Znum))#依靠Znum(游戏账号分配到的id)来动态生成不同的线程
exec('t{}.setDaemon(True)'.format(Znum))
exec('t{}.start()'.format(Znum))
while True:#开始接收我们是否发出了停止的命令
if conT[Znum] == 0:
time.sleep(1)
else:
break
print('进程' + str(Znum) +':已退出')再补充它生产出的子线程所执行的方法(不可用)
def RunMain(hwnd,Znum):
RM=0#运行次数,因为用多进程后无法向用户节目输出,所以已弃用
hdc=wg.GetWindowDC(int(hwnd))#获取目标页游(flash)的hdc,用来获取指定坐标的颜色
while True:
while str(wg.GetPixel(hdc,919,280))!=str(10248996):#检测游戏角色是否处在房间界面(初始需要用户手动将游戏角色进入房间界面),用于检测游戏角色是否退出了副本回到了游戏房间
print("房间")
doClick(hwnd,5,5)
time.sleep(1)
if Chose_FB(hwnd,hdc) == 1:#查看当前两个副本中又那个副本开放,其实这个设计并不合理,如果当前没副本开放就出bug了,不过我只会在有副本开放才会运行这个脚本对吧-,-
FB_MS(hwnd,hdc)#启动1号副本方案
else:
FB_JD(hwnd,hdc)#二号副本方案
RM = RM + 1当然,,现在由于主题和篇幅原因,我就不补充副本的流程方法了, 但这样可能会导致运行时报错
我们可以将它删减成
def RunMain(hwnd,Znum):
white True:
print("我在运行")
time.sleep(1)这样在勾选运行的时候,
终端就会不停地显示 我在运行
直到我们把运行的钩子取消后,就不会再显示了(线程被kill掉了)
熟悉按键精灵的大佬们都应该用过一个叫大漠的插件
但先讲不依赖大漠的情况下,用微软官方的指令来实现脚本的操作
import win32com.client as wc,win32gui as wg,threading as xc,time,tkinter as tk,win32api as wa,win32con as wn,multiprocessing as jc
def init_window():
global cs,wd
wd = tk.Tk()
cs = tk.Canvas(wd,
width = 800,
height = 500,
bg = 'white')
wd.minsize(800, 500) # 最小尺寸
wd.maxsize(800, 500)
wd.title('DDTHelper')
pic = tk.PhotoImage(file="pic.png")
cs.create_image(400,250,image = pic)
cs.pack()
bt = tk.Button(wd,
text='初始化',
bg=('white'),
font=('微软雅黑',20),
width=155,
height=48,
command=BT_onCreat)
bt.pack()
cs.create_window(530,70,
width=155,
height=48,
window=bt)
wd.mainloop()
def init_control(Znum,name):
global v1,v2,v3,tx1,t2,tx2,t3,tx3,txn1,txn2,txn3
if Znum==1:
v1=tk.IntVar()
tx1=tk.StringVar()
#txn1=tk.StringVar()
elif Znum==2:
v2=tk.IntVar()
tx2=tk.StringVar()
#txn2=tk.StringVar()
elif Znum==3:
v3=tk.IntVar()
tx3=tk.StringVar()
#txn3=tk.StringVar()
exec('tx{}.set("未运行")'.format(Znum))
exec('lb{} = tk.Label(wd,text="{}",bg=("#ffffff"),font=("微软雅黑",20))'.format(Znum,name))
#exec('lbn{} = tk.Label(wd,textvariable=txn{},bg=("#ffffff"),font=("微软雅黑",10))'.format(Znum,Znum))
exec('cb{} = tk.Checkbutton(wd,textvariable=tx{},bg=("#ffffff"),font=("微软雅黑",10),variable = v{}, height=5,width = 0,command=BT_onRun{})'.format(Znum,Znum,Znum,Znum))
exec('cb{}.pack()'.format(Znum))
exec('lb{}.pack()'.format(Znum))
#exec('lbn{}.pack()'.format(Znum))
Ytmp=Znum*100
Ytmp=Ytmp+70
exec('cs.create_window(630,{},width=0,height=0,window=lb{})'.format(Ytmp,Znum))
Ytmp=Ytmp+40
#exec('cs.create_window(630,{},width=35,height=25,window=lbn{})'.format(Ytmp,Znum))
exec('cs.create_window(710,{},width=70,height=25,window=cb{})'.format(Ytmp,Znum))
def BT_onCreat():
global Znum,D1,D2,D3,conT
Znum = 0
wg.EnumWindows(get_all_hwnd, 0)
conT = jc.Manager().Array("i",[3,0,0,0])
for h,t in hwnd_title.items():
if "4399" in t:
hwnd = t.split("|")[3]
name = t.split("|")[2]
print("账号:" + name + "句柄:" + hwnd)
Znum = Znum + 1
hwnd = int(hwnd)
init_control(Znum,name)
if Znum == 1:
D1 = jc.Manager().Array("i",[1,hwnd])
elif Znum == 2:
D2 = jc.Manager().Array("i",[2,hwnd])
elif Znum == 3:
D3 = jc.Manager().Array("i",[3,hwnd])
def get_all_hwnd(hwnd,mouse):
if wg.IsWindow(hwnd) and wg.IsWindowEnabled(hwnd) and wg.IsWindowVisible(hwnd):
hwnd_title.update({hwnd:wg.GetWindowText(hwnd)})
def all_run(Znum):
while Znum >0:
exec('t{}.start()'.format(Znum))
Znum = Znum - 1
#操作类--------------------------------------------------------------------------------------------------------------
def climb(hwnd,jl,fx):
if fx==1:#右边
#适应方向及防止无效
wa.SendMessage(hwnd,wn.WM_KEYDOWN,68,None)
wa.SendMessage(hwnd,wn.WM_KEYUP,68,None)
#1.3=1屏距
wa.SendMessage(hwnd,wn.WM_KEYDOWN,68,None)
time.sleep(jl*1.3)
wa.SendMessage(hwnd,wn.WM_KEYUP,68,None)
else:
#适应方向及防止无效
wa.SendMessage(hwnd,wn.WM_KEYDOWN,65,None)
wa.SendMessage(hwnd,wn.WM_KEYUP,65,None)
#1.3=1屏距
wa.SendMessage(hwnd,wn.WM_KEYDOWN,65,None)
time.sleep(jl*1.3)
wa.SendMessage(hwnd,wn.WM_KEYUP,65,None)
def doAngle(hwnd,jd):
for i in range(jd):
time.sleep(0.05)
wa.SendMessage(hwnd,wn.WM_KEYDOWN,87,None)
wa.SendMessage(hwnd,wn.WM_KEYUP,87,None)
def doClick(hwnd,cx,cy):
long_position = wa.MAKELONG(cx, cy)
wa.SendMessage(hwnd, wn.WM_LBUTTONDOWN, wn.MK_LBUTTON, long_position)
wa.SendMessage(hwnd, wn.WM_LBUTTONUP, wn.MK_LBUTTON, long_position)
def doFire(hwnd,ld):
wa.SendMessage(hwnd,wn.WM_KEYFIRST,66,None)#先摁大
wa.SendMessage(hwnd,wn.WM_KEYFIRST,69,None)#先摁技能
wa.SendMessage(hwnd,wn.WM_KEYFIRST,97,None)
wa.SendMessage(hwnd,wn.WM_KEYFIRST,98,None)
wa.SendMessage(hwnd,wn.WM_KEYFIRST,97,None)#11大招
wa.SendMessage(hwnd,wn.WM_KEYFIRST,100,None)
wa.SendMessage(hwnd,wn.WM_KEYDOWN,32,None)
time.sleep(ld * 0.04)
wa.SendMessage(hwnd,wn.WM_KEYUP,32,None)
#游戏流程处理类---------------------------------------------------------------------------------------------------------
def Chose_FB(hwnd,hdc):
doClick(hwnd,600,200)#打开菜单
time.sleep(1)
doClick(hwnd,626,188)#单人副本
time.sleep(1)
while True:
doClick(hwnd,5,5)
if str(wg.GetPixel(hdc,244,237))==str(2041582):
doClick(hwnd,289,243)#魔石
FBn=1
break
elif str(wg.GetPixel(hdc,337,278))==str(13298869):
doClick(hwnd,292,299)#技能丹
FBn=2
break
time.sleep(1)
doClick(hwnd,726,501)#难度
time.sleep(1)
doClick(hwnd,504,563)#确定
time.sleep(1)
doClick(hwnd,951,491)
return(FBn)
def FB_MS(hwnd,hdc):
time.sleep(24)
while str(wg.GetPixel(hdc,497,169))!=str(5418993):#回合检测
doClick(hwnd,5,5)
time.sleep(0.5)
while True:
doClick(hwnd,5,5)
colx=wg.GetPixel(hdc,917,486)
if str(colx)==str(36645):
print("位置1")
JD=18
break
else:
print("位置2")
climb(hwnd,0.5,0)
JD=25
break
wa.SendMessage(hwnd,wn.WM_KEYFIRST,69,None)#波谷专用
wa.SendMessage(hwnd,wn.WM_KEYFIRST,80,None)#第一次pass
time.sleep(5)
for i in range(2):
while str(wg.GetPixel(hdc,497,169))!=str(5418993):#回合检测
doClick(hwnd,5,5)
time.sleep(0.5)
wa.SendMessage(hwnd, wn.WM_KEYDOWN, 65, None)
wa.SendMessage(hwnd, wn.WM_KEYUP, 65, None)
doFire(hwnd,20)
time.sleep(6)
doAngle(hwnd,JD)
time.sleep(10)
while True:
#回合循环
cs = 0
while str(wg.GetPixel(hdc,497,169))!=str(5418993):#回合检测
if cs>=20:#超时退出
break
else:
doClick(hwnd,5,5)
time.sleep(1)
cs=cs+1
#退出
if cs==20:
print("退出副本")
break
else:
doFire(hwnd,20)
def FB_JD(hwnd,hdc):
while True:
cs = 0
cg = 0
while str(wg.GetPixel(hdc,497,169))!=str(5418993):#回合检测
if cs>=20:#超时退出
cg=1
cs=0
break
else:
doClick(hwnd,5,5)
time.sleep(1)
cs=cs+1
if cg==1:
break
else:
doFire(hwnd,60)
#程序流程模块类----------------------------------------------------------------------------------------------------------
def RunMain(hwnd):
RM=0
hdc=wg.GetWindowDC(hwnd)
while True:
while str(wg.GetPixel(hdc,919,280))!=str(10248996):#房间检测
print("房间")
doClick(hwnd,5,5)
time.sleep(1)
if Chose_FB(hwnd,hdc) == 1:
FB_MS(hwnd,hdc)
else:
FB_JD(hwnd,hdc)
RM = RM + 1
def Con(Data,conT):
#设置守护线程
Znum = Data[0]
print(str(Data[0]))
hwnd = Data[1]
time.sleep(1)
exec('t{} = xc.Thread(target=RunMain,args=(hwnd,))'.format(Znum))
exec('t{}.setDaemon(True)'.format(Znum))
exec('t{}.start()'.format(Znum))
while True:
if conT[Znum] == 0:
time.sleep(1)
else:
break
print('进程' + str(Znum) +':已退出')
def onRunMan(Znum):
if onRunMan2(Znum) == 1:
conT[Znum]=0
exec('tx{}.set("运行中")'.format(Znum))
exec('p{} = jc.Process(target=Con,args=(D{},conT))'.format(Znum,Znum))
exec('p{}.daemon=True'.format(Znum))
exec('p{}.start()'.format(Znum))
else:
conT[Znum]=1
#exec('del p{}'.format(Znum))
exec('tx{}.set("未运行")'.format(Znum))
def onRunMan2(Znum):
if Znum ==1:
return v1.get()
elif Znum == 2:
return v2.get()
elif Znum ==3:
return v3.get()
def onRunMan3(Znum):
if Znum ==1:
if p1.is_alive:
return(1)
else:
return(0)
elif Znum == 2:
if p2.is_alive:
return(1)
else:
return(0)
elif Znum ==3:
if p3.is_alive:
return(1)
else:
return(0)
def BT_onRun1():
onRunMan(1)
def BT_onRun2():
onRunMan(2)
def BT_onRun3():
onRunMan(3)
if __name__ == '__main__':
hwnd_title = dict()
init_window()我已经将模块代码用--区分开来
之前我们讲过了 窗口界面 和 程序线程
重点在于 操作类
负责向指定游戏窗口发生鼠标点击命令的方法
def doClick(hwnd,cx,cy):
long_position = wa.MAKELONG(cx, cy)#模拟鼠标指针 传送到指定坐标
wa.SendMessage(hwnd, wn.WM_LBUTTONDOWN, wn.MK_LBUTTON, long_position)#模拟鼠标按下
wa.SendMessage(hwnd, wn.WM_LBUTTONUP, wn.MK_LBUTTON, long_position)#模拟鼠标弹起这个方法把原本复杂的代码压缩了,于是我们要点击游戏界面的时候,就可以调用该方法来实现,比如
doClick(目标窗口句柄,x坐标,y坐标)
是不是就有内味了?
再看看其他方法
def climb(hwnd,jl,fx):
if fx==1:#右边
#适应方向及防止无效
wa.SendMessage(hwnd,wn.WM_KEYDOWN,68,None)
wa.SendMessage(hwnd,wn.WM_KEYUP,68,None)
#1.3秒=1屏距
wa.SendMessage(hwnd,wn.WM_KEYDOWN,68,None)
time.sleep(jl*1.3)
wa.SendMessage(hwnd,wn.WM_KEYUP,68,None)
else:
#适应方向及防止无效
wa.SendMessage(hwnd,wn.WM_KEYDOWN,65,None)
wa.SendMessage(hwnd,wn.WM_KEYUP,65,None)
#1.3=1屏距
wa.SendMessage(hwnd,wn.WM_KEYDOWN,65,None)
time.sleep(jl*1.3)
wa.SendMessage(hwnd,wn.WM_KEYUP,65,None)
def doAngle(hwnd,jd):
for i in range(jd):
time.sleep(0.05)
wa.SendMessage(hwnd,wn.WM_KEYDOWN,87,None)
wa.SendMessage(hwnd,wn.WM_KEYUP,87,None)
def doFire(hwnd,ld):
wa.SendMessage(hwnd,wn.WM_KEYFIRST,66,None)#先摁大招
wa.SendMessage(hwnd,wn.WM_KEYFIRST,69,None)#先摁技能
wa.SendMessage(hwnd,wn.WM_KEYFIRST,97,None)
wa.SendMessage(hwnd,wn.WM_KEYFIRST,98,None)#如果有大招,
wa.SendMessage(hwnd,wn.WM_KEYFIRST,97,None)#11大招
wa.SendMessage(hwnd,wn.WM_KEYFIRST,100,None)
wa.SendMessage(hwnd,wn.WM_KEYDOWN,32,None)#空格蓄力
time.sleep(ld * 0.04)#每蓄力1力度约用时0.04秒,受游戏延迟和电脑性能会有误差,总体可以接受,也可以改成识别力度条(更精准,但因为力度条颜色不纯干扰暂且搁置方案)
wa.SendMessage(hwnd,wn.WM_KEYUP,32,None)#松开空格这里的方法基本都是发送一些键盘操作的集合
比如说
方法climb是用来控制游戏中人物的爬行,
方法doAngle是用来调整游戏中人物发射炮弹的角度
方法doFire就是操作游戏人物发动攻击
总结以上方法,模拟键盘按键有3条指令
wa.SendMessage(游戏窗口句柄,wn.WM_KEYDOWN,按键码,None)
wa.SendMessage(游戏窗口句柄,wn.WM_KEYUP,按键码,None)
wa.SendMessage(游戏窗口句柄,wn.WM_KEYFIRST,按键码,None)它们分别是向游戏窗口发送 摁下指定按键 弹起指定按键 和集合摁下和弹起一体的 点击指定按键
但需要注意的是
如果需要重复点击一个按键的时候,千万不要用 点击指定按键 这个代码
这样会产生一个bug,相当于按下了按键却没有弹起,导致失控
需要像doAngle方法那样,使用按下和弹起来保证不会出bug
然后再到游戏取色
因为没有提取的必要,我就没有单独分离出来
取色需要用到hdc(想知道hdc的可以去百度 hdc和hwnd)
hdc=wg.GetWindowDC(int(hwnd))↑利用hwnd来获取hdc
color = wg.GetPixel(hdc,x坐标,y坐标)↑获取指定点的颜色
细心的小伙伴们可以发现
在每个获取颜色的代码附近都有doClick的调用
那是因为防止用户点击了游戏界面后又点击了其他地方,导致游戏窗口失焦,所以使用doClick强制激活窗口
这里需要注意一点
因为这个游戏官方允许使用脚本,所以微软官方的指令是可以用的
否则的话可以尝试用大漠插件或者别的插件来发送硬件级别的模拟按键信息
下面讲解调用大漠插件的方法
大漠插件下载:点我下载
注意:大漠插件是32位的,所以调用时必须使用32位的py,不然会报错
下载好后把里面的dm.dll放在和脚本同一个目录下
使用
import win32com.client
dm = win32com.client.Dispatch('dm.dmsoft') #调用大漠插件
print(dm.ver())#输出版本号就可以成功地调用大漠插件并输出版本号
绑定窗口
dm_ret = dm.BindWindow(hwnd,"gdi", "windows", "windows", 0)绑定字典
dm.setDict(0, '字典.txt')#把字典文件放到和脚本同一个目录下
dm.useDict(0)可以说,在成功注册了大漠插件后
它的使用代码基本和它里面自带的说明书里面的使用代码一致了
需要的小伙伴可以多看看它自带的说明书
不过dm.dll经常被defender报毒。。。导致我想用都用不了
虽然大漠的识别系统很强大,但毕竟是闭源付费,还强制得换成32位python。。
还是少用为妙
相关推荐
- win10怎么开机进入安全模式(win10开机怎么进安全模式怎么进)
-
进入Windows10安全模式有以下几种方法:方法一:使用开机高级选项1.在按下电源开机键后,持续按住F8键,直到你进入启动选项页面;2.从菜单中选择“安全模式”。方法二:使用系统配置1...
- 华硕电脑怎么重新安装系统(华硕电脑怎么重新安装系统教程)
-
第一步:备份重要数据重装系统前,务必先备份重要的个人数据。你可以将数据保存在外部存储设备上,或者使用云存储服务,确保数据安全可靠。第二步:下载系统镜像为了重装系统,你需要下载华硕笔记本电脑适用的操作系...
- 电脑显示此windows副本不是正版
-
1、第一步在电脑搜索框搜索命令提示符,鼠标右键以管理员的身份运行,2、第二步以管理员身份进去命令提示符之后输入"SLMGR-REARM",3、第三步按回车键可以看到命令已经成功重启一下...
- 电脑怎么复制粘贴按键(电脑复制粘贴按键是哪个)
-
电脑键盘上的粘贴键是:Ctrl+V按键。具体操作:1、以在excel表格中进行复制粘贴操作为例,首先选中需要复制粘贴操作的单元格。2、然后按下键盘上的“Ctrl+C”按键执行复制操作。3、然后将鼠标单...
- 笔记本黑屏但还在运行(笔记本电脑黑屏但运行)
-
具体修复方法:1、直接按下电脑机箱上的启动键让电脑重启,等待重新正常进入系统中。然后打开电脑系统盘,右键点击c盘进入属性设置面板中;2、在硬盘的属性设置中切换到工具标签;3、在查错选项中点击检查错误按...
- 从u盘启动怎么弄bios(u盘怎么在bios启动)
-
1、开启电脑,在电脑出现开机画面的时候连续按下“Esc”键进入BIOS设置;(部分电脑可能会是Delete、F2或F6)2、进入BIOSFEATURESSETUP中,将Boot(启动顺序)设定为U...
- 两台电脑怎么共享文件夹(如何把电脑c盘的存储移到d盘)
-
一、QQ共享简单易行既然使用QQ直接传递文件行不通,那么不妨试试使用QQ的文件共享功能。1.共享文件点击QQ面板的“菜单”→“工具”→“共享文件”命令。在打开的共享文件窗口中,单击“新建共享”按钮,...
- 怎么查看电脑产品密钥(怎么查看自己电脑产品密钥)
-
准备工具:电脑1.打开电脑,在电脑中找到我的电脑选项,双击该选项打开我的电脑进入我的电脑主页面。2.在我的电脑主页面中找到磁盘下方的空白位置,鼠标右键单击该位置调出功能选项框。3.在功能选项框中找到下...
- 不知道密码怎么连接wifi网络
-
不知道WiFi密码怎么连接,如果你不知道WiFi密码的话,那我没有办法连接网络,你必须去找WiFi密码是主人,然后询问密码,只有你得到了最准确的密码以后,你才可以开启你的WiFi网络设置,然后输入正确...
- u盘写了保护怎么把保护删掉了
-
U盘写保护可以通过以下几种方法去除:1.取消U盘的写保护开关。有些U盘上面自带写保护的开关,如果被拨到写保护状态时,就会对U盘进行写保护,这种情况解决的办法最简单,直接将开关拨回原位即可。2.修复...
- 深度ghost精简xp(深度ghost文件)
-
windowsxp下运行ghost方法如下:1、首先把GHOST.EXE程序复制到你的硬盘某区上(不要是C区,假如是E区)。2、然后重新启动电脑,重启过程中按DEL键进入BIOS设置,设置为从光驱启...
- 固态硬盘如何安装(固态硬盘如何安装系统)
-
1、首先要在在机箱内找到固态硬盘安装的电源连接线,是从电脑的电源引出的一根线。形状是扁嘴形上面一般印着一个白色的“P4”2、然后要在主板上找固态硬盘的数据接口,用于数据输入输出,俗称SATA接口,再找...
- windows怎么打开注册表(windows怎么打开注册表管理器)
-
方法一、直接打开注册表1、点击屏幕左下角的“开始”按钮,再点击“运行”;2、或者直接按Win键+R键,打开“运行”对话框;3、在“运行”输入框中输入“regedit”命令;4、这样就能够打开注册表编辑...
- windows7安装windows10(windows7安装光盘下载)
-
在安装Win7时,出现提示“Windows无法安装到这个磁盘。这台计算机的硬件可能不支持启动到此磁盘。请确保在计算机的bios菜单中启用了磁盘的控制器。” 解决方法: 1.如果之前你做过BIOS设置,...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
python入门到脱坑 输入与输出—str()函数
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
慕ke 前端工程师2024「完整」
-
失业程序员复习python笔记——条件与循环
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
