在不覆盖透明度的情况下更改表面的颜色
Changing colour of a surface without overwriting transparency
我想在运行时动态改变矩形的颜色。目前 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
中创建的所有透明像素。
有没有办法将颜色遮盖或混合到矩形上,这样它就不会替换任何透明度?
您可以通过 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_image
与 self.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()
我想在运行时动态改变矩形的颜色。目前 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
中创建的所有透明像素。
有没有办法将颜色遮盖或混合到矩形上,这样它就不会替换任何透明度?
您可以通过 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_image
与 self.image
混合以获得所需的结果:
self.image.blit(self.original_image, (0, 0), special_flags=pg.BLEND_MULT)
最小示例:
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()