Something about programming

SDL2 in Python Programming Language

Previous tutorial: Classes in Python
Next tutorial: Hello World in Python SDL2
SDL2 in Python Programming Language

In previous tutorial we saw how to make Hello World program using sdl2.ext in Python programming language. sdl2.ext package contains advanced features (like interface elements) and wrappers which hide what happens under the cover. In this tutorial we'll throw away sdl2.ext crutch and will work with sdl2 directly. All functions we'll use are mapped directly to SDL2 library in other languages.

First we'll make a new "Hello World" program that not uses sdl2.ext. This version of Hello World is more complex and in it I'll introduce surfaces.

Python SDL2 Hello World

As we already know, SDL2 is cross-platform library. Initially it's written in C language, but it has wrappers in different languages. We are interested in Python programming language. Most Python version functions maps directly to C language version. That means that you can look at C language reference of functions and use it in Python.

Let's examine the SDL2 Hello World in Python programming language and then improve it by adding surfaces:

import ctypes import sdl2 sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) width = 400 height = 400 window = sdl2.SDL_CreateWindow(b"Hello World", 100, 20, width, height, sdl2.SDL_WINDOW_SHOWN) is_running = True event = sdl2.SDL_Event() while is_running: while sdl2.SDL_PollEvent(ctypes.byref(event)) != 0: if event.type == sdl2.SDL_QUIT: is_running = False break sdl2.SDL_DestroyWindow(window) sdl2.SDL_Quit()

We import sdl2 module, not just sdl2.ext, to get full capabilities of SDL2. Additionally we imported ctypes module. ctypes (C language types) allows using C language libraries in the Python code. As C language has different data types than Python language, we can say that this package builds the bridge between two languages.

All functions from sdl2 module I've prepended with sdl. - you can get rid of this infix if you import all names from sdl2 like this:

from sdl2 import *

First line of code initializes sdl2 library. As you can see I've passed SDL_INIT_VIDEO argument. There is another value possible: SDL_INIT_AUDIO - it will initialize audio capabilities of sdl2, but we don't need them now. Next valuable line:

window = sdl2.SDL_CreateWindow(b"Hello World", 100, 20, width, height, sdl2.SDL_WINDOW_SHOWN)

It creates the window. First argument - title - you need to pass the byte string and it means we can't use non-English titles (but that's temporary).

Second and third arguments - position of window in relation of screen, second - offset from left side of a screen, third - offset from the top side of a screen.

Next there are width and height of the window. The last argument is the most interesting. It allows to define the behavior of a window. SDL_WINDOW_SHOWN means that the window is visible. Other constants allow to create minimized, resizable or even fullscreen windows.

Last two lines of code destroy window and quit the SDL environment. Now let's check events.

SDL2 events. Event-driven programming in Python programming language

In previous example we used test event processor, but to continue moving on we need to replace it with more real example.

All games are relate to set of program that can be called event-driven. In such programs there is infinite loop. In each iteration all logic of game is processed: AI, movements, audio, video rendering. Usually one iteration of such loop equals one frame of a game. At any moment there is possibility for some event to happen. There are different kind of events: user closed the program, user clicked the mouse button or pressed the key on keyboard, enemy started shooting and so on. On each event our program should decide what to do. Here is example of simple event processor that has only one event:

is_running = True event = sdl2.SDL_Event() while is_running: while sdl2.SDL_PollEvent(ctypes.byref(event)) != 0: if event.type == sdl2.SDL_QUIT: is_running = False break

is_running variable is used to control the infinite loop. Loop ends when SDL_QUIT event happens. Such event will happen when user decide to close the program.

On each iteration we try to get event from event queue with SDL_PollEvent function.

In next Python programming language tutorials we'll work with event processor a lot and you'll quickly get used to it. In C language implementation argument is a pointer. Python language doesn't have such concept, that's why we are converting event to C language compatible type with ctypes module.

SDL2 Surfaces

Now we'll improve Hello World program. We'll make content of window black and will place red square in the center.

To add red square on the window we need to add 6 lines of code before is_running variable declaration.

window_surface = sdl2.SDL_GetWindowSurface(window) sdl2.SDL_FillRect(window_surface, None, 0x000000) rtile = sdl2.SDL_CreateRGBSurface(0, 50,50,32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff) sdl2.SDL_FillRect(rtile, None, 0xff0000ff) sdl2.SDL_BlitSurface(rtile, None, window_surface, sdl2.SDL_Rect(int(width/2-25), int(height/2-25), 50,50)) sdl2.SDL_UpdateWindowSurface(window)

First string get surface of a window of a program. Surface is just a rectangular area on which you can draw (anything). Internally surface is an array of pixels. Each pixel has three channels for colors: red, green and blue.

Second line fills the surface with black color. First argument - window surface we got earlier, second - rectangle on the surface we want to fill. As we want all surface black, we pass None. Last argument is the color we want to fill the surface. 0x means it's hexadecimal value, first two digits - red channel, next two - green and last two - blue. Each channel can vary from 00 (no color component at all) to ff (255 in decimal) - it means full color value of channel. Pure red color in such value will be: 0xff0000, pure green - 0x00ff00, pure blue - 0x0000ff, white - 0xffffff and black 0x000000.

Next line create new surface in memory. That will be the 50*50 pixels red rectangle. SDL_CreateRGB_Surface receives 8 arguments. First is always 0 - it reserved. Then width and height of surface. 4th - depth of pixel - it says how many bytes will be used for pixel. In our case there are 32 bytes. It allows to use 4 channels for pixel: red, green, white and alpha. We can say that alpha channel represents transparency, but it has additional uses in blending. For now just think that ff - pixel is visible, 00 - pixel is transparent. Last four arguments - masks for channels: red, green, blue, alpha. Here we say on which position each channel should be placed. In our case the order is RGBA, but it can be different:

rtile = sdl2.SDL_CreateRGBSurface(0, 50,50,32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)

Pixels of this surface will have channels in this order: ABGR. We'll always use RGBA order.

I called the variable which contains new surface rtile, it's from red tile. Next:

sdl2.SDL_FillRect(rtile, None, 0xff0000ff)

This line fills rtile with red color: red and alpha channels have maximum values. After that we blit the rtile surface on window surface:

sdl2.SDL_BlitSurface(rtile, None, window_surface, sdl2.SDL_Rect(int(width/2-25), int(height/2-25), 50,50))

Blit - is an operation of copying array (or it's part) of bytes into another array (or it's part). In other words: it's copying of one image onto another. In old days for blitting on consoles where used separate chip that implemented blit operation in hardware.

First argument of SDL_BlitSurface is source surface, second - rectangle on source surface that should be copied, if None - full surface will be copied. Third argument - destination surface. In our case we copy rtile on window surface. Last argument - rectangle on destination surface that should be replaced by source surface. It should be of type SDL_Rect. In this case we copy rtile in the center of window_surface.

And on last line of code we update window with the new content of it's surface. After this line the user will see the result of blitting.

Conclusion

In this tutorial we looked under the hood of SDL2 library and learned about important concept of surfaces.

Material from this tutorial is applicable not only in Python programming language or only in SDL2. Most of this stuff is fundamental in computer 2d graphics. Doesn't matter what programming language or what graphics library you'll choose, there are always surfaces and blitter. Though in 3d graphics there are other fundamental concepts but we'll learn about them in future.

In next tutorials we'll build helper library with which we'll be able make cool demos like mazes and search algorithms.

Comments:

No comments yet