概述
本文講如何通過python發送鍵盤控制命令控制游戲
前篇:深度強化學習制作森林冰火人游戲AI(二)獲取游戲螢屏
后篇:深度強化學習制作森林冰火人游戲AI(四)獲取視窗部分界面
獲取視窗句柄
視窗句柄就像是行程唯一process id 一樣,應該是每個視窗有唯一的handle
獲取視窗句柄的方法
window_name="FlashPlay"
handle=windll.user32.FindWindowW(None, window_name)
嗯,沒錯,復制上篇文章的
查詢句柄的子句柄
一個句柄下面可能還有其他的句柄,就像是程式下面掛著幾個其他的子程式一樣
#handle為父視窗句柄id
def get_child_windows(handle):
'''
獲得parent的所有子視窗句柄
回傳子視窗句柄串列
'''
if not handle:
return
hwndChildList = []
win32gui.EnumChildWindows(handle, lambda hwnd, param: param.append(hwnd), hwndChildList)
return hwndChildList
為什么要有這部分,是因為后續在控制的時候博主發現通過名字找到的這個視窗句柄并不能直接用于控制游戲
但是它的孩子可以
查詢句柄型別
現在我們有一個父親句柄,還有他的若干孩子句柄
但是只有其中一部分能用來控制游戲,那么是那部分有用呢?
這里就用到查詢句柄型別
handle_type=win32gui.GetClassName(handle)
將所有句柄進行查詢,發現結果如下
父親句柄型別:Qt5QWindowIcon
孩子句柄型別:CefBrowserWindow,Chrome_WidgetWin_0,Chrome_RenderWidgetHostHWND
我沒有查到這些型別的區別在哪……
最終經過測驗(測驗方法在后面),發現只有向 Chrome_WidgetWin_0 和 Chrome_RenderWidgetHostHWND 兩個型別的句柄發送控制命令才能控制游戲角色
發送鍵盤控制命令
# 獲取句柄
handle = windll.user32.FindWindowW(None, window_name)
w2hd=win32gui.FindWindowEx(handle, None, None, None)
#選中視窗
win32gui.SetForegroundWindow(w2hd)
#按下按鍵D
win32api.PostMessage(handle, win32con.WM_KEYDOWN,ord('D'), 0)
#延時
time.sleep(self.time_sleep)
#松開按鍵D
win32api.PostMessage(handle, win32con.WM_KEYUP, ord('D'), 0)
其中 ord(“D”)可以替換成其他按鍵,具體是哪些按鍵可以查表
虛擬鍵表
選擇句柄
剛剛說過了,如果只是通過“FlashPlayer”找到的句柄是無法控制游戲的,真正控制游戲的句柄另有其柄
hwndChildList = []
win32gui.EnumChildWindows(andle, lambda hwnd, param: param.append(hwnd), hwndChildList)
for i in hwndChildList:
if win32gui.GetClassName(i)=='Chrome_WidgetWin_0' :
handle=i
break
if win32gui.GetClassName(i)=='Chrome_RenderWidgetHostHWND' :
handle=i
break
print(handle)
這里兩個似乎都可以控制游戲,所以我都加上去了,找到其中之一的就可以用制游戲
最終測驗
from ctypes import windll
import time
import win32api
import win32con
import win32gui
class Player():
def __init__(self,player,window_name,time_sleep=0.1):
self.time_sleep=time_sleep
self.__handle = windll.user32.FindWindowW(None, window_name)
self.__w2hd=win32gui.FindWindowEx(self.__handle, None, None, None)
hwndChildList = []
win32gui.EnumChildWindows(self.__handle, lambda hwnd, param: param.append(hwnd), hwndChildList)
for i in hwndChildList:
if win32gui.GetClassName(i)=='Chrome_WidgetWin_0' :
self.__handle=i
break
if win32gui.GetClassName(i)=='Chrome_RenderWidgetHostHWND' :
self.__handle=i
break
if player=='red':
self.__right=ord('D')
self.__left=ord('A')
self.__up=ord('W')
self.__down=ord('S')
elif player=='blue':
self.__right=39
self.__left=37
self.__up=38
self.__down=40
else:
print("沒有這個角色")
#horizontal 三個離散值,1右走,0不動,-1左走
#jump 兩個離散 0不跳,1跳
def move(self,horizontal,jump):
if horizontal==1:
press_key=self.__right
elif horizontal==-1:
press_key=self.__left
else:
press_key=None
win32gui.SetForegroundWindow(self.__w2hd)
if press_key!=None:
win32api.PostMessage(self.__handle, win32con.WM_KEYDOWN, press_key, 0)
if jump==1:
win32api.PostMessage(self.__handle, win32con.WM_KEYDOWN,self.__up, 0)
time.sleep(self.time_sleep)
win32gui.SetForegroundWindow(self.__w2hd)
if press_key!=None:
win32api.PostMessage(self.__handle, win32con.WM_KEYUP, press_key, 0)
if jump==1:
win32api.PostMessage(self.__handle, win32con.WM_KEYUP,self.__up, 0)
if __name__ == "__main__":
window_name='FlashPlay'
fire_man=Player(player='blue',window_name=window_name,time_sleep=0.2)
for i in range(10):
fire_man.move(-1,1)
博主已經集成了控制部分的演算法,并根據森林冰火人中冰娃火娃的操控方式做好了控制
最終效果
放不了視頻,隨便截個圖湊數吧

后篇:深度強化學習制作森林冰火人游戲AI(四)獲取視窗部分界面
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/287239.html
標籤:其他
