Login | Register
Nerd ParadiseArtisanal tutorials since 1999
In the previous installment, I briefly talked about and used Surface objects. You can instantiate a blank surface by simply calling the Surface constructor with a width and height tuple...
surface = pygame.Surface((100100))

This will create a blank 24-bit RGB image that's 100 x 100 pixels. The default color will be black.
Blitting such an image on a white background will result in this:

However, if you want a 32-bit RGBA image, you can also include an optional argument in the Surface constructor...
surface = pygame.Surface((100100), pygame.SRCALPHA)

This will create a 100 x 100 image that's initialized to transparent.
Blitting such an image on a whilte background will result in this:

Solid color images and rectangles aren't very interesting. Let's use an image file.

Suppose you had a friendly PNG image...

To load an image from file, there is a simple call to pygame.image.load...
image = pygame.image.load('ball.png')

replacing your pygame.Surface((100, 100)) code with the code above will result in:

Do not use pygame.image.load repeatedly on the same image within your game loop. That would be embarrassing for you as a programmer and me as a tutorial writer. Initialize images once.

One strategy I like to use is to create a string-to-surface dictionary in one centralized location. Then I write a function called get_image that takes in a file path. If the image has been loaded already, then it returns the initialized image. If not, it does the initialization. The beauty of this is that it is fast and it removes the clutter of initializing images at the beginning of key areas of your game logic. You can also use it to centralize the abstraction of directory separators for different operating systems. But a code snippet is worth a thousand words...

import pygame
import os

_image_library = {}
def get_image(path):
        global _image_library
        image = _image_library.get(path)
        if image == None:
                canonicalized_path = path.replace('/', os.sep).replace('\\', os.sep)
                image = pygame.image.load(canonicalized_path)
                _image_library[path] = image
        return image

screen = pygame.display.set_mode((400300))
done = False
clock = pygame.time.Clock()

while not done:
        for event in pygame.event.get():
                if event.type == pygame.QUIT:
                        done = True
        screen.blit(get_image('ball.png'), (2020))

Big Scary Warning

Windows is not case sensitive when it comes to file names. All other major operating systems are. If your file is called ball.png and you use pygame.image.load('BALL.PNG') it will work if you are on windows. However when you give your game to someone running on a mac or linux, it will explode and they won't be very happy with you. So be careful. After a few embarrassing PyWeek hotfixes I had to send out, I now play it safe and make ALL of my image files lowercase. Then in my get_image function, I call .lower() in the canonicalize_path step.

Setting the alpha of images

If you have a surface that does not have per-pixel alpha (e.g. a surface you initialized without pygame.SRCALPHA) then you can set the alpha of the whole surface with the set_alpha method. Then, when you blit the image, it will be blitted at the faded opacity. If you would like to blit an image with per-pixel alpha at a faded opacity, that is unfortunately impossible to do directly. However, I did invent a lovely hack to get around this limitation which you can read about here if you are interested.

If you want to change a 24-bit image to 32-bit or vice versa, use the .convert_alpha() method. For vice-versa, use the .convert() method which will overlay any per-pixel alpha values over black.

That concludes this installment. Next up: Sound.
Hey, there, Python folks. Hope you enjoyed the post. I just wanted to give a quick shout-out for a weekly Python code golf that I recently started up over on StringLabs.io. If you like Python puzzles please come check it out!