<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Eli Bendersky's website - Pygame tutorial</title><link href="https://eli.thegreenplace.net/" rel="alternate"></link><link href="https://eli.thegreenplace.net/feeds/pygame-tutorial.atom.xml" rel="self"></link><id>https://eli.thegreenplace.net/</id><updated>2024-05-04T19:46:23-07:00</updated><entry><title>Writing a game in Python with Pygame. Part IV</title><link href="https://eli.thegreenplace.net/2009/02/13/writing-a-game-in-python-with-pygame-part-iv" rel="alternate"></link><published>2009-02-13T17:18:13-08:00</published><updated>2024-05-04T19:46:23-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2009-02-13:/2009/02/13/writing-a-game-in-python-with-pygame-part-iv</id><summary type="html">
        &lt;p&gt;This is part IV of the &lt;a class="reference external" href="https://eli.thegreenplace.net/tag/pygame-tutorial"&gt;&amp;quot;Writing a game in Python with Pygame&amp;quot; tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="back-to-the-creeps"&gt;
&lt;h3&gt;Back to the Creeps&lt;/h3&gt;
&lt;p&gt;After a digression into the exciting world of path-finding in the previous part, we're now back to our &amp;quot;Creeps&amp;quot; game. Here's a screenshot of our final product for this part:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/02/creeps_screenshot_4.png" /&gt;
&lt;p&gt;As you …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">
        &lt;p&gt;This is part IV of the &lt;a class="reference external" href="https://eli.thegreenplace.net/tag/pygame-tutorial"&gt;&amp;quot;Writing a game in Python with Pygame&amp;quot; tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="back-to-the-creeps"&gt;
&lt;h3&gt;Back to the Creeps&lt;/h3&gt;
&lt;p&gt;After a digression into the exciting world of path-finding in the previous part, we're now back to our &amp;quot;Creeps&amp;quot; game. Here's a screenshot of our final product for this part:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/02/creeps_screenshot_4.png" /&gt;
&lt;p&gt;As you can see, things look quite different now. Indeed, there's a lot of changes in the code, and a lot of new features were added for this part &lt;a class="footnote-reference" href="#id5" id="id1"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here's a brief summary of what we'll go over today:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Making creeps look prettier, especially when rotated&lt;/li&gt;
&lt;li&gt;Major code refactoring into classes with well-defined responsibilities&lt;/li&gt;
&lt;li&gt;Separation of &amp;quot;GUI elements&amp;quot; from the game logic&lt;/li&gt;
&lt;li&gt;Handling transparency&lt;/li&gt;
&lt;li&gt;Drawing walls&lt;/li&gt;
&lt;li&gt;Incorporating the path-finding code to create directed movement for the creeps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you see, this is a lot of material, and indeed I feel very content with the amount of code written for this section. The final product is a very complete simulation having all the elements to turn into many kinds of games.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-code"&gt;
&lt;h3&gt;The code&lt;/h3&gt;
&lt;p&gt;The full code for this section can be taken &lt;a href="https://github.com/eliben/code-for-blog/tree/main/2009/pygame_creeps_game"&gt;from here&lt;/a&gt;. Make sure you download and run it (execute &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;creeps.py&lt;/span&gt;&lt;/tt&gt;) before reading the rest of this tutorial.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="prettier-creeps"&gt;
&lt;h3&gt;Prettier creeps&lt;/h3&gt;
&lt;p&gt;I've re-created the creep images using the amazing &lt;a class="reference external" href="http://www.inkscape.org/"&gt;Inkscape&lt;/a&gt; tool. Inkscape allows to draw vector-graphics (SVG), so it's much better suited than plain pixel-banging .png for drawing figures for games. I've included the source .svg files for the creep images in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;images/&lt;/span&gt;&lt;/tt&gt; directory of the code package.&lt;/p&gt;
&lt;p&gt;But my biggest problem with the creeps of the previous parts was how creeps rotated by 45 degrees look. While rotating a square image perfectly in multiples of 90 degrees is simple, multiples of 45 are much tougher. When the image is small, there's a big change it will come up ugly, because the rotation can't perfectly convey all the information stored in it. And indeed, when I just let Pygame to rotate the images 45 degrees for me, it didn't look very pretty.&lt;/p&gt;
&lt;p&gt;So I've taken a different path this time. I rotated the images to 45 degrees in Inkscape (which does it perfectly because it stores them as vector graphics), and now there are two images for each creep: one pointing &amp;quot;east&amp;quot; and one pointing &amp;quot;north-east&amp;quot;. Given these two, with rotations by 90 degrees I can achieve all 8 possible multiples of 45 degrees. You will notice in the code that &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; now accepts a pair of images as an argument, and unpacks them:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #007f00"&gt;# base_image_0/45 hold the original images, un-rotated&lt;/span&gt;
&lt;span style="color: #007f00"&gt;#&lt;/span&gt;
&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.base_image_0 = creep_images[&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;]
&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.base_image_45 = creep_images[&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;]
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now the image rotation is done as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #007f00"&gt;# Make the creep image point in the correct direction.&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# Note that two images are used, one for diagonals&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# and one for horizontals/verticals.&lt;/span&gt;
&lt;span style="color: #007f00"&gt;#&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# round() on the angle is necessary, to make it&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# exact, despite small deviations that may result from&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# floating-point calculations&lt;/span&gt;
&lt;span style="color: #007f00"&gt;#&lt;/span&gt;
&lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; &lt;span style="color: #00007f"&gt;int&lt;/span&gt;(&lt;span style="color: #00007f"&gt;round&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.angle)) % &lt;span style="color: #007f7f"&gt;90&lt;/span&gt; == &lt;span style="color: #007f7f"&gt;45&lt;/span&gt;:
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image = pygame.transform.rotate(
        &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.base_image_45, -(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.angle + &lt;span style="color: #007f7f"&gt;45&lt;/span&gt;))
&lt;span style="color: #00007f; font-weight: bold"&gt;elif&lt;/span&gt; &lt;span style="color: #00007f"&gt;int&lt;/span&gt;(&lt;span style="color: #00007f"&gt;round&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.angle)) % &lt;span style="color: #007f7f"&gt;90&lt;/span&gt; == &lt;span style="color: #007f7f"&gt;0&lt;/span&gt;:
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image = pygame.transform.rotate(
        &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.base_image_0, -&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.angle)
&lt;span style="color: #00007f; font-weight: bold"&gt;else&lt;/span&gt;:
    &lt;span style="color: #00007f; font-weight: bold"&gt;assert&lt;/span&gt; &lt;span style="color: #00007f"&gt;False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the creep's current direction is an odd multiple of 45 degrees, the 45-degree image is used for rotations. Otherwise the 0-degree image is used.&lt;/p&gt;
