Programmare in Python - Parte 15
This month we are going to explore Pygame, a set of modules designed for writing games. The website is http://www.pygame.org/. To quote from the Pygame read-me: “Pygame is a cross-platform library designed to make it easy to write multimedia software, such as games, in Python. Pygame requires the Python language and SDL multimedia library. It can also make use of several other popular libraries.”
You can install Pygame through Synaptic as 'python-pygame'. Do this now so we can move forward.
First, we import Pygame (see above right). Next, we set the os.environ to make our window centered in our screen. Next, we initialize Pygame, then set the Pygame window to 800x600 pixels, and set the caption. Finally, we display the screen, and go into a loop waiting for a keystroke or mouse-button-down event. The screen is an object that will contain anything we decide to put on it. It's called a surface. Think of it as a piece of paper that we will draw things onto.
Not very exciting, but it's a start. Let's make it a bit less boring. We can change the background color to something less dark. I found a program called “colorname” that you can install via the Ubuntu Software Center. This allows you to use the “color wheel” to pick a color you like, and it will give you the RGB or Red, Green, Blue values of that color. We must use RGB colors if we don't want to use the predefined colors that Pygame gives us. It's a neat utility that you should consider installing.
Right after the import statements, add...
Background = 208, 202, 104
This will set the variable Background to a tanish color. Next, after the pygame.display.set_caption line, add the following lines...
The screen.fill() method will set the color to whatever we pass it. The next line, pygame.display.update(), actually updates the changes to our screen.
Save this off as pygame1.py, and we'll move on.
Now we will display some text in our bland looking window. Again, let's start with our import statements and the background variable assignment from our last program.
import pygame from pygame.locals import * import os Background = 208, 202, 104
Now, add an additional variable assignment for the foreground color of our font.
FontForeground = 255,255,255 # White
Then, we will add in the majority of the code from our last program (shown right).
If you run this now, nothing has changed visually since all we did is add the foreground definition. Now, after the screen.fill() line, and before the loop portion of our code, enter the following lines:
font = pygame.font.Font(None,27) text = font.render('Here is some text', True, FontForeground, Background) textrect = text.get_rect() screen.blit(text,textrect) pygame.display.update()
Go ahead, save the program as pygame2.py, and run the program. On the top left of our window, you should see the text “Here is some text”.
Let's break down the new commands. First, we call the Font method and pass it two arguments. The first is the name of the font we wish to use, and the second is the font size. Right now, we'll just use 'None', and let the system pick a generic font for us, and set the font size to 27 points.
Next we have the font.render() method. This has four arguments. In order, they are the text we wish to display, whether we want to use anti-aliasing (True in this case), the foreground color of the font, and, finally, the background color of the font.
The next line (text.get_rect()) assigns a rectangle object that we will use to put the text on the screen. This is an important thing, since almost everything else we will deal with is rectangles. (You'll understand more in a bit.) Then we blit the rectangle onto the screen. And, finally, we update the screen to show our text. What is blit, and why the heck should I want to do something that sounds so weird? Well, the term goes WAY back to the 1970s, and came from Xerox PARC (which is where we owe so much of today's technology). The term was originally called BitBLT which stands for Bit (or Bitmap) Block Transfer. That changed to Blit (possibly because it's shorter). Basically we are plopping our image or text on to the screen.
What if we want the text to be centered in the screen instead of on the top line where it takes a bit of time to see? In between the text.get_rect() line and the screen.blit line, put the following two lines:
textRect.centerx = screen.get_rect().centerx textRect.centery = screen.get_rect().centery
Here we are getting the center of the screen object (remember surface) in x and y pixel positions, and setting our textRect object x and y center points to those values.
Run the program. Now our text is centered within our surface. You can also modify the text by using (in our sample code) font.set_bold(True) and/or font.set_italic(True) right after the pygame.font.Font line.
Remember we discussed very briefly the 'None' option when we set the font to a generic font. Let's say you want to use a fancier font. As I stated before, the pygame.font.Font() method takes two arguments. The first is the path and file name of the font we want to use, and the second is the font size. The problem is multi-fold at this point. How do we know what the actual path and filename of the font we want to use is on any given system? Thankfully, Pygame has a function that takes care of that for us. It's called match_font. Here's a quick program that will print the path and filename of (in this case) the Courier New font.
import pygame from pygame.locals import * import os print pygame.font.match_font('Courier New')
On my system, the returned value is “/usr/share/fonts/truetype/msttcorefonts/cour.ttf”. If, however, the font is not found, the return value is “None”. Assuming that the font IS found, then we can assign the returned value to a variable, and we can then use the following assignment.
courier = pygame.font.match_font('Courier New') font = pygame.font.Font(courier,27)
Change your last version of the program to include these two lines and try it again. The bottom line is, either use a font that you KNOW will be available on the end user's machine, or include it when you distribute your program and hard code the font path and name. There are other ways around this, but I'll leave that to you to figure out so we can move on.
While text is nice, graphics are better. I found a really nice tutorial for Pygame written by Peyton McCollugh, and thought I'd take and modify it. For this part, we need to start with a picture that will move around our surface. This picture is known as a sprite. Use GIMP or some other tool and create a stick figure. Nothing fancy, just a generic stick figure. I'll assume that you are using GIMP. Start a new image, set the size to 50 pixels in both height and width, and, under advance options, set the 'Fill With' option to Transparency. Use the pencil tool with a brush of Circle (03). Draw your little figure, and save it as stick.png into the same folder you have been using for the code this time. Here is what mine looks like. I'm sure you can do better.
I know...I'm not an artist. However, for our purposes, that will do. We saved it as a .png file, and set the background to be transparent, so that just the little black lines of our stick figure show up - and not a white or other color background will show.
Let's talk about what we want the program to do. We want to show a Pygame window that has our stick figure drawing in it. We want the figure to move when we press any of the arrow keys up, down, right and left, assuming we aren't at the edge of the screen and cannot move any further. We want the game to quit when we press the “q” key. Now, moving the sprite around might seem easy, and it is, but it is a bit harder than it initially sounds. We start by creating two rectangles. One for the sprite itself and one that is the same size but is blank. We blit the sprite onto the surface to start, then, when the user presses a key, we blit the blank rectangle over the original sprite, figure out the new position, and blit the sprite back onto the surface at its new position. Pretty much what we did with the alphabet game last time. That's about it for this program. It will give us an idea how to actually place a graphic on the screen and move it around.
So, start a new program, and call it pygame4.py. Put in the includes we've been using during this tutorial. This time we'll use a minty green background so those values should be 0, 255, 127 (see above).
Next, we create a class that will handle our graphic or sprite (next page, shown bottom left). Put this right after the imports.
What is all this doing? Let's start with the init routine. We initialize the sprite module of Pygame with the pygame.sprte.Sprite.init line. We then set the surface, and call it screen. This will allow us to check to see if the sprite is going off the screen. We then create and set the position of the blank oldsprite variable, which will keep the old position of our sprite. Now we load our stick figure sprite with the pygame.image.load routine, passing it the filename (and path, if it's not in the program's path). Then we get a reference (self.rect) to the sprite which sets up the width and height of the rectangle automatically, and set the x,y position of that rectangle to the position we pass into the routine.
The update routine basically makes a copy of the sprite, then checks to see if the sprite goes off the screen. If so, it's left where it was, otherwise its position is moved the amount we send into it.
Now, after the screen.fill statement, put the code shown on the following page (right-hand side).
Here we create an instance of our class, calling it character. Then we blit the sprite. We create the blank sprite rectangle, and fill it with the background color. We update the surface and start our loop.
As long as DoLoop is equal to 1, we loop through the code. We use pygame.event.get() to get a keyboard character. We then test it against the event type. If it's QUIT, we exit. If it's a pygame KEYDOWN event, we process it. We look at the key value returned, and compare it to constants defined by Pygame. We then call the update routine in our class. Notice here that we simply are passing a list containing the number of pixels on the X and Y axis to move the character. We bump it by 10 pixels (positive for right or down, negative for left or up. If the key value is equal to “q”, we set DoLoop to 0, and so will break out of the loop. After all of that, we blit the blank character to the old position, blit the sprite to the new position, and finally update - but in this case, we update only the two rectangles containing the blank sprite and the active sprite. This saves a tremendous amount of time and processing.
As always, the full code is available at www.thedesignatedgeek.com or at http://fullcirclemagazine.pastebin.com/DvSpZbaj.
There's a ton more that Pygame can do. I suggest that you hop over to their website, and look at the reference page (http://www.pygame.org/docs/ref/index.html). In addition, you can take a look at some of the games that others have put up.
Next time, we will be digging deeper into Pygame by creating a game that comes from my past...my very DISTANT past.
Incollare la traduzione qui al posto di questa riga e anche nel paragrafo "Revisione".
Incollare la revisione qui al posto di questa riga.