当在Pygame中使用colorkey透明度blrite精灵时,应该是透明的区域是黑色的

时间:2010-09-12 18:54:50

标签: python transparency pygame

我有一个简单的程序,将背景图像blit到显示区域,然后在左上角放置一个精灵。精灵使用colorkey透明度,但是当我对精灵进行blit时,应该是透明的区域是黑色的。用于colorkey的颜色是浅绿色,因此colorkey正在做一些事情,至少。

这是我的主要模块,其中包含大部分显示代码:

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

我发现的所有教程都让我相信这段代码是正确的。有人看到我做错了吗?


编辑:搜索相关问题,我发现image.convert()不保留alpha像素,因此在另一个问题中建议,我将其更改为image.convert_alpha()。然而,现在,我只获得了colorkey的颜色,而不是黑色区域。我已经三重检查了颜色值,我确定它是正确的。还有什么我可以错过的吗?

4 个答案:

答案 0 :(得分: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

它使我的代码变得更加混乱,可能会慢一点,但它确实有效。如果有人能告诉我为什么它必须以这种方式工作,并且可能如何让它变得不那么难看,那就太好了。

答案 1 :(得分:1)

现在问题中发布的代码问题可能是你正在混合convert_alpha(),这会导致带有alpha通道的sprite,颜色为alpha 255. SDL中的colorkey检查只是一个整数比较,所以即使你没有指定一个alpha通道,你只会匹配0x007888FF,而不是eg 0x007888FE或0x00788800。

如果您的精灵首先使用了Alpha通道,则没有理由使用颜色键。只需使用精灵的alpha通道即可使您想要的部分透明。

答案 2 :(得分:0)

您对loadImage的调用(隐式)传递None作为colorkey参数。当colorkey为None时,loadImage函数不会设置任何颜色键。

答案 3 :(得分:0)

这是我在pygame示例中找到的一个图像加载代码块。您可以将其插入主python文件以处理与脚本相同的工作,而无需导入它:

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处,然后将其用作颜色键。