【问题标题】:Changing colour of a surface without overwriting transparency [duplicate]在不覆盖透明度的情况下更改表面颜色[重复]
【发布时间】:2020-10-04 01:01:38
【问题描述】:

我想在运行时动态更改矩形的颜色。目前set_colour 正在用单一颜色值填充表面的所有像素。这可行,但是当调用像 set_outline 这样的方法时会出现问题,这会修改表面的透明度。

class Rectangle(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.original_image = pg.Surface((10, 10))
        self.image = self.original_image
        self.rect = self.image.get_rect()

    def set_colour(self, colour_value):
        self.colour = colour_value
        self.image.fill(self.colour)
        self.original_image.fill(self.colour)

    def set_outline(self, thickness):
        self.thickness = thickness
        size = self.image.get_size()

        calc = thickness/100
        p_width, p_height = size[0], size[1]
        width, height = size[0]*calc, size[1]*calc

        self.image = self.image.convert_alpha()

        center_x, center_y = (p_width//2)-(width//2), (p_height//2)-(height//2)
        pg.draw.rect(self.image, (0, 0, 0, 0), (center_x, center_y, width, height))

现在,如果我尝试在运行时更改该矩形的颜色,它将覆盖在 set_outline 中创建的所有透明像素。

有没有办法将颜色遮盖或混合到矩形上,所以它不会替换任何透明度?

【问题讨论】:

    标签: python pygame sprite blending


    【解决方案1】:

    您可以通过 2 个步骤实现此目的。 self.original_image 包含具有所需颜色的填充矩形:

    self.original_image.fill(self.colour)
    

    生成一个完全白色的矩形和透明区域。使用 (self.image) 和混合模式 BLEND_MAX 混合矩形(参见 pygame.Surface.blit):

    whiteTransparent = pg.Surface(self.image.get_size(), pg.SRCALPHA)
    whiteTransparent.fill((255, 255, 255, 0))
    self.image.blit(whiteTransparent, (0, 0), special_flags=pg.BLEND_MAX)
    

    现在矩形是完全白色的,但是透明区域被保留了。使用混合模式BLEND_MULT 和混合self.original_imageself.image 以获得所需的结果:

    self.image.blit(self.original_image, (0, 0), special_flags=pg.BLEND_MULT)
    

    最小示例: repl.it/@Rabbid76/PyGame-ChangeColorOfSpriteArea

    import pygame as pg
    
    class Rectangle(pg.sprite.Sprite):
        def __init__(self):
            pg.sprite.Sprite.__init__(self)
            self.original_image = pg.Surface((150, 150))
            self.image = self.original_image
            self.rect = self.image.get_rect(center = (150, 150))
    
        def set_colour(self, colour_value):
            self.colour = colour_value
            self.original_image.fill(self.colour)
    
            whiteTransparent = pg.Surface(self.image.get_size(), pg.SRCALPHA)
            whiteTransparent.fill((255, 255, 255, 0))
            self.image.blit(whiteTransparent, (0, 0), special_flags=pg.BLEND_MAX)
    
            self.image.blit(self.original_image, (0, 0), special_flags=pg.BLEND_MULT)
    
        def set_outline(self, thickness):
            self.thickness = thickness
            size = self.image.get_size()
    
            calc = thickness/100
            p_width, p_height = size[0], size[1]
            width, height = size[0]*calc, size[1]*calc
    
            self.image = self.image.convert_alpha()
    
            center_x, center_y = (p_width//2)-(width//2), (p_height//2)-(height//2)
            pg.draw.rect(self.image, (0, 0, 0, 0), (center_x, center_y, width, height))
    
    pg.init()
    window = pg.display.set_mode((300, 300))
    clock = pg.time.Clock()
    
    sprite = Rectangle()
    sprite.set_colour((255, 0, 0, 255))
    sprite.set_outline(50)
    
    group = pg.sprite.Group(sprite)
    
    colorVal = 0
    colorAdd = 5
    run = True
    while run:
        clock.tick(60)
        for event in pg.event.get():
            if event.type == pg.QUIT:
                run = False
    
        sprite.set_colour((min(colorVal, 255), max(0, min(511-colorVal, 255)), 0, 255))
        colorVal += colorAdd
        if colorVal <= 0 or colorVal >= 511:
            colorAdd *= -1
    
        window.fill(0)
        group.draw(window)
        pg.display.flip()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      相关资源
      最近更新 更多