проблема с прозрачностью фона изображения: pygame - PullRequest
1 голос
/ 21 июня 2011

Я сейчас работаю над простым репетитором по печатанию с использованием pygame.Моя проблема в том, что я использую изображение с белым фоном waves1.png.Теперь я указал, что хочу, чтобы белый цвет был прозрачным на изображении (self.image.set_colorkey((255, 255, 255))), и это для всего, кроме текстового блока.Когда волны пересекаются с объектом text, белый фон волн отображается в верхней части текста.Вы можете попробовать запустить это, если у вас есть pygame (за исключением изображения waves1.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 ]

1 голос
/ 17 мая 2014

Молодец! Вы на самом деле все сделали правильно, чтобы воспользоваться прозрачностью и цветовой клавишей (т. Е. Убедиться, что вызовите функцию convert на поверхности, не забудьте передать цвет в метод set_colorkey и т. Д.).

Проблема связана с порядком вызовов для рисования и очистки соответствующих групп спрайтов «all» и «waveList». После рендеринга текстовых блоков с помощью вызова all.draw вы следуете за ним, вызывая waveList.clear.

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

Если вы хотите сделать это правильно, попробуйте сделать это в следующем порядке:

  1. waves.update ()
  2. all.clear (экран, фон)
  3. waveList.clear (экран, фон)
  4. all.draw (экран)
  5. waveList.draw (экран)

(проще - просто переместите waveList.clear (экран, фон) на линию чуть ниже all.clear (экран, фон); это должно быть сделано)

Когда я работаю с группами спрайтов, я обычно пытаюсь сгруппировать их так, чтобы каждая группа спрайтов вызывала один и тот же метод в следующем порядке: очищает, обновляет, проверяет столкновения (если есть), рисует.

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

1 голос
/ 21 июня 2011

Я не знаю, подходит ли вам этот вариант, но вы должны получить лучшие результаты благодаря собственной альфа-прозрачности png.

Если вы можете редактировать / воссоздать png самостоятельно, попробуйте использовать прозрачный фон.

Оттуда вы можете использовать convert_alpha () после загрузки изображения.(вместо использования цветовой клавиши)

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

РЕДАКТИРОВАНИЕ: еще один аспект заключается в том, что изображение может иметь альфа-канал, мешающий цветовой клавише.Лучше всего убедиться, что вы не пытаетесь использовать оба.

Мне сказали, что вы можете определять альфа-канал изображения программно.Что-то вроде ...

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

Смотрите здесь http://pygame.org/docs/ref/surface.html#Surface.get_masks

HTH

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...