使图像背景透明的问题:pygame

时间:2011-06-20 23:07:03

标签: python transparency pygame color-key

我正在使用pygame开发一个简单的打字导师。我的问题是我使用的是具有白色背景的图像waves1.png。现在我已经指定我希望白色在图像中是透明的(self.image.set_colorkey((255, 255, 255))),它适用于除文本块之外的所有内容。当波与text对象相交时,波浪的白色背景显示在文本的顶部。如果你有pygame(wave1.png图像除外),你可以尝试运行它。

import pygame
from pygame.locals import *

class TextSprite(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.wordList = ['words yes', 'hello', 'this is a sentence', 'this is another sentence'] # read directly from external file
        self.pos = 0
        self.wordNum = 0
        self.update1()

    def update1(self):
        # Render the given word
        self.image = pygame.font.Font(None, 36).render(self.wordList[self.wordNum], 1, (0, 0, 0))
        # Render the correctly guessed letters
        self.correct = pygame.font.Font(None, 36).render(self.wordList[self.wordNum][:self.pos], 1, (255, 0, 0))
        # Copy correct letters onto given word
        self.image.blit(self.correct, (0, 0))

        self.rect = self.image.get_rect()
        # set the center of the center the given word to the center of the screen
        self.rect.center = pygame.display.get_surface().get_rect().center

    def keyin(self, key):
        word = self.wordList[self.wordNum]
        letter = word[self.pos]
        if letter == key:
            self.pos = self.pos + 1
        if self.pos == len(word):
            self.reset()
        self.update1()

    def reset(self):
        self.pos = 0
        self.wordNum = self.wordNum + 1
        self.update1()



class Waves(pygame.sprite.Sprite):

    # Constructor. Pass in the color of the block, 
    # and its x and y position
    def __init__(self, filename):
        # Call the parent class (Sprite) constructor
        pygame.sprite.Sprite.__init__(self) 

        # Create an image of the block, and fill it with a color.
        # This could also be an image loaded from the disk.
        self.image = pygame.image.load(filename).convert()
        # makes any white in the image transparent
        self.image.set_colorkey((255, 255, 255))
        self.rect = self.image.get_rect()

    # Decrease the y coordinate so the waves look like they're moving up
    def update(self, text):
        self.rect.y = self.rect.y - 6
        if self.rect.y <= 200:
            text.reset()
            self.rect.y = 485


def main():

    #I - Import and initialize
    pygame.init()

    #D - Display configuration
    # The screen variable is a pygame Surface object
    # Note that the set_mode() method creates a Surface object for you automatically
    screen = pygame.display.set_mode((640, 480))
    pygame.display.set_caption("Typing Game")

    #E - Entities (just background for now)
    background = pygame.Surface(screen.get_size())
    background = background.convert()
    background.fill((255, 255, 255))
    screen.blit(background, (0,0))



    #A - Action (broken into ALTER steps)

    #A - Assign values to key variables
    clock = pygame.time.Clock()
    keepGoing = True

    # Collect the sprite in a list
    all = pygame.sprite.RenderPlain()
    waveList = pygame.sprite.RenderPlain()

    text = TextSprite()
    all.add(text)

    waves = Waves("waves1.png")
    waveList.add(waves)
    waves.rect.x = 0
    waves.rect.y = 485

    #L - Set up main loop
    while keepGoing:

        #T - Timer to set frame rate
        # Tick is a method in the Clock class that determines the maximum frame rate
        clock.tick(30)

        #E - Event handling
        for event in pygame.event.get():
            if event.type == QUIT:
                keepGoing = False
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    keepGoing = False
                else:
                    text.keyin(event.unicode)

        # update position of waves
        waves.update(text)

        # clears screen
        all.clear(screen, background)

        # update screen
        all.draw(screen)

        waveList.clear(screen, background)
        waveList.draw(screen)


        # display.flip is a method that copies everything from the screen object to the actual visual display
        pygame.display.flip()

pygame.quit ()
if __name__ == '__main__': main()

2 个答案:

答案 0 :(得分:1)

我不知道它是否适合你,但你应该通过png的原生alpha透明度获得更好的结果。

如果您可以自己编辑/重新创建png,请尝试使用透明背景。

从那里,您可以在加载图像后使用convert_alpha()。 (而不是使用颜色键)

http://pygame.org/docs/ref/surface.html#Surface.convert_alpha

编辑:另一个方面是,图片可能有一个alpha通道干扰了colorkey。最好确保你不要同时使用它们。

我被告知您可以通过编程方式检测图像的Alpha通道。有点像...

 if self.image.get_masks()[3]!=0:
   print "image has alpha!"

请参阅此处http://pygame.org/docs/ref/surface.html#Surface.get_masks

HTH

答案 1 :(得分:1)

干得好!您实际上已经正确地完成了所有操作以利用透明度和colorkey(即确保在表面上调用convert,确保将颜色传递给set_colorkey方法等)。

问题在于调用和清除相应精灵组的调用顺序,&#34;所有&#34;和#34; waveList&#34;。在通过调用all.draw渲染文本块之后,然后通过调用waveList.clear来跟随它。

问题在于:一旦你画了文字精灵,你就不想清除波浪精灵下方的空间,或者会消除与已经重叠的区域 - 绘制的文本块。

如果您想要正确执行此操作,请尝试按此顺序执行此操作:

  1. waves.update()
  2. all.clear(屏幕,背景)
  3. waveList.clear(屏幕,背景)
  4. all.draw(画面)
  5. waveList.draw(画面)
  6. (更简单地说,只需将waveList.clear(屏幕,背景)移动到all.clear(屏幕,背景)下方的行;应该这样做)

    当我使用精灵组时,我通常会尝试对其进行分组,以便每个精灵组按此顺序调用相同的方法:清除,更新,碰撞检查(如果有),绘制。

    这通常以正确的顺序处理事情。那么你仍然可能需要注意是否有任何精灵的分层,但那是另一天的另一个故事。