Surfaces
In tkinter, we have the canvas, which we could draw on top of. Pygame works slightly differently; instead of having a single canvas to shapes and images on, we have different surfaces. A surface can be thought of as a collection on pixels, and they are always rectangular.
The display that the user sees is a surface, but so are other things, like images. We can draw on any surface we want, and we can draw a surface onto another surface.
Take a look at the following code:
screen.fill((r,g,b))
Here, screen is a surface object. On it we can call the fill method, which takes in an RGB value. So, this line of code will take the screen surface and fill it with the desired rgb value of your choice. For more details, check out the surface reference.
Creating your display
Pygame surfaces can be made by calling Pygame.surface, and providing it an argument about it's size and some other optional parameters. However, to make your display, it's a bit different. Consider the following code:
pygame.display.set_mode((width, height))
pygame.display.set_caption("title")
This sets up the display the user will see as a special type of surface. In the rest of this section, we'll refer to screen as the user display.
Placing an image on a surface (Blit)
Remember, in Pygame images are surfaces. That means that if we want to take an image and draw it on the display surface, we just need to take the pixels from one surface and slap them onto a region of another surface. We can do this using the 'blit' method.
surface.blit(source, dest, area=None)
Here, we take the pixels from the source and blit them onto the surface the method is being called on. With the dest argument, we can tell Pygame where exactly to place the image in our surface by giving it an xy-coordinate location of the top-left corner.
The dest can be passed in two different ways:
- As a tuple of xy-coordinates:
screen.blit(myImage, (50,50))
As a Pygame Rect object:
screen.blit(myImage, Rect(50,50,40,40))
Pygame Rect objects can be made with four values - x-coordinate of the left edge, y-coordinate of the top, width and height. Pygame Rect objects are really only used to hold this information, but is used in a lot of built-in functions because it makes it simple to access information about the image and give lots of functionality.
The optional area argument tells which region of the source to copy over. If none is specified, it copied the entire image. This is also taken in as a Rect object.
Drawing on a surface
Pygame has all those draw functions you knew and loved in tkinter. Here are a few:
pygame.draw.rect(Surface, (r,g,b), Rect, width=0)
pygame.draw.polygon(Surface, (r,g,b), [(x0,y0),(x1,y1)...], Rect, width=0)
pygame.draw.line(Surface, (r,g,b), start_pos, end_pos, width=1)
You'll find that you won't be using much draw functions, if any. Images typically look nicer, and drawing shapes and lines can cause aliasing problems.
Surface Transformations
Pygame comes built-in with a lot of surface operations. Here are a few:
pygame.transform.rotate(surface, angle)
pygame.transform.flip(surface, x-bool, y-bool)
pygame.transform.scale(surface, (width,height), dest=none)
One thing to remember when doing Pygame transformations is that surfaces are ALWAYS rectangles. This means that when we rotate images, the resulting image will be larger if it's not a multiple of 90 degrees. So, if you see yourself rotating images a lot, it'll be a good idea to store the original image and rotate the original image each time, rather than rotating in increments.
For more information about transformations, check out the link here.