Take the 2-minute tour ×

I have a simple program that blits a background image onto the display area, and then puts a sprite in the upper left corner. The sprite uses colorkey transparency, but when I blit the sprite, the areas that should be transparent are black, instead. The color used for the colorkey is a greenish color, so the colorkey is doing something, at least.

Here's my main module, which has most of the display code:

import pygame
from pygame.locals import *

import sprites

    import psyco
    print "psyco failed to import"

class PatchCon(object): # main game class
    def __init__(self):
        self.screen = pygame.display.set_mode((832, 768))
        self.sprites = pygame.sprite.RenderPlain((sprites.Actor("Reimu")))

    def refresh(self):
        self.screen.blit(self.background, (0,0))

    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

if __name__ == '__main__':
    game = PatchCon()

My other module, 'sprites.py', deals with loading images and constructing sprite objects:

import os
import pygame
from pygame.locals import *

# there are four different backgrounds compiled into one big image.
bgcoords = ((0,0,832,768),

# 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)
        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):
        self.sprites = SpriteDict(name)
        self.image = self.sprites.choose('N', 0, 1)
        self.rect = self.image.get_rect()

All the tutorials I've found lead me to believe this code is correct. Anyone see what I'm doing wrong?

EDIT: searching around the related questions, I found that image.convert() doesn't preserve alpha pixels, so as suggested in another question, I changed it to image.convert_alpha(). Now, however, instead of black areas, I just get the color of the colorkey. I've triple-checked the color value, and I'm certain its correct. Anything else I could be missing?

share|improve this question

4 Answers 4

up vote 1 down vote accepted

Well, I solved my problem. It involved changing the guts of SpriteDict so that it didn't call loadImage(), but instead handled loading the image and applying the transparency in the constructor itself, like so:

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
                char[0] += self.spriteSize[0]+2
            char[1] += self.spriteSize[1]+2

It makes my code a lot messier, and probably a good bit slower, but it works. If someone could tell me why it has to work this way, and possibly how to make it not so ugly, that'd be great.

share|improve this answer

Your call to loadImage passes (implicitly) None as the colorkey parameter. Your loadImage function, when the colorkey is None, does not set any colorkey.

share|improve this answer
In the constructor of SpriteDict, I had a call to loadImage I forgot to show. It specifies the colorkey as '#007888'. Sorry about that. –  Max Sep 12 '10 at 19:24

The problem with the code that is posted in the question now is probably that you are mixing convert_alpha(), which results in a sprite with an alpha channel, with a color with alpha 255. A colorkey check in SDL is just an integer comparison, so even though you did not specify an alpha channel, you are only going to match 0x007888FF, not e.g. 0x007888FE or 0x00788800.

If you have a sprite with an alpha channel in the first place, there is no reason to use a colorkey. Simply use the sprite's alpha channel to make the parts you want transparent.

share|improve this answer
The sprite does not have an alpha channel. I had convert_alpha() there in an attempt to see if it would fix the problem. Originally I had regular convert() there. –  Max Sep 16 '10 at 18:45

Here's a block of image loading code I found within the pygame examples. You can plug this into your main python file to handle the same job as your script, without having to import it:

import os, sys #required to use this block
def load_image(name, colorkey=None):
    fullname = os.path.join('name for images folder here', name)
        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()

Some notes:

Loading a circular object whose diameter touches the rect's dimensions will cause issues. You can fix that by making the image size larger than the circle. This happened when loading PNGs, but I don't know what happens when loading other extension formats.

This block is extremely versatile; you can copy-paste this in any script and it will work. When you want to load an image, call load_image('image.bmp', -1). a colorkey of -1 will tell the function to locate the pixel at 0,0 of the sprite, then use that as the colorkey.

share|improve this answer

Your Answer


