Есть ли способ в pygame вывести что-то на экран внутри маски. Например: если бы у вас была маска, в которой все биты были установлены на 1, кроме верхнего левого угла и полностью черного изображения, без изменения изображения, могли бы вы оставить левый верхний угол (такой же, как маска) чистым? Поможет только обновление маски (а не прямоугольника).
Pygame - есть ли способ только блицировать или обновлять в маске
Ответы (2)
Хорошо, если я правильно понимаю ваш вопрос, хитрость заключается в флаге BLEND_RGBA_MULT
.
Я решил проверить это на себе, потому что мне было любопытно. Я начал с этого изображения:
Я сделал изображение с белым, где я хотел, чтобы изображение было видно, и прозрачностью, где я хотел, чтобы оно было замаскировано. Я даже придал ему различные уровни прозрачности, чтобы увидеть, смогу ли я получить нечеткую маскировку.
^^^ Возможно, вы не видите изображение, потому что оно белое на прозрачном, но оно есть. Вы можете просто щелкнуть правой кнопкой мыши и скачать его.
Я загрузил два изображения, обязательно используя convert_alpha()
:
background = pygame.image.load("leaves.png").convert_alpha()
mask = pygame.image.load("mask-fuzzy.png").convert_alpha()
Затем, чтобы замаскировать изображение, я сделал копию маскируемого изображения,
masked = background.copy()
...Я скопировал маску на эту копию, используя BLEND_RGBA_MULT
,
masked.blit(mask, (0, 0), None, pygame.BLEND_RGBA_MULT)
...и я нарисовал это на экране.
display.blit(masked, (0, 0))
Конечно же, это сработало:
Вот полный код, который я использовал.
import pygame
from pygame.locals import *
pygame.init()
display = pygame.display.set_mode((320, 240))
background = pygame.image.load("leaves.png").convert_alpha()
mask = pygame.image.load("mask-fuzzy.png").convert_alpha()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# draw
display.fill(Color(255, 0, 255))
masked = background.copy()
masked.blit(mask, (0, 0), None, pygame.BLEND_RGBA_MULT)
display.blit(masked, (0, 0))
pygame.display.flip()
Если вам нужна переменная маска, вы можете попробовать вручную отредактировать поверхность и использовать ее в качестве маски.
Редактировать: Вот пример создания маски путем редактирования поверхности:
mask = pygame.Surface((320, 240), pygame.SRCALPHA)
for y in range(0, 240):
for x in range(0, 320):
if (x/16 + y/16) % 2 == 0:
mask.set_at((x, y), Color("white"))
Это дает такой результат:
Теперь я хочу использовать это в игре!
Итак, если я правильно понимаю, вопрос был - можно ли использовать битовые маски для блитинга. Ответ да, и нет. Насколько я знаю, в pygame нет поддержки 1-битных масок, это означает, что вы должны использовать 32-битный RGBA (флаг SRCALPHA), чтобы исходная поверхность блистала прозрачностью, и в этом случае вы используете 8-битную маску = 256 степеней прозрачности на пиксель, и это описано в предыдущем ответе. Другой вариант — использовать блиттинг «colorkey». В данном случае она больше похожа на 1-битную маску и используется со стандартными 24-битными RGB-поверхностями. Вы просто устанавливаете, какой цвет исходной поверхности вы не хотите записывать в пункт назначения. См. «Surface.set_colorkey» в документации. Однако проблема с методом colorkey заключается в том, что вы можете случайно получить несколько пикселей в исходном коде, которые имеют тот же цвет, что и colorkey, но которые вы все еще хотите рисовать. Так что вы должны быть осторожны. Я лично использую для маскирования поверхности RGBA, это мощнее, но почти всегда мне не нужны 8-битные, достаточно 1-битной маски. Так что мне кажется немного странным, что нет поддержки блитинга по битовой маске. То же самое и с переключением буфера — вы можете описать области экранного буфера для обновления только списком прямоугольников. Более гибким и простым было бы использование битовых масок, но это тоже невозможно. Вероятно, нужно преобразовать битовую маску в список прямоугольников, но я не пробовал. Третий вариант - не использовать поверхность pygame и использовать Numpy для ваших данных, а затем использовать копирование массива:
pygame.surfarray.blit_array(Destination_surface, my_array)
Тогда вы можете делать со своими данными все, что захотите, но это уже другая история.