深度强化学习制作森林冰火人游戏AI向游戏输出键盘控制信息

Posted 怪皮蛇皮怪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度强化学习制作森林冰火人游戏AI向游戏输出键盘控制信息相关的知识,希望对你有一定的参考价值。

概述

本文讲如何通过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_0Chrome_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(四)获取窗口部分界面

以上是关于深度强化学习制作森林冰火人游戏AI向游戏输出键盘控制信息的主要内容,如果未能解决你的问题,请参考以下文章

深度强化学习制作森林冰火人游戏AI获取游戏屏幕

深度强化学习制作森林冰火人游戏AI识别游戏状态

深度强化学习制作森林冰火人游戏AI下载游戏

深度强化学习制作4399小游戏ai

教程 | 深度强化学习入门:用TensorFlow构建你的第一个游戏AI

使用深度 Q 学习的 AI 驱动蛇游戏 源码分享