2010-11-25 22 views
13

¿Es posible visualizar superficies PyGame con alpha controlable? Me gustaría tomar una superficie con su propio alfa por píxel y mostrarlo con un nivel de translucidez variable sin afectar los datos de superficie y mantener la transparencia intacta, es decir, los objetos en la superficie mantendrían sus formas pero sus "contenidos" se volverían más o menos translúcido.PyGame: sprites translúcidos con por pixel alpha

En otras palabras, quiero combinar el alfa por píxel de la imagen de origen con el alfa por superficie calculado en el tiempo de ejecución.

Respuesta

4

Después de comprobar tanto PyGame y documentaciones SDL que llegaron a la conclusión de que lo que le pedía no era factible en PyGame mediante las funciones estándar.

Los documentos SDL indican que el alfa por píxel y el alfa por superficie no se pueden combinar con el primero teniendo siempre prioridad. La única forma de lograr el efecto que deseo es escribir un código que actualice los valores alfa por píxel de la superficie de origen antes del blit.

4

Sí, puedes. El documentation of the Surface class explica cómo hacerlo. Todo se reduce a sólo dos casos: O se configura una bandera durante la creación del objeto Superficie:

s = pygame.Surface((16, 16), flags=pygame.SRCALPHA) 

o le dará un canal alfa a una superficie que no tiene uno todavía:

s = pygame.image.load('spam.png') 
s.convert_alpha() 

La documentación del módulo pygame.image dice que la aplicación convert_alpha es necesaria para PNG con transparencia.

Si lo desea, puede modificar el valor alfa de cada píxel con los módulos draw y surfarray. Al especificar un color, utilice una tupla de cuatro enteros: (rojo, verde, azul, alfa). El parámetro alfa va de 0 (totalmente transparente) a 255 (totalmente opaco).

import pygame 
pygame.init() 
screen = pygame.display.set_mode((320, 200)) 
screen.fill((200, 100, 200)) 
s = pygame.Surface((64, 64), flags=pygame.SRCALPHA) 
for i in range(64): 
    pygame.draw.line(s, (0, 0, 0, i*4), (0, i), (64, i)) 

screen.blit(s, (50, 30)) 
pygame.display.flip() 
+0

+1 ejemplos son siempre bienvenidos. especialmente cuando funciona, y muestra lo que se necesita: D – admalledd

+5

Bueno, eso explica cómo mostrar superficies con alfa por píxel (por ejemplo, desde el archivo PNG). Ya estoy enterado de eso. Pero busco una forma de mostrar esas superficies con translucidez controlable por código. p.ej. para hacer que esos sprites pasen de ser completamente transparentes a su transparencia original por píxel. Algo como Surface.set_alpha() pero sin deshabilitar la transparencia por píxel que ya está presente en la superficie. Combinando la transparencia por píxel con el valor de transparencia general. –

1

Si su imagen de entrada tiene habilitada alfa por píxel, pero solo utiliza un bit para transparencia (por ejemplo, sprites .png con un fondo o texto transparente), puede convertir el fondo transparente en un colorkey-alpha background con bastante facilidad, y luego use set_alpha() para mezclar toda la textura en lo que sea.

Ésta es una función rápida y sucia ayudante que he usado para la decoloración efectos de texto y otras cosas:

def convert_to_colorkey_alpha(surf, colorkey=pygame.color.Color("magenta")): 
    newsurf = surface.Surface(surf.get_size()) 
    newsurf.fill(colorkey) 
    newsurf.blit(surf, (0, 0)) 
    newsurf.set_colorkey(colorkey) 
    return newsurf 

Un par de otros trucos potencialmente resolver este problema podría ser:

  • Haciendo per- edición de píxeles para modificar el canal alfa antes de blitting
  • Blitting una superficie semitransparente llena de blanco o negro con special_flags = BLEND_RGBA_MULT o BLEND_RGBA_SUB en su superficie de origen.
5

El Pygame documentation dice que no se puede combinar con alfa alfa superficie por píxel, pero si usted está usando Pygame 1.8.1 o posterior, que puede evitar esto usando el parámetro special_flags-.blit().

Así es como lo hice:

# Load an image with per-pixel alpha 
s = pygame.image.load('spam.png') 
s.convert_alpha() 

# Simulate s.set_alpha(alpha) 
alpha_img = pygame.Surface(s.get_rect().size, pygame.SRCALPHA) 
alpha_img.fill((255, 255, 255, alpha)) 
s.blit(alpha_img, (0, 0), special_flags=pygame.BLEND_RGBA_MULT) 

La forma en que esto funciona es crear una segunda superficie del mismo tamaño que el primero, y en blit al primer usuario RGBA multiplication. Al tener las componentes R, G y B de la segunda imagen igual a 255, la multiplicación no afectará el color de la imagen, pero escalará el canal alfa por el factor alfa dado.

Tenga en cuenta que el método anterior difiere de llamar a set_alpha() en que set_alpha() puede revertirse llamando al set_alpha(255). Si utilizas el método anterior, se producirán cambios en los pixel alphas de cada píxel, por lo que el proceso no puede invertirse directamente.

+0

'self' debería ser' s'? – Jason

+0

@Jason: arreglado, gracias! – talljosh