欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    教程為新手學習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。。
    還是少用為妙

    金豬腳本(原飛豬腳本)以按鍵精靈教學為主,涉及UiBot,Python,Lua等腳本編程語言,教學包括全自動辦公腳本,游戲輔助腳本,引流腳本,網頁腳本,安卓腳本,IOS腳本,注冊腳本,點贊腳本,閱讀腳本以及網賺腳本等各個領域。想制作腳本和學習按鍵精靈的朋友可以添加按鍵精靈學習交流群:554127455 學習路上不再孤單,金豬腳本伴你一同成長.

    上周跟大家介紹了關于游戲地圖的尋路方式,也以烈焰游戲無題材向大家分享了下最簡單的尋路方法—直接輸入坐標尋路法,看過之后,想必大家對游戲的尋路方式有了一定的認知,小編今天再跟大家分享下進階版的尋路方法,即換算地圖坐標尋路法

    換算地圖坐標尋路法

    神馬叫換算游戲坐標尋路法呢?顧名思義就是游戲地圖上顯示的坐標跟我們屏幕實際坐標不一致,需要通過相應關系的換算才能算出地圖坐標相對于屏幕實際坐標的偏移量,然后鼠標相對偏移量點擊地圖某位置后即可自動進行尋路,聽到這里估計大家還是不大懂,沒關系,下面小編就以神途游戲為例子,跟大家深度解析下

    游戲地圖




    圖上左上角紅色的點0,0為游戲地圖的起始坐標,

    右下角紅色的點為游戲地圖的終點坐標830,690,

    但是實際上我們用qq截圖功能對地圖區域進行截圖

    會發現該地圖圖片的實際大小大概只有660*415像素,

    除了游戲初始(0,0)坐標跟實際鼠標偏移坐標一致外,

    其他游戲地圖坐標跟實際鼠標偏移坐標都是不一致的

    再進一步來講就是相對于游戲地圖初始點坐標(0,0)來講

    游戲坐標(830,690)=實際鼠標偏移坐標(660,412)

    那根據這個關系我們怎么進行坐標換算呢

    坐標換算

    該游戲地圖的大小都是660*412像素(實際是600*375,上傳到論壇變大了,為了方便對照,我們就以上面的圖片為例),那比如我們當前人物如上圖所示坐標是(258,266),游戲地圖最大坐標是(830,690),那么相對于游戲地圖起始坐標(0,0)點來講,我們人物角色當前的所在位置(也就是地圖上橘黃色的點的中心位置)就應該等于:

    實際偏移X坐標=int(660/830*258)=205

    實際偏移Y坐標=int(412/690*266)=159


    到底對不對呢,我們不妨用大漠綜合工具的浮動抓圖功能截取上面的圖片來驗證看看:




    有圖有真相,事實證明小編的計算是正確的

    思路流程




    技術難點:

    1.地圖名不一樣所對應的地圖最大X、Y坐標都不一樣

    2.如何確定地圖初始點(0,0)位置,然后進行坐標換算后偏移

    3.移動過程中,如何判斷人物是否已經移動到了指定坐標點,開始下一步動作

    綁定窗口

    今天我們寫的腳本有用到大漠插件,并且是后臺的

    因為是單開腳本,頂層窗口句柄就是游戲所對應的客戶區句柄,所有用的是大漠的findwindow命令,查找符合類名或者標題名的頂層 可見窗口

    后臺綁定模式:

    圖色模式:dx2

    鼠標模式:windows

    鍵盤模式:windows

    關于大漠綁定模式如何獲知

    請參閱相關院刊:

    【院刊】-【201501期】沙盤后臺綁定游戲

    判斷地圖名



    游戲左下角會顯示地圖名及坐標,由于游戲不同的地圖對應的游戲最大X坐標、Y坐標都是不一樣的,所以我們要先識別當前的地圖名,然后根據識別到的地圖名對最大X坐標、Y坐標進行相應賦值,由于左下角會顯示地圖名和坐標,相互之間有時會有影響,所以做了倆個字庫(坐標字庫、地圖名字庫),分開調用

    打開地圖

    為了避免地圖已經打開的情況

    我們要先判斷地圖有沒有打開,沒有打開的話才去按Tab鍵打開地圖

    因為后面我們找字的時候就是要在地圖上找字,所以我們先進行找字

    沒找到字的情況下說明地圖沒打開,再按Tab鍵打開地圖

    確定地圖初始點坐標

    找地圖上的"復活區"字,找到后就會得到該字左上角第一點坐標(IntX,IntY)然后通過大漠工具精確抓圖獲取到地圖初始點位置(0,0)相對于"復活區" 偏移的坐標



    地圖起始點X坐標=IntX-154

    地圖起始點Y坐標=IntY+31

    判斷尋路是否到達

    這個在上一期的尋路院刊已經介紹過了,這邊就不重復說明了,具體請查看院刊:按鍵有屎以來最智能尋路系列

    整體代碼

    1. Call 注冊大漠()
    2. Set dm = createobject("dm.dmsoft")//創建大漠對象
    3. Call 找句柄()
    4. Delay 100
    5. Call 大漠綁定()
    6. dm_ret = dm.SetPath("D:\test")//設置全局路徑
    7. dm_ret = dm.SetDict(0, "神途地圖名字庫.txt")//設置字庫為地圖名字庫為0號字庫
    8. dm_ret = dm.SetExactOcr(1)//設置找字方式為精確查找,避免類似字符的干擾
    9. //地圖起始點X坐標=找"復活區"字-155
    10. //地圖起始點Y坐標=找"復活區"字+31
    11. Delay 1000
    12. Call 尋路(360, 360)
    13. Function 尋路(X坐標, Y坐標)
    14. Call 識別當前地圖名//主要作用在于給當前地圖最大X、Y坐標賦值
    15. dm_ret = dm.SetDict(1, "神途坐標字庫.txt")//設置坐標字庫為1號字庫
    16. dm_ret = dm.UseDict(1)//使用1號字庫來找字
    17. Call 找字
    18. Delay 1000
    19. x =int(600/地圖最大X坐標*X坐標)
    20. y =int(375/地圖最大Y坐標*Y坐標)
    21. TracePrint x
    22. TracePrint y
    23. dm.MoveTo intX-154+x,intY+31+y//相對于地圖起始點坐標進行換算后的鼠標偏移點擊
    24. Delay 1000
    25. dm.leftclick
    26. Do
    27. s = dm.Ocr(77,746,133,764, "ffffff-000000", 0.9)
    28. If len(s) > 0 Then
    29. 坐標 = split(s, ":")//分割游戲左下角顯示的x、y坐標
    30. TracePrint "當前角色所在坐標為"&s
    31. // TracePrint cint(坐標(0))
    32. // TracePrint cint(坐標(1))
    33. If (abs(x坐標 - cint(坐標(0))) < 3) and (abs(y坐標 - cint(坐標(1))) < 3) Then //當前位置坐標與指定坐標的距離差的絕對值小于3則判斷到達指定坐標
    34. dm.keypress 9////按tab關閉地圖
    35. Call Plugin.Msg.Tips("到達指定坐標,尋路結束并關閉地圖")//托盤信息提示到達指定坐標
    36. Exit Do
    37. Else Call Plugin.Msg.Tips("尋路中!!!當前角色所在坐標為"&s) //托盤信息提示還未到達指定坐標
    38. End If
    39. End If
    40. Delay 500
    41. Loop
    42. End Function
    43. Function 找字
    44. Do
    45. dm_ret = dm.FindStrFast(0, 0, w, h, "復活區", "ffe34a-000000", 0.9, intX, intY)
    46. If intX >= 0 and intY >= 0 Then
    47. TracePrint intX
    48. TracePrint intY
    49. Exit Do
    50. Else
    51. dm.keypress 9//按tab打開地圖
    52. End If
    53. Delay 2000
    54. loop
    55. End Function
    56. Function 識別當前地圖名
    57. Do
    58. s = dm.Ocr(4,728,200,768, "ffffff-000000", 0.8)//識別當前地圖名
    59. If len(s) > 0 Then
    60. TracePrint s
    61. Select Case s
    62. Case "土城"http://地圖名是"土城"則對當前地圖最大坐標賦值
    63. TracePrint "當前角色在土城"
    64. 地圖最大X坐標=830
    65. 地圖最大Y坐標 = 690
    66. Case "客棧一樓"http://地圖名是"客棧一樓"則對當前地圖最大坐標賦值
    67. 地圖最大X坐標=27
    68. 地圖最大Y坐標 = 31
    69. // Case 其他···
    70. End Select
    71. Exit Do
    72. End If
    73. Delay 1000
    74. Loop
    75. End Function
    76. Function 找句柄
    77. For i = 0 To 20
    78. hwnd = dm.FindWindow("GAME","神途")
    79. Delay 2000
    80. If hwnd > 0 Then
    81. TracePrint hwnd
    82. dm_ret = dm.GetClientSize(hwnd,w,h) //獲取窗口客戶區大小
    83. TracePrint "游戲客戶區寬度:" & w & ",高度:" & h
    84. dm_ret = dm.SetWindowState(hwnd, 1)
    85. Exit For
    86. Elseif i >= 20 Then MsgBox"未檢測到游戲窗口,請確認游戲窗口已經打開"
    87. End If
    88. Next
    89. End Function
    90. Function 注冊大漠()
    91. Dim i
    92. //釋放附件內容
    93. PutAttachment "D:\test", "*.*"
    94. Set ws = createobject("Wscript.Shell")
    95. For i = 0 To 20
    96. //注冊atl跟dm插件
    97. ws.run("regsvr32 atl.dll -s")
    98. ws.run ("regsvr32 D:\test\dm.dll -s")
    99. Delay 200
    100. Set ws = nothing
    101. Set dm = createobject("dm.dmsoft")
    102. ver = dm.ver()
    103. //輸出版本號
    104. If ver <> "" Then
    105. Exit For
    106. End If
    107. Next
    108. If i >= 20 Then
    109. TracePrint "大漠插件注冊失敗!"
    110. EndScript
    111. End If
    112. Set dm = nothing
    113. Delay 10
    114. End Function
    115. Function 大漠綁定
    116. For i = 0 To 20
    117. dm_ret = dm.BindWindowEx(hwnd, "dx2", "windows", "windows", "", 0)'綁定窗口
    118. Delay 500
    119. If dm_ret = 1 Then
    120. TracePrint "綁定窗口成功"
    121. Exit For
    122. Elseif i>=20 Then TracePrint "綁定失敗"
    123. End If
    124. Next
    125. End Function
    126. Sub OnScriptExit()//解綁大漠
    127. dm_ret = dm.UnBindWindow()
    128. End Sub

    復制代碼

    效果演示

    由于游戲窗口里錄制的視頻太大了,壓縮后還是上傳不了,還是只能用代碼演示了

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有