【问题标题】:When blitting a sprite with colorkey transparency in Pygame, the areas that should be transparent are black在 Pygame 中使用 colorkey 透明度对精灵进行 blitting 时,应该透明的区域是黑色的
【发布时间】:2011-04-11 09:36:29
【问题描述】:

我有一个简单的程序,可以将背景图像blit 到显示区域,然后在左上角放置一个精灵。 sprite 使用 colorkey 透明度,但是当我对 sprite 进行 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()。然而,现在,我只得到颜色键的颜色,而不是黑色区域。我已经三次检查了颜色值,我确定它是正确的。还有什么我可能会遗漏的吗?

【问题讨论】:

    标签: python transparency pygame


    【解决方案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
    

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

    【讨论】:

      【解决方案2】:

      现在问题中发布的代码的问题可能是您正在混合 convert_alpha(),这会产生一个带有 alpha 通道的精灵,带有 alpha 255 的颜色。SDL 中的颜色键检查只是一个整数比较,因此即使您没有指定 alpha 通道,您也只会匹配 0x007888FF,而不是例如0x007888FE 或 0x00788800。

      如果您的精灵一开始就带有 Alpha 通道,则没有理由使用颜色键。只需使用精灵的 Alpha 通道即可使您想要的部分透明。

      【讨论】:

      • 精灵没有 Alpha 通道。我在那里有 convert_alpha() 试图看看它是否能解决问题。最初我在那里有常规的 convert()。
      【解决方案3】:

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

      【讨论】:

      • SpriteDict 的构造函数中,我调用了忘记显示的loadImage。它将颜色键指定为“#007888”。对此感到抱歉。
      【解决方案4】:

      这是我在 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)。 -1 的颜色键将告诉函数将像素定位在精灵的 0,0 处,然后将其用作颜色键。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-29
        • 2017-04-25
        • 1970-01-01
        相关资源
        最近更新 更多