При перетаскивании спрайта с прозрачностью с помощью цветовой клавиши в Pygame области, которые должны быть прозрачными, будут черными - PullRequest
1 голос
/ 12 сентября 2010

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

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

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 () не сохраняет альфа-пиксели, поэтому, как было предложено в другом вопросе, я изменил его на image.convert_alpha (). Однако теперь вместо черных областей я просто получаю цвет цветовой клавиши. Я трижды проверил значение цвета и уверен, что он правильный. Что-нибудь еще, что я мог бы пропустить?

Ответы [ 4 ]

1 голос
/ 13 сентября 2010

Ну, я решил свою проблему.Это включало изменение кишок 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 голос
/ 13 сентября 2010

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

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

0 голосов
/ 02 мая 2012

Вот блок кода загрузки изображения, который я нашел в примерах пигмеев. Вы можете подключить его к основному файлу 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 спрайта, а затем использовать его в качестве цветового ключа.

0 голосов
/ 12 сентября 2010

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

...