python怎么制作游戏脚本

本文将以4399小游戏《宠物连连看经典版2》作为测试案例,通过识别小图标,模拟鼠标点击,快速完成配对完成游戏脚本。

python怎么制作游戏脚本浏览器打开游戏窗口(单个一个窗口),游戏主要界面截图需要两个坐标(左上角坐标和右下角坐标)来确定,原点一般是屏幕左上角,不确定坐标点值的同学,可以全屏截图,用编辑图片软件查看坐标值。(推荐学习:Python视频教程)

获取窗口句柄,这里就是浏览器标题栏的标题了(右键-查看源代码-title,加上软件名)比如:“宠物连连看经典2,宠物连连看经典版2小游戏,4399小游戏 www.4399.com – Google Chrome“。获取窗口句柄就可以开始了。

总体开发思路:截取游戏主图 —> 分割成小图 —> 对比每个小图,对比图片相识度,编号存入矩阵 —> 对矩阵进行可连计算 —> 模拟点击。

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

立即学习“Python免费学习笔记(深入)”;

python可以使用win32gui模块调用Windows API实现对窗口的操作,使用FindWindow()方法可以获取窗口的句柄(handle),需要传入两个参数,第一个为父窗口句柄(这里填0即可),第二个参数是窗口的名称(标签title – Google Chrome)。获取句柄之后然后通过SetForegroundWindows() 设置窗口在前面,这里传入游戏窗口的举报即可,代码如下:

import win32guiclass 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):        """屏幕截图"""        # 1、用grab函数截图,参数为左上角和右下角左标        # image = ImageGrab.grab((417, 257, 885, 569))        image = ImageGrab.grab(self.scree_left_and_right_point)        # 2、分切小图        # 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):        """将图标矩阵转换成数字矩阵"""        # 1、创建全零矩阵和空的一维数组        arr = np.zeros((10, 14), dtype=np.int32)    # 以数字代替图片        image_type_list = []        # 2、识别出不同的图片,将图片矩阵转换成数字矩阵        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):        # 1、先判断值是否相同        if self.im2num_arr[x1][y1] != self.im2num_arr[x2][y2]:            return False        # 1、分别获取两个坐标同行或同列可连的坐标数组        list1 = self.getDirectConnectList(x1, y1)        list2 = self.getDirectConnectList(x2, y2)        # print(x1, y1, list1)        # print(x2, y2, list2)        # exit()        # 2、比较坐标数组中是否可连        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):        # 1、位置完全相同        if x1 == x2 and y1 == y2:            return False        # 2、行列都不同的        if x1 != x2 and y1 != y2:            return False        # 3、同行        if x1 == x2 and self.isRowConnect(x1, y1, y2):            return True        # 4、同列        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怎么制作游戏脚本的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2252800.html

(0)
上一篇 2025年2月27日 01:09:06
下一篇 2025年2月27日 01:09:24

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 阶乘python怎么打

    阶乘python怎么打? 整数的阶乘(英语:factorial)是所有小于及等于该数的正整数的积,0的阶乘为1。即:n!=1×2×3×…×n。 实例 #!/usr/bin/python3 # Filename : test.py…

    2025年2月27日
    200
  • mac怎么安装python

    mac电脑自带python环境,打开终端,输入python,按下enter键,查看自己电脑中的python版本(默认安装的是python2.7版本) 【提示:查看完python的版本后,输入exit(),或者quit()即可退出终端中的py…

    2025年2月27日 编程技术
    200
  • python的for循环语句怎么写

    python的for循环语句怎么写? Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串。 语法: for循环的语法格式如下: for iterating_var in sequence:   statements(s…

    2025年2月27日
    200
  • 自学python可以做什么兼职

    很多朋友都会说,我身边有朋友或者同学是做程序员的。但是他们具体的工作内容,其实很多人是不了解的,这几年随着一些影视作品的出现,里面的主演有的从事开发工程师,大家初步有了一个印象。 如果我不想去公司坐班,自己通过这个技能怎么来赚钱。(推荐学习…

    2025年2月27日
    200
  • python中的map怎么使用(方法详解)

    python中的map怎么使用? python中map的使用方法: map函数的原型是map(function, iterable, …),它的返回结果是一个列表。 参数function传的是一个函数名,可以是python内置的,也可以是自…

    2025年2月27日
    200
  • Mac上用什么写python

    Vim(推荐学习:Python视频教程) Vim 可以说是 Python 最好的 IDE。Vim 是高级文本编辑器,旨在提供实际的 Unix 编辑器‘Vi’功能,支持更多更完善的特性集。Vim 不需要花费太多的学习时间,一旦你需要一个无缝的…

    2025年2月27日
    200
  • python中demo是什么

    demo是”demonstration”的缩写。demo的中文含意为“示范”、“展示”、“样片”、“样稿”、“原型”,常被用来称呼具有示范或展示功能及意味的事物。 例:python简单分布式demo(推荐学习:Pyt…

    2025年2月27日
    200
  • python的format怎么用

    python的format怎么用? python的format函数用法 它增强了字符串格式化的功能。基本语法是通过 {} 和 : 来代替以前的 % 。format 函数可以接受不限个参数,位置可以不按顺序。 **例一:**format 函数…

    2025年2月27日
    200
  • python怎么爬图片

    学完了爬网页中的文本,今天我们来试着学习爬图片。目标网址:http://www.netbian.com/我们的目标就是爬取这些壁纸 打开网址 查看网页结构(推荐学习:Python视频教程) 用火狐浏览器打开链接 F12查看 由于我使用的py…

    2025年2月27日
    200
  • python一般用什么软件

    python一般用什么软件? python一般用的软件有:Sublime Text、Atom、PyCharm等。 Sublime Text Sublime Text是一款非常流行的代码编辑器,其开发者是一名谷歌的工程师,其梦想是使之成为更好…

    2025年2月27日
    200

发表回复

登录后才能评论