在不合并Alpha的情况下将曲面拖到另一个表面

时间:2018-10-20 23:12:41

标签: python python-3.x pygame alpha blit

在我正在从事的pygame项目中,角色和对象的精灵将阴影投射到地形上。阴影和地形都是正常的pygame曲面,因此,为了显示它们,阴影被涂抹到了地形上。当没有其他阴影(只有一个阴影和地形)时,一切正常,但是当角色进入阴影区域时,在投射自己的阴影时,两个阴影会组合其alpha值,从而使地形更加模糊。 我想要的是避免这种行为,保持alpha值稳定。有什么办法吗?

编辑:这是我在Photoshop中制作的图像,用于显示问题 enter image description here

EDIT2:@sloth的答案是可以的,但我忽略了评论我的项目比这更复杂。阴影不是整个正方形,而是更类似于“模具”。像真实的阴影一样,它们是从其投射对象的轮廓,因此它们需要每个像素的Alpha,这些Alpha与ColorKey和整个Alpha值不兼容。

这里是YouTube video,可以更清楚地显示问题。

3 个答案:

答案 0 :(得分:2)

解决此问题的一种简单方法是先将阴影阴影在另一个具有alpha值但没有每个像素alpha的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

答案 1 :(得分:0)

您可以创建一个测试阴影碰撞的函数,并相应地调整阴影的混合值。

答案 2 :(得分:0)

您可以通过将每个像素的alpha阴影涂抹到辅助表面上,然后用透明的白色填充此表面并传递pygame.BLEND_RGBA_MIN标志作为special_flags参数来组合它们。填充颜​​色的Alpha值应等于或小于阴影的Alpha。传递pygame.BLEND_RGBA_MIN标志意味着对于每个像素,每个颜色通道的值都将较低,因此它将重叠阴影的增加的alpha减小为填充颜色alpha。

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

这是shadow.png。

enter image description here