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

681 阅读4分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

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

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

本篇博客目的

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

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

image.png

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

import pygame
import os
import 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 读取一大堆图片进来,再获取一张图片上的那么一小块区域

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

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() 函数转换为透明像素格式,那在进行透明度设置会实现混合效果。

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

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

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

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