2010-09-12 19 views
1

J'ai un programme simple qui bloque une image d'arrière-plan dans la zone d'affichage, puis place une image-objet dans le coin supérieur gauche. Le sprite utilise la transparence des touches de couleur, mais lorsque je blitte l'image-objet, les zones qui doivent être transparentes sont noires. La couleur utilisée pour la clé de couleur est une couleur verdâtre, donc la touche de couleur fait au moins quelque chose.Lors de la fusion d'une image-objet avec transparence de couleur dans Pygame, les zones qui doivent être transparentes sont noires.

Voici mon module principal, qui a la plupart du code d'affichage:

import pygame 
from pygame.locals import * 

import sprites 

try: 
    import psyco 
    psyco.full() 
except: 
    print "psyco failed to import" 

class PatchCon(object): # main game class 
    def __init__(self): 
     pygame.init() 
     self.screen = pygame.display.set_mode((832, 768)) 
     pygame.display.set_caption('PatchCon') 
     self.setBackground() 
     self.sprites = pygame.sprite.RenderPlain((sprites.Actor("Reimu"))) 

    def refresh(self): 
     self.sprites.update() 
     self.screen.blit(self.background, (0,0)) 
     self.sprites.draw(self.screen) 
     pygame.display.update() 

    def setBackground(self): 
     self.background = pygame.Surface(self.screen.get_size()) 
     backgrounds = sprites.loadImage('patchconbackgrounds.png') 
     self.background.blit(backgrounds[0], (0,0), sprites.bgcoords[3]) 
     self.background = self.background.convert() 

    def mainLoop(self): 
     while True: 
      for event in pygame.event.get(): 
       if event.type == QUIT: return 
      self.refresh() 



if __name__ == '__main__': 
    game = PatchCon() 
    game.mainLoop() 

Mon autre module, 'sprites.py', traite des images de chargement et la construction d'objets d'images-objets:

import os 
import pygame 
from pygame.locals import * 


# there are four different backgrounds compiled into one big image. 
bgcoords = ((0,0,832,768), 
      (0,769,832,1537), 
      (833,0,1664,768), 
      (833,769,1664,1537)) 

# the top left pixels of characters' sprites in the sprite sheet 
charCoords = { "Reimu" : (1, 10), 
       "Marisa" : (334, 10)} 


def loadImage(name, colorkey=None): 
    fullname = os.path.join('images', name) 
    try: 
     image = pygame.image.load(fullname) 
    except pygame.error, message: 
     print 'Cannot load image:', fullname 
     raise SystemExit, message 
    image = image.convert_alpha() 
    if colorkey is not None: 
     if colorkey is -1: 
      colorkey = image.get_at((0,0)) 
     image.set_colorkey(colorkey, RLEACCEL) 
    return image, image.get_rect() 



class SpriteDict(object): 
    """SpriteDict has a list that holds all of the different images 
    the sprites have. It's in charge of finding character's sprites on a big 
    sprite sheet and loading them into that list.""" 
    def __init__(self): 
     self.spritesheet = loadImage("patchconsprites.png", pygame.Color('#007888'))[0] 
     # more code here 

    def choose(self, dir, step, color): 
     """This function returns an image from the sprite list.""" 



class Actor(pygame.sprite.Sprite): 
    def __init__(self, name): 
     pygame.sprite.Sprite.__init__(self) 
     self.sprites = SpriteDict(name) 
     self.image = self.sprites.choose('N', 0, 1) 
     self.rect = self.image.get_rect() 

Tous les tutoriels que j'ai trouvés m'amènent à croire que ce code est correct. Quelqu'un voit ce que je fais mal?


EDIT: la recherche, je trouve autour des questions connexes qui image.convert() ne conserve pas pixels alpha, donc comme l'a suggéré dans une autre question, je l'ai changé image.convert_alpha(). Maintenant, cependant, au lieu de zones noires, je viens d'obtenir la couleur de la clé de couleur. J'ai triplé la valeur de la couleur, et je suis certain que c'est correct. Y at-il autre chose que je pourrais manquer?

Répondre

1

