0

0

python怎么制作游戏脚本

(*-*)浩

(*-*)浩

发布时间:2019-07-04 10:44:18

|

9427人浏览过

|

来源于php中文网

原创

本文将以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 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数组中。 

Pixelfox AI
Pixelfox AI

多功能AI图像编辑工具

下载
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教程栏目进行学习!

相关文章

在线游戏
在线游戏

海量精品小游戏合集,无需安装即点即玩,休闲益智、动作闯关应有尽有,秒开即玩,轻松解压,快乐停不下来

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

23

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

25

2026.03.03

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

77

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

60

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

48

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

26

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

20

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

4

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

388

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 4.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号