2010-09-12 1 views
1

У меня есть простая программа, которая смещает фоновое изображение на область отображения, а затем помещает спрайт в верхний левый угол. Спрайт использует прозрачность colorkey, но когда я заливаю спрайт, области, которые должны быть прозрачными, являются черными. Цвет, используемый для colorkey, является зеленоватым цветом, поэтому colorkey делает что-то, по крайней мере.Когда blitting sprite с прозрачностью colorkey в Pygame, области, которые должны быть прозрачными, являются черными

Вот мой основной модуль, который имеет большую часть кода отображения:

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

Мой другой модуль, 'sprites.py', имеет дело с загрузкой изображений и создания объектов спрайтов:

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

Все найденные мной уроки привели меня к тому, что этот код верен. Кто-нибудь видит, что я делаю неправильно?


EDIT: поиск вокруг соответствующих вопросов, я обнаружил, что image.convert() не сохраняет альфа пикселей, так как это было предложено в другом вопросе, я изменил его на image.convert_alpha(). Теперь, однако, вместо черных областей, я просто получаю цвет colorkey. Я проверил трехзначное значение цвета, и я уверен, что это правильно. Что-нибудь еще, что мне не хватало?

ответ

1

Ну, я решил свою проблему. Она включала изменения начинки SpriteDict так, чтобы он не звонил loadImage(), но вместо этого обрабатывается загрузки изображения и применение прозрачности в самом конструкторе, например, так:

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 

Это делает мой код намного грязнее, и вероятно, немного медленнее, но он работает. Если бы кто-нибудь мог сказать мне, почему он должен работать таким образом, и, возможно, как сделать его не таким уродливым, это было бы здорово.

0

Ваш вызов loadImage проходит (неявно) Нет как параметр colorkey. Функция loadImage, когда colorkey is None, не устанавливает colorkey.

+0

В конструкторе 'SpriteDict' у меня был вызов loadImage, который я забыл показать. Он указывает colorkey как '# 007888'. Извини за это. – Max

1

Проблема с кодом, опубликованным в вопросе сейчас, вероятно, заключается в том, что вы смешиваете convert_alpha(), что приводит к спрайту с альфа-каналом с цветом с альфа-255. Проверка colorkey в SDL - это просто целочисленное сравнение, поэтому, хотя вы не указали альфа-канал, вы будете только соответствовать 0x007888FF, а не, например, 0x007888FE или 0x00788800.

Если у вас есть спрайт с альфа-каналом в первую очередь, нет причин использовать colorkey. Просто используйте альфа-канал спрайта, чтобы сделать части, которые вы хотите прозрачными.

+0

Спрайт не имеет альфа-канала. У меня был convert_alpha() там, пытаясь понять, устранит ли это проблему. Первоначально у меня был обычный convert(). – Max

0

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

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

Некоторые ноты:

Загрузка круговой объект, диаметр которого касается размеров прямоугольника будет вызывать вопросы. Вы можете исправить это, сделав размер изображения больше круга. Это произошло при загрузке PNG, но я не знаю, что происходит при загрузке других форматов расширений.

Этот блок чрезвычайно универсален; вы можете скопировать-вставить это в любой скрипт, и он будет работать. Когда вы хотите загрузить изображение, вызовите load_image('image.bmp', -1).colorkey из -1 скажет функции, чтобы найти пиксель в 0,0 спрайта, а затем использовать это как colorkey.