Eh bien, j'ai résolu mon problème. Il consistait à remplacer le courage de SpriteDict afin qu'il n'a pas appelé loadImage(), mais plutôt traitée chargement de l'image et l'application de la transparence dans le constructeur lui-même, comme ceci:

class SpriteDict(object): 
    def __init__(self, name): 
     self.spriteSize = (35, 35) 
     # change this old line: 
     #self.spritesheet = loadImage("patchconsprites.png", (0,120,136,0))[0] 
     # to this: 
     self.spritesheet = pygame.image.load("./images/patchconsprites.png") 
     self.sprites = [] 
     start = charCoords[name] 
     char = list(start) 
     image = pygame.Surface((35,35)) 
     for y in range(5): 
      char[0] = start[0] 
      for x in range(9): 
       rect = (char[0], char[1], char[0]+self.spriteSize[0], char[1]+self.spriteSize[1]) 
       image.blit(self.spritesheet, (0,0), rect) 
       # and put the transparency code here: 
       image = image.convert() 
       colorkey = image.get_at((0,0)) 
       image.set_colorkey(colorkey, RLEACCEL) 
       # end new code 
       self.sprites.append(image) 
       char[0] += self.spriteSize[0]+2 
      char[1] += self.spriteSize[1]+2 

Il fait mon code beaucoup messier, et probablement un peu plus lent, mais ça marche. Si quelqu'un pouvait me dire pourquoi ça devait fonctionner de cette façon, et peut-être comment le rendre moins laid, ce serait génial.

0

Votre appel à loadImage transmet (implicitement) None comme paramètre colorkey. Votre fonction loadImage, lorsque la touche de couleur est None, ne définit aucune touche de couleur.

+0

Dans le constructeur de 'SpriteDict', j'ai appelé loadImage que j'ai oublié d'afficher. Il spécifie la clé de couleur comme '# 007888'. Désolé pour ça. – Max

1

Le problème avec le code qui est posté dans la question est probablement que vous mélangez convert_alpha(), qui se traduit par un sprite avec un canal alpha, avec une couleur avec alpha 255. Une vérification colorkey dans SDL est juste une comparaison entière, donc même si vous n'avez pas spécifié un canal alpha, vous allez seulement correspondre à 0x007888FF, pas par exemple 0x007888FE ou 0x00788800.

Si vous avez un sprite avec une couche alpha en premier lieu, il n'y a aucune raison d'utiliser une couleur. Utilisez simplement le canal alpha du sprite pour rendre les parties que vous voulez transparentes.

+0

L'image-objet n'a pas de canal alpha. J'ai eu convert_alpha() là dans une tentative de voir si cela réglerait le problème. À l'origine, j'avais régulièrement convertir() là-bas. – Max

0

Voici un bloc de code de chargement d'image que j'ai trouvé dans les exemples de pygame. Vous pouvez le brancher dans votre fichier principal python pour gérer le même travail que votre script, sans avoir à importer:

import os, sys #required to use this block 
... 
-snip- 
... 
def load_image(name, colorkey=None): 
    fullname = os.path.join('name for images folder here', name) 
    try: 
     image = pygame.image.load(fullname) 
    except pygame.error, message: 
     print 'Cannot load image:', name 
     raise SystemExit, message 
    image = image.convert() 
    if colorkey is not None: 
     if colorkey is -1: 
      colorkey = image.get_at((0,0)) 
     image.set_colorkey(colorkey, RLEACCEL) 
    return image, image.get_rect() 

Quelques notes:

chargement d'un objet circulaire dont le diamètre touche les dimensions du rect causeront problèmes. Vous pouvez corriger cela en augmentant la taille de l'image par rapport au cercle. Cela s'est produit lors du chargement de fichiers PNG, mais je ne sais pas ce qui se passe lors du chargement d'autres formats d'extension.

Ce bloc est extrêmement polyvalent; vous pouvez copier-coller ceci dans n'importe quel script et cela fonctionnera. Lorsque vous souhaitez charger une image, appelez load_image('image.bmp', -1).une couleur de -1 indiquera à la fonction de localiser le pixel à 0,0 de l'image-objet, puis l'utilisera comme clé de couleur.