Разбивая поверхность на другую, не комбинируя альфа - PullRequest
0 голосов
/ 21 октября 2018

В проекте Pygame, над которым я работаю, спрайты персонажей и объектов отбрасывают тень на местность.И тень, и местность - это обычные поверхности пигмеев, поэтому, чтобы показать их, тень переместилась на местность.Когда другой тени нет (только одна тень и рельеф), все работает нормально, но когда персонаж входит в область тени, отбрасывая собственную тень, обе тени объединяют свои альфа-значения, еще больше затеняя местность.Я хочу избежать такого поведения, сохраняя альфа-значение стабильным.Есть ли способ сделать это?

РЕДАКТИРОВАТЬ: Это изображение, которое я сделал в Photoshop, чтобы показать проблему enter image description here

EDIT2: @ sloth'sОтвет в порядке, но я не стал комментировать, что мой проект более сложный, чем этот.Тени - это не целые квадраты, а больше похожи на «трафареты».Как и настоящие тени, они представляют собой силуэты объектов, из которых они отбрасываются, и поэтому им требуются альфа-пиксели на пиксель, которые не совместимы с цветовыми ключами и целыми альфа-значениями.это показывает проблему немного яснее.

Ответы [ 3 ]

0 голосов
/ 22 октября 2018

Простой способ решить эту проблему - сначала отбросить ваши тени на другой Surface, который имеет альфа-значение, но не на пиксель альфа.Затем перетащите это Surface на экран.

Вот простой пример, показывающий результат:

from pygame import *
import pygame

pygame.init()
screen = pygame.display.set_mode((800, 600))

# we create two "shadow" surfaces, a.k.a. black with alpha channel set to something
# we use these to illustrate the problem
shadow = pygame.Surface((128, 128), pygame.SRCALPHA)
shadow.fill((0, 0, 0, 100))
shadow2 = shadow.copy()

# a helper surface we use later for the fixed shadows
shadow_surf = pygame.Surface((800, 600))
# we set a colorkey to easily make this surface transparent
colorkey_color = (2,3,4)
shadow_surf.set_colorkey(colorkey_color)
# the alpha value of our shadow
shadow_surf.set_alpha(100)

# just something to see the shadow effect
test_surface = pygame.Surface((800, 100))
test_surface.fill(pygame.Color('cyan'))

running = True
while running:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            running = False

    screen.fill(pygame.Color('white'))

    screen.blit(test_surface, (0, 150))

    # first we blit the alpha channel shadows directly to the screen 
    screen.blit(shadow, (100, 100))
    screen.blit(shadow2, (164, 164))

    # here we draw the shadows to the helper surface first
    # since the helper surface has no per-pixel alpha, the shadows
    # will be fully black, but the alpha value for the full Surface image
    # is set to 100, so we still have transparent shadows
    shadow_surf.fill(colorkey_color)
    shadow_surf.blit(shadow, (100, 100))
    shadow_surf.blit(shadow2, (164, 164))

    screen.blit(shadow_surf, (400, 0))

    pygame.display.update()

enter image description here

0 голосов
/ 24 октября 2018

Вы можете комбинировать альфа-тени для каждого пикселя, перетаскивая их на вспомогательную поверхность, а затем заливая эту поверхность прозрачным белым и передавая флаг pygame.BLEND_RGBA_MIN в качестве аргумента special_flags.Альфа-значение цвета заливки должно быть равно или меньше альфа-тени.Пропуск флага pygame.BLEND_RGBA_MIN означает, что для каждого пикселя будет взято более низкое значение каждого цветового канала, поэтому уменьшится увеличенная альфа перекрывающихся теней до альфа цвета заливки.

import pygame as pg


pg.init()
screen = pg.display.set_mode((800, 600))
clock = pg.time.Clock()
shadow = pg.image.load('shadow.png').convert_alpha()
# Shadows will be blitted onto this surface.
shadow_surf = pg.Surface((800, 600), pg.SRCALPHA)

running = True
while running:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False

    screen.fill((130, 130, 130))
    screen.blit(shadow, (100, 100))
    screen.blit(shadow, (154, 154))

    shadow_surf.fill((0, 0, 0, 0))  # Clear the shadow_surf each frame.
    shadow_surf.blit(shadow, (100, 100))
    shadow_surf.blit(shadow, (154, 154))
    # Now adjust the alpha values of each pixel by filling the `shadow_surf` with a
    # transparent white and passing the pygame.BLEND_RGBA_MIN flag. This will take
    # the lower value of each channel, therefore the alpha should be lower than
    # the shadow alphas.
    shadow_surf.fill((255, 255, 255, 120), special_flags=pg.BLEND_RGBA_MIN)
    # Finally, blit the shadow_surf onto the screen.
    screen.blit(shadow_surf, (300, 0))

    pg.display.update()
    clock.tick(60)

enter image description here

Вот тень.

enter image description here

0 голосов
/ 21 октября 2018

Вы можете создать функцию, которая проверяет столкновение теней и соответственно корректирует значения смешивания теней.

...