【问题标题】:Setting an alpha on a pygame surface在 pygame 表面上设置 alpha
【发布时间】:2020-06-22 00:16:38
【问题描述】:

我正在使用pygame 创建一个 GUI 库。我想支持透明表面以及透明rects。当我使用self.original_image.set_alpha(100) 时,透明矩形起作用。我正在转换 pygame 表面,以便它可以接受带有surface.convert() 的 alpha,但是当我这样做时,图像最终会出现黑色背景和一些失真。 surface.convert_alpha() 好像没有任何效果。

class UIComponent(pg.sprite.Sprite):

    def __init__(self, width=10, height=10, visible=True):
        pg.sprite.Sprite.__init__(self)
        self.width_percent, self.height_percent = 0, 0
        self.x_offset, self.y_offset = 0, 0
        self.alignments = []
        self.original_image = pg.Surface((width, height))
        self.image = self.original_image
        self.original_image.set_alpha(100)
        self.rect = self.image.get_rect()

    def set_image(self, surface):
        self.original_image = surface.convert()
        self.image = self.original_image

surface.convert() 之后的表面是什么样子

实际图像的样子。

编辑: 请求与UIComponent 交互的代码以创建剑。

self.slot_icon = UILib.UIComponent()
self.slot_icon.set_image(win.icon)
self.slot_icon.add_alignment(self.slot_icon.relative_width)
self.slot_icon.add_alignment(self.slot_icon.height_ratio_constraint)
self.slot_icon.width_percent = 0.03
self.slot_icon.add_alignment(self.slot_icon.center_x)
self.slot_icon.add_alignment(self.slot_icon.center_y)

win:

def __init__(self):
    self.s_width = 0
    self.s_height = 0
    self.screen = pg.display.set_mode()
    self.icon = pg.image.load("icon.png")

【问题讨论】:

  • 能否请附上剑(?)位图与UIComponent一起使用的代码。
  • 所以当您调用set_image() 时,它只是将self.image 替换为提供的位图。因此没有维护任何set_alpha() 操作。我是否正确理解这一点?这是你想要的吗?你的意思是也调整参数的 alpha 吗?还是别的什么?

标签: python pygame


【解决方案1】:

pygame 支持三种不同的透明度:colorkeys、surface alphas 和 pixel alphas;而且你不能轻易混合表面 alpha 和像素 alpha

如果你想使用set_alpha 来设置整个Surface 的透明度,你可以使用surface alpha(也就是说,设置整个表面的alpha 值)。

但是您要使用的图像是使用 pixel alpha 的 PNG(这意味着每个像素都有自己的 alpha 值);所以你应该在加载图像后在Surface上调用convert_alpha

如果你想改变这样一张图片的表面alpha,基本上有两种方法:

选项 1:使用颜色键

import pygame
import itertools

class UIComponent(pygame.sprite.Sprite):

    def __init__(self, width=10, height=10, visible=True):
        pygame.sprite.Sprite.__init__(self)
        self.width_percent, self.height_percent = 0, 0
        self.x_offset, self.y_offset = 0, 0
        self.alignments = []
        self.original_image = pygame.Surface((width, height))
        self.image = self.original_image
        self.rect = self.image.get_rect()

    def set_image(self, surface):
        self.original_image = surface
        self.image = pygame.Surface(surface.get_size())
        self.image.fill((1,2,3))
        self.image.set_colorkey((1,2,3))
        self.image.blit(self.original_image.copy(), (0, 0))
        self.rect = self.image.get_rect(center=self.rect.center)
        
def main():
    pygame.init()
    screen = pygame.display.set_mode((200, 200))
    
    comp = UIComponent()
    comp.set_image(pygame.transform.scale2x(pygame.image.load('sword.png').convert_alpha()))
    comp.rect.center = screen.get_rect().center
    
    sprites = pygame.sprite.Group(comp)
    E = pygame.USEREVENT + 1
    alphas = itertools.cycle((10, 100, 200, 255))
    pygame.time.set_timer(E, 1000)
    while True:
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                return
            if e.type == E:
                comp.image.set_alpha(next(alphas))
        screen.fill((30, 30, 30))
        sprites.update()
        sprites.draw(screen)
        pygame.display.flip()
        
main()

选项 2:使用临时表面和 BLEND_RGBA_MULT 来“应用”透明度:

import pygame
import itertools

class UIComponent(pygame.sprite.Sprite):

    def __init__(self, width=10, height=10, visible=True):
        pygame.sprite.Sprite.__init__(self)
        self.width_percent, self.height_percent = 0, 0
        self.x_offset, self.y_offset = 0, 0
        self.alignments = []
        self.original_image = pygame.Surface((width, height))
        self.image = self.original_image
        self.rect = self.image.get_rect()

    def set_image(self, surface):
        self.original_image = surface
        self.image = self.original_image.copy()
        self.rect = self.image.get_rect(center=self.rect.center)

    def set_alpha(self, alpha_value):
        tmp = pygame.Surface(self.rect.size, pygame.SRCALPHA)
        tmp.fill((255, 255, 255, alpha_value))
        self.image = self.original_image.copy()
        self.image.blit(tmp, (0, 0), special_flags=pygame.BLEND_RGBA_MULT)
        
def main():
    pygame.init()
    screen = pygame.display.set_mode((200, 200))
    
    comp = UIComponent()
    comp.set_image(pygame.transform.scale2x(pygame.image.load('sword.png').convert_alpha()))
    comp.rect.center = screen.get_rect().center
    
    sprites = pygame.sprite.Group(comp)
    E = pygame.USEREVENT + 1
    alphas = itertools.cycle((10, 100, 200, 255))
    pygame.time.set_timer(E, 1000)
    while True:
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                return
            if e.type == E:
                comp.set_alpha(next(alphas))
        screen.fill((30, 30, 30))
        sprites.update()
        sprites.draw(screen)
        pygame.display.flip()
        
main()

结果是一样的:

【讨论】:

  • 这个问题是每次显示改变大小时我都会用另一种方法调整表面大小:self.rect.width = win.s_width * self.width_percentself.image = pg.transform.smoothscale(self.original_image, self.rect.size)。所以image 在我改变表面的比例时发生了变化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多