&lt;p&gt;This way all creeps look pretty now rotated in whichever direction.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="code-refactoring"&gt;
&lt;h3&gt;Code refactoring&lt;/h3&gt;
&lt;p&gt;The creeps code after part II wasn't exactly production quality. It was what experimentation-code usually looks like, and except the Creep class, it wasn't very well organized.&lt;/p&gt;
&lt;p&gt;If you look at the code now, the situation is different. I've separated it to several classes, and moved out related functionality into separate files. A lot of the code that was just dispersed in the main file was collected into the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Game&lt;/span&gt;&lt;/tt&gt; class, which is responsible for creating and running the game.&lt;/p&gt;
&lt;p&gt;Another interesting change was the addition of the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Timer&lt;/span&gt;&lt;/tt&gt; class (in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;utils.py&lt;/span&gt;&lt;/tt&gt;). &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Timer&lt;/span&gt;&lt;/tt&gt; mimics the behavior or timers in event-driven systems like GUI toolkits. You create it with an interval and a callback function. Then, as time passes you should &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt; it with the amount of time passed (just like calling the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt; of creeps to let them compute their position), and the timer will call the callback periodically (with the supplied period).&lt;/p&gt;
&lt;p&gt;A good example of the use of the timer is in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;SimpleAnimation&lt;/span&gt;&lt;/tt&gt; class (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;simpleanimation.py&lt;/span&gt;&lt;/tt&gt;) which we use to show how creeps &amp;quot;explode&amp;quot; when their life bar reaches 0. The constructor of the animation creates two timers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.scroll_timer = Timer(scroll_period, &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._advance_img)
&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.active_timer = Timer(duration, &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._inactivate, &lt;span style="color: #00007f"&gt;True&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The scroll timer is responsible for scrolling through the animation's images periodically, while the active timer is responsible for inactivating the animation after its duration has passed (it's also a one-shot timer, which means it only acts once).&lt;/p&gt;
&lt;p&gt;This is a good example of decoupling. &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Timer&lt;/span&gt;&lt;/tt&gt; takes care of the common task of keeping time and doing events periodically, so now &amp;quot;user&amp;quot; code like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;SimpleAnimation&lt;/span&gt;&lt;/tt&gt; doesn't have to implement time keeping explicitly itself.&lt;/p&gt;
&lt;p&gt;Another example of the usage of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Timer&lt;/span&gt;&lt;/tt&gt; is in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Game&lt;/span&gt;&lt;/tt&gt; class. Feel free to explore how &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;creep_spawn_timer&lt;/span&gt;&lt;/tt&gt; is used to periodically &amp;quot;spawn&amp;quot; new creeps into the game.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="gui-widgets"&gt;
&lt;h3&gt;GUI &amp;quot;widgets&amp;quot;&lt;/h3&gt;
&lt;p&gt;If you've ever programmed GUIs, you've undoubtedly run into the term &amp;quot;&lt;a class="reference external" href="http://en.wikipedia.org/wiki/GUI_widget"&gt;widget&lt;/a&gt;&amp;quot;. A widget is a generic graphical GUI element that you see on the screen and can sometimes interact with. Text boxes are widgets, buttons are widgets, scroll boxes, tables, labels are widgets, etc.&lt;/p&gt;
&lt;p&gt;Pygame is not a GUI toolkit. It's a more low-level tool that specializes in graphics - efficient drawing on the screen. This, together with the concept of time, is all one really needs to create widgets, though, and indeed several &lt;a class="reference external" href="http://www.pygame.org/tags/gui"&gt;GUI libraries for Pygame&lt;/a&gt; sprang up.&lt;/p&gt;
&lt;p&gt;Rather than using a ready-made library, I've decided to create just the primitives I need for the creeps game. See &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;widgets.py&lt;/span&gt;&lt;/tt&gt; for two useful widget classes that I use for drawing framed boxes and message boards.&lt;/p&gt;
&lt;p&gt;The classes are very simple - each has a constructor and a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;draw&lt;/span&gt;&lt;/tt&gt; method, along with other utility methods &lt;a class="footnote-reference" href="#id6" id="id2"&gt;[2]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By taking out these utilities into a separate file as widget classes, I've achieved another goal of refactoring - keeping logically separate code in different files. Now the main code can create boxes and message boards at its will, without worrying too much about how they're implemented.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="handling-transparency"&gt;
&lt;h3&gt;Handling transparency&lt;/h3&gt;
&lt;p&gt;You've surely noticed by now that creeps come out from a semi-transparent square in the upper-left corner of the screen and disappear into a similar square in the bottom-right corner.&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/02/transparency_1.png" /&gt;
&lt;p&gt;These squares are drawn transparently as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;draw_portals&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;):
    entrance_sf = pygame.Surface((&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.entrance_rect.w, &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.entrance_rect.h))
    entrance_sf.fill(Color(&lt;span style="color: #007f7f"&gt;80&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;200&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;80&lt;/span&gt;))
    entrance_sf.set_alpha(&lt;span style="color: #007f7f"&gt;150&lt;/span&gt;)
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.screen.blit(entrance_sf, &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.entrance_rect)

    exit_sf = pygame.Surface((&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.exit_rect.w, &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.exit_rect.h))
    exit_sf.fill(Color(&lt;span style="color: #007f7f"&gt;200&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;80&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;80&lt;/span&gt;))
    exit_sf.set_alpha(&lt;span style="color: #007f7f"&gt;150&lt;/span&gt;)
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.screen.blit(exit_sf, &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.exit_rect)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &amp;quot;magic&amp;quot; here is done with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;set_alpha&lt;/span&gt;&lt;/tt&gt; method of a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Surface&lt;/span&gt;&lt;/tt&gt;. &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Alpha_channel"&gt;Alpha&lt;/a&gt; in graphics nomenclature means the measure of transparency of a color - how much it will be blended into its background when drawn.&lt;/p&gt;
&lt;p&gt;Note that these &amp;quot;portals&amp;quot; are drawn after the creeps are drawn. Can you figure out why? (see exercise 1).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="drawing-walls"&gt;
&lt;h3&gt;Drawing walls&lt;/h3&gt;
&lt;p&gt;Since we're making our creeps avoid obstacles using path-finding, we should have some obstacles, right? Obstacles in our game are &amp;quot;walls&amp;quot;, and are kept in the dictionary &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;self.walls&lt;/span&gt;&lt;/tt&gt; inside the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Game&lt;/span&gt;&lt;/tt&gt; object. The walls are drawn onto the screen as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;draw_walls&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;):
    wallcolor = Color(&lt;span style="color: #007f7f"&gt;140&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;140&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;140&lt;/span&gt;)

    &lt;span style="color: #00007f; font-weight: bold"&gt;for&lt;/span&gt; wall &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.walls:
        nrow, ncol = wall

        pos_x = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.field_rect.left + ncol * &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.GRID_SIZE + &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.GRID_SIZE / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;
        pos_y = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.field_rect.top + nrow * &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.GRID_SIZE + &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.GRID_SIZE / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;
        radius = &lt;span style="color: #007f7f"&gt;3&lt;/span&gt;

        pygame.draw.polygon(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.screen, wallcolor,
            [   (pos_x - radius, pos_y), (pos_x, pos_y + radius),
                (pos_x + radius, pos_y), (pos_x, pos_y - radius)])

        &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; (nrow + &lt;span style="color: #007f7f"&gt;1&lt;/span&gt;, ncol) &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.walls:
            pygame.draw.line(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.screen, wallcolor,
                (pos_x, pos_y), (pos_x, pos_y + &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.GRID_SIZE), &lt;span style="color: #007f7f"&gt;3&lt;/span&gt;)
        &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; (nrow, ncol + &lt;span style="color: #007f7f"&gt;1&lt;/span&gt;) &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.walls:
            pygame.draw.line(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.screen, wallcolor,
                (pos_x, pos_y), (pos_x + &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.GRID_SIZE, pos_y), &lt;span style="color: #007f7f"&gt;3&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First, a polygonal &amp;quot;blob&amp;quot; is drawn in the center of the grid square &lt;a class="footnote-reference" href="#id7" id="id3"&gt;[3]&lt;/a&gt; where the wall is located. Then, the neighbor squares are examined (see exercise 2). If a neighbor has a wall in it too, the two are connected by a thick line, making an appearance of a real wall.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="creep-find-thy-way"&gt;
&lt;h3&gt;Creep, find thy way!&lt;/h3&gt;
&lt;p&gt;It's a good time to review &lt;a class="reference external" href="https://eli.thegreenplace.net/2009/01/09/writing-a-game-in-python-with-pygame-part-iii/"&gt;part III of the tutorial&lt;/a&gt; now, because I assume you already know what's explained there (namely, what path-finding is, and how I've implemented it).&lt;/p&gt;
&lt;div class="section" id="implementing-path-finding-for-the-game"&gt;
&lt;h4&gt;Implementing path-finding for the game&lt;/h4&gt;
&lt;p&gt;Two classes were important in my implementation of path-finding on a rectangular grid:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;GridMap&lt;/span&gt;&lt;/tt&gt;, which represents a rectangular grid, providing methods to set which squares are blocked and cost functions for the path-finding code.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt;, a generic, efficient A* path-finder that receives an abstract representation of the game graph (via &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;successors&lt;/span&gt;&lt;/tt&gt; and cost functions) and computes optimal paths from point to point on that graph.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For creeps, I've created a proxy class named &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;GridPath&lt;/span&gt;&lt;/tt&gt; that encapsulates the interaction with the path-finding code completely, providing a convenient interface for the creeps. It's only 50 lines of code or so, most of it comments and doc-strings, so you can easily understand it.&lt;/p&gt;
&lt;p&gt;Here's the constructor:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;__init__&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;, nrows, ncols, goal):
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.map = GridMap(nrows, ncols)
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.goal = goal

    &lt;span style="color: #007f00"&gt;# Path cache. For a coord, keeps the next coord to move&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# to in order to reach the goal. Invalidated when the&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# grid changes (with set_blocked)&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;#&lt;/span&gt;
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._path_cache = {}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can see that it uses &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;GridMap&lt;/span&gt;&lt;/tt&gt; under the hood to implement the rectangular map with its costs and successor function.&lt;/p&gt;
&lt;p&gt;The main trick that makes &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;GridPath&lt;/span&gt;&lt;/tt&gt; cool is caching. I wouldn't want to re-compute the path for each creep to the goal 30 times a second, why should I, if the game field rarely if ever changes?&lt;/p&gt;
&lt;p&gt;Instead, path results are cached, and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;GridPath&lt;/span&gt;&lt;/tt&gt; answers one simple question - &amp;quot;where to next from here?&amp;quot;. When one creep asks it, in all likeness another creep will ask it at one time or another, so it makes sense to cache the results.&lt;/p&gt;
&lt;p&gt;Here it is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;get_next&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;, coord):
    &lt;span style="color: #7f007f"&gt;&amp;quot;&amp;quot;&amp;quot; Get the next coordinate to move to from &amp;#39;coord&amp;#39;&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;        towards the goal.&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# If the next path for this coord is not cached, compute&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# it&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;#&lt;/span&gt;
    &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; &lt;span style="color: #0000aa"&gt;not&lt;/span&gt; (coord &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._path_cache):
        &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._compute_path(coord)

    &lt;span style="color: #007f00"&gt;# _compute_path adds the path for the coord to the cache.&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# If it&amp;#39;s still not cached after the computation, it means&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# that no path exists to the goal from this coord.&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;#&lt;/span&gt;
    &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; coord &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._path_cache:
        &lt;span style="color: #00007f; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._path_cache[coord]
    &lt;span style="color: #00007f; font-weight: bold"&gt;else&lt;/span&gt;:
        &lt;span style="color: #00007f; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #00007f"&gt;None&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When asked the question, it first checks the cache. If the cache already contains the answer, it is returned. Otherwise the path is recomputed and added to the cache (see method &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_compute_path&lt;/span&gt;&lt;/tt&gt; for that). At this point, if the path is again not in the cache it means there isn't any valid path from this point.&lt;/p&gt;
&lt;p&gt;But what if the game field changes? - you might (rightly) ask. No problems, in this case the cache is just invalidated (cleared) and new questions will cause it to be filled again (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;set_blocked&lt;/span&gt;&lt;/tt&gt; clears the cache).&lt;/p&gt;
&lt;p&gt;The actual result of this is that path computations hardly take any time. Only when the map is changed, the path is recomputed (which takes several milliseconds). In all other cases, the result is returned instantly from the cache.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="smarter-movement-for-creeps"&gt;
&lt;h4&gt;Smarter movement for creeps&lt;/h4&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; class needed to undergo some minor changes to incorporate path-finding. The main change is in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_compute_direction&lt;/span&gt;&lt;/tt&gt; method, that replaces the method that just randomly changed the direction of the creep once in a while.&lt;/p&gt;
&lt;p&gt;Here is its:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;_compute_direction&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;, time_passed):
    &lt;span style="color: #7f007f"&gt;&amp;quot;&amp;quot;&amp;quot; Finds out where to go&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    coord = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.game.xy2coord(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos)

    &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.game.is_goal_coord(coord):
        &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._die()
    &lt;span style="color: #00007f; font-weight: bold"&gt;else&lt;/span&gt;:
        x_mid, y_mid = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.game.coord2xy_mid(coord)

        &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; (    (x_mid - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x) * (x_mid - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.prev_pos.x) &amp;lt; &lt;span style="color: #007f7f"&gt;0&lt;/span&gt; &lt;span style="color: #0000aa"&gt;or&lt;/span&gt;
                (y_mid - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.y) * (y_mid - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.prev_pos.y) &amp;lt; &lt;span style="color: #007f7f"&gt;0&lt;/span&gt;):
            next_coord = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.game.next_on_path(coord)

            &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction = vec2d(
                next_coord[&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;] - coord[&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;],
                next_coord[&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;] - coord[&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;]).normalized()
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Most of the code is straightforward. The creep first finds out where it is (by asking the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Game&lt;/span&gt;&lt;/tt&gt; object to translate its position into a coordinate on the game map). Then, it checks whether it has reached its goal. If it did, the creep dies. Otherwise, it computes where to turn, if a turn is required.&lt;/p&gt;
&lt;p&gt;This is one of the trickiest parts of the code, so it warrants special attention.&lt;/p&gt;
&lt;p&gt;Recall &lt;a class="footnote-reference" href="#id8" id="id4"&gt;[4]&lt;/a&gt; that the creep keeps its position on the screen in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;self.pos&lt;/span&gt;&lt;/tt&gt;. It's done in a &amp;quot;centered way&amp;quot;, meaning that the center of the creep's image is located at &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;self.pos&lt;/span&gt;&lt;/tt&gt;, and its actual body is around it. To simulate realistic movement through the grid, I want the creeps to move through the grid's centers (i.e. the whole body of the creep to fit into a grid square before a turn is made).&lt;/p&gt;
&lt;p&gt;Here's a diagram for clarification:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/02/dot_cross.png" /&gt;
&lt;p&gt;Imagine that the red dot represents the center of the creep which has just entered a new grid square. Suppose that it has entered from the upper-left neighbor of this square. Also, suppose that the path-finding code tells the creep to continue to the neighbor below this square. How will the creep move?&lt;/p&gt;
&lt;p&gt;Well, if it continuously checks for a change of direction, the creep will start moving down right away, so it will move on the edges of the squares, and not inside them (see exercise 3). This results in unrealistic movement and interference with walls. How can this be fixed?&lt;/p&gt;
&lt;p&gt;I've had several ideas while developing the code, but most of them didn't work out. One that does work, can be described with this diagram:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/02/dot_cross_2.png" /&gt;
&lt;p&gt;Assume an imaginary cross through the middle of the square. We can detect when the creep passes from one quadrant of the cross to another quite simply, so we have a way of knowing when it's about in the center of the square. This is the idea actually implemented in the second part of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_compute_direction&lt;/span&gt;&lt;/tt&gt;, and as you can see in the game itself, it works nicely. You can turn the grid on (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Ctrl-g&lt;/span&gt;&lt;/tt&gt;) and see how nicely the creeps move through the centers of the squares.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;As always, please check the exercises in the bottom of the tutorial. Even if you don't actually implement the solutions, at least read the questions and try to understand what is being asked.&lt;/p&gt;
&lt;p&gt;Our creeps code is now quite a complete simulation, incorporating many of the elements of game programming:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Graphics&lt;/li&gt;
&lt;li&gt;Keeping and updating game state&lt;/li&gt;
&lt;li&gt;Movement&lt;/li&gt;
&lt;li&gt;Path-finding&lt;/li&gt;
&lt;li&gt;User interaction&lt;/li&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I personally feel that I've learned a lot about Pygame by writing it, and hope that you have too. At this point, I'm not sure whether I'll continue this tutorial, because I don't know if I want to pursue the topic further. Perhaps if someone suggests an interesting enough future direction for it, I'll be motivated enough to continue.&lt;/p&gt;
&lt;p&gt;For now, thanks for reading!&lt;/p&gt;
&lt;div align="center" class="align-center"&gt;&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="exercises"&gt;
&lt;h3&gt;Exercises&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Try to change the relative drawing order of creeps and portals. What do you see? Can you explain why this happens?&lt;/li&gt;
&lt;li&gt;In &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;draw_walls&lt;/span&gt;&lt;/tt&gt; only the neighbors to the east and to the south are examined. Is this always enough to connect all walls? Why?&lt;/li&gt;
&lt;li&gt;Simplify the code of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_compute_direction&lt;/span&gt;&lt;/tt&gt; so that the creeps won't wait for getting to the middle of a square for turning. How does it look now on the screen? Which is better?&lt;/li&gt;
&lt;li&gt;Note that the wall-collision code has been removed from the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; class. Can you figure out why it's no longer required?&lt;/li&gt;
&lt;li&gt;Note that no new creeps spawn as old ones disappear. Can you modify the code so that disappearing creeps will be replaced by new ones?&lt;/li&gt;
&lt;li&gt;Change the message board to announce how many creeps have safely reached the exit portal.&lt;/li&gt;
&lt;li&gt;Think up some game ideas that could be implemented relatively easily based on the creeps code base. Let me know if you come up with something interesting.&lt;/li&gt;
&lt;/ol&gt;
&lt;div align="center" class="align-center"&gt;&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;&lt;/div&gt;
&lt;table class="docutils footnote" frame="void" id="id5" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Which is why it took so long to publish it!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id6" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;For more dynamic widgets, an &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt; method can be added that will be called by the event loop (just like the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt; of timers and creeps is called), and on the basis of the information sent to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt; the widget can update its internal state and draw something different the next time &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;draw&lt;/span&gt;&lt;/tt&gt; is called.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id7" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Note that we've divided the &amp;quot;playing field&amp;quot; into a rectangular grid for drawing walls and assisting pathfinding. &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;GRID_SIZE&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;20&lt;/span&gt;&lt;/tt&gt; is a constant in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Game&lt;/span&gt;&lt;/tt&gt; that specifies that each grid square is 20 x 20 pixels in size. The methods &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;xy2coord&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;coord2xy_mid&lt;/span&gt;&lt;/tt&gt; convert to and from the grid coordinates to actual pixel coordinates on the screen. You can see this grid by clicking &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Ctrl+g&lt;/span&gt;&lt;/tt&gt; while the game is running.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id8" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id4"&gt;[4]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Look at the code now. Do a search of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;self.pos&lt;/span&gt;&lt;/tt&gt; in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; code to see how the position is computed and used.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

    </content><category term="misc"></category><category term="Pygame tutorial"></category></entry><entry><title>Writing a game in Python with Pygame. Part III</title><link href="https://eli.thegreenplace.net/2009/01/09/writing-a-game-in-python-with-pygame-part-iii" rel="alternate"></link><published>2009-01-09T15:45:43-08:00</published><updated>2024-05-04T19:46:23-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2009-01-09:/2009/01/09/writing-a-game-in-python-with-pygame-part-iii</id><summary type="html">
        &lt;p&gt;This is part III of the &lt;a class="reference external" href="https://eli.thegreenplace.net/tag/pygame-tutorial"&gt;&amp;quot;Writing a game in Python with Pygame&amp;quot; tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="a-digression"&gt;
