写点什么

pygame 读取一大堆图片进来,再获取一张图片上的那么一小块区域

发布于: 刚刚

本系列专栏将通过不断编写游戏的方式,带你夯实 Python 知识。


本专栏追求迅速掌握 pygame 的同时,夯实 python 知识,所以一起来学习吧。

本篇博客目的

一次性加载所有素材图片,在通过调用指定图片的名称,获取图片上的某个目标区域(子图)。


可以先临摹并理解代码,最终实现效果如下所示。



实现上图效果的代码如下所示,在编写的时候可以在重要部分增加注释,辅助理解。


import pygameimport osimport sys
pygame.init()screen = pygame.display.set_mode((400, 400))# accept 参数限制了传入的图片格式def load_graphics(path, accept=(".jpg", ".png", ".jpeg")): graphics = {} for pic in os.listdir(path): name, ext = os.path.splitext(pic)
if ext.lower() in accept: img = pygame.image.load(os.path.join(path, pic)) # 判断图片是否透明背景 if img.get_alpha(): img = img.convert_alpha() else: # 加快游戏加载图片操作 img = img.convert() graphics[name] = img return graphics

def get_image(target, x, y, width, height, colorkey): image = pygame.Surface((width, height)) image.blit(target, (0, 0), (x, y, width, height)) image.set_colorkey(colorkey) return image

if __name__ == "__main__": while True: # imgs 文件夹里面的图片自行准备即可,文件名随意 # 可以准备各种后缀名的图片 graphics = load_graphics("./imgs") print(graphics) for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit()
screen.fill((12, 200, 180)) # 类似 335,160,70,60,都是根据不同图片测量的,你可以通过截图工具或者画板进行测量。 small_img = get_image( graphics["one_pic1"], 335, 160, 70, 60, (0, 0, 0)) screen.blit(small_img, (100, 100))
pygame.display.update()
复制代码

代码部分的详细说明与避坑指南

load_graphics 函数作用是调用文件夹所有图片,然后再返回一个字典,字典的键为图片名,值是 pygame.image.load 函数加载的一个 Surface 对象。


代码中需要掌握的重点函数有 img.get_alpha(),该函数用于判断图片是否为透明图片,即带 alpha 值。


使用方式为 pygame.Surface.get_alpha() ,可获取整个图像的透明度,当图片有透明区域的时候,会返回具体的值,一般都是 255,测试本场景可以在文件夹中放置一些不具备透明度的图片,根据文件名进行返回,不透明图片返回不是 0,是 None。


图片1.png 255图片2.png 255图片3.png 255图片4.png 255图片5.jpg None
复制代码


pygame.Surface.convert() 函数用于修改图像(Surface 对象)为像素格式;pygame.Surface.convert_alpha() 函数也用于修改图像(Surface 对象)为像素格式,在颜色元组中比多了 alpha 值。


对于这二者的区别,就是透明与透明的区别,这两个函数会将图片转换成一种特殊的像素格式图片(pygame 内部实现的),会使得游戏渲染图片速度加快,核心原理先不用深究,只需要在编写 pygame 的时候,使用这个函数即可。


在代码编写过程中,一定要记得中文名称会产生的问题,不过该案例无中文 BUG,图片读取中,图片名如果设置为中文,可以正常读取,但建议使用英文单词进行命名。



上文代码,在运行过程中,还会出现如下错误:


pygame.error: No video mode has been set
复制代码


该异常出现的原因是调用图片之前,没有对游戏窗口进行初始化操作,也就是缺少了下述代码。


screen = pygame.display.set_mode((400, 400))
复制代码

提取图片某个区域

该部分的内容是一个新知识点,也需要重点的学习一下,代码部分如下:


def get_image(target, x, y, width, height, colorkey):    image = pygame.Surface((width, height))    image.blit(target, (0, 0), (x, y, width, height))    image.set_colorkey(colorkey)    return image
复制代码


通过 get_image 函数,可以获取指定图片区域,构造 Surface 对象的函数在之前的博客中已经学习了。


image = pygame.Surface((width, height)) 创建了一个 Surface 对象。


image.blit(target, (0, 0), (x, y, width, height)) 在上一行代码创建的 Surface 对象上进行绘制,目标图片是 target,请回顾 blit 函数的三个参数含义,分别是图像,绘制的坐标点,绘制的截面。


翻译过来就是在一个 Surface 对象的 (0,0) 点开始绘制 target 上的一个区域。


或者理解成之前博客中提及的描述,拿着一个透明玻璃在一张图片上进行滑动,寻找目标区域。


set_colorkeyget_colorkey


这两个函数时用来操作透明相关数据的,set_colorkey 目标是当绘制 Surface 对象时,将与 colorkeys 相同的颜色值设为透明,colorkeys 一般传入 RGB 颜色,如果传入 None,则取消 colorkeys 设置。


需要注意,如果代码中的图片已经使用 convert_alpha() 函数转换为透明像素格式,那在进行透明度设置会实现混合效果。


不过该函数使用之后,效果并不是很理想,建议透明图片还是提前准备好。



上图上部图片是白色背景,下部图片是设置白色区域透明,效果不理想


本系列专栏属于番外篇,希望你能学到新知识。有任何疑问,都可以联系橡皮擦进行解决,一起做游戏吧本专栏每天的练习量大概在 1 小时左右,整篇博客节奏会比较快,毕竟咱们是有基础的人。

发布于: 刚刚阅读数: 2
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
pygame 读取一大堆图片进来,再获取一张图片上的那么一小块区域