python怎么制作游戏脚本-Python教程

资源魔 18 0
本文将以4399小游戏《宠物连连看经典版2》作为测试案例,经过辨认小图标,模仿鼠标点击,疾速实现配对实现游戏剧本。

阅读器关上游戏窗口(单个一个窗口),游戏次要界面截图需求两个坐标(左上角坐标以及右下角坐标)来确定,原点普通是屏幕左上角,没有确定坐标点值的同窗,能够全屏截图,用编纂图片软件查看坐标值。(保举学习:Python视频教程)

猎取窗口句柄,这里就是阅读器题目栏的题目了(右键-查看源代码-title,加之软件名)比方:“宠物连连看经典2,宠物连连看经典版2小游戏,4399小游戏 www.4399.com - Google Chrome“。猎取窗口句柄就能够开端了。

总体开发思绪:截取游戏主图 ---> 宰割成小图 ---> 比照每一个小图,比照图片相识度,编号存入矩阵 ---> 对矩阵进行可连较量争论 ---> 模仿点击。

猎取窗口句柄,把窗口置顶

python能够应用win32gui模块挪用Windows API完成对窗口的操作,应用FindWindow()办法能够猎取窗口的句柄(handle),需求传入两个参数,第一个为父窗口句柄(这里填0便可),第二个参数是窗口的称号(标签title - Google Chrome)。猎取句柄之后而后经过SetForegroundWindows() 设置窗口正在后面,这里传入游戏窗口的告发便可,代码以下:

import win32gui

class GameAssist:

    def __init__(self, wdname):
        """初始化"""

        # 获得窗口句柄
        self.hwnd = win32gui.FindWindow(0, wdname)
        if not self.hwnd:
            print("窗口找没有到,请确认窗口句柄称号:【%s】" % wdname )
            exit()
        # 窗口显示最后面
        win32gui.SetForegroundWindow(self.hwnd)


if __name__ == "__main__":
    # wdname 为连连看窗口的称号,必需写完好
    wdname = u'宠物连连看经典版2,宠物连连看经典版2小游戏,4399小游戏 www.4399.com - Google Chrome'

    demo = GameAssist(wdname)
    demo.start()

截取游戏界面,宰割图标,图片比拟

这里需求破费一些工夫来校验顺序,假如截取的图片欠好,则会影响后续操作,以是比拟次要的是确认游戏左上角以及右下角这两个坐标值,和每一个小图标的宽高。以下图所示,先截取整个游戏界面图,而后宰割小图标,接着对每一个图标进行比拟,而后以编号替代图标存入矩阵(这里的编号矩阵以及游戏图纷歧致,原理同样)。

python-29.png依据初始化设定的左上角以及右下角两个坐标,应用ImageGrab.grab()办法进行截图,传入一个元组便可,而后对这个年夜图进行宰割,切割成一个个小图标存入到images_list数组中。 

def screenshot(self):
        """屏幕截图"""

        # 一、用grab函数截图,参数为左上角以及右下角左标
        # image = ImageGrab.grab((417, 257, 885, 569))
        image = ImageGrab.grab(self.scree_left_and_right_point)

        # 二、分切小图
        # exit()
        image_list = {}
        offset = self.im_width  # 39

        # 8行12列
        for x in range(8):
            image_list[x] = {}
            for y in range(12):
                # print("show",x, y)
                # exit()
                top = x * offset
                left = y * offset
                right = (y + 1) * offset
                bottom = (x + 1) * offset

                # 用crop函数切割成小图标,参数为图标的左上角以及右下角右边
                im = image.crop((left, top, right, bottom))
                # 将切割好的图标存入对应的地位
                image_list[x][y] = im

        return image_list

经过下面代码切割的小图标,转成数字矩阵,假如图标曾经存入image_type_list则前往这个索引,假如没有存正在,则正在追加出来,而后以后长度就是这个新退出图标的编号,代码以下所示:

def image2num(self, image_list):
        """将图标矩阵转换成数字矩阵"""

        # 一、创立全零矩阵以及空的一维数组
        arr = np.zeros((10, 14), dtype=np.int32)    # 以数字替代图片
        image_type_list = []

        # 二、辨认出没有同的图片,将图片矩阵转换成数字矩阵
        for i in range(len(image_list)):
            for j in range(len(image_list[0])):
                im = image_list[i][j]
                
                # 验证以后图标能否已存入
                index = self.getIndex(im, image_type_list)

                # 没有存正在image_type_list
                if index < 0:
                    image_type_list.append(im)
                    arr[i + 1][j + 1] = len(image_type_list)
                else:
                    arr[i + 1][j + 1] = index + 1

        print("图标数:", len(image_type_list))

        self.im2num_arr = arr
        return arr

下面的getIndex就是比照图片,判别图标能否呈现过(能否已存正在image_type_list中,没呈现则追加出来),这里应用汉明间隔判别两个图片的相识度,设置阀值10,当小于阀值则以为是同一个图片,详细代码以下:  

# 反省数组中能否有图标,假如有则前往索引下表
    def getIndex(self,im, im_list):
        for i in range(len(im_list)):
            if self.isMatch(im, im_list[i]):
                return i

        return -1

    # 汉明间隔判别两个图标能否同样
    def isMatch(self, im1, im2):

        # 减少图标,转成灰度
        image1 = im1.resize((20, 20), Image.ANTIALIAS).convert("L")
        image2 = im2.resize((20, 20), Image.ANTIALIAS).convert("L")

        # 将灰度图标转成01串,即系二进制数据
        pixels1 = list(image1.getdata())
        pixels2 = list(image2.getdata())

        avg1 = sum(pixels1) / len(pixels1)
        avg2 = sum(pixels2) / len(pixels2)
        hash1 = "".join(map(lambda p: "1" if p > avg1 else "0", pixels1))
        hash2 = "".join(map(lambda p: "1" if p > avg2 else "0", pixels2))

        # 统计两个01串没有同数字的个数
        match = sum(map(operator.ne, hash1, hash2))

        # 阀值设为10
        return match < 10

顺序外围-图标衔接算法(门路寻觅)

这里仅对算法代码进行简略剖析,假如对顺序欠好了解,能够留言,后续能够图文剖析。

经过下面的开发流程,根本猎取以下这样的矩阵,只需比拟两个编号相反的值进行可连门路寻觅,假如找到即进行模仿点击操作。这里简略引见上游戏规定:8行乘12列游戏图标区域,核心的0其实示意寻觅门路的时分能够经过,例如坐标(1, 1)能够与(1,10)进行衔接、(7, 1)以及(7,2)进行衔接。

arr = [
    [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
    [ 0,  1,  2,  3,  4,  5,  4,  6,  7,  2,  1,  1,  8,  0],
    [ 0,  9,  3,  3, 10,  4,  7, 11,  7,  2,  3,  1,  6,  0],
    [ 0,  6,  7,  4, 11,  5,  8,  1,  6,  5,  4,  2,  8,  0],
    [ 0,  6,  2,  9,  6,  8,  9,  7, 12, 11,  3, 11, 11,  0],
    [ 0,  5,  9,  8,  9,  2,  6, 11, 11,  3,  9,  2, 12,  0],
    [ 0, 12,  5, 12,  5, 10,  5,  6,  5,  7, 12,  4,  3,  0],
    [ 0,  1,  8, 10, 12,  9, 10,  4,  3,  7,  2,  1, 10,  0],
    [ 0,  1,  4, 10,  8, 12, 10, 10,  9, 12,  8,  7, 11,  0],
    [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0]
]

法的思绪:门路的寻觅起首是寻觅一个坐标的横向竖向能够间接相连的坐标荟萃,比方坐标p1(1,1)这样的荟萃有[ (0,1), (1,0) ],另一个坐标p2(1,10)的可连荟萃为[ (0,10) ],而后再对p1以及p2的可连坐标荟萃进行比拟,假如荟萃中坐标也有可连,则示意p1以及p2可连,很显著,(0,1)以及(0,10)为同一行且可连,这样就示意p1以及p2两点存正在可连门路了,代码以下所示:

简略剖析下代码完成进程:正在isReachable()传入两个需求比拟的坐标值,而后辨别猎取两个点反正向(isRowConnect()、isColConnect())能够衔接的坐标荟萃,最初再对荟萃进行遍历比拟能否存正在可连的,假如存正在则示意传入的两个坐标是能够衔接的。

# 能否为偕行或同列且可连
    def isReachable(self, x1, y1, x2, y2):
        # 一、先判别值能否相反
        if self.im2num_arr[x1][y1] != self.im2num_arr[x2][y2]:
            return False

        # 一、辨别猎取两个坐标偕行或同列可连的坐标数组
        list1 = self.getDirectConnectList(x1, y1)
        list2 = self.getDirectConnectList(x2, y2)
        # print(x1, y1, list1)
        # print(x2, y2, list2)

        # exit()

        # 二、比拟坐标数组中能否可连
        for x1, y1 in list1:
            for x2, y2 in list2:
                if self.isDirectConnect(x1, y1, x2, y2):
                    return True
        return False

    # 猎取偕行或同列可连的坐标数组
    def getDirectConnectList(self, x, y):

        plist = []
        for px in range(0, 10):
            for py in range(0, 14):
                # 猎取偕行或同列且为0的坐标
                if self.im2num_arr[px][py] == 0 and self.isDirectConnect(x, y, px, py):
                    plist.append([px, py])

        return plist

    # 能否为偕行或同列且可连
    def isDirectConnect(self, x1, y1, x2, y2):
        # 一、地位齐全相反
        if x1 == x2 and y1 == y2:
            return False

        # 二、行列都没有同的
        if x1 != x2 and y1 != y2:
            return False

        # 三、偕行
        if x1 == x2 and self.isRowConnect(x1, y1, y2):
            return True

        # 四、同列
        if y1 == y2 and self.isColConnect(y1, x1, x2):
            return True

        return False

    # 判别偕行能否可连
    def isRowConnect(self, x, y1, y2):
        minY = min(y1, y2)
        maxY = max(y1, y2)

        # 相邻间接可连
        if maxY - minY == 1:
            return True

        # 判别两个坐标之间能否全为0
        for y0 in range(minY + 1, maxY):
            if self.im2num_arr[x][y0] != 0:
                return False
        return True

    # 判别同列能否可连
    def isColConnect(self, y, x1, x2):
        minX = min(x1, x2)
        maxX = max(x1, x2)

        # 相邻间接可连
        if maxX - minX == 1:
            return True

        # 判别两个坐标之间能否全为0
        for x0 in range(minX + 1, maxX):
            if self.im2num_arr[x0][y] != 0:
                return False
        return True

学习这样一个游戏辅佐剧本,关于集体造就编程兴味也是有不少协助的,正在工作之余没有失为一个好的消遣形式,当前会多向这些标的目的钻研学习。

更多Python相干技巧文章,请拜访Python教程栏目进行学习!

以上就是python怎样制造游戏剧本的具体内容,更多请存眷资源魔其它相干文章!

标签: Python python教程 python编程 python使用问题

抱歉,评论功能暂时关闭!