&lt;h3&gt;A digression&lt;/h3&gt;
&lt;p&gt;This part will be a digression from the first two, in the sense that it won't deal with the &amp;quot;Creeps&amp;quot; simulation we've been developing so far. Rather, we'll explore &lt;em&gt;pathfinding&lt;/em&gt; - an important &amp;quot;artificial intelligence …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">
        &lt;p&gt;This is part III of the &lt;a class="reference external" href="https://eli.thegreenplace.net/tag/pygame-tutorial"&gt;&amp;quot;Writing a game in Python with Pygame&amp;quot; tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="a-digression"&gt;
&lt;h3&gt;A digression&lt;/h3&gt;
&lt;p&gt;This part will be a digression from the first two, in the sense that it won't deal with the &amp;quot;Creeps&amp;quot; simulation we've been developing so far. Rather, we'll explore &lt;em&gt;pathfinding&lt;/em&gt; - an important &amp;quot;artificial intelligence&amp;quot; technique for games. Pathfinding will be crucial for the future development of our game, so I'm spending a whole part on it.&lt;/p&gt;
&lt;p&gt;I'll start by presenting my implementation of the A* pathfinding algoritm. The implementation is generic, and has nothing to do with our game. I assume a basic acquaintance with computer-science algorithms and data structures here, so depending on your background you may find it a bit dense. Don't worry, you can skip it entirely without any real loss - you'll be able to understand the rest of the tutorial.&lt;/p&gt;
&lt;p&gt;Next, I'll show a useful Pygame-based demo of the algorithm at work - this is recommended even if you don't want to dive into the implementation of the algorithm, as it ties the algorithm with our game.&lt;/p&gt;
&lt;p&gt;Here's a teaser screenshot:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/01/path_1.png" /&gt;
&lt;/div&gt;
&lt;!--more--&gt;
&lt;div class="section" id="the-code"&gt;
&lt;h3&gt;The code&lt;/h3&gt;
&lt;p&gt;The code for this part can be downloaded &lt;a href="https://github.com/eliben/code-for-blog/tree/main/2009/pygame_creeps_game"&gt;from here&lt;/a&gt;. It contains the implementation of the pathfinding algorithm and the demo Pygame application.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pathfinding"&gt;
&lt;h3&gt;Pathfinding&lt;/h3&gt;
&lt;p&gt;Pathfinding is one of the most important aspects of game AI (Artificial Intelligence). I'll quote &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Pathfinding"&gt;Wikipedia&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
Pathfinding in this context concerns the way in which a moving entity finds a path around an obstacle; the most frequent context is real time strategy games (in which the player directs units around a play area containing obstacles), but may also be first person shooters. Pathfinding has grown in importance as games and their environments have become more complex.&lt;/blockquote&gt;
&lt;p&gt;Consider a game character controlled by the computer (AI) that wants to get from one place to another. Assuming it can't just instantly teleport itself to the destination, how does it know which way to go ?&lt;/p&gt;
&lt;p&gt;Pathfinding is the answer. And the most popular and well-known algorithm for pathfinding is called A* (A-star). This is the algorithm I'm going to implement in Python and integrate into a Pygame demo in this part.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="a"&gt;
&lt;h3&gt;A*&lt;/h3&gt;
&lt;p&gt;I have no intention of teaching A* in this tutorial. Others have done it
already, and there are wonderful introductions, full of nice diagrams, online.
Two I recommend highly are (in this order): Patrick Lester's &lt;a class="reference
external" href="https://csis.pace.edu/~benjamin/teaching/cs627/webfiles/Astar.pdf"&gt;A*
Pathfinding for Beginners&lt;/a&gt; and Amit's &lt;a class="reference external" href="http://theory.stanford.edu/~amitp/GameProgramming/"&gt;A* Pages&lt;/a&gt;.
Patrick's article is sufficient for you to understand the algorithm and the rest
of my tutorial. Amit's is a great resource if you want to learn more about the
algorithm. I'm sure there are many other articles online - just Google the
subject.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;...time passes as you engorge yourself with A* knowledge...&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Oh, so you know how A* works now! That's really cool, so let's proceed with the tutorial. I'll just post a short reminder, for those who've learned about A* before and can't be bothered to read a full tutorial:

