diff --git a/docs/reST/tut/ChimpLineByLine.rst b/docs/reST/tut/ChimpLineByLine.rst index 1bf45a0663..4e7a284d7c 100644 --- a/docs/reST/tut/ChimpLineByLine.rst +++ b/docs/reST/tut/ChimpLineByLine.rst @@ -24,7 +24,7 @@ Line By Line Chimp Introduction ------------ -In the *pygame* examples there is a simple example named, "chimp". +In the *pygame* examples there is a simple example named "chimp". This example simulates a punchable monkey moving around a small screen with promises of riches and reward. The example itself is very simple, and a bit thin on error-checking code. This example program demonstrates many of @@ -35,14 +35,14 @@ The program and images can be found inside the standard source distribution of pygame. For version 1.3 of pygame, this example was completely rewritten to add a couple more features and correct error checking. This about doubled the size of the original example, but now gives us much more to look at, -as well as code the I can recommend reusing for your own projects. +as well as the code I can recommend reusing for your own projects. This tutorial will go through the code block by block. Explaining how -the code works. There will also be mention of how the code could be improved -and what errorchecking could help out. +the code works. There will also be mention of how the code could be improved +and what error checking could help out. This is an excellent tutorial for people getting their first look at -the *pygame* code. Once *pygame* is fully installed, you can find +the *pygame* code. Once *pygame* is fully installed, you can find and run the chimp demo for yourself in the examples directory. .. container:: fullwidth leading trailing @@ -75,20 +75,21 @@ us to do things like create platform independent file paths. In the next line, we import the pygame package. When pygame is imported it imports all the modules belonging to pygame. Some pygame modules are optional, -and if they aren't found, their value is set to "None". +and if they aren't found, their value is set to `None`. -There is a special *pygame* module named "locals". This module -contains a subset of *pygame*\ . The members of this module are commonly -used constants and functions that have proven useful to put into your program's +There is a special *pygame* module named :mod:`locals `. This module +contains a subset of *pygame*. The members of this module are commonly +used constants and functions that have proven useful to put into your program's global namespace. This locals module includes functions like "Rect" to create -a rectangle object, and many constants like "QUIT, HWSURFACE" that are -used to interact with the rest of *pygame*\ . Importing the locals module -into the global namespace like this is entirely optional. If you choose -not to import it, all the members of locals are always available in the -*pygame* module. +a rectangle object, and many constants like "QUIT, HWSURFACE" that are +used to interact with the rest of *pygame*. Importing the locals module +into the global namespace like this is entirely optional. If you choose +not to import it, all the members of locals are always available in the +*pygame* module. -Lastly, we decide to print a nice warning message if the font or sound -modules in pygame are not available. +Lastly, we decide to print a nice warning message if the :mod:`font +` or :mod:`mixer ` modules in pygame are not +available. Loading Resources @@ -112,27 +113,27 @@ look at each function individually in this section. :: return image, image.get_rect() This function takes the name of an image to load. It also optionally -takes an argument it can use to set a colorkey for the image. A colorkey -is used in graphics to represent a color of the image that is transparent. +takes an argument it can use to set a colorkey for the image. A colorkey +is used in graphics to represent a color of the image that is transparent. The first thing this function does is create a full pathname to the file. In this example all the resources are in a "data" subdirectory. By using -the os.path.join function, a pathname will be created that works for whatever +the `os.path.join` function, a pathname will be created that works for whatever platform the game is running on. -Next we load the image using the pygame.image.load function. We wrap -this function in a try/except block, so if there is a problem loading the -image, we can exit gracefully. After the image is loaded, we make an important -call to the convert() function. This makes a new copy of a Surface and converts +Next we load the image using the :func:`pygame.image.load` function. We wrap +this function in a try/except block, so if there is a problem loading the +image, we can exit gracefully. After the image is loaded, we make an important +call to the `convert()` function. This makes a new copy of a Surface and converts its color format and depth to match the display. This means blitting the image to the screen will happen as quickly as possible. Last, we set the colorkey for the image. If the user supplied an argument for the colorkey argument we use that value as the colorkey for the image. This would usually just be a color RGB value, like (255, 255, 255) for -white. You can also pass a value of -1 as the colorkey. In this case the -function will lookup the color at the topleft pixel of the image, and use -that color for the colorkey. :: +white. You can also pass a value of -1 as the colorkey. In this case the +function will lookup the color at the topleft pixel of the image, and use +that color for the colorkey. :: def load_sound(name): class NoneSound: @@ -148,15 +149,15 @@ that color for the colorkey. :: return sound Next is the function to load a sound file. The first thing this function -does is check to see if the pygame.mixer module was imported correctly. -If not, it returns a small class instance that has a dummy play method. -This will act enough like a normal Sound object for this game to run without -any extra error checking. +does is check to see if the :mod:`pygame.mixer` module was imported correctly. +If not, it returns a small class instance that has a dummy play method. +This will act enough like a normal Sound object for this game to run without +any extra error checking. This function is similar to the image loading function, but handles some different problems. First we create a full path to the sound image, and -load the sound file inside a try/except block. Then we simply return the -loaded Sound object. +load the sound file inside a try/except block. Then we simply return the +loaded Sound object. Game Object Classes @@ -192,24 +193,24 @@ them one at a time here. :: self.punching = 0 Here we create a class to represent the players fist. It is derived from -the Sprite class included in the pygame.sprite module. The __init__ function +the `Sprite` class included in the :mod:`pygame.sprite` module. The `__init__` function is called when new instances of this class are created. The first thing -we do is be sure to call the __init__ function for our base class. This -allows the Sprite's __init__ function to prepare our object for use as a +we do is be sure to call the `__init__` function for our base class. This +allows the Sprite's `__init__` function to prepare our object for use as a sprite. This game uses one of the sprite drawing Group classes. These classes -can draw sprites that have an "image" and "rect" attribute. By simply changing +can draw sprites that have an "image" and "rect" attribute. By simply changing these two attributes, the renderer will draw the current image at the current position. -All sprites have an update() method. This function is typically called -once per frame. It is where you should put code that moves and updates -the variables for the sprite. The update() method for the fist moves the -fist to the location of the mouse pointer. It also offsets the fist position -slightly if the fist is in the "punching" state. +All sprites have an `update()` method. This function is typically called +once per frame. It is where you should put code that moves and updates +the variables for the sprite. The `update()` method for the fist moves the +fist to the location of the mouse pointer. It also offsets the fist position +slightly if the fist is in the "punching" state. -The following two functions punch() and unpunch() change the punching -state for the fist. The punch() method also returns a true value if the fist -is colliding with the given target sprite. :: +The following two functions `punch()` and `unpunch()` change the punching +state for the fist. The `punch()` method also returns a true value if the fist +is colliding with the given target sprite. :: class Chimp(pygame.sprite.Sprite): """moves a monkey critter across the screen. it can spin the @@ -259,43 +260,43 @@ is colliding with the given target sprite. :: self.dizzy = 1 self.original = self.image -The chimp class is doing a little more work than the fist, but nothing -more complex. This class will move the chimp back and forth across the -screen. When the monkey is punched, he will spin around to exciting effect. -This class is also derived from the base Sprite class, and is initialized -the same as the fist. While initializing, the class also sets the attribute -"area" to be the size of the display screen. - -The update function for the chimp simply looks at the current "dizzy" -state, which is true when the monkey is spinning from a punch. It calls either -the _spin or _walk method. These functions are prefixed with an underscore. -This is just a standard python idiom which suggests these methods should -only be used by the Chimp class. We could go so far as to give them a double -underscore, which would tell python to really try to make them private -methods, but we don't need such protection. :) - -The walk method creates a new position for the monkey by moving the current +The `Chimp` class is doing a little more work than the fist, but nothing +more complex. This class will move the chimp back and forth across the +screen. When the monkey is punched, he will spin around to exciting effect. +This class is also derived from the base :class:`Sprite ` +class, and is initialized the same as the fist. While initializing, the class +also sets the attribute "area" to be the size of the display screen. + +The `update` function for the chimp simply looks at the current "dizzy" +state, which is true when the monkey is spinning from a punch. It calls either +the `_spin` or `_walk` method. These functions are prefixed with an underscore. +This is just a standard python idiom which suggests these methods should +only be used by the `Chimp` class. We could go so far as to give them a double +underscore, which would tell python to really try to make them private +methods, but we don't need such protection. :) + +The `_walk` method creates a new position for the monkey by moving the current rect by a given offset. If this new position crosses outside the display area of the screen, it reverses the movement offset. It also mirrors the -image using the pygame.transform.flip function. This is a crude effect that -makes the monkey look like he's turning the direction he is moving. +image using the :func:`pygame.transform.flip` function. This is a crude effect +that makes the monkey look like he's turning the direction he is moving. -The spin method is called when the monkey is currently "dizzy". The dizzy +The `_spin` method is called when the monkey is currently "dizzy". The dizzy attribute is used to store the current amount of rotation. When the monkey has rotated all the way around (360 degrees) it resets the monkey image -back to the original, non-rotated version. Before calling the transform.rotate -function, you'll see the code makes a local reference to the function simply -named "rotate". There is no need to do that for this example, it is just -done here to keep the following line's length a little shorter. Note that -when calling the rotate function, we are always rotating from the original -monkey image. When rotating, there is a slight loss of quality. Repeatedly -rotating the same image and the quality would get worse each time. Also, -when rotating an image, the size of the image will actually change. This -is because the corners of the image will be rotated out, making the image -bigger. We make sure the center of the new image matches the center of the -old image, so it rotates without moving. - -The last method is punched() which tells the sprite to enter its dizzy +back to the original, non-rotated version. Before calling the +:func:`pygame.transform.rotate` function, you'll see the code makes a local +reference to the function simply named "rotate". There is no need to do that +for this example, it is just done here to keep the following line's length a +little shorter. Note that when calling the `rotate` function, we are always +rotating from the original monkey image. When rotating, there is a slight loss +of quality. Repeatedly rotating the same image and the quality would get worse +each time. Also, when rotating an image, the size of the image will actually +change. This is because the corners of the image will be rotated out, making +the image bigger. We make sure the center of the new image matches the center +of the old image, so it rotates without moving. + +The last method is `punched()` which tells the sprite to enter its dizzy state. This will cause the image to start spinning. It also makes a copy of the current image named "original". @@ -304,32 +305,32 @@ Initialize Everything --------------------- Before we can do much with pygame, we need to make sure its modules -are initialized. In this case we will also open a simple graphics window. -Now we are in the main() function of the program, which actually runs everything. :: +are initialized. In this case we will also open a simple graphics window. +Now we are in the `main()` function of the program, which actually runs everything. :: pygame.init() screen = pygame.display.set_mode((468, 60)) pygame.display.set_caption('Monkey Fever') pygame.mouse.set_visible(0) -The first line to initialize pygame takes care of a bit of -work for us. It checks through the imported pygame modules and attempts +The first line to initialize *pygame* takes care of a bit of +work for us. It checks through the imported *pygame* modules and attempts to initialize each one of them. It is possible to go back and check if modules failed to initialize, but we won't bother here. It is also possible to -take a lot more control and initialize each specific module by hand. That -type of control is generally not needed, but is available if you desire. +take a lot more control and initialize each specific module by hand. That +type of control is generally not needed, but is available if you desire. Next we set up the display graphics mode. Note that the pygame.display module is used to control all the display settings. In this case we are -asking for a simple skinny window. There is an entire separate tutorial -on setting up the graphics mode, but if we really don't care, pygame +asking for a simple skinny window. There is an entire separate tutorial +on setting up the graphics mode, but if we really don't care, *pygame* will do a good job of getting us something that works. Pygame will pick the best color depth, since we haven't provided one. Last we set the window title and turn off the mouse cursor for our -window. Very basic to do, and now we have a small black window ready to +window. Very basic to do, and now we have a small black window ready to do our bidding. Usually the cursor defaults to visible, so there is no need -to really set the state unless we want to hide it. +to really set the state unless we want to hide it. Create The Background @@ -344,7 +345,7 @@ repeatedly use that. The first step is to create the surface. :: background.fill((250, 250, 250)) This creates a new surface for us that is the same size as the display -window. Note the extra call to convert() after creating the Surface. The +window. Note the extra call to `convert()` after creating the Surface. The convert with no arguments will make sure our background is the same format as the display window, which will give us the fastest results. @@ -355,8 +356,8 @@ takes an RGB triplet as the color argument. Put Text On The Background, Centered ------------------------------------ -Now that we have a background surface, lets get the text rendered -to it. We only do this if we see the pygame.font module has imported properly. +Now that we have a background surface, lets get the text rendered to it. We +only do this if we see the :mod:`pygame.font` module has imported properly. If not, we just skip this section. :: if pygame.font: @@ -366,22 +367,22 @@ If not, we just skip this section. :: background.blit(text, textpos) As you see, there are a couple steps to getting this done. First we -must create the font object and render it into a new surface. We then find -the center of that new surface and blit (paste) it onto the background. +must create the font object and render it into a new surface. We then find +the center of that new surface and blit (paste) it onto the background. -The font is created with the font module's Font() constructor. Usually +The font is created with the `font` module's `Font()` constructor. Usually you will pass the name of a TrueType font file to this function, but we -can also pass None, which will use a default font. The Font constructor +can also pass `None`, which will use a default font. The `Font` constructor also needs to know the size of font we want to create. -We then render that font into a new surface. The render function creates +We then render that font into a new surface. The `render` function creates a new surface that is the appropriate size for our text. In this case -we are also telling render to create antialiased text (for a nice smooth -look) and to use a dark grey color. +we are also telling render to create antialiased text (for a nice smooth +look) and to use a dark grey color. Next we need to find the centered position of the text on our display. We create a "Rect" object from the text dimensions, which allows us to -easily assign it to the screen center. +easily assign it to the screen center. Finally we blit (blit is like a copy or paste) the text onto the background image. @@ -391,19 +392,19 @@ Display The Background While Setup Finishes ------------------------------------------- We still have a black window on the screen. Lets show our background -while we wait for the other resources to load. :: +while we wait for the other resources to load. :: screen.blit(background, (0, 0)) pygame.display.flip() This will blit our entire background onto the display window. The -blit is self explanatory, but what about this flip routine? +blit is self explanatory, but what about this flip routine? In pygame, changes to the display surface are not immediately visible. Normally, a display must be updated in areas that have changed for them -to be visible to the user. With double buffered displays the display must -be swapped (or flipped) for the changes to become visible. In this case -the flip() function works nicely because it simply handles the entire window +to be visible to the user. With double buffered displays the display must +be swapped (or flipped) for the changes to become visible. In this case +the `flip()` function works nicely because it simply handles the entire window area and handles both single- and double-buffered surfaces. @@ -421,19 +422,20 @@ Here we create all the objects that the game is going to need. allsprites = pygame.sprite.RenderPlain((fist, chimp)) clock = pygame.time.Clock() -First we load two sound effects using the load_sound function we defined +First we load two sound effects using the `load_sound` function we defined above. Then we create an instance of each of our sprite classes. And lastly -we create a sprite Group which will contain all our sprites. - -We actually use a special sprite group named RenderPlain. This sprite -group can draw all the sprites it contains to the screen. It is called RenderPlain -because there are actually more advanced Render groups. But for our game, -we just need simple drawing. We create the group named "allsprites" by -passing a list with all the sprites that should belong in the group. We -could later on add or remove sprites from this group, but in this game -we won't need to. - -The clock object we create will be used to help control our game's framerate. +we create a sprite :class:`Group ` which will contain all +our sprites. + +We actually use a special sprite group named :class:`RenderPlain +`. This sprite group can draw all the sprites it +contains to the screen. It is called `RenderPlain` because there are actually +more advanced Render groups. But for our game, we just need simple drawing. We +create the group named "allsprites" by passing a list with all the sprites that +should belong in the group. We could later on add or remove sprites from this +group, but in this game we won't need to. + +The `clock` object we create will be used to help control our game's framerate. we will use it in the main loop of our game to make sure it doesn't run too fast. @@ -446,11 +448,11 @@ Nothing much here, just an infinite loop. :: clock.tick(60) All games run in some sort of loop. The usual order of things is to -check on the state of the computer and user input, move and update the -state of all the objects, and then draw them to the screen. You'll see -that this example is no different. +check on the state of the computer and user input, move and update the +state of all the objects, and then draw them to the screen. You'll see +that this example is no different. -We also make a call to our clock object, which will make sure our game +We also make a call to our `clock` object, which will make sure our game doesn't run faster than 60 frames per second. @@ -475,27 +477,27 @@ This is an extremely simple case of working the event queue. :: First we get all the available Events from pygame and loop through each of them. The first two tests see if the user has quit our game, or pressed -the escape key. In these cases we just return from the main() function and +the escape key. In these cases we just return from the `main()` function and the program cleanly ends. Next we just check to see if the mouse button was pressed or released. -If the button was pressed, we ask the fist object if it has collided with -the chimp. We play the appropriate sound effect, and if the monkey was hit, -we tell him to start spinning (by calling his punched() method). +If the button was pressed, we ask the fist object if it has collided with +the chimp. We play the appropriate sound effect, and if the monkey was hit, +we tell him to start spinning (by calling his `punched()` method). Update the Sprites ------------------ :: + allsprites.update() -Sprite groups have an update() method, which simply calls the update method +Sprite groups have an `update()` method, which simply calls the update method for all the sprites it contains. Each of the objects will move around, depending on which state they are in. This is where the chimp will move one step side to side, or spin a little farther if he was recently punched. - - + Draw The Entire Scene --------------------- @@ -508,9 +510,9 @@ Now that all the objects are in the right place, time to draw them. :: The first blit call will draw the background onto the entire screen. This erases everything we saw from the previous frame (slightly inefficient, but -good enough for this game). Next we call the draw() method of the sprite +good enough for this game). Next we call the `draw()` method of the sprite container. Since this sprite container is really an instance of the "DrawPlain" -sprite group, it knows how to draw our sprites. Lastly, we flip() the contents +sprite group, it knows how to draw our sprites. Lastly, we `flip()` the contents of pygame's software double buffer to the screen. This makes everything we've drawn visible all at once. @@ -518,8 +520,8 @@ drawn visible all at once. Game Over --------- -User has quit, time to clean up +User has quit, time to clean up. Cleaning up the running game in *pygame* is extremely simple. -In fact since all variables are automatically destructed, we really don't -have to do anything. +In fact since all variables are automatically destructed, we really don't +have to do anything.