2010-11-25 9 views
13

È possibile visualizzare le superfici PyGame con alpha controllabile? Vorrei prendere una superficie con alfa per pixel e visualizzarla con un livello di traslucenza variabile senza influenzare i dati di superficie e mantenere intatta la trasparenza, ovvero gli oggetti sulla superficie manterrebbero le loro forme ma i loro "contenuti" diventeranno più o meno traslucido.PyGame: sprite traslucidi con pixel alfa

In altre parole, desidero combinare l'alfa pixel per l'immagine di origine con alfa di superficie calcolata al runtime.

risposta

4

Dopo aver controllato sia PyGame e documentazioni SDL sono venuto a conclusione che ciò che ho chiesto non era fattibile in PyGame utilizzando funzioni standard.

I documenti SDL indicano che l'alfa per pixel e l'alfa per superficie non possono essere combinati con il primo sempre prendendo la precedenza. L'unico modo per ottenere l'effetto che voglio è scrivere un codice che aggiorni i valori alfa per pixel della superficie di origine prima del blit.

4

Sì, è possibile. Il documentation of the Surface class spiega come farlo. Si riduce a solo due casi: O si imposta una bandiera durante la creazione dell'oggetto superficie:

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

o dare un canale alfa per una superficie che non dispone ancora di uno:

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

La documentazione del modulo pygame.image dice che l'applicazione di convert_alpha è necessaria per i PNG con trasparenza.

Se si desidera è possibile modificare il valore alfa di ciascun pixel con il disegno dei moduli e il surfarray. Quando si specifica un colore, utilizzare quindi una tupla di quattro numeri interi: (rosso, verde, blu, alfa). Il parametro alfa va da 0 (totalmente trasparente) 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 esempi sono sempre i benvenuti. specialmente quando funziona e mostra cosa è necessario: D – admalledd

+5

Bene, questo spiega come visualizzare superfici con alfa pixel (ad esempio dal file PNG). Ne sono già consapevole. Ma cerco un modo per visualizzare quelle superfici con traslucenza controllabile dal codice. per esempio. per rendere quegli sprite passano da completamente trasparenti alla loro trasparenza originale per pixel. Qualcosa come Surface.set_alpha() ma senza disabilitare la trasparenza per pixel già presente nella superficie. Unendo la trasparenza per pixel con il valore complessivo di trasparenza. –

1

Se l'immagine in ingresso ha per-pixel alpha abilitato, ma è solo con un singolo bit per la trasparenza (ad esempio, .png sprite con uno sfondo trasparente o testo), è possibile convertire lo sfondo trasparente ad uno sfondo colorkey-alfa abbastanza facilmente, e quindi usare set_alpha() per fondere l'intera trama su qualsiasi cosa.

Si tratta di una funzione veloce e sporco aiutante che ho usato per dissolvenza effetti di testo e altre cose:

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 paio di altri trucchi potenzialmente risolvere questo problema potrebbe essere:

  • Facendo per- modifica pixel per modificare il canale alfa prima del blitter
  • Bloccare una superficie semitrasparente bianca o nera con i flag_spaziente = BLEND_RGBA_MULT o BLEND_RGBA_SUB sulla superficie di origine.
5

Il Pygame documentation dice che non è possibile combinare alpha superficie con per-pixel alpha, ma se si sta utilizzando Pygame 1.8.1 o più recente, è possibile aggirare questo utilizzando il parametro special_flags-.blit().

Ecco come ho fatto:

# 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) 

Il modo in cui funziona è quello di creare una seconda superficie delle stesse dimensioni del primo, e blit è al primo utilizzo RGBA multiplication. Avendo le componenti R, G e B della seconda immagine uguali a 255, la moltiplicazione non influenzerà il colore dell'immagine, ma scalerà il canale alfa per il fattore alfa specificato.

Si noti che il metodo di cui sopra è diverso da chiamare set_alpha() in quel set_alpha() può essere invertito chiamando set_alpha(255). Se si utilizza il metodo sopra riportato, l'alfa pixel di ogni pixel viene modificato, quindi il processo non può essere invertito in modo diretto.

+0

'self' dovrebbe essere' s'? – Jason

+0

@Jason: risolto, grazie! – talljosh