A* is a greedy &lt;a href="http://en.wikipedia.org/wiki/Best-first_search"&gt;best-first search algorithm&lt;/a&gt;. From the start node, it starts considering nodes that could lead it to the goal, judging them by relative merit - the cost to get to them plus an estimated cost to get to the goal from them (more on this heuristic estimation later). All the nodes that are still to be considered are kept in an &lt;em&gt;open list&lt;/em&gt;, and all the nodes with which the algorithm is done (i.e. explored all their successors) are kept in a &lt;i&gt;closed list&lt;/i&gt;. At each "step" the cheapest node from the open list is considered as the next one, and all its successors are added to the open list (where they're sorted by cost), unless they're already there. If a node is already in an open list but now a cheaper path was found to reach it, its cost in the open list is updated. This goes on until the algorithm runs into the goal node, at which point it declares success and returns the path.

That's about it, in short. If you've just finished the A* tutorial, or are familiar with A* from before, the previous paragraph should sound very familiar. If you still don't understand it and want to understand my implementation, I recommend you to read the tutorial again.


&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pathfinder"&gt;
&lt;h3&gt;PathFinder&lt;/h3&gt;
&lt;p&gt;In the code for this part you'll find the file &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pathfinder.py&lt;/span&gt;&lt;/tt&gt; with the class &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt;. This is the class implementing path finding in Python. The class is well documented and if you understand how A* works you should have no trouble with it. There are just two points I want to clarify before we get into the code.&lt;/p&gt;
&lt;div class="section" id="representing-graphs-and-costs"&gt;
&lt;h4&gt;Representing graphs and costs&lt;/h4&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; is a generic class that doesn't care how you represent your graph, and how you represent and compute the costs of moving from place to place. It lets you specify this information by passing functions into its constructor (this is a good time to have the code of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; open in an editor).&lt;/p&gt;
&lt;p&gt;To understand the terminology, consider this graph:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/01/graph_1.png" /&gt;
&lt;p&gt;A graph consists of nodes &lt;a class="footnote-reference" href="#id4" id="id1"&gt;[1]&lt;/a&gt; (the circles) and edges (the arrows). For our pathfinding needs, we're interested in finding out paths from one node to another, through several edges and intermediary nodes. The costs associated with the movement will be marked as numbers on the edges. For instance, we can move in one step from node C to node B, and it will cost us 7 &lt;a class="footnote-reference" href="#id5" id="id2"&gt;[2]&lt;/a&gt;. We can further move from B to D for a cost of 5, so the total cost for movement from C to D bia B is 12.&lt;/p&gt;
&lt;p&gt;So how does &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; know how your graph looks? Very simple, you just specify it with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;successors&lt;/span&gt;&lt;/tt&gt; function passed in as an argument. The &lt;em&gt;successors&lt;/em&gt; of a node are all the nodes that can be reached from this node in a single step. For example, in the graph above, the successors of A are C and B, the successor of B is D, and D has no successors.&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; also knows about the costs because you provide it with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;move_cost&lt;/span&gt;&lt;/tt&gt; function, that tells it the cost between each two nodes.&lt;/p&gt;
&lt;p&gt;The third function passed to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; is &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;heuristic_to_goal&lt;/span&gt;&lt;/tt&gt;. You should be familiar with it from the A* articles, and I'll have more to say about it later.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="implementing-the-open-set"&gt;
&lt;h4&gt;Implementing the open set&lt;/h4&gt;
&lt;p&gt;You'll recall that the A* algorithm uses the &lt;em&gt;open set&lt;/em&gt; to keep track of the nodes it still has to visit. The open set is perhaps the most important data structure for A*, and implementing it correctly is non-trivial.&lt;/p&gt;
&lt;p&gt;I was surprised to find out that most of the implementations of the open set online are very inefficient. I also began with an inefficient implementation, but then A* just took too long to run on even simple graphs! Optimizing the open set with the correct data structure speeded things up by about 100! To read about the various considerations of the implementation, &lt;a class="reference external" href="http://theory.stanford.edu/~amitp/GameProgramming/ImplementationNotes.html"&gt;Amit's Implementation notes&lt;/a&gt; is a terrific resource.&lt;/p&gt;
&lt;p&gt;My implementation uses the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PriorityQueueSet&lt;/span&gt;&lt;/tt&gt; class defined in the file &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;priorityqueueset.py&lt;/span&gt;&lt;/tt&gt;. It is a marriage of a priority queue with a set, which is required, because the open set must be both sorted by priority and the nodes in it must be unique.&lt;/p&gt;
&lt;p&gt;The data structure is very efficient except for one operation. This operation is updating a node in the queue to a lower priority. Luckily, it doesn't happen often in realistic pathfinding problems, so overall it doesn't hinder the performance too much.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-implementation-of-a"&gt;
&lt;h4&gt;The implementation of A*&lt;/h4&gt;
&lt;p&gt;Finally, you're ready to tackle &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;compute_path&lt;/span&gt;&lt;/tt&gt;, the method of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; that implements A*. You'll quickly see how closely it follows the various pseudocodes for A* you find in articles. Python is very pseudocode-like, it's one of its greatest powers!&lt;/p&gt;
&lt;p&gt;One important thing you should keep in mind while reading the code of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; is its usage of the helper &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_Node&lt;/span&gt;&lt;/tt&gt; class. This node holds the point in your graph and its associated costs that help A* do its work. Read its documentation string for more information.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="gridmap"&gt;
&lt;h4&gt;GridMap&lt;/h4&gt;
&lt;p&gt;For pathfinding in our game we're interested in a very special type of graph - a rectangular grid. Such a grid graph is implemented in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;gridmap.py&lt;/span&gt;&lt;/tt&gt;. The idea is as follows:&lt;/p&gt;
&lt;p&gt;The grid is rectangular, and you can get from any square to any neighbor square (up, down, left, right and diagonally), unless that square is blocked &lt;a class="footnote-reference" href="#id6" id="id3"&gt;[3]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Consider the 4 full squares (one of them blocked) on the following image:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/01/squares_blocked.png" /&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;GridMap&lt;/span&gt;&lt;/tt&gt; will represent this map using the following graph:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/01/graph_2.png" /&gt;
&lt;p&gt;Several things to note here:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;The arrows are bi-directional, meaning that a path exists between two nodes both ways (which usually makes sense in game maps).&lt;/li&gt;
&lt;li&gt;Node D is unreachable - it represents the blocked square in the map.&lt;/li&gt;
&lt;li&gt;The costs for moving between nodes is the &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Euclidean_distance"&gt;Euclidean distance&lt;/a&gt; between them.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now, if you run the file &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pathfinder.py&lt;/span&gt;&lt;/tt&gt; - you'll see a small ASCII demo of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; in action on a map created using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;GridMap&lt;/span&gt;&lt;/tt&gt;. You can play with the settings and see how &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; responds.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-distance-to-goal-heurustic"&gt;
&lt;h4&gt;The distance-to-goal heurustic&lt;/h4&gt;
&lt;p&gt;As promised, I'll mention the distance-to-goal heuristic which is required for the correct usage of the A* algorithm. In rectangular grids, the heuristic is easy to compute - it is simply the distance between the point and the goal.&lt;/p&gt;
&lt;p&gt;Here's an example:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2009/01/heuristic_goal.png" /&gt;
&lt;p&gt;Suppose the algorithm has currently reached the blue node and the goal is green. The two yellow nodes are being considered as candidates for the next step. Both are distance 1 from the blue node, but which one should be picked?&lt;/p&gt;
&lt;p&gt;The distance-to-goal heuristic states that the node closer to the goal should be picked, because it has more chance of leading to the goal quickly. The distance can be estimated as the &amp;quot;line-of-sight Euclidean distance&amp;quot;, so the node to the right of the blue node will be picked next (but see exercise 1).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="the-pathfinder-visualizer-demo"&gt;
&lt;h3&gt;The pathfinder visualizer demo&lt;/h3&gt;

&lt;p&gt;The file &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pathfinder_visualize.py&lt;/span&gt;&lt;/tt&gt; (in the example_code directory) contains a simple visualization of the pathfinding algorithm using Pygame. Just run it and read the directions at the top. You can mark goals and starting points, set and unset obstacles, and then ask it to compute a path by pressing F5.&lt;/p&gt;
&lt;p&gt;There's nothing new in terms of Pygame in this demo - if you've followed the tutorial so far, you should have no trouble understanding its code. Note especially how it uses &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PathFinder&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MapGrid&lt;/span&gt;&lt;/tt&gt; to compute and display paths.&lt;/p&gt;
&lt;p&gt;Demos like this are very helpful for analyzing and playing around with code and algorithms. Luckily we know Pygame now, so they're quite simple to implement .&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In this part we went on a short side-walk from our Creeps game, to implement a pathfinding algorithm that we can later incorporate into the game.&lt;/p&gt;
&lt;p&gt;The algorithm itself is A*, and while you're encouraged to understand how it works using the articles I've pointed to and my code, it's not a must. You'll be able to continue learning how to build the game even by treating it as a black box. Keep in mind, though, that if you're serious about game programming, you will be eventually forced to understand A* and pathfinding, as it's a very vital component of almost any game's AI.&lt;/p&gt;
&lt;p&gt;In the next part we'll get back to our Creeps, making them a bit more intelligent using the algorithm we've covered here.&lt;/p&gt;
&lt;div align="center" class="align-center"&gt;&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="exercises"&gt;
&lt;h3&gt;Exercises&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;The distance-to-goal heuristic makes most sense for such maps. However, sometimes it misleads the algorithm to attempt a longer way. Can you think of such situations? Hint: what if there's a long obstacle on the line-of-sight path between the nodes? Simulate this using the visualizer demo.&lt;/li&gt;
&lt;li&gt;Try to give the visualizer an impossible problem, by surrounding the goal with walls, for example. How does it behave?&lt;/li&gt;
&lt;li&gt;Can you make up a map that takes the pathfinder a long time to find a path in? What's the longest time you've managed to make it run?&lt;/li&gt;
&lt;li&gt;Try to change the implementation of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PriorityQueueSet&lt;/span&gt;&lt;/tt&gt; to use simpler data structures. For example, use a simple sorted array. Time the pathfinder algorithm now - how long does it take to solve problems on 20x20 grids?&lt;/li&gt;
&lt;li&gt;Can you cause the PathFinder almost never find paths that include diagonal movement, but still find them when they're the only option to reach a goal? Hint: use the movement cost function to help it decide.&lt;/li&gt;
&lt;/ol&gt;
&lt;div align="center" class="align-center"&gt;&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;&lt;/div&gt;
&lt;table class="docutils footnote" frame="void" id="id4" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Also called vertices in graph terminology.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id5" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;7 what, apples? It depends on what you use the graph for. For our pathfinding needs, the cost can represent the time it takes the character to move from one node to another.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id6" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This represents an obstacle.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

    </content><category term="misc"></category><category term="Pygame tutorial"></category></entry><entry><title>Writing a game in Python with Pygame. Part II</title><link href="https://eli.thegreenplace.net/2008/12/20/writing-a-game-in-python-with-pygame-part-ii" rel="alternate"></link><published>2008-12-20T12:34:33-08:00</published><updated>2024-05-04T19:46:23-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2008-12-20:/2008/12/20/writing-a-game-in-python-with-pygame-part-ii</id><summary type="html">
        &lt;p&gt;This is part II of the &lt;a class="reference external" href="https://eli.thegreenplace.net/tag/pygame-tutorial"&gt;&amp;quot;Writing a game in Python with Pygame&amp;quot; tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="welcome-back"&gt;
&lt;h3&gt;Welcome back&lt;/h3&gt;
&lt;p&gt;In the first part of this tutorial we've created a simple simulation of &amp;quot;Creeps&amp;quot; - round creatures moving around the screen and bouncing off walls. Not much of a game there, but a good start …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">
        &lt;p&gt;This is part II of the &lt;a class="reference external" href="https://eli.thegreenplace.net/tag/pygame-tutorial"&gt;&amp;quot;Writing a game in Python with Pygame&amp;quot; tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="welcome-back"&gt;
&lt;h3&gt;Welcome back&lt;/h3&gt;
&lt;p&gt;In the first part of this tutorial we've created a simple simulation of &amp;quot;Creeps&amp;quot; - round creatures moving around the screen and bouncing off walls. Not much of a game there, but a good start nonetheless.&lt;/p&gt;
&lt;p&gt;In this part, we are going to extend this simulation, making it much more game-like. It is not the final step, of course. The final product of this part is still going to be far from a real, interesting game, but many useful game programming concepts will be introduced, and the simulation will definitely have much more feeling of a game in it.&lt;/p&gt;
&lt;p&gt;Here's a teaser screenshot of the final product of this part:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/creeps_screenshot_2.png" /&gt;
&lt;/div&gt;
&lt;div class="section" id="the-code"&gt;
&lt;h3&gt;The code&lt;/h3&gt;
&lt;p&gt;The full code for this part can be downloaded &lt;a href="https://github.com/eliben/code-for-blog/tree/main/2009/pygame_creeps_game"&gt;from here&lt;/a&gt;. As before, it is highly recommended to download it, run it and have it open in the editor while reading this tutorial.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="goals-for-this-part"&gt;
&lt;h3&gt;Goals for this part&lt;/h3&gt;
&lt;p&gt;In this part I'm going to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;A prettier background for the game&lt;/li&gt;
&lt;li&gt;Responding to user events&lt;/li&gt;
&lt;li&gt;A more complex internal state for the creeps&lt;/li&gt;
&lt;li&gt;Simple animation&lt;/li&gt;
&lt;li&gt;Rendering text&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So let's get started.&lt;/p&gt;
&lt;/div&gt;
&lt;!--more--&gt;
&lt;div class="section" id="background"&gt;
&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;In the first part we've just splashed a bucket of greenish swamp-like color onto the screen and called that a background. Since we want the game to be a bit more appealing, this won't do any longer.&lt;/p&gt;
&lt;p&gt;We'll now &lt;em&gt;tile&lt;/em&gt; a pretty background image onto the screen, and create a bounded &amp;quot;game field&amp;quot; for the creeps to roam in.&lt;/p&gt;
&lt;p&gt;What is tiling, you ask? Tiling, in simple terms, is taking a small surface and repeating it in a pattern until a larger surface is covered. In our case, we'll take this image:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/brick_tile.png" /&gt;
&lt;p&gt;And tile it in a simple repeating-row pattern. The code doing it is in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;draw_background&lt;/span&gt;&lt;/tt&gt; function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;draw_background&lt;/span&gt;(screen, tile_img, field_rect):
    img_rect = tile_img.get_rect()

    nrows = &lt;span style="color: #00007f"&gt;int&lt;/span&gt;(screen.get_height() / img_rect.height) + &lt;span style="color: #007f7f"&gt;1&lt;/span&gt;
    ncols = &lt;span style="color: #00007f"&gt;int&lt;/span&gt;(screen.get_width() / img_rect.width) + &lt;span style="color: #007f7f"&gt;1&lt;/span&gt;

    &lt;span style="color: #00007f; font-weight: bold"&gt;for&lt;/span&gt; y &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; &lt;span style="color: #00007f"&gt;range&lt;/span&gt;(nrows):
        &lt;span style="color: #00007f; font-weight: bold"&gt;for&lt;/span&gt; x &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; &lt;span style="color: #00007f"&gt;range&lt;/span&gt;(ncols):
            img_rect.topleft = (x * img_rect.width,
                                y * img_rect.height)
            screen.blit(tile_img, img_rect)

    field_color = (&lt;span style="color: #007f7f"&gt;109&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;41&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;1&lt;/span&gt;)
    draw_rimmed_box(screen, field_rect, field_color, &lt;span style="color: #007f7f"&gt;4&lt;/span&gt;, Color(&lt;span style="color: #7f007f"&gt;&amp;#39;black&amp;#39;&lt;/span&gt;))
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The loop does the tiling. The last line of the function creates the &lt;em&gt;playing field&lt;/em&gt; - a dark-brown filled rectangle to which the creeps will be restricted. The field is drawn using the utility function &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;draw_rimmed_box&lt;/span&gt;&lt;/tt&gt; - it's very simple, and you can study it on your own &lt;a class="footnote-reference" href="#id5" id="id1"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the game screenshot above you can also see another box with some text on the right. This is drawn separately, and we'll get to it soon enough.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="hey-you-ve-clicked-me"&gt;
&lt;h3&gt;Hey, you've clicked me!&lt;/h3&gt;
&lt;p&gt;So far the only user event our game has responded to was closing closing the game window. Not much interaction there, so we'll pump it up. Here's the new event handler in our main loop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;for&lt;/span&gt; event &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; pygame.event.get():
    &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; event.type == pygame.QUIT:
        exit_game()
    &lt;span style="color: #00007f; font-weight: bold"&gt;elif&lt;/span&gt; event.type == pygame.KEYDOWN:
        &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; event.key == pygame.K_SPACE:
            paused = &lt;span style="color: #0000aa"&gt;not&lt;/span&gt; paused
    &lt;span style="color: #00007f; font-weight: bold"&gt;elif&lt;/span&gt; (  event.type == pygame.MOUSEBUTTONDOWN &lt;span style="color: #0000aa"&gt;and&lt;/span&gt;
            pygame.mouse.get_pressed()[&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;]):
        &lt;span style="color: #00007f; font-weight: bold"&gt;for&lt;/span&gt; creep &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; creeps:
            creep.mouse_click_event(pygame.mouse.get_pos())
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A couple of things were added. First, there's a handler for the user's pressing the space key on the keyboard. This flips the &amp;quot;paused&amp;quot; state of the game - try it now.&lt;/p&gt;
&lt;p&gt;The second handler is only slightly more complex. When a left mouse button is clicked inside the application, each creep gets its &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;mouse_click_event&lt;/span&gt;&lt;/tt&gt; method called with the mouse click coordinates.&lt;/p&gt;
&lt;p&gt;The idea is simple: creeps have &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;health&lt;/span&gt;&lt;/tt&gt;, and we can decrease their health by successfully clicking on them. A health bar is drawn above each creep showing its health as a proportion of red to green (click on some creeps to see their health decrease).&lt;/p&gt;
&lt;p&gt;The implementation is also quite simple. Here's the mouse click handler of a creep:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;mouse_click_event&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;, pos):
    &lt;span style="color: #7f007f"&gt;&amp;quot;&amp;quot;&amp;quot; The mouse was clicked in pos.&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._point_is_inside(vec2d(pos)):
        &lt;span style="color: #00007f"&gt;self&lt;/span&gt;._decrease_health(&lt;span style="color: #007f7f"&gt;3&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You see that when the click was found to be inside the creep, its health is decreased. Let's see how the click inside the creep is detected:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;_point_is_inside&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;, point):
    &lt;span style="color: #7f007f"&gt;&amp;quot;&amp;quot;&amp;quot; Is the point (given as a vec2d) inside our creep&amp;#39;s&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;        body?&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    img_point = point - vec2d(
        &lt;span style="color: #00007f"&gt;int&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_w / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;),
        &lt;span style="color: #00007f"&gt;int&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.y - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_h / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;))

    &lt;span style="color: #00007f; font-weight: bold"&gt;try&lt;/span&gt;:
        pix = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image.get_at(img_point)
        &lt;span style="color: #00007f; font-weight: bold"&gt;return&lt;/span&gt; pix[&lt;span style="color: #007f7f"&gt;3&lt;/span&gt;] &amp;gt; &lt;span style="color: #007f7f"&gt;0&lt;/span&gt;
    &lt;span style="color: #00007f; font-weight: bold"&gt;except&lt;/span&gt; IndexError:
        &lt;span style="color: #00007f; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #00007f"&gt;False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This method detects if the click is inside the creep. More specifically, inside the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;solid&lt;/span&gt; &lt;span class="pre"&gt;area&lt;/span&gt;&lt;/tt&gt; of the creep's image. Clicking inside the creep's bounding box but outside its body won't result in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/tt&gt;. Here's how it's done:&lt;/p&gt;
&lt;p&gt;First, the click point is recomputed to be relatively to the creep's image. If the point isn't inside its image on the screen, there's nothing to talk about. If it is inside, we still don't know if it's in the solid region. For this purpose, the pixel at the point of the click is examined. If the alpha constituent of the point is positive, this is part of the creep's body. Otherwise, it's just part of its bounding box but outside the body (see &lt;a class="footnote-reference" href="#id6" id="id2"&gt;[2]&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Drawing the health bars is very simple, and you should be able to understand the code of the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;draw&lt;/span&gt;&lt;/tt&gt; method (which replaces &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;blitme&lt;/span&gt;&lt;/tt&gt; from the code of part I) that implements this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="simple-animation"&gt;
&lt;h3&gt;Simple animation&lt;/h3&gt;
&lt;p&gt;What happens when the creep's health goes down to 0? I hope you've already experimented with the game and saw it, but if you didn't, here's a screenshot:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/explode1.png" /&gt;
&lt;p&gt;If you've played with the game, however, you've surely noticed that the explosion the creep undergoes is animated - it's changing with time.&lt;/p&gt;
&lt;p&gt;What is an animation? In its simplest form, it is a sequence of images that are drawn one after another in the same location, creating the appearance of movement. It's not unlike our creeps moving on the screen (you can see the whole game as an animation, really), but for the sake of this part I'm specifically referring to a &lt;em&gt;static&lt;/em&gt; animation that stays in the same place.&lt;/p&gt;
&lt;p&gt;The animation is implemented in the module &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;simpleanimation.py&lt;/span&gt;&lt;/tt&gt; which you can find in the downloaded code package. You can experiment with it by running it standalone (the module uses Python's &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;if&lt;/span&gt; &lt;span class="pre"&gt;__name__&lt;/span&gt; &lt;span class="pre"&gt;==&lt;/span&gt; &lt;span class="pre"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;/tt&gt; feature to allow stand-alone running).&lt;/p&gt;
&lt;p&gt;The code should be very simple to understand, because there's nothing much to it. The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;SimpleAnimation&lt;/span&gt;&lt;/tt&gt; class receives a list of image objects and draws them to the screen with the given period and duration. Note how the explosion is simulated by taking the same image, rotating it by 90 degrees and using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;SimpleAnimation&lt;/span&gt;&lt;/tt&gt; to change the two in rapid succession.&lt;/p&gt;
&lt;p&gt;Back in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;creeps.py&lt;/span&gt;&lt;/tt&gt;, our creep uses &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;SimpleAnimation&lt;/span&gt;&lt;/tt&gt; to show its own explosion after its health has reached 0:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;_explode&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;):
    &lt;span style="color: #7f007f"&gt;&amp;quot;&amp;quot;&amp;quot; Starts the explosion animation that ends the Creep&amp;#39;s&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;        life.&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.state = Creep.EXPLODING
    pos = ( &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.explosion_images[&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;].get_width() / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;,
            &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.y - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.explosion_images[&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;].get_height() / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;)
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.explode_animation = SimpleAnimation(
        &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.screen, pos, &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.explosion_images,
        &lt;span style="color: #007f7f"&gt;100&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;300&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It's very straightforward, really.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="creep-state"&gt;
&lt;h3&gt;Creep state&lt;/h3&gt;
&lt;p&gt;The creeps of this part are much more complex than of part I. They have health which can decrease, and they can explode and disappear. To manage this complexity, we're going to use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;a&lt;/span&gt; &lt;span class="pre"&gt;state&lt;/span&gt; &lt;span class="pre"&gt;machine&lt;/span&gt;&lt;/tt&gt; &lt;a class="footnote-reference" href="#id7" id="id3"&gt;[3]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What states can the creep be in? A normal state, when the creep is roaming around, an exploding state in which the creep is replaced by the explosion animation, and an inactive state, in which the creep no longer functions. These are coded as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;(ALIVE, EXPLODING, DEAD) = &lt;span style="color: #00007f"&gt;range&lt;/span&gt;(&lt;span style="color: #007f7f"&gt;3&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See the code of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt; for state management - the creep is updated differently, depending on which state it's in. The same is true for the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;draw&lt;/span&gt;&lt;/tt&gt; method. It's a good idea now to search for &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;self.state&lt;/span&gt;&lt;/tt&gt; throughout the code, taking note of where the state is modified, and where it is used.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="displaying-textual-information"&gt;
&lt;h3&gt;Displaying textual information&lt;/h3&gt;
&lt;p&gt;When you run the game (or in the large screenshot at the top of this part), you'll see a simple scoreboard in the top right corner of the screen. It counts the amount of active creeps on the screen, and will also display an exciting message when you've killed all the creeps.&lt;/p&gt;
&lt;p&gt;This display is implemented in the function &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;draw_messageboard&lt;/span&gt;&lt;/tt&gt; - study its code now, it should be quite simple to understand in conjunction with &lt;a class="reference external" href="http://pygame.org/docs/ref/font.html"&gt;the docs&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="sprites-and-sprite-groups"&gt;
&lt;h3&gt;Sprites and sprite Groups&lt;/h3&gt;
&lt;p&gt;I hope you've noticed that in both parts of the tutorial, the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; class derives from &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pygame.sprite.Sprite&lt;/span&gt;&lt;/tt&gt;. &lt;a class="reference external" href="http://pygame.org/docs/ref/sprite.html"&gt;Sprite&lt;/a&gt; is a utility class of Pygame that implements some useful common methods for managing the animated images that represent the actors of the game (known in game programming jargon as &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Sprite_(computer_graphics)"&gt;sprites&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In the first part I didn't use any of its capabilities at all. Here, I'm using its capability of being collected into &lt;a class="reference external" href="http://pygame.org/docs/ref/sprite.html#pygame.sprite.Group"&gt;sprite Groups&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The list of creeps in the main function has now turned into a sprite group. The cool thing is that whenever a sprite is added to a group, it keeps track of which groups it's in, so calling &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;self.kill()&lt;/span&gt;&lt;/tt&gt; in a sprite causes it to be removed from all the groups and thus from the game. The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt; method of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; calls &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;kill()&lt;/span&gt;&lt;/tt&gt; when the explosion has ended. This way, the main loop doesn't have to explicitly keep track of which sprites are active in the group - they do it themselves.&lt;/p&gt;
&lt;p&gt;That said, I'm still not sure I'm going to use the full capabilities of Sprites. For me, they're just a guideline, not a must. Perhaps I'll find out later that my code can be structured better with them. Or perhaps I'll see I don't need them at all. We'll see &lt;a class="footnote-reference" href="#id8" id="id4"&gt;[4]&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="wrapping-up"&gt;
&lt;h3&gt;Wrapping up&lt;/h3&gt;
&lt;p&gt;All the goals stated in the beginning of this part were achieved, so that's it, for now. We've turned the simplistic creeps simulation into something resembling a rudimentary game. True, it's more likely to pave your way to severe &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Repetitive_strain_injury"&gt;RSI&lt;/a&gt; than cause you any serious fun, but it's a simple game nonetheless. Not bad for just 450 lines of Python code!&lt;/p&gt;
&lt;p&gt;In future parts of this tutorial, we'll continue developing the code on our way to a real game, so stay tuned. Oh, and give the exercises a go, I guarantee you they will make your understanding of the material much deeper.&lt;/p&gt;
&lt;div align="center" class="align-center"&gt;&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="exercises"&gt;
&lt;h3&gt;Exercises&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Try to pause the game (press SPACE), click a couple of times on a creep, and resume the game. Notice that the creep's health decreased? Try to fix this, i.e. block mouse events during the pause.&lt;/li&gt;
&lt;li&gt;Can you see that when a creep is facing diagonally, his health bar is a bit farther from his body than when he's facing up or to the side? Can you figure out why? (Hint: re-read the section of part I dealing with the size of the rotated image). Propose ways to fix this.&lt;/li&gt;
&lt;li&gt;Review the code of the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_explode&lt;/span&gt;&lt;/tt&gt; method. Note the complex computation of the explosion's position. Why is it needed? Try to modify it (for example, removing the consideration of the explosion image's size) and observe the difference.&lt;/li&gt;
&lt;li&gt;Add a running clock to the scoreboard. It should begin at 00:00 and advance by 1 each second. When the game ends, the clock should stop.&lt;/li&gt;
&lt;li&gt;Set the creeps' speed to higher than the default and attempt to catch them. It's quite challenging!&lt;/li&gt;
&lt;/ol&gt;
&lt;div align="center" class="align-center"&gt;&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;&lt;/div&gt;
&lt;table class="docutils footnote" frame="void" id="id5" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Note also the usage of the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Color&lt;/span&gt;&lt;/tt&gt; &lt;a class="reference external" href="http://www.pygame.org/docs/ref/color.html"&gt;module&lt;/a&gt; to specify color. This is a useful PyGame module, and I've changed almost all the hard-coded color references in the code to named colors.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id6" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;The images of creeps are stored in PNG files that support &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Alpha_compositing"&gt;alpha transparency&lt;/a&gt;. If you examine the image with an image editor that supports transparency (Paint.NET or GIMP, for example), you'll see that the area outside the creep's round body is transparent. This is used to blend the creep in a pleasing way into its background, and can also be employed to detect what's inside and what's outside of the creeps's body.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id7" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;I assume you know what a state machine is, and if you don't, &lt;a class="reference external" href="http://en.wikipedia.org/wiki/State_machine"&gt;Wikipedia&lt;/a&gt; and Google are your friends.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id8" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id4"&gt;[4]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;To learn more about Pygame sprites, read &lt;a class="reference external" href="http://www.sacredchao.net/~piman/writing/sprite-tutorial.shtml"&gt;this tutorial.&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

    </content><category term="misc"></category><category term="Pygame tutorial"></category></entry><entry><title>Writing a game in Python with Pygame. Part I</title><link href="https://eli.thegreenplace.net/2008/12/13/writing-a-game-in-python-with-pygame-part-i" rel="alternate"></link><published>2008-12-13T11:18:50-08:00</published><updated>2024-05-04T19:46:23-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2008-12-13:/2008/12/13/writing-a-game-in-python-with-pygame-part-i</id><summary type="html">
        &lt;div class="section" id="introduction"&gt;
&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Games are one of the most applicative areas of programming. To write even the simplest games, you have to get into graphics, math, physics and even AI. It's a great and fun way to practice programming.&lt;/p&gt;
&lt;p&gt;If you're a fan of Python (and even if you aren't) and are …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">
        &lt;div class="section" id="introduction"&gt;
&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Games are one of the most applicative areas of programming. To write even the simplest games, you have to get into graphics, math, physics and even AI. It's a great and fun way to practice programming.&lt;/p&gt;
&lt;p&gt;If you're a fan of Python (and even if you aren't) and are interested in games, &lt;a class="reference external" href="http://www.pygame.org"&gt;Pygame&lt;/a&gt; is a great library for game programming, and you should definitely check it out. It runs on all major platforms, and provides simple tools to manage complex graphical worlds with movement and sounds.&lt;/p&gt;
&lt;p&gt;There are quite a lot of Pygame tutorials on the web, but most of them are basic. Even the &lt;a class="reference external" href="https://eli.thegreenplace.net/2008/12/06/book-review-beginning-game-development-with-python-and-pygame-by-will-mcgugan/"&gt;Pygame book&lt;/a&gt; stays at an introductory level. In order to proceed to a higher level of mastery, I've decided to write a tutorial of my own, hoping that it will provide the next logical step for persons wanting to use Pygame.&lt;/p&gt;
&lt;p&gt;This tutorial explicitly encourages you to tinker with the code. It is also highly recommended to do the exercises in the end. These will greatly aid your understanding of the learned material.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="preliminaries"&gt;
&lt;h3&gt;Preliminaries&lt;/h3&gt;
&lt;p&gt;For reasons I've mentioned above, this tutorial is not for complete beginners. If you're just beginning with Pygame, first go through some of the tutorials from &lt;a class="reference external" href="http://www.pygame.org/wiki/tutorials"&gt;this page&lt;/a&gt;. &lt;a class="reference external" href="http://lorenzod8n.wordpress.com/category/pygame-tutorial/"&gt;This tutorial&lt;/a&gt; is also recommended as a basic introduction to Pygame.&lt;/p&gt;
&lt;p&gt;Here, I assume that you have the following knowledge:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Python (you don't have to be an advanced user, but not a complete beginner either)&lt;/li&gt;
&lt;li&gt;Basics of math and physics (vectors, rectangles, laws of movement, probability, etc.). I will explain all the non-trivial tricks, but I won't teach how to add vectors, and so on.&lt;/li&gt;
&lt;li&gt;An acquaintance with Pygame. I.e. you've already went through at least a couple of the tutorials mentioned above.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oh, and another thing... This tutorial will focus on a 2D game. 3D is a whole new level of complexity, and I prefer a simpler but complete game to a half-baked 3D demo.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="let-s-get-started"&gt;
&lt;h3&gt;Let's get started&lt;/h3&gt;
&lt;p&gt;In this part, we'll end up writing a demo - a complete simulation of &lt;em&gt;creeps&lt;/em&gt;, round creatures that move around the screen, bouncing off walls and changing their direction from time to time:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/creeps_screenshot_1.png" /&gt;
&lt;p&gt;While this is not yet a &lt;em&gt;game&lt;/em&gt; per se, it's a useful starting point, from which we can implement many various ideas. I'll leave myself the luxury of postponing the decision of which game it will eventually be, for now.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-code"&gt;
&lt;h3&gt;The code&lt;/h3&gt;
&lt;p&gt;The complete package for part 1, with all the required images, can be downloaded &lt;a href="https://github.com/eliben/code-for-blog/tree/main/2009/pygame_creeps_game"&gt;from here&lt;/a&gt;.
I recommend you to download it and run the demo.
Having the code in front of your eyes is very useful.
I tested it with Python 2.5.2 and Pygame 1.8.1, although it will probably work with other versions as well.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pygame-s-docs"&gt;
&lt;h3&gt;Pygame's docs&lt;/h3&gt;
&lt;p&gt;Pygame's API is documented &lt;a class="reference external" href="http://www.pygame.org/docs/"&gt;fairly well&lt;/a&gt;. There is a complete list of modules, classes, constants and functions provided by Pygame there, and I encourage you to consult this resource often - for each Pygame class/method you're not familiar with.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="creeps"&gt;
&lt;h3&gt;Creeps&lt;/h3&gt;
&lt;p&gt;Okay, so first let's set the goals for this part:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;We want to have creeps moving around the screen&lt;/li&gt;
&lt;li&gt;The number of creeps and their appearance should be easily configurable&lt;/li&gt;
&lt;li&gt;The creeps will bounce off walls correctly&lt;/li&gt;
&lt;li&gt;To make things more interesting, the creeps will exhibit semi-random behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So what is a creep ?&lt;/p&gt;
&lt;p&gt;A creep is a small image that will be moved around the screen and rotated
using Pygame's capabilities. Keeping rotated images pretty takes more artistic
skill than I possess, so I'll limit the rotations to quantas of 45 degrees
(meaning that creeps will move up, down, left, right or in 4 diagonals).&lt;/p&gt;
&lt;p&gt;The creep images contained in the downloadable package are small .png
files &lt;a class="footnote-reference" href="#id3" id="id1"&gt;[1]&lt;/a&gt;&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/pinkcreep.png" /&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/bluecreep.png" /&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/graycreep.png" /&gt;
&lt;p&gt;Note that all the creep images have the same orientation. This is
significant, as we will learn later.&lt;/p&gt;
&lt;p&gt;How do creeps move?&lt;/p&gt;
&lt;p&gt;As you've undoubtedly read in one of the basic Pygame tutorials (haven't you
??), movement is an illusion. Nothing really &lt;em&gt;moves&lt;/em&gt; on a computer
screen. Rather, the program displays a sequence of images with small
displacements fast enough for the human eye to perceive movement. The rule of
thumb is that anything 30 updates per second &lt;a class="footnote-reference" href="#id4" id="id2"&gt;[2]&lt;/a&gt; or faster is good enough and looks smooth to the
average person.&lt;/p&gt;
&lt;p&gt;To implement periodic update of the screen, games use the game loop.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-game-loop"&gt;
&lt;h3&gt;The game loop&lt;/h3&gt;
&lt;p&gt;Just like a GUI, every game has the &amp;quot;main loop&amp;quot;. In Pygame you implement it with a Python loop, which is simple enough. Here's our main loop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #007f00"&gt;# The main game loop&lt;/span&gt;
&lt;span style="color: #007f00"&gt;#&lt;/span&gt;
&lt;span style="color: #00007f; font-weight: bold"&gt;while&lt;/span&gt; &lt;span style="color: #00007f"&gt;True&lt;/span&gt;:
    &lt;span style="color: #007f00"&gt;# Limit frame speed to 50 FPS&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;#&lt;/span&gt;
    time_passed = clock.tick(&lt;span style="color: #007f7f"&gt;50&lt;/span&gt;)

    &lt;span style="color: #00007f; font-weight: bold"&gt;for&lt;/span&gt; event &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; pygame.event.get():
        &lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; event.type == pygame.QUIT:
            exit_game()

    &lt;span style="color: #007f00"&gt;# Redraw the background&lt;/span&gt;
    screen.fill(BG_COLOR)

    &lt;span style="color: #007f00"&gt;# Update and redraw all creeps&lt;/span&gt;
    &lt;span style="color: #00007f; font-weight: bold"&gt;for&lt;/span&gt; creep &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; creeps:
        creep.update(time_passed)
        creep.blitme()

    pygame.display.flip()
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Jumping right into the code, eh ? Well, let's see what goes on here. As I've said, it's your basic Python loop - endless, until the user asks to quit. &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pygame.QUIT&lt;/span&gt;&lt;/tt&gt; is the only event handled here, as you can see. It arrives when the user attempts to close the program's window.&lt;/p&gt;
&lt;p&gt;How often does this loop run ? This is decided by the call to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;clock.tick&lt;/span&gt;&lt;/tt&gt;. &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;clock&lt;/span&gt;&lt;/tt&gt; is a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pygame.time.Clock&lt;/span&gt;&lt;/tt&gt; object, created earlier. The call to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tick&lt;/span&gt;&lt;/tt&gt; basically says this: sleep until the next 1/50 second boundary, at most. In practice, this limits the game speed to 50 FPS, which is a good thing, because we want the game to be smooth on one hand, and not eat up most of the CPU on the other hand. You can experiment with this effect by playing with the value. Lower it to 10, for example. How does the demo look ? Also, see exercises 1 and 3.&lt;/p&gt;
&lt;p&gt;Now is a good time to immerse yourself in the documentation of &lt;a class="reference external" href="http://www.pygame.org/docs/ref/time.html#pygame.time.Clock"&gt;tick&lt;/a&gt;, by the way.&lt;/p&gt;
&lt;p&gt;The really interesting stuff happens later. On each iteration, the screen is refilled with the background color and all the creeps are updated and drawn. Finally, the display is updated with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;flip&lt;/span&gt;&lt;/tt&gt; (Yes, you should read &lt;a class="reference external" href="http://www.pygame.org/docs/ref/display.html#pygame.display.flip"&gt;its documentation&lt;/a&gt; now).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-comes-before-the-loop"&gt;
&lt;h3&gt;What comes before the loop&lt;/h3&gt;
&lt;p&gt;Now let's see what comes before the main loop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #007f00"&gt;# Game parameters&lt;/span&gt;
SCREEN_WIDTH, SCREEN_HEIGHT = &lt;span style="color: #007f7f"&gt;400&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;400&lt;/span&gt;
BG_COLOR = &lt;span style="color: #007f7f"&gt;150&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;150&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;80&lt;/span&gt;
CREEP_FILENAMES = [
    &lt;span style="color: #7f007f"&gt;&amp;#39;bluecreep.png&amp;#39;&lt;/span&gt;,
    &lt;span style="color: #7f007f"&gt;&amp;#39;pinkcreep.png&amp;#39;&lt;/span&gt;,
    &lt;span style="color: #7f007f"&gt;&amp;#39;graycreep.png&amp;#39;&lt;/span&gt;]
N_CREEPS = &lt;span style="color: #007f7f"&gt;20&lt;/span&gt;

pygame.init()
screen = pygame.display.set_mode(
            (SCREEN_WIDTH, SCREEN_HEIGHT), &lt;span style="color: #007f7f"&gt;0&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;32&lt;/span&gt;)
clock = pygame.time.Clock()

&lt;span style="color: #007f00"&gt;# Create N_CREEPS random creeps.&lt;/span&gt;
creeps = []
&lt;span style="color: #00007f; font-weight: bold"&gt;for&lt;/span&gt; i &lt;span style="color: #0000aa"&gt;in&lt;/span&gt; &lt;span style="color: #00007f"&gt;range&lt;/span&gt;(N_CREEPS):
    creeps.append(Creep(screen,
                        choice(CREEP_FILENAMES),
                        (   randint(&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;, SCREEN_WIDTH),
                            randint(&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;, SCREEN_HEIGHT)),
                        (   choice([-&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;1&lt;/span&gt;]),
                            choice([-&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;1&lt;/span&gt;])),
                        &lt;span style="color: #007f7f"&gt;0.1&lt;/span&gt;))
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;OK, not much magic here. The first few lines are self-explanatory. I also assume you already know how to initialize Pygame and create a display object. What about the creation of creeps, though?&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;creeps&lt;/span&gt;&lt;/tt&gt; is a list of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; objects - the heart and soul of this game. Here's the declaration of the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; class with its constructor's signature:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #00007f"&gt;Creep&lt;/span&gt;(Sprite):
    &lt;span style="color: #7f007f"&gt;&amp;quot;&amp;quot;&amp;quot; A creep sprite that bounces off walls and changes its&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;        direction from time to time.&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;__init__&lt;/span&gt;(
            &lt;span style="color: #00007f"&gt;self&lt;/span&gt;, screen, img_filename, init_position,
            init_direction, speed):
        &lt;span style="color: #7f007f"&gt;&amp;quot;&amp;quot;&amp;quot; Create a new Creep.&lt;/span&gt;

&lt;span style="color: #7f007f"&gt;            screen:&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;                The screen on which the creep lives (must be a&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;                pygame Surface object, such as pygame.display)&lt;/span&gt;

&lt;span style="color: #7f007f"&gt;            img_filaneme:&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;                Image file for the creep.&lt;/span&gt;

&lt;span style="color: #7f007f"&gt;            init_position:&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;                A vec2d or a pair specifying the initial position&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;                of the creep on the screen.&lt;/span&gt;

&lt;span style="color: #7f007f"&gt;            init_direction:&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;                A vec2d or a pair specifying the initial direction&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;                of the creep. Must have an angle that is a&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;                multiple of 45 degres.&lt;/span&gt;

&lt;span style="color: #7f007f"&gt;            speed:&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;                Creep speed, in pixels/millisecond (px/ms)&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The arguments are well documented, and you can see how they are matched by the passed values when the creeps are created:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;creeps.append(Creep(screen,
                    choice(CREEP_FILENAMES),
                    (   randint(&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;, SCREEN_WIDTH),
                        randint(&lt;span style="color: #007f7f"&gt;0&lt;/span&gt;, SCREEN_HEIGHT)),
                    (   choice([-&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;1&lt;/span&gt;]),
                        choice([-&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;, &lt;span style="color: #007f7f"&gt;1&lt;/span&gt;])),
                    &lt;span style="color: #007f7f"&gt;0.1&lt;/span&gt;))
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First, we pass the screen &lt;a class="reference external" href="http://www.pygame.org/docs/ref/surface.html"&gt;surface&lt;/a&gt; to the Creep. It will use it to figure out how to bounce off walls, and where to draw itself.&lt;/p&gt;
&lt;p&gt;Next, the Creep is provided with a random image from the list of images (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;choice&lt;/span&gt;&lt;/tt&gt; is a function from Python's standard &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;random&lt;/span&gt;&lt;/tt&gt; module), and is set in a random position on the screen (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;randint&lt;/span&gt;&lt;/tt&gt; is also from &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;random&lt;/span&gt;&lt;/tt&gt;), with a random direction (more about the direction later). The speed is set to 0.1 px/ms (0.1 pixels per millisecond), or 100 pixels per second.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="vectors-and-directions"&gt;
&lt;h3&gt;Vectors and directions&lt;/h3&gt;
&lt;p&gt;This is perhaps the least simple part of the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;creeps&lt;/span&gt;&lt;/tt&gt; demo. Grokking vectors in game programming is essential, since vectors are the chief mathematical tool for making computations related to movement on the screen.&lt;/p&gt;
&lt;p&gt;We'll use vectors for two things. One is to describe the position and velocity (displacement) of creeps. As you surely know, a position (a point) on the XY plane can be represented by a 2D vector. The difference between two vectors is the velocity (displacement) vector. In other words, adding the velocity vector to the original position vector yields the new position:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/pos_velocity.png" /&gt;
&lt;p&gt;This is all good and nice, except for a small twist. While in the mathematical world, we're accustomed to the XY plane to look as it does on the diagram above (positive X pointing right, positive Y pointing up), when we're drawing on the screen we must think a bit differently. In almost all graphical drawing interfaces, the top-left corner is (0, 0), X increases to the right, and Y increases to downwards. In other words, the screen drawing XY plane is:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/vectors_01.png" /&gt;
&lt;p&gt;This is a very important diagram! It represents the basic 8 &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Normalized_vector"&gt;normalized vectors&lt;/a&gt; we'll be using in the creep demo. These are the directions the creep can be pointing in (all multiples of 45 degrees over the unit circle). Make sure you understand it before moving on.&lt;/p&gt;
&lt;p&gt;Recall the direction argument to the constructor of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; ? This is the vector that specifies the initial direction of the creep. Actually, the constructor allows to pass in a pair, which is later turned into a vector and normalized (so, for instance, passing the pair (-1, -1) will result in the expected north-west direction).&lt;/p&gt;
&lt;p&gt;This direction will be later changed by the creep itself when it either decides to go another way or bounces off a wall.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="implementing-vectors"&gt;
&lt;h3&gt;Implementing vectors&lt;/h3&gt;
&lt;p&gt;Surprisingly, Pygame doesn't have a &amp;quot;standard&amp;quot; vector implementation shipping with it. So game writers have to either roll their own or find vector modules online.&lt;/p&gt;
&lt;p&gt;Included in the package is the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;vec2d.py&lt;/span&gt;&lt;/tt&gt; file, a 2D vector implementation I've borrowed from the &lt;a class="reference external" href="http://pygame.org/wiki/2DVectorClass"&gt;Pygame Wiki&lt;/a&gt;. It is a pretty good implementation of a 2D vector with a lot of useful utility functions. There's no need for you to read and understand its full code now, but see exercise 4.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="updating-the-creep"&gt;
&lt;h3&gt;Updating the creep&lt;/h3&gt;
&lt;p&gt;The most interesting function of this demo is the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt; method of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;update&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;, time_passed):
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This method is called periodically by the main loop and is passed the amount of time passed (in milliseconds) since the previous call. Using this knowledge, the creep can compute its next location.&lt;/p&gt;
&lt;p&gt;Let's learn the code of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt;, step by step:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #007f00"&gt;# Maybe it&amp;#39;s time to change the direction ?&lt;/span&gt;
&lt;span style="color: #007f00"&gt;#&lt;/span&gt;
&lt;span style="color: #00007f"&gt;self&lt;/span&gt;._change_direction(time_passed)

&lt;span style="color: #007f00"&gt;# Make the creep point in the correct direction.&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# Since our direction vector is in screen coordinates&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# (i.e. right bottom is 1, 1), and rotate() rotates&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# counter-clockwise, the angle must be inverted to&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# work correctly.&lt;/span&gt;
&lt;span style="color: #007f00"&gt;#&lt;/span&gt;
&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image = pygame.transform.rotate(
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.base_image, -&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.angle)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First, the internal &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_change_direction&lt;/span&gt;&lt;/tt&gt; is called to see if the creep wants to randomly change its direction. The code of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_change_direction&lt;/span&gt;&lt;/tt&gt; will be simple to understand after we complete going through &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt;, so I'm leaving it for exercise 5.&lt;/p&gt;
&lt;p&gt;The next operation is to rotate the creep image in the correct direction. Recall how I noted that all the creep images point to the right? This is essential for correct and consistent rotation. &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;transform.rotate&lt;/span&gt;&lt;/tt&gt; (read its docs!) rotates a given surface counterclockwise by the provided angle.&lt;/p&gt;
&lt;p&gt;Now, why do we give it a negation of the angle ? This is exactly because of the inverted &amp;quot;screen XY plane&amp;quot; I've mentioned before.
Imagine the base creep image (which is, by the way, loaded in the constructor of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Creep&lt;/span&gt;&lt;/tt&gt; - see how):&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/bluecreep.png" /&gt;
&lt;p&gt;And suppose our direction is 45 degrees (that is, south-east in our screen coordinates). If we give 45 degrees to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;rotate&lt;/span&gt;&lt;/tt&gt;, it will make the creep point north-east (as its rotation is counterclockwise). So to perform the correct rotation, we have to negate the angle.&lt;/p&gt;
&lt;p&gt;Next in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt;, we see:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #007f00"&gt;# Compute and apply the displacement to the position&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# vector. The displacement is a vector, having the angle&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# of self.direction (which is normalized to not affect&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# the magnitude of the displacement)&lt;/span&gt;
&lt;span style="color: #007f00"&gt;#&lt;/span&gt;
displacement = vec2d(
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.x * &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.speed * time_passed,
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.y * &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.speed * time_passed)

&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos += displacement
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As I said, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;self.direction&lt;/span&gt;&lt;/tt&gt; is a normalized vector that tells us where the creep points to. It is important for it to be normalized for this computation to work correctly, because we don't want it to affect the magnitude of the displacement. The displacement is computed from the basic rule of motion that distance equals speed multiplied by time, just in 2 dimensions.&lt;/p&gt;
&lt;p&gt;The next part of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;update&lt;/span&gt;&lt;/tt&gt; deals with bouncing off walls. To make it more intelligible, I want to first show how the creep is drawn to the screen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="blitme"&gt;
&lt;h3&gt;Blitme!&lt;/h3&gt;
&lt;p&gt;&lt;a class="reference external" href="http://en.wikipedia.org/wiki/Blitting"&gt;Blitting&lt;/a&gt; is the game programmers' jargon for transferring an image (or a pattern) onto a drawable surface. In Pygame this is implemented with the &lt;a class="reference external" href="http://www.pygame.org/docs/ref/surface.html#Surface.blit"&gt;blit&lt;/a&gt; function.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #00007f"&gt;blitme&lt;/span&gt;(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;):
    &lt;span style="color: #7f007f"&gt;&amp;quot;&amp;quot;&amp;quot; Blit the creep onto the screen that was provided in&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;        the constructor.&lt;/span&gt;
&lt;span style="color: #7f007f"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# The creep image is placed at self.pos.&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# To allow for smooth movement even when the creep rotates&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# and the image size changes, its placement is always&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;# centered.&lt;/span&gt;
    &lt;span style="color: #007f00"&gt;#&lt;/span&gt;
    draw_pos = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image.get_rect().move(
        &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_w / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;,
        &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.y - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_h / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;)
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.screen.blit(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image, draw_pos)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Blitting, like many other things in Pygame, use the versatile &lt;a class="reference external" href="http://www.pygame.org/docs/ref/rect.html"&gt;pygame.Rect&lt;/a&gt; class. The call to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;blit&lt;/span&gt;&lt;/tt&gt; accepts an image (a surface, actually) and a rectangle that specifies where this image will be blitted to the surface on which &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;blit&lt;/span&gt;&lt;/tt&gt; is invoked.&lt;/p&gt;
&lt;p&gt;And sure enough, we provide the drawing position as the creep's current position (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;self.pos&lt;/span&gt;&lt;/tt&gt;) but with a small adjustment. What for ?&lt;/p&gt;
&lt;p&gt;Thing is, when images are rotated in Pygame, their size increases. Here's why:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/creep_rotation.png" /&gt;
&lt;p&gt;Since the image is square, Pygame has to include all of its information in the rotated image, so the rotated image has to grow in size. This only happens for rotations that are not multiples of 90 degrees, by the way (see exercise 6).&lt;/p&gt;
&lt;p&gt;So, whenever a creep turns, its image size changes. Without a special adjustment, the creep will shift with each turn and the animation won't be smooth and pretty.&lt;/p&gt;
&lt;p&gt;The adjustment is simple enough: we &lt;em&gt;center&lt;/em&gt; the creep when we draw it. Look at this code again:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;draw_pos = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image.get_rect().move(
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_w / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;,
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.y - &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_h / &lt;span style="color: #007f7f"&gt;2&lt;/span&gt;)
&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.screen.blit(&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image, draw_pos)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The draw position is computed to be the center of the creep's image. Even when the image rotates and grows, its center stays in the same place, so there will be no noticeable shift in the creep this way.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="bouncing-off-walls"&gt;
&lt;h3&gt;Bouncing off walls&lt;/h3&gt;
&lt;p&gt;Make sure you understand the &amp;quot;centered drawing&amp;quot; trick described in the previous section (and see exercise 7) first. Once you do, understanding how the creep bounces off walls is easy. Here's the code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #007f00"&gt;# When the image is rotated, its size is changed.&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# We must take the size into account for detecting&lt;/span&gt;
&lt;span style="color: #007f00"&gt;# collisions with the walls.&lt;/span&gt;
&lt;span style="color: #007f00"&gt;#&lt;/span&gt;
&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_w, &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_h = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image.get_size()
bounds_rect = &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.screen.get_rect().inflate(
                -&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_w, -&lt;span style="color: #00007f"&gt;self&lt;/span&gt;.image_h)

&lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x &amp;lt; bounds_rect.left:
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x = bounds_rect.left
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.x *= -&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;
&lt;span style="color: #00007f; font-weight: bold"&gt;elif&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x &amp;gt; bounds_rect.right:
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x = bounds_rect.right
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.x *= -&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;
&lt;span style="color: #00007f; font-weight: bold"&gt;elif&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.y &amp;lt; bounds_rect.top:
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.y = bounds_rect.top
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.y *= -&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;
&lt;span style="color: #00007f; font-weight: bold"&gt;elif&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.y &amp;gt; bounds_rect.bottom:
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.y = bounds_rect.bottom
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.y *= -&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First, the screen boundary itself is computed, by taking the rectangle representing the screen and adjusting it to the image size (this is required for our centered drawing).&lt;/p&gt;
&lt;p&gt;Then, for each of the 4 walls we compute whether the creep collides with it, and if it does, the creep's direction is inverted in the axis perpendicular to the wall, simulating a smooth bounce. Let's dissect one of such conditions:&lt;/p&gt;
&lt;img src="https://eli.thegreenplace.net/images/2008/12/left_bounce.png" /&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #00007f; font-weight: bold"&gt;if&lt;/span&gt; &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x &amp;lt; bounds_rect.left:
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.pos.x = bounds_rect.left
    &lt;span style="color: #00007f"&gt;self&lt;/span&gt;.direction.x *= -&lt;span style="color: #007f7f"&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is for the bounce off the left wall. The creeps always arrives to it from the right, so when we negate the X component of its direction vector while keeping the Y component intact, it will start moving to the right but with the same vertical direction.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;We've seen most of the interesting code of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;creeps.py&lt;/span&gt;&lt;/tt&gt; now. If something still remains unclear, go through the whole code with the diagrams from this tutorial in front of your eyes. If things remain unclear, let me know and I'll gladly help.&lt;/p&gt;
&lt;p&gt;One can understand a tutorial or a lecture on several levels. The most basic is just reading it. To make understanding deeper, one must also practice the material. And to master something, you should apply your brain to new material, new challenges based on the tutorial but not directly explained in it. For this, I once again warmly encourage you to at least look at the exercises and try to think how to do them. The best would be implementing solutions and tinkering with the code itself.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-s-next"&gt;
&lt;h3&gt;What's next&lt;/h3&gt;
&lt;p&gt;The creeps demo can serve as a good basis for quite a few games. I haven't decided which I want to write, yet, and how far I want to take this tutorial at all. So its future direction depends a lot on your feedback. Feel free to comment or write me an email.&lt;/p&gt;
&lt;div align="center" class="align-center"&gt;&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="exercises"&gt;
&lt;h3&gt;Exercises&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Increase the amount of creeps by modifying the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;N_CREEPS&lt;/span&gt;&lt;/tt&gt; constant. On my PC, the demo runs easily and smoothly with hundreds of creeps.&lt;/li&gt;
&lt;li&gt;Modify the creep creation line to have 60% gray creeps, 20% blue and 20% pink.&lt;/li&gt;
&lt;li&gt;Experiment with the call to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;clock.tick&lt;/span&gt;&lt;/tt&gt; in the main loop. Try to print out the time passed between ticks, and then modify the argument to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tick&lt;/span&gt;&lt;/tt&gt;. If you provide no argument, it runs as fast as it can. See how much time passes between ticks when the amount of creeps increases.&lt;/li&gt;
&lt;li&gt;Open &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;vec2d.py&lt;/span&gt;&lt;/tt&gt;, and read the code of all the methods and attributes used in our creeps demo.&lt;/li&gt;
&lt;li&gt;Modify the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_change_direction&lt;/span&gt;&lt;/tt&gt; method to change the behavior of creeps. (1) Make them change direction more often and observe the behavior. (2) Can you make them stop for a second once in a while ? You'd have to modify the speed for that.&lt;/li&gt;
&lt;li&gt;Can you use basic trigonometry to compute by how much the image increases when it's rotated by 45 degrees in Pygame ?&lt;/li&gt;
&lt;li&gt;Rewrite the drawing code to cancel centered drawing (just provide the unadjusted image rectangle to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;blit&lt;/span&gt;&lt;/tt&gt;). How does it look ?&lt;/li&gt;
&lt;/ol&gt;
&lt;div align="center" class="align-center"&gt;&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="updates"&gt;
&lt;h3&gt;Updates&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;13.12.2008 - Simplified the code for bouncing off walls. Thanks to Andrei for the tip.&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="center" class="align-center"&gt;&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;&lt;/div&gt;
&lt;table class="docutils footnote" frame="void" id="id3" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;PNG is a useful format - it is free, provides efficient lossless compression and supports alpha (transparency).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id4" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Or Frames Per Second (FPS) in game programming jargon. Counting FPS is the hobby of game programmers worldwide.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

    </content><category term="misc"></category><category term="Pygame tutorial"></category><category term="Python"></category></entry></feed>