added completly new version for haslach 2025

This commit is contained in:
fotobox
2025-03-17 03:47:13 +01:00
parent 152832515c
commit 769ab91da8
2333 changed files with 409208 additions and 341 deletions

View File

@@ -0,0 +1,374 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pygame Tutorials - Camera Module Introduction &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Pygame Tutorials - Line By Line Chimp Example" href="ChimpLineByLine.html" />
<link rel="prev" title="pygame.transform" href="../ref/transform.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="pygame-tutorials-camera-module-introduction">
<section id="camera-module-introduction">
<h2>Camera Module Introduction<a class="headerlink" href="#camera-module-introduction" title="Permalink to this heading"></a></h2>
<dl class="docinfo field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>by Nirav Patel</p>
</dd>
<dt class="field-even">Contact<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="mailto:nrp&#37;&#52;&#48;eclecti&#46;cc">nrp<span>&#64;</span>eclecti<span>&#46;</span>cc</a></p>
</dd>
</dl>
<p>Pygame 1.9 comes with support for interfacing cameras, allowing you to capture
still images, watch live streams, and do some simple computer vision. This
tutorial will cover all of those use cases, providing code samples you can base
your app or game on. You can refer to the <a class="reference internal" href="../ref/camera.html#module-pygame.camera" title="pygame.camera: pygame module for camera use"><code class="xref py py-mod docutils literal notranslate"><span class="pre">reference</span> <span class="pre">documentation</span></code></a>
for the full API.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>As of Pygame 1.9, the camera module offers native support for cameras
that use v4l2 on Linux. There is support for other platforms via Videocapture
or OpenCV, but this guide will focus on the native module. Most of the code
will be valid for other platforms, but certain things like controls will not
work. The module is also marked as <strong>EXPERIMENTAL</strong>, meaning the API could
change in subsequent versions.</p>
</div>
<section id="import-and-init">
<h3>Import and Init<a class="headerlink" href="#import-and-init" title="Permalink to this heading"></a></h3>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pygame</span>
<span class="kn">import</span> <span class="nn">pygame.camera</span>
<span class="kn">from</span> <span class="nn">pygame.locals</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">camera</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
</pre></div>
</div>
<p>As the camera module is optional, it needs to be imported and initialized
manually as shown above.</p>
</section>
<section id="capturing-a-single-image">
<h3>Capturing a Single Image<a class="headerlink" href="#capturing-a-single-image" title="Permalink to this heading"></a></h3>
<p>Now we will go over the simplest case of opening a camera and capturing a frame
as a surface. In the below example, we assume that there is a camera at
/dev/video0 on the computer, and initialize it with a size of 640 by 480.
The surface called image is whatever the camera was seeing when get_image() was
called.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">cam</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">camera</span><span class="o">.</span><span class="n">Camera</span><span class="p">(</span><span class="s2">&quot;/dev/video0&quot;</span><span class="p">,(</span><span class="mi">640</span><span class="p">,</span><span class="mi">480</span><span class="p">))</span>
<span class="n">cam</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">cam</span><span class="o">.</span><span class="n">get_image</span><span class="p">()</span>
</pre></div>
</div>
<section id="listing-connected-cameras">
<h4>Listing Connected Cameras<a class="headerlink" href="#listing-connected-cameras" title="Permalink to this heading"></a></h4>
<p>You may be wondering, what if we don't know the exact path of the camera?
We can ask the module to provide a list of cameras attached to the
computer and initialize the first camera in the list.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">camlist</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">camera</span><span class="o">.</span><span class="n">list_cameras</span><span class="p">()</span>
<span class="k">if</span> <span class="n">camlist</span><span class="p">:</span>
<span class="n">cam</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">camera</span><span class="o">.</span><span class="n">Camera</span><span class="p">(</span><span class="n">camlist</span><span class="p">[</span><span class="mi">0</span><span class="p">],(</span><span class="mi">640</span><span class="p">,</span><span class="mi">480</span><span class="p">))</span>
</pre></div>
</div>
</section>
<section id="using-camera-controls">
<h4>Using Camera Controls<a class="headerlink" href="#using-camera-controls" title="Permalink to this heading"></a></h4>
<p>Most cameras support controls like flipping the image and changing brightness.
set_controls() and get_controls() can be used at any point after using start().</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">cam</span><span class="o">.</span><span class="n">set_controls</span><span class="p">(</span><span class="n">hflip</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span> <span class="n">vflip</span> <span class="o">=</span> <span class="kc">False</span><span class="p">)</span>
<span class="nb">print</span> <span class="n">camera</span><span class="o">.</span><span class="n">get_controls</span><span class="p">()</span>
</pre></div>
</div>
</section>
</section>
<section id="capturing-a-live-stream">
<h3>Capturing a Live Stream<a class="headerlink" href="#capturing-a-live-stream" title="Permalink to this heading"></a></h3>
<p>The rest of this tutorial will be based around capturing a live stream of
images. For this, we will be using the class below. As described, it will
simply blit a constant stream of camera frames to the screen, effectively
showing live video. It is basically what you would expect, looping get_image(),
blitting to the display surface, and flipping it. For performance reasons,
we will be supplying the camera with the same surface to use each time.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Capture</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="p">(</span><span class="mi">640</span><span class="p">,</span><span class="mi">480</span><span class="p">)</span>
<span class="c1"># create a display surface. standard pygame stuff</span>
<span class="bp">self</span><span class="o">.</span><span class="n">display</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="c1"># this is the same as what we saw before</span>
<span class="bp">self</span><span class="o">.</span><span class="n">clist</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">camera</span><span class="o">.</span><span class="n">list_cameras</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">clist</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Sorry, no cameras detected.&quot;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cam</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">camera</span><span class="o">.</span><span class="n">Camera</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">clist</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cam</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="c1"># create a surface to capture to. for performance purposes</span>
<span class="c1"># bit depth is the same as that of the display surface.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">surface</span><span class="o">.</span><span class="n">Surface</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">get_and_flip</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># if you don&#39;t want to tie the framerate to the camera, you can check</span>
<span class="c1"># if the camera has an image ready. note that while this works</span>
<span class="c1"># on most cameras, some will never return true.</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cam</span><span class="o">.</span><span class="n">query_image</span><span class="p">():</span>
<span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cam</span><span class="o">.</span><span class="n">get_image</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">)</span>
<span class="c1"># blit it to the display surface. simple!</span>
<span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">going</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">while</span> <span class="n">going</span><span class="p">:</span>
<span class="n">events</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
<span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">events</span><span class="p">:</span>
<span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">QUIT</span> <span class="ow">or</span> <span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">KEYDOWN</span> <span class="ow">and</span> <span class="n">e</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_ESCAPE</span><span class="p">):</span>
<span class="c1"># close the camera safely</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cam</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
<span class="n">going</span> <span class="o">=</span> <span class="kc">False</span>
<span class="bp">self</span><span class="o">.</span><span class="n">get_and_flip</span><span class="p">()</span>
</pre></div>
</div>
<p>Since get_image() is a blocking call that could take quite a bit of time on a
slow camera, this example uses query_image() to see if the camera is ready.
This allows you to separate the framerate of your game from that of your camera.
It is also possible to have the camera capturing images in a separate thread,
for approximately the same performance gain, if you find that your camera does
not support the query_image() function correctly.</p>
</section>
<section id="basic-computer-vision">
<h3>Basic Computer Vision<a class="headerlink" href="#basic-computer-vision" title="Permalink to this heading"></a></h3>
<p>By using the camera, transform, and mask modules, pygame can do some basic
computer vision.</p>
<section id="colorspaces">
<h4>Colorspaces<a class="headerlink" href="#colorspaces" title="Permalink to this heading"></a></h4>
<p>When initializing a camera, colorspace is an optional parameter, with 'RGB',
'YUV', and 'HSV' as the possible choices. YUV and HSV are both generally more
useful for computer vision than RGB, and allow you to more easily threshold by
color, something we will look at later in the tutorial.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">cam</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">camera</span><span class="o">.</span><span class="n">Camera</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">clist</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="s2">&quot;RGB&quot;</span><span class="p">)</span>
</pre></div>
</div>
<img alt="../_images/camera_rgb.jpg" class="trailing" src="../_images/camera_rgb.jpg" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">cam</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">camera</span><span class="o">.</span><span class="n">Camera</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">clist</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="s2">&quot;YUV&quot;</span><span class="p">)</span>
</pre></div>
</div>
<img alt="../_images/camera_yuv.jpg" class="trailing" src="../_images/camera_yuv.jpg" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">cam</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">camera</span><span class="o">.</span><span class="n">Camera</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">clist</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="s2">&quot;HSV&quot;</span><span class="p">)</span>
</pre></div>
</div>
<img alt="../_images/camera_hsv.jpg" class="trailing" src="../_images/camera_hsv.jpg" />
</section>
<section id="thresholding">
<h4>Thresholding<a class="headerlink" href="#thresholding" title="Permalink to this heading"></a></h4>
<p>Using the threshold() function from the transform module, one can do simple
green screen like effects, or isolate specifically colored objects in a scene.
In the below example, we threshold out just the green tree and make the rest
of the image black. Check the reference documentation for details on the
<a class="reference internal" href="../ref/transform.html#pygame.transform.threshold" title="pygame.transform.threshold"><code class="xref py py-func docutils literal notranslate"><span class="pre">threshold</span> <span class="pre">function</span></code></a>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">thresholded</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">surface</span><span class="o">.</span><span class="n">Surface</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cam</span><span class="o">.</span><span class="n">get_image</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">)</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">threshold</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">thresholded</span><span class="p">,</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">,(</span><span class="mi">0</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">),(</span><span class="mi">90</span><span class="p">,</span><span class="mi">170</span><span class="p">,</span><span class="mi">170</span><span class="p">),(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
<img alt="../_images/camera_thresholded.jpg" class="trailing" src="../_images/camera_thresholded.jpg" />
<p>Of course, this is only useful if you already know the exact color of the object
you are looking for. To get around this and make thresholding usable in the
real world, we need to add a calibration stage where we identify the color of an
object and use it to threshold against. We will be using the average_color()
function of the transform module to do this. Below is an example calibration
function that you could loop until an event like a key press, and an image of
what it would look like. The color inside the box will be the one that is
used for the threshold. Note that we are using the HSV colorspace in the below
images.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">calibrate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># capture the image</span>
<span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cam</span><span class="o">.</span><span class="n">get_image</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">)</span>
<span class="c1"># blit it to the display surface</span>
<span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="c1"># make a rect in the middle of the screen</span>
<span class="n">crect</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">draw</span><span class="o">.</span><span class="n">rect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="p">,</span> <span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">145</span><span class="p">,</span><span class="mi">105</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">30</span><span class="p">),</span> <span class="mi">4</span><span class="p">)</span>
<span class="c1"># get the average color of the area inside the rect</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ccolor</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">average_color</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">,</span> <span class="n">crect</span><span class="p">)</span>
<span class="c1"># fill the upper left corner with that color</span>
<span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">fill</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ccolor</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">50</span><span class="p">,</span><span class="mi">50</span><span class="p">))</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
</pre></div>
</div>
<img alt="../_images/camera_average.jpg" class="trailing" src="../_images/camera_average.jpg" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pygame</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">threshold</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">thresholded</span><span class="p">,</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">,</span><span class="bp">self</span><span class="o">.</span><span class="n">ccolor</span><span class="p">,(</span><span class="mi">30</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">30</span><span class="p">),(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
<img alt="../_images/camera_thresh.jpg" class="trailing" src="../_images/camera_thresh.jpg" />
<p>You can use the same idea to do a simple green screen/blue screen, by first
getting a background image and then thresholding against it. The below example
just has the camera pointed at a blank white wall in HSV colorspace.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">calibrate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># capture a bunch of background images</span>
<span class="n">bg</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">5</span><span class="p">):</span>
<span class="n">bg</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cam</span><span class="o">.</span><span class="n">get_image</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">background</span><span class="p">))</span>
<span class="c1"># average them down to one to get rid of some noise</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">average_surfaces</span><span class="p">(</span><span class="n">bg</span><span class="p">,</span><span class="bp">self</span><span class="o">.</span><span class="n">background</span><span class="p">)</span>
<span class="c1"># blit it to the display surface</span>
<span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
</pre></div>
</div>
<img alt="../_images/camera_background.jpg" class="trailing" src="../_images/camera_background.jpg" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pygame</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">threshold</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">thresholded</span><span class="p">,</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">,(</span><span class="mi">0</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">),(</span><span class="mi">30</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">30</span><span class="p">),(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span><span class="mi">1</span><span class="p">,</span><span class="bp">self</span><span class="o">.</span><span class="n">background</span><span class="p">)</span>
</pre></div>
</div>
<img alt="../_images/camera_green.jpg" class="trailing" src="../_images/camera_green.jpg" />
</section>
<section id="using-the-mask-module">
<h4>Using the Mask Module<a class="headerlink" href="#using-the-mask-module" title="Permalink to this heading"></a></h4>
<p>The stuff above is great if you just want to display images, but with the
<a class="reference internal" href="../ref/mask.html#module-pygame.mask" title="pygame.mask: pygame module for image masks."><code class="xref py py-mod docutils literal notranslate"><span class="pre">mask</span> <span class="pre">module</span></code></a>, you can also use a camera as an
input device for a game. For example, going back to the example of
thresholding out a specific object, we can find the position of that object and
use it to control an on screen object.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">get_and_flip</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cam</span><span class="o">.</span><span class="n">get_image</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">)</span>
<span class="c1"># threshold against the color we got before</span>
<span class="n">mask</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">mask</span><span class="o">.</span><span class="n">from_threshold</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">ccolor</span><span class="p">,</span> <span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">30</span><span class="p">))</span>
<span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">snapshot</span><span class="p">,(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="c1"># keep only the largest blob of that color</span>
<span class="n">connected</span> <span class="o">=</span> <span class="n">mask</span><span class="o">.</span><span class="n">connected_component</span><span class="p">()</span>
<span class="c1"># make sure the blob is big enough that it isn&#39;t just noise</span>
<span class="k">if</span> <span class="n">mask</span><span class="o">.</span><span class="n">count</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">100</span><span class="p">:</span>
<span class="c1"># find the center of the blob</span>
<span class="n">coord</span> <span class="o">=</span> <span class="n">mask</span><span class="o">.</span><span class="n">centroid</span><span class="p">()</span>
<span class="c1"># draw a circle with size variable on the size of the blob</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">draw</span><span class="o">.</span><span class="n">circle</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span> <span class="n">coord</span><span class="p">,</span> <span class="nb">max</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span><span class="n">mask</span><span class="o">.</span><span class="n">count</span><span class="p">()</span><span class="o">/</span><span class="mi">400</span><span class="p">),</span><span class="mi">5</span><span class="p">))</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
</pre></div>
</div>
<img alt="../_images/camera_mask.jpg" class="trailing" src="../_images/camera_mask.jpg" />
<p>This is just the most basic example. You can track multiple different colored
blobs, find the outlines of objects, have collision detection between real life
and in game objects, get the angle of an object to allow for even finer control,
and more. Have fun!</p>
</section>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/CameraIntro.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="ChimpLineByLine.html" title="Pygame Tutorials - Line By Line Chimp Example"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../ref/transform.html" title="pygame.transform"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Pygame Tutorials - Camera Module Introduction</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,593 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pygame Tutorials - Line By Line Chimp Example &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="pygame/examples/chimp.py" href="chimp.py.html" />
<link rel="prev" title="Pygame Tutorials - Camera Module Introduction" href="CameraIntro.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="pygame-tutorials-line-by-line-chimp-example">
<section id="line-by-line-chimp">
<h2>Line By Line Chimp<a class="headerlink" href="#line-by-line-chimp" title="Permalink to this heading"></a></h2>
<dl class="docinfo field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Pete Shinners</p>
</dd>
<dt class="field-even">Contact<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="mailto:pete&#37;&#52;&#48;shinners&#46;org">pete<span>&#64;</span>shinners<span>&#46;</span>org</a></p>
</dd>
</dl>
<div class="toctree-wrapper compound">
</div>
<section id="introduction">
<h3>Introduction<a class="headerlink" href="#introduction" title="Permalink to this heading"></a></h3>
<p>In the <em>pygame</em> examples there is a simple example named &quot;chimp&quot;.
This example simulates a punchable monkey moving around the screen with
promises of riches and reward. The example itself is very simple, and a
bit thin on error-checking code. This example program demonstrates many of
pygame's abilities, like creating a window, loading images and sounds,
rendering text, and basic event and mouse handling.</p>
<p>The program and images can be found inside the standard source distribution
of pygame. You can run it by running <cite>python -m pygame.examples.chimp</cite> in
your terminal.</p>
<p>This tutorial will go through the code block by block. Explaining how
the code works. There will also be mention of how the code could be improved
and what error checking could help out.</p>
<p>This is an excellent tutorial for people getting their first look at
the <em>pygame</em> code. Once <em>pygame</em> is fully installed, you can find
and run the chimp demo for yourself in the examples directory.</p>
<div class="fullwidth leading trailing docutils container">
<p class="small-heading">(no, this is not a banner ad, it's the screenshot)</p>
<img alt="chimp game banner" src="../_images/chimpshot.gif" />
<p><a class="reference internal" href="chimp.py.html"><span class="doc">Full Source</span></a></p>
</div>
</section>
<section id="import-modules">
<h3>Import Modules<a class="headerlink" href="#import-modules" title="Permalink to this heading"></a></h3>
<p>This is the code that imports all the needed modules into your program.
It also checks for the availability of some of the optional pygame modules.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Import Modules</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">pygame</span> <span class="k">as</span> <span class="nn">pg</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">pg</span><span class="o">.</span><span class="n">font</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Warning, fonts disabled&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">pg</span><span class="o">.</span><span class="n">mixer</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Warning, sound disabled&quot;</span><span class="p">)</span>
<span class="n">main_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="vm">__file__</span><span class="p">))[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">data_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">main_dir</span><span class="p">,</span> <span class="s2">&quot;data&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>First, we import the standard &quot;os&quot; python module. This allow
us to do things like create platform independent file paths.</p>
<p>In the next line, we import the pygame package. In our case, we import
pygame as <code class="docutils literal notranslate"><span class="pre">pg</span></code>, so that all of the functionality of pygame is able to
be referenced from the namespace <code class="docutils literal notranslate"><span class="pre">pg</span></code>.</p>
<p>Some pygame modules are optional, and if they aren't found,
they evaluate to <code class="docutils literal notranslate"><span class="pre">False</span></code>. Because of that, we decide to print
a nice warning message if the <a class="reference internal" href="../ref/font.html#module-pygame.font" title="pygame.font: pygame module for loading and rendering fonts"><code class="xref py py-mod docutils literal notranslate"><span class="pre">font</span></code></a> or
<a class="reference internal" href="../ref/mixer.html#module-pygame.mixer" title="pygame.mixer: pygame module for loading and playing sounds"><code class="xref py py-mod docutils literal notranslate"><span class="pre">mixer</span></code></a> modules in pygame are not available.
(Although they will only be unavailable in very uncommon situations).</p>
<p>Lastly, we prepare two paths for the rest of the code to use.
<code class="docutils literal notranslate"><span class="pre">main_dir</span></code> uses the <cite>os.path</cite> module and the <cite>__file__</cite> variable provided
by Python to locate the game's python file, and extract the folder from
that path. It then prepares the variable <code class="docutils literal notranslate"><span class="pre">data_dir</span></code> to tell the
loading functions exactly where to look.</p>
</section>
<section id="loading-resources">
<h3>Loading Resources<a class="headerlink" href="#loading-resources" title="Permalink to this heading"></a></h3>
<p>Here we have two functions we can use to load images and sounds. We will
look at each function individually in this section.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">load_image</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">colorkey</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="n">fullname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">data_dir</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="n">size</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">get_size</span><span class="p">()</span>
<span class="n">size</span> <span class="o">=</span> <span class="p">(</span><span class="n">size</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">scale</span><span class="p">,</span> <span class="n">size</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="n">scale</span><span class="p">)</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">scale</span><span class="p">(</span><span class="n">image</span><span class="p">,</span> <span class="n">size</span><span class="p">)</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="k">if</span> <span class="n">colorkey</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">if</span> <span class="n">colorkey</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="n">colorkey</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">get_at</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="n">image</span><span class="o">.</span><span class="n">set_colorkey</span><span class="p">(</span><span class="n">colorkey</span><span class="p">,</span> <span class="n">pg</span><span class="o">.</span><span class="n">RLEACCEL</span><span class="p">)</span>
<span class="k">return</span> <span class="n">image</span><span class="p">,</span> <span class="n">image</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
</pre></div>
</div>
<p>This function takes the name of an image to load. It also optionally
takes an argument it can use to set a colorkey for the image, and an argument
to scale the image. A colorkey is used in graphics to represent a color of the
image that is transparent.</p>
<p>The first thing this function does is create a full pathname to the file.
In this example all the resources are in a &quot;data&quot; subdirectory. By using
the <cite>os.path.join</cite> function, a pathname will be created that works for whatever
platform the game is running on.</p>
<p>Next we load the image using the <a class="tooltip reference internal" href="../ref/image.html#pygame.image.load" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.image.load()</span></code><span class="tooltip-content">load new image from a file (or file-like object)</span></a> function.
After the image is loaded, we make an important
call to the <cite>convert()</cite> function. This makes a new copy of a Surface and converts
its color format and depth to match the display. This means blitting the
image to the screen will happen as quickly as possible.</p>
<p>We then scale the image, using the <a class="tooltip reference internal" href="../ref/transform.html#pygame.transform.scale" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.transform.scale()</span></code><span class="tooltip-content">resize to new resolution</span></a> function.
This function takes a Surface and the size it should be scaled to. To scale
by a scalar, we can get the size and scale the x and y by the scalar.</p>
<p>Last, we set the colorkey for the image. If the user supplied an argument
for the colorkey argument we use that value as the colorkey for the image.
This would usually just be a color RGB value, like (255, 255, 255) for
white. You can also pass a value of -1 as the colorkey. In this case the
function will lookup the color at the topleft pixel of the image, and use
that color for the colorkey.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">load_sound</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="k">class</span> <span class="nc">NoneSound</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">play</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">pg</span><span class="o">.</span><span class="n">mixer</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">pg</span><span class="o">.</span><span class="n">mixer</span><span class="o">.</span><span class="n">get_init</span><span class="p">():</span>
<span class="k">return</span> <span class="n">NoneSound</span><span class="p">()</span>
<span class="n">fullname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">data_dir</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="n">sound</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">mixer</span><span class="o">.</span><span class="n">Sound</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="k">return</span> <span class="n">sound</span>
</pre></div>
</div>
<p>Next is the function to load a sound file. The first thing this function
does is check to see if the <a class="tooltip reference internal" href="../ref/mixer.html#module-pygame.mixer" title=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">pygame.mixer</span></code><span class="tooltip-content">pygame module for loading and playing sounds</span></a> module was imported correctly.
If not, it returns a small class instance that has a dummy play method.
This will act enough like a normal Sound object for this game to run without
any extra error checking.</p>
<p>This function is similar to the image loading function, but handles some
different problems. First we create a full path to the sound image, and
load the sound file. Then we simply return the loaded Sound object.</p>
</section>
<section id="game-object-classes">
<h3>Game Object Classes<a class="headerlink" href="#game-object-classes" title="Permalink to this heading"></a></h3>
<p>Here we create two classes to represent the objects in our game. Almost
all the logic for the game goes into these two classes. We will look over
them one at a time here.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Fist</span><span class="p">(</span><span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;moves a clenched fist on the screen, following the mouse&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="c1"># call Sprite initializer</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">load_image</span><span class="p">(</span><span class="s2">&quot;fist.png&quot;</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">fist_offset</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">235</span><span class="p">,</span> <span class="o">-</span><span class="mi">80</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">punching</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;move the fist based on the mouse position&quot;&quot;&quot;</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">mouse</span><span class="o">.</span><span class="n">get_pos</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">topleft</span> <span class="o">=</span> <span class="n">pos</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move_ip</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fist_offset</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">punching</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move_ip</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">25</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">punch</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;returns true if the fist collides with the target&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">punching</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">punching</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">hitbox</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">inflate</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="p">,</span> <span class="o">-</span><span class="mi">5</span><span class="p">)</span>
<span class="k">return</span> <span class="n">hitbox</span><span class="o">.</span><span class="n">colliderect</span><span class="p">(</span><span class="n">target</span><span class="o">.</span><span class="n">rect</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">unpunch</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;called to pull the fist back&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">punching</span> <span class="o">=</span> <span class="kc">False</span>
</pre></div>
</div>
<p>Here we create a class to represent the players fist. It is derived from
the <cite>Sprite</cite> class included in the <a class="tooltip reference internal" href="../ref/sprite.html#module-pygame.sprite" title=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">pygame.sprite</span></code><span class="tooltip-content">pygame module with basic game object classes</span></a> module. The <cite>__init__</cite> function
is called when new instances of this class are created. The first thing
we do is be sure to call the <cite>__init__</cite> function for our base class. This
allows the Sprite's <cite>__init__</cite> function to prepare our object for use as a
sprite. This game uses one of the sprite drawing Group classes. These classes
can draw sprites that have an &quot;image&quot; and &quot;rect&quot; attribute. By simply changing
these two attributes, the renderer will draw the current image at the current
position.</p>
<p>All sprites have an <cite>update()</cite> method. This function is typically called
once per frame. It is where you should put code that moves and updates
the variables for the sprite. The <cite>update()</cite> method for the fist moves the
fist to the location of the mouse pointer. It also offsets the fist position
slightly if the fist is in the &quot;punching&quot; state.</p>
<p>The following two functions <cite>punch()</cite> and <cite>unpunch()</cite> change the punching
state for the fist. The <cite>punch()</cite> method also returns a true value if the fist
is colliding with the given target sprite.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Chimp</span><span class="p">(</span><span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;moves a monkey critter across the screen. it can spin the</span>
<span class="sd"> monkey when it is punched.&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="c1"># call Sprite initializer</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">load_image</span><span class="p">(</span><span class="s2">&quot;chimp.png&quot;</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">get_surface</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">area</span> <span class="o">=</span> <span class="n">screen</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">topleft</span> <span class="o">=</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">90</span>
<span class="bp">self</span><span class="o">.</span><span class="n">move</span> <span class="o">=</span> <span class="mi">18</span>
<span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;walk or spin, depending on the monkeys state&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_spin</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_walk</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">_walk</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;move the monkey across the screen, and turn at the ends&quot;&quot;&quot;</span>
<span class="n">newpos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">move</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">contains</span><span class="p">(</span><span class="n">newpos</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">left</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">left</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">right</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">right</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">move</span> <span class="o">=</span> <span class="o">-</span><span class="bp">self</span><span class="o">.</span><span class="n">move</span>
<span class="n">newpos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">move</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">flip</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="kc">True</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">newpos</span>
<span class="k">def</span> <span class="nf">_spin</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;spin the monkey image&quot;&quot;&quot;</span>
<span class="n">center</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">center</span>
<span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">+</span> <span class="mi">12</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">&gt;=</span> <span class="mi">360</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">=</span> <span class="kc">False</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">original</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">rotate</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">rotate</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span> <span class="o">=</span> <span class="n">rotate</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">original</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">get_rect</span><span class="p">(</span><span class="n">center</span><span class="o">=</span><span class="n">center</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">punched</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;this will cause the monkey to start spinning&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">=</span> <span class="kc">True</span>
<span class="bp">self</span><span class="o">.</span><span class="n">original</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">image</span>
</pre></div>
</div>
<p>The <cite>Chimp</cite> class is doing a little more work than the fist, but nothing
more complex. This class will move the chimp back and forth across the
screen. When the monkey is punched, he will spin around to exciting effect.
This class is also derived from the base <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Sprite" title="pygame.sprite.Sprite"><code class="xref py py-class docutils literal notranslate"><span class="pre">Sprite</span></code></a>
class, and is initialized the same as the fist. While initializing, the class
also sets the attribute &quot;area&quot; to be the size of the display screen.</p>
<p>The <cite>update</cite> function for the chimp simply looks at the current &quot;dizzy&quot;
state, which is true when the monkey is spinning from a punch. It calls either
the <cite>_spin</cite> or <cite>_walk</cite> method. These functions are prefixed with an underscore.
This is just a standard python idiom which suggests these methods should
only be used by the <cite>Chimp</cite> class. We could go so far as to give them a double
underscore, which would tell python to really try to make them private
methods, but we don't need such protection. :)</p>
<p>The <cite>_walk</cite> method creates a new position for the monkey by moving the current
rect by a given offset. If this new position crosses outside the display
area of the screen, it reverses the movement offset. It also mirrors the
image using the <a class="tooltip reference internal" href="../ref/transform.html#pygame.transform.flip" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.transform.flip()</span></code><span class="tooltip-content">flip vertically and horizontally</span></a> function. This is a crude effect
that makes the monkey look like he's turning the direction he is moving.</p>
<p>The <cite>_spin</cite> method is called when the monkey is currently &quot;dizzy&quot;. The dizzy
attribute is used to store the current amount of rotation. When the monkey
has rotated all the way around (360 degrees) it resets the monkey image
back to the original, non-rotated version. Before calling the
<a class="tooltip reference internal" href="../ref/transform.html#pygame.transform.rotate" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.transform.rotate()</span></code><span class="tooltip-content">rotate an image</span></a> function, you'll see the code makes a local
reference to the function simply named &quot;rotate&quot;. There is no need to do that
for this example, it is just done here to keep the following line's length a
little shorter. Note that when calling the <cite>rotate</cite> function, we are always
rotating from the original monkey image. When rotating, there is a slight loss
of quality. Repeatedly rotating the same image and the quality would get worse
each time. Also, when rotating an image, the size of the image will actually
change. This is because the corners of the image will be rotated out, making
the image bigger. We make sure the center of the new image matches the center
of the old image, so it rotates without moving.</p>
<p>The last method is <cite>punched()</cite> which tells the sprite to enter its dizzy
state. This will cause the image to start spinning. It also makes a copy
of the current image named &quot;original&quot;.</p>
</section>
<section id="initialize-everything">
<h3>Initialize Everything<a class="headerlink" href="#initialize-everything" title="Permalink to this heading"></a></h3>
<p>Before we can do much with pygame, we need to make sure its modules
are initialized. In this case we will also open a simple graphics window.
Now we are in the <cite>main()</cite> function of the program, which actually runs everything.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pg</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">1280</span><span class="p">,</span> <span class="mi">480</span><span class="p">),</span> <span class="n">pg</span><span class="o">.</span><span class="n">SCALED</span><span class="p">)</span>
<span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_caption</span><span class="p">(</span><span class="s2">&quot;Monkey Fever&quot;</span><span class="p">)</span>
<span class="n">pg</span><span class="o">.</span><span class="n">mouse</span><span class="o">.</span><span class="n">set_visible</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
</pre></div>
</div>
<p>The first line to initialize <em>pygame</em> takes care of a bit of
work for us. It checks through the imported <em>pygame</em> modules and attempts
to initialize each one of them. It is possible to go back and check if modules
failed to initialize, but we won't bother here. It is also possible to
take a lot more control and initialize each specific module by hand. That
type of control is generally not needed, but is available if you desire.</p>
<p>Next we set up the display graphics mode. Note that the <a class="tooltip reference internal" href="../ref/display.html#module-pygame.display" title=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">pygame.display</span></code><span class="tooltip-content">pygame module to control the display window and screen</span></a>
module is used to control all the display settings. In this case we are
asking for a 1280 by 480 window, with the <code class="docutils literal notranslate"><span class="pre">SCALED</span></code> display flag.
This automatically scales up the window for displays much larger than the
window.</p>
<p>Last we set the window title and turn off the mouse cursor for our
window. Very basic to do, and now we have a small black window ready to
do our bidding. Usually the cursor defaults to visible, so there is no need
to really set the state unless we want to hide it.</p>
</section>
<section id="create-the-background">
<h3>Create The Background<a class="headerlink" href="#create-the-background" title="Permalink to this heading"></a></h3>
<p>Our program is going to have text message in the background. It would
be nice for us to create a single surface to represent the background and
repeatedly use that. The first step is to create the surface.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">background</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">Surface</span><span class="p">(</span><span class="n">screen</span><span class="o">.</span><span class="n">get_size</span><span class="p">())</span>
<span class="n">background</span> <span class="o">=</span> <span class="n">background</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="n">background</span><span class="o">.</span><span class="n">fill</span><span class="p">((</span><span class="mi">170</span><span class="p">,</span> <span class="mi">238</span><span class="p">,</span> <span class="mi">187</span><span class="p">))</span>
</pre></div>
</div>
<p>This creates a new surface for us that is the same size as the display
window. Note the extra call to <cite>convert()</cite> after creating the Surface. The
convert with no arguments will make sure our background is the same format
as the display window, which will give us the fastest results.</p>
<p>We also fill the entire background with a certain green color. The fill()
function usually takes an RGB triplet as arguments, but supports many
input formats. See the <a class="tooltip reference internal" href="../ref/color.html#pygame.Color" title=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">pygame.Color</span></code><span class="tooltip-content">pygame object for color representations</span></a> for all the color formats.</p>
</section>
<section id="put-text-on-the-background-centered">
<h3>Put Text On The Background, Centered<a class="headerlink" href="#put-text-on-the-background-centered" title="Permalink to this heading"></a></h3>
<p>Now that we have a background surface, lets get the text rendered to it. We
only do this if we see the <a class="tooltip reference internal" href="../ref/font.html#module-pygame.font" title=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">pygame.font</span></code><span class="tooltip-content">pygame module for loading and rendering fonts</span></a> module has imported properly.
If not, we just skip this section.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">pg</span><span class="o">.</span><span class="n">font</span><span class="p">:</span>
<span class="n">font</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">font</span><span class="o">.</span><span class="n">Font</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">64</span><span class="p">)</span>
<span class="n">text</span> <span class="o">=</span> <span class="n">font</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s2">&quot;Pummel The Chimp, And Win $$$&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">,</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
<span class="n">textpos</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">get_rect</span><span class="p">(</span><span class="n">centerx</span><span class="o">=</span><span class="n">background</span><span class="o">.</span><span class="n">get_width</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="n">background</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">textpos</span><span class="p">)</span>
</pre></div>
</div>
<p>As you see, there are a couple steps to getting this done. First we
must create the font object and render it into a new surface. We then find
the center of that new surface and blit (paste) it onto the background.</p>
<p>The font is created with the <cite>font</cite> module's <cite>Font()</cite> constructor. Usually
you will pass the name of a TrueType font file to this function, but we
can also pass <cite>None</cite>, which will use a default font. The <cite>Font</cite> constructor
also needs to know the size of font we want to create.</p>
<p>We then render that font into a new surface. The <cite>render</cite> function creates
a new surface that is the appropriate size for our text. In this case
we are also telling render to create antialiased text (for a nice smooth
look) and to use a dark grey color.</p>
<p>Next we need to find the centered position of the text on our display.
We create a &quot;Rect&quot; object from the text dimensions, which allows us to
easily assign it to the screen center.</p>
<p>Finally we blit (blit is like a copy or paste) the text onto the background
image.</p>
</section>
<section id="display-the-background-while-setup-finishes">
<h3>Display The Background While Setup Finishes<a class="headerlink" href="#display-the-background-while-setup-finishes" title="Permalink to this heading"></a></h3>
<p>We still have a black window on the screen. Lets show our background
while we wait for the other resources to load.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
</pre></div>
</div>
<p>This will blit our entire background onto the display window. The
blit is self explanatory, but what about this flip routine?</p>
<p>In pygame, changes to the display surface are not immediately visible.
Normally, a display must be updated in areas that have changed for them
to be visible to the user. In this case the <cite>flip()</cite> function works nicely
because it simply handles the entire window area.</p>
</section>
<section id="prepare-game-object">
<h3>Prepare Game Object<a class="headerlink" href="#prepare-game-object" title="Permalink to this heading"></a></h3>
<p>Here we create all the objects that the game is going to need.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">whiff_sound</span> <span class="o">=</span> <span class="n">load_sound</span><span class="p">(</span><span class="s2">&quot;whiff.wav&quot;</span><span class="p">)</span>
<span class="n">punch_sound</span> <span class="o">=</span> <span class="n">load_sound</span><span class="p">(</span><span class="s2">&quot;punch.wav&quot;</span><span class="p">)</span>
<span class="n">chimp</span> <span class="o">=</span> <span class="n">Chimp</span><span class="p">()</span>
<span class="n">fist</span> <span class="o">=</span> <span class="n">Fist</span><span class="p">()</span>
<span class="n">allsprites</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">RenderPlain</span><span class="p">((</span><span class="n">chimp</span><span class="p">,</span> <span class="n">fist</span><span class="p">))</span>
<span class="n">clock</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">Clock</span><span class="p">()</span>
</pre></div>
</div>
<p>First we load two sound effects using the <cite>load_sound</cite> function we defined
above. Then we create an instance of each of our sprite classes. And lastly
we create a sprite <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group" title="pygame.sprite.Group"><code class="xref py py-class docutils literal notranslate"><span class="pre">Group</span></code></a> which will contain all
our sprites.</p>
<p>We actually use a special sprite group named <a class="reference internal" href="../ref/sprite.html#pygame.sprite.RenderPlain" title="pygame.sprite.RenderPlain"><code class="xref py py-class docutils literal notranslate"><span class="pre">RenderPlain</span></code></a>. This sprite group can draw all the sprites it
contains to the screen. It is called <cite>RenderPlain</cite> because there are actually
more advanced Render groups. But for our game, we just need simple drawing. We
create the group named &quot;allsprites&quot; by passing a list with all the sprites that
should belong in the group. We could later on add or remove sprites from this
group, but in this game we won't need to.</p>
<p>The <cite>clock</cite> object we create will be used to help control our game's framerate.
we will use it in the main loop of our game to make sure it doesn't run too fast.</p>
</section>
<section id="main-loop">
<h3>Main Loop<a class="headerlink" href="#main-loop" title="Permalink to this heading"></a></h3>
<p>Nothing much here, just an infinite loop.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">going</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">while</span> <span class="n">going</span><span class="p">:</span>
<span class="n">clock</span><span class="o">.</span><span class="n">tick</span><span class="p">(</span><span class="mi">60</span><span class="p">)</span>
</pre></div>
</div>
<p>All games run in some sort of loop. The usual order of things is to
check on the state of the computer and user input, move and update the
state of all the objects, and then draw them to the screen. You'll see
that this example is no different.</p>
<p>We also make a call to our <cite>clock</cite> object, which will make sure our game
doesn't run faster than 60 frames per second.</p>
</section>
<section id="handle-all-input-events">
<h3>Handle All Input Events<a class="headerlink" href="#handle-all-input-events" title="Permalink to this heading"></a></h3>
<p>This is an extremely simple case of working the event queue.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pg</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">QUIT</span><span class="p">:</span>
<span class="n">going</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">KEYDOWN</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">K_ESCAPE</span><span class="p">:</span>
<span class="n">going</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">MOUSEBUTTONDOWN</span><span class="p">:</span>
<span class="k">if</span> <span class="n">fist</span><span class="o">.</span><span class="n">punch</span><span class="p">(</span><span class="n">chimp</span><span class="p">):</span>
<span class="n">punch_sound</span><span class="o">.</span><span class="n">play</span><span class="p">()</span> <span class="c1"># punch</span>
<span class="n">chimp</span><span class="o">.</span><span class="n">punched</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">whiff_sound</span><span class="o">.</span><span class="n">play</span><span class="p">()</span> <span class="c1"># miss</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">MOUSEBUTTONUP</span><span class="p">:</span>
<span class="n">fist</span><span class="o">.</span><span class="n">unpunch</span><span class="p">()</span>
</pre></div>
</div>
<p>First we get all the available Events from pygame and loop through each
of them. The first two tests see if the user has quit our game, or pressed
the escape key. In these cases we just set <code class="docutils literal notranslate"><span class="pre">going</span></code> to <code class="docutils literal notranslate"><span class="pre">False</span></code>, allowing
us out of the infinite loop.</p>
<p>Next we just check to see if the mouse button was pressed or released.
If the button was pressed, we ask the fist object if it has collided with
the chimp. We play the appropriate sound effect, and if the monkey was hit,
we tell him to start spinning (by calling his <cite>punched()</cite> method).</p>
</section>
<section id="update-the-sprites">
<h3>Update the Sprites<a class="headerlink" href="#update-the-sprites" title="Permalink to this heading"></a></h3>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">allsprites</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
</pre></div>
</div>
<p>Sprite groups have an <cite>update()</cite> method, which simply calls the update method
for all the sprites it contains. Each of the objects will move around, depending
on which state they are in. This is where the chimp will move one step side
to side, or spin a little farther if he was recently punched.</p>
</section>
<section id="draw-the-entire-scene">
<h3>Draw The Entire Scene<a class="headerlink" href="#draw-the-entire-scene" title="Permalink to this heading"></a></h3>
<p>Now that all the objects are in the right place, time to draw them.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="n">allsprites</span><span class="o">.</span><span class="n">draw</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
</pre></div>
</div>
<p>The first blit call will draw the background onto the entire screen. This
erases everything we saw from the previous frame (slightly inefficient, but
good enough for this game). Next we call the <cite>draw()</cite> method of the sprite
container. Since this sprite container is really an instance of the &quot;RenderPlain&quot;
sprite group, it knows how to draw our sprites. Lastly, we <cite>flip()</cite> the contents
of pygame's software double buffer to the screen. This makes everything we've
drawn visible all at once.</p>
</section>
<section id="game-over">
<h3>Game Over<a class="headerlink" href="#game-over" title="Permalink to this heading"></a></h3>
<p>User has quit, time to clean up.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pg</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
</pre></div>
</div>
<p>Cleaning up the running game in <em>pygame</em> is extremely simple.
Since all variables are automatically destructed, we don't really have to do
anything, but calling <cite>pg.quit()</cite> explicitly cleans up pygame's internals.</p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/ChimpLineByLine.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="chimp.py.html" title="pygame/examples/chimp.py"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="CameraIntro.html" title="Pygame Tutorials - Camera Module Introduction"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Pygame Tutorials - Line By Line Chimp Example</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,310 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pygame Tutorials - Setting Display Modes &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Pygame Tutorials - Import and Initialize" href="ImportInit.html" />
<link rel="prev" title="pygame/examples/chimp.py" href="chimp.py.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="pygame-tutorials-setting-display-modes">
<section id="setting-display-modes">
<h2>Setting Display Modes<a class="headerlink" href="#setting-display-modes" title="Permalink to this heading"></a></h2>
<dl class="docinfo field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Pete Shinners</p>
</dd>
<dt class="field-even">Contact<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="mailto:pete&#37;&#52;&#48;shinners&#46;org">pete<span>&#64;</span>shinners<span>&#46;</span>org</a></p>
</dd>
</dl>
<section id="introduction">
<h3>Introduction<a class="headerlink" href="#introduction" title="Permalink to this heading"></a></h3>
<p>Setting the display mode in <em>pygame</em> creates a visible image surface
on the monitor.
This surface can either cover the full screen, or be windowed
on platforms that support a window manager.
The display surface is nothing more than a standard <em>pygame</em> surface object.
There are special functions needed in the <a class="tooltip reference internal" href="../ref/display.html#module-pygame.display" title=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">pygame.display</span></code><span class="tooltip-content">pygame module to control the display window and screen</span></a>
module to keep the image surface contents updated on the monitor.</p>
<p>Setting the display mode in <em>pygame</em> is an easier task than with most
graphic libraries.
The advantage is if your display mode is not available,
<em>pygame</em> will emulate the display mode that you asked for.
<em>Pygame</em> will select a display resolution and color depth that best matches
the settings you have requested,
then allow you to access the display with the format you have requested.
In reality, since the <a class="tooltip reference internal" href="../ref/display.html#module-pygame.display" title=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">pygame.display</span></code><span class="tooltip-content">pygame module to control the display window and screen</span></a> module is
a binding around the SDL library, SDL is really doing all this work.</p>
<p>There are advantages and disadvantages to setting the display mode in this
manner.
The advantage is that if your game requires a specific display mode,
your game will run on platforms that do not support your requirements.
It also makes life easier when you're getting something started,
it is always easy to go back later and make the mode selection a little more
particular.
The disadvantage is that what you request is not always what you will get.
There is also a performance penalty when the display mode must be emulated.
This tutorial will help you understand the different methods for querying
the platforms display capabilities, and setting the display mode for your game.</p>
</section>
<section id="setting-basics">
<h3>Setting Basics<a class="headerlink" href="#setting-basics" title="Permalink to this heading"></a></h3>
<p>The first thing to learn about is how to actually set the current display mode.
The display mode may be set at any time after the <a class="tooltip reference internal" href="../ref/display.html#module-pygame.display" title=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">pygame.display</span></code><span class="tooltip-content">pygame module to control the display window and screen</span></a>
module has been initialized.
If you have previously set the display mode,
setting it again will change the current mode.
Setting the display mode is handled with the function
<a class="tooltip reference internal" href="../ref/display.html#pygame.display.set_mode" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.set_mode((width,</span> <span class="pre">height),</span> <span class="pre">flags,</span> <span class="pre">depth)</span></code><span class="tooltip-content">Initialize a window or screen for display</span></a>.
The only required argument in this function is a sequence containing
the width and height of the new display mode.
The depth flag is the requested bits per pixel for the surface.
If the given depth is 8, <em>pygame</em> will create a color-mapped surface.
When given a higher bit depth, <em>pygame</em> will use a packed color mode.
Much more information about depths and color modes can be found in the
documentation for the display and surface modules.
The default value for depth is 0.
When given an argument of 0, <em>pygame</em> will select the best bit depth to use,
usually the same as the system's current bit depth.
The flags argument lets you control extra features for the display mode.
Again, more information about this is found in the <em>pygame</em> reference documents.</p>
</section>
<section id="how-to-decide">
<h3>How to Decide<a class="headerlink" href="#how-to-decide" title="Permalink to this heading"></a></h3>
<p>So how do you select a display mode that is going to work best with your
graphic resources and the platform your game is running on?
There are several methods for gathering information about the display device.
All of these methods must be called after the display module has been
initialized, but you likely want to call them before setting the display mode.
First, <a class="tooltip reference internal" href="../ref/display.html#pygame.display.Info" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.Info()</span></code><span class="tooltip-content">Create a video display information object</span></a>
will return a special object type of VidInfo,
which can tell you a lot about the graphics driver capabilities.
The function
<a class="tooltip reference internal" href="../ref/display.html#pygame.display.list_modes" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.list_modes(depth,</span> <span class="pre">flags)</span></code><span class="tooltip-content">Get list of available fullscreen modes</span></a>
can be used to find the supported graphic modes by the system.
<a class="tooltip reference internal" href="../ref/display.html#pygame.display.mode_ok" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.mode_ok((width,</span> <span class="pre">height),</span> <span class="pre">flags,</span> <span class="pre">depth)</span></code><span class="tooltip-content">Pick the best color depth for a display mode</span></a> takes the same arguments as
<a class="reference internal" href="../ref/display.html#pygame.display.set_mode" title="pygame.display.set_mode"><code class="xref py py-func docutils literal notranslate"><span class="pre">set_mode()</span></code></a>,
but returns the closest matching bit depth to the one you request.
Lastly, <a class="tooltip reference internal" href="../ref/display.html#pygame.display.get_driver" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.get_driver()</span></code><span class="tooltip-content">Get the name of the pygame display backend</span></a>
will return the name of the graphics driver selected by <em>pygame</em>.</p>
<p>Just remember the golden rule.
<em>Pygame</em> will work with pretty much any display mode you request.
Some display modes will need to be emulated,
which will slow your game down,
since <em>pygame</em> will need to convert every update you make to the
&quot;real&quot; display mode. The best bet is to always let <em>pygame</em>
choose the best bit depth,
and convert all your graphic resources to that format when they are loaded.
You let <em>pygame</em> choose its bit depth by calling
<a class="reference internal" href="../ref/display.html#pygame.display.set_mode" title="pygame.display.set_mode"><code class="xref py py-func docutils literal notranslate"><span class="pre">set_mode()</span></code></a>
with no depth argument or a depth of 0,
or you can call
<a class="reference internal" href="../ref/display.html#pygame.display.mode_ok" title="pygame.display.mode_ok"><code class="xref py py-func docutils literal notranslate"><span class="pre">mode_ok()</span></code></a>
to find a closest matching bit depth to what you need.</p>
<p>When your display mode is windowed,
you usually must match the same bit depth as the desktop.
When you are fullscreen, some platforms can switch to any bit depth that
best suits your needs.
You can find the depth of the current desktop if you get a VidInfo object
before ever setting your display mode.</p>
<p>After setting the display mode,
you can find out information about its settings by getting a VidInfo object,
or by calling any of the Surface.get* methods on the display surface.</p>
</section>
<section id="functions">
<h3>Functions<a class="headerlink" href="#functions" title="Permalink to this heading"></a></h3>
<p>These are the routines you can use to determine the most appropriate
display mode.
You can find more information about these functions in the display module
documentation.</p>
<blockquote>
<div><p><a class="tooltip reference internal" href="../ref/display.html#pygame.display.mode_ok" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.mode_ok(size,</span> <span class="pre">flags,</span> <span class="pre">depth)</span></code><span class="tooltip-content">Pick the best color depth for a display mode</span></a></p>
<blockquote>
<div><p>This function takes the exact same arguments as pygame.display.set_mode().
It returns the best available bit depth for the mode you have described.
If this returns zero,
then the desired display mode is not available without emulation.</p>
</div></blockquote>
<p><a class="tooltip reference internal" href="../ref/display.html#pygame.display.list_modes" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.list_modes(depth,</span> <span class="pre">flags)</span></code><span class="tooltip-content">Get list of available fullscreen modes</span></a></p>
<blockquote>
<div><p>Returns a list of supported display modes with the requested
depth and flags.
An empty list is returned when there are no modes.
The flags argument defaults to <a class="reference internal" href="../ref/display.html#pygame.display.set_mode" title="pygame.display.set_mode"><code class="xref any py py-func docutils literal notranslate"><span class="pre">FULLSCREEN</span></code></a>.
If you specify your own flags without <a class="reference internal" href="../ref/display.html#pygame.display.set_mode" title="pygame.display.set_mode"><code class="xref any py py-func docutils literal notranslate"><span class="pre">FULLSCREEN</span></code></a>,
you will likely get a return value of -1.
This means that any display size is fine, since the display will be windowed.
Note that the listed modes are sorted largest to smallest.</p>
</div></blockquote>
<p><a class="tooltip reference internal" href="../ref/display.html#pygame.display.Info" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.Info()</span></code><span class="tooltip-content">Create a video display information object</span></a></p>
<blockquote>
<div><p>This function returns an object with many members describing
the display device.
Printing the VidInfo object will quickly show you all the
members and values for this object.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">pygame.display</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">info</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">Info</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">info</span><span class="p">)</span>
<span class="go">&lt;VideoInfo(hw = 0, wm = 1,video_mem = 0</span>
<span class="go"> blit_hw = 0, blit_hw_CC = 0, blit_hw_A = 0,</span>
<span class="go"> blit_sw = 0, blit_sw_CC = 0, blit_sw_A = 0,</span>
<span class="go"> bitsize = 32, bytesize = 4,</span>
<span class="go"> masks = (16711680, 65280, 255, 0),</span>
<span class="go"> shifts = (16, 8, 0, 0),</span>
<span class="go"> losses = (0, 0, 0, 8),</span>
<span class="go"> current_w = 1920, current_h = 1080</span>
<span class="go">&gt;</span>
</pre></div>
</div>
</div></blockquote>
</div></blockquote>
<p>You can test all these flags as simply members of the VidInfo object.</p>
</section>
<section id="examples">
<h3>Examples<a class="headerlink" href="#examples" title="Permalink to this heading"></a></h3>
<p>Here are some examples of different methods to init the graphics display.
They should help you get an idea of how to go about setting your display mode.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="c1"># give me the best depth with a 640 x 480 windowed display</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c1"># give me the biggest 16-bit display available</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">modes</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">list_modes</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">if</span> <span class="ow">not</span> <span class="n">modes</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;16-bit not supported&#39;</span><span class="p">)</span>
<span class="gp">... </span><span class="k">else</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Found Resolution:&#39;</span><span class="p">,</span> <span class="n">modes</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="gp">... </span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">(</span><span class="n">modes</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">FULLSCREEN</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c1"># need an 8-bit surface, nothing else will do</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">if</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">mode_ok</span><span class="p">((</span><span class="mi">800</span><span class="p">,</span> <span class="mi">600</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">8</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Can only work with an 8-bit display, sorry&#39;</span><span class="p">)</span>
<span class="gp">... </span><span class="k">else</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">800</span><span class="p">,</span> <span class="mi">600</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span>
</pre></div>
</div>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/DisplayModes.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="ImportInit.html" title="Pygame Tutorials - Import and Initialize"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="chimp.py.html" title="pygame/examples/chimp.py"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Pygame Tutorials - Setting Display Modes</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,193 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pygame Tutorials - Import and Initialize &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Making Games With Pygame" href="MakeGames.html" />
<link rel="prev" title="Pygame Tutorials - Setting Display Modes" href="DisplayModes.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="pygame-tutorials-import-and-initialize">
<section id="import-and-initialize">
<h2>Import and Initialize<a class="headerlink" href="#import-and-initialize" title="Permalink to this heading"></a></h2>
<dl class="docinfo field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Pete Shinners</p>
</dd>
<dt class="field-even">Contact<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="mailto:pete&#37;&#52;&#48;shinners&#46;org">pete<span>&#64;</span>shinners<span>&#46;</span>org</a></p>
</dd>
</dl>
<p>Getting pygame imported and initialized is a very simple process. It is also
flexible enough to give you control over what is happening. Pygame is a
collection of different modules in a single python package. Some of the
modules are written in C, and some are written in python. Some modules
are also optional, and might not always be present.</p>
<p>This is just a quick introduction on what is going on when you import pygame.
For a clearer explanation definitely see the pygame examples.</p>
<section id="import">
<h3>Import<a class="headerlink" href="#import" title="Permalink to this heading"></a></h3>
<p>First we must import the pygame package. Since pygame version 1.4 this
has been updated to be much easier. Most games will import all of pygame like this.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pygame</span>
<span class="kn">from</span> <span class="nn">pygame.locals</span> <span class="kn">import</span> <span class="o">*</span>
</pre></div>
</div>
<p>The first line here is the only necessary one. It imports all the available pygame
modules into the pygame package. The second line is optional, and puts a limited
set of constants and functions into the global namespace of your script.</p>
<p>An important thing to keep in mind is that several pygame modules are optional.
For example, one of these is the font module. When you &quot;import pygame&quot;, pygame
will check to see if the font module is available. If the font module is available
it will be imported as &quot;pygame.font&quot;. If the module is not available, &quot;pygame.font&quot;
will be set to None. This makes it fairly easy to later on test if the font module is available.</p>
</section>
<section id="init">
<h3>Init<a class="headerlink" href="#init" title="Permalink to this heading"></a></h3>
<p>Before you can do much with pygame, you will need to initialize it. The most common
way to do this is just make one call.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pygame</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
</pre></div>
</div>
<p>This will attempt to initialize all the pygame modules for you. Not all pygame modules
need to be initialized, but this will automatically initialize the ones that do. You can
also easily initialize each pygame module by hand. For example to only initialize the
font module you would just call.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pygame</span><span class="o">.</span><span class="n">font</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
</pre></div>
</div>
<p>Note that if there is an error when you initialize with &quot;pygame.init()&quot;, it will silently fail.
When hand initializing modules like this, any errors will raise an exception. Any
modules that must be initialized also have a &quot;get_init()&quot; function, which will return true
if the module has been initialized.</p>
<p>It is safe to call the init() function for any module more than once.</p>
</section>
<section id="quit">
<h3>Quit<a class="headerlink" href="#quit" title="Permalink to this heading"></a></h3>
<p>Modules that are initialized also usually have a quit() function that will clean up.
There is no need to explicitly call these, as pygame will cleanly quit all the
initialized modules when python finishes.</p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/ImportInit.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="MakeGames.html" title="Making Games With Pygame"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="DisplayModes.html" title="Pygame Tutorials - Setting Display Modes"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Pygame Tutorials - Import and Initialize</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,233 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Making Games With Pygame &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Revision: Pygame fundamentals" href="tom_games2.html" />
<link rel="prev" title="Pygame Tutorials - Import and Initialize" href="ImportInit.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="making-games-with-pygame">
<section id="id1">
<h2>Making Games With Pygame<a class="headerlink" href="#id1" title="Permalink to this heading"></a></h2>
<div class="toctree-wrapper compound">
</div>
<section id="table-of-contents">
<h3>Table of Contents<a class="headerlink" href="#table-of-contents" title="Permalink to this heading"></a></h3>
<p>1. <a class="reference internal" href="#makegames-1"><span class="std std-ref">Introduction</span></a></p>
<blockquote>
<div><p>1.1. <a class="reference internal" href="#makegames-1-1"><span class="std std-ref">A note on coding styles</span></a></p>
</div></blockquote>
<p>2. <a class="reference internal" href="tom_games2.html#makegames-2"><span class="std std-ref">Revision: Pygame fundamentals</span></a></p>
<blockquote>
<div><p>2.1. <a class="reference internal" href="tom_games2.html#makegames-2-1"><span class="std std-ref">The basic pygame game</span></a></p>
<p>2.2. <a class="reference internal" href="tom_games2.html#makegames-2-2"><span class="std std-ref">Basic pygame objects</span></a></p>
<p>2.3. <a class="reference internal" href="tom_games2.html#makegames-2-3"><span class="std std-ref">Blitting</span></a></p>
<p>2.4. <a class="reference internal" href="tom_games2.html#makegames-2-4"><span class="std std-ref">The event loop</span></a></p>
<p>2.5. <a class="reference internal" href="tom_games2.html#makegames-2-5"><span class="std std-ref">Ta-da!</span></a></p>
</div></blockquote>
<p>3. <a class="reference internal" href="tom_games3.html#makegames-3"><span class="std std-ref">Kicking things off</span></a></p>
<blockquote>
<div><p>3.1. <a class="reference internal" href="tom_games3.html#makegames-3-1"><span class="std std-ref">The first lines, and loading modules</span></a></p>
<p>3.2. <a class="reference internal" href="tom_games3.html#makegames-3-2"><span class="std std-ref">Resource handling functions</span></a></p>
</div></blockquote>
<p>4. <a class="reference internal" href="tom_games4.html#makegames-4"><span class="std std-ref">Game object classes</span></a></p>
<blockquote>
<div><p>4.1. <a class="reference internal" href="tom_games4.html#makegames-4-1"><span class="std std-ref">A simple ball class</span></a></p>
<blockquote>
<div><p>4.1.1. <a class="reference internal" href="tom_games4.html#makegames-4-1-1"><span class="std std-ref">Diversion 1: Sprites</span></a></p>
<p>4.1.2. <a class="reference internal" href="tom_games4.html#makegames-4-1-2"><span class="std std-ref">Diversion 2: Vector physics</span></a></p>
</div></blockquote>
</div></blockquote>
<p>5. <a class="reference internal" href="tom_games5.html#makegames-5"><span class="std std-ref">User-controllable objects</span></a></p>
<blockquote>
<div><p>5.1. <a class="reference internal" href="tom_games5.html#makegames-5-1"><span class="std std-ref">A simple bat class</span></a></p>
<blockquote>
<div><p>5.1.1. <a class="reference internal" href="tom_games5.html#makegames-5-1-1"><span class="std std-ref">Diversion 3: Pygame events</span></a></p>
</div></blockquote>
</div></blockquote>
<p>6. <a class="reference internal" href="tom_games6.html#makegames-6"><span class="std std-ref">Putting it all together</span></a></p>
<blockquote>
<div><p>6.1. <a class="reference internal" href="tom_games6.html#makegames-6-1"><span class="std std-ref">Let the ball hit sides</span></a></p>
<p>6.2. <a class="reference internal" href="tom_games6.html#makegames-6-2"><span class="std std-ref">Let the ball hit bats</span></a></p>
<p>6.3. <a class="reference internal" href="tom_games6.html#makegames-6-3"><span class="std std-ref">The Finished product</span></a></p>
</div></blockquote>
</section>
<section id="introduction">
<span id="makegames-1"></span><h3>1. Introduction<a class="headerlink" href="#introduction" title="Permalink to this heading"></a></h3>
<p>First of all, I will assume you have read the <a class="reference internal" href="ChimpLineByLine.html"><span class="doc">Line By Line Chimp</span></a>
tutorial, which introduces the basics of Python and pygame. Give it a read before reading this
tutorial, as I won't bother repeating what that tutorial says (or at least not in as much detail). This tutorial is aimed at those
who understand how to make a ridiculously simple little &quot;game&quot;, and who would like to make a relatively simple game like Pong.
It introduces you to some concepts of game design, some simple mathematics to work out ball physics, and some ways to keep your
game easy to maintain and expand.</p>
<p>All the code in this tutorial works toward implementing <a class="reference external" href="http://tomchance.org.uk/projects/pong">TomPong</a>,
a game I've written. By the end of the tutorial, you should not only have a firmer grasp of pygame, but
you should also understand how TomPong works, and how to make your own version.</p>
<p>Now, for a brief recap of the basics of pygame. A common method of organising the code for a game is to divide it into the following
six sections:</p>
<blockquote>
<div><ul class="simple">
<li><p><strong>Load modules</strong> which are required in the game. Standard stuff, except that you should
remember to import the pygame local names as well as the pygame module itself</p></li>
<li><p><strong>Resource handling classes</strong>; define some classes to handle your most basic resources,
which will be loading images and sounds, as well as connecting and disconnecting to and from networks, loading save game
files, and any other resources you might have.</p></li>
<li><p><strong>Game object classes</strong>; define the classes for your game object. In the pong example,
these will be one for the player's bat (which you can initialise multiple times, one for each player in the game), and one
for the ball (which can again have multiple instances). If you're going to have a nice in-game menu, it's also a good idea to make a
menu class.</p></li>
<li><p><strong>Any other game functions</strong>; define other necessary functions, such as scoreboards, menu
handling, etc. Any code that you could put into the main game logic, but that would make understanding said logic harder, should
be put into its own function. So as plotting a scoreboard isn't game logic, it should be moved into a function.</p></li>
<li><p><strong>Initialise the game</strong>, including the pygame objects themselves, the background, the game
objects (initialising instances of the classes) and any other little bits of code you might want to add in.</p></li>
<li><p><strong>The main loop</strong>, into which you put any input handling (i.e. watching for users hitting
keys/mouse buttons), the code for updating the game objects, and finally for updating the screen.</p></li>
</ul>
</div></blockquote>
<p>Every game you make will have some or all of those sections, possibly with more of your own. For the purposes of this tutorial, I will
write about how TomPong is laid out, and the ideas I write about can be transferred to almost any kind of game you might make. I will
also assume that you want to keep all of the code in a single file, but if you're making a reasonably large game, it's often a good
idea to source certain sections into module files. Putting the game object classes into a file called <code class="docutils literal notranslate"><span class="pre">objects.py</span></code>, for
example, can help you keep game logic separate from game objects. If you have a lot of resource handling code, it can also be handy
to put that into <code class="docutils literal notranslate"><span class="pre">resources.py</span></code>. You can then <code class="code docutils literal notranslate"><span class="pre">from</span> <span class="pre">objects,resources</span> <span class="pre">import</span> <span class="pre">*</span></code> to import all of the
classes and functions.</p>
</section>
<section id="a-note-on-coding-styles">
<span id="makegames-1-1"></span><h3>1.1. A note on coding styles<a class="headerlink" href="#a-note-on-coding-styles" title="Permalink to this heading"></a></h3>
<p>The first thing to remember when approaching any programming project is to decide on a coding style, and stay consistent. Python
solves a lot of the problems because of its strict interpretation of whitespace and indentation, but you can still choose the size
of your indentations, whether you put each module import on a new line, how you comment code, etc. You'll see how I do all of this
in the code examples; you needn't use my style, but whatever style you adopt, use it all the way through the program code. Also try
to document all of your classes, and comment on any bits of code that seem obscure, though don't start commenting the obvious. I've
seen plenty of people do the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">player1</span><span class="o">.</span><span class="n">score</span> <span class="o">+=</span> <span class="n">scoreup</span> <span class="c1"># Add scoreup to player1 score</span>
</pre></div>
</div>
<p>The worst code is poorly laid out, with seemingly random changes in style, and poor documentation. Poor code is not only annoying
for other people, but it also makes it difficult for you to maintain.</p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/MakeGames.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="tom_games2.html" title="Revision: Pygame fundamentals"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="ImportInit.html" title="Pygame Tutorials - Import and Initialize"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Making Games With Pygame</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,653 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pygame Tutorials - Help! How Do I Move An Image? &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Pygame Intro" href="PygameIntro.html" />
<link rel="prev" title="Putting it all together" href="tom_games6.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="pygame-tutorials-help-how-do-i-move-an-image">
<section id="help-how-do-i-move-an-image">
<h2>Help! How Do I Move An Image?<a class="headerlink" href="#help-how-do-i-move-an-image" title="Permalink to this heading"></a></h2>
<dl class="docinfo field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Pete Shinners</p>
</dd>
<dt class="field-even">Contact<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="mailto:pete&#37;&#52;&#48;shinners&#46;org">pete<span>&#64;</span>shinners<span>&#46;</span>org</a></p>
</dd>
</dl>
<p>Many people new to programming and graphics have a hard time figuring
out how to make an image move around the screen. Without understanding
all the concepts, it can be very confusing. You're not the first person
to be stuck here, I'll do my best to take things step by step. We'll even
try to end with methods of keeping your animations efficient.</p>
<p>Note that we won't be teaching you to program with python in this article,
just introduce you to some of the basics with pygame.</p>
<section id="just-pixels-on-the-screen">
<h3>Just Pixels On The Screen<a class="headerlink" href="#just-pixels-on-the-screen" title="Permalink to this heading"></a></h3>
<p>Pygame has a display Surface. This is basically an image that is visible
on the screen, and the image is made up of pixels. The main way you change
these pixels is by calling the blit() function. This copies the pixels
from one image onto another.</p>
<p>This is the first thing to understand. When you blit an image onto the
screen, you are simply changing the color of the pixels on the screen.
Pixels aren't added or moved, we just change the colors of the pixels already
on the screen. These images you blit to the screen are also Surfaces in
pygame, but they are in no way connected to the display Surface. When they
are blitted to the screen they are copied into the display, but you still
have a unique copy of the original.</p>
<p>With this brief description. Perhaps you can already understand what
is needed to &quot;move&quot; an image. We don't actually move anything at all. We
simply blit the image in a new position. But before we draw the image in
the new position, we'll need to &quot;erase&quot; the old one. Otherwise the image
will be visible in two places on the screen. By rapidly erasing the image
and redrawing it in a new place, we achieve the &quot;illusion&quot; of movement.</p>
<p>Through the rest of this tutorial we will break this process down into
simpler steps. Even explaining the best ways to have multiple images moving
around the screen. You probably already have questions. Like, how do we
&quot;erase&quot; the image before drawing it in a new position? Perhaps you're still
totally lost? Well hopefully the rest of this tutorial can straighten things
out for you.</p>
</section>
<section id="let-s-go-back-a-step">
<h3>Let's Go Back A Step<a class="headerlink" href="#let-s-go-back-a-step" title="Permalink to this heading"></a></h3>
<p>Perhaps the concept of pixels and images is still a little foreign to
you? Well good news, for the next few sections we are going to use code that
does everything we want, it just doesn't use pixels. We're going to create
a small python list of 6 numbers, and imagine it represents some fantastic
graphics we could see on the screen. It might actually be surprising how
closely this represents exactly what we'll later be doing with real graphics.</p>
<p>So let's begin by creating our screen list and fill it with a beautiful
landscape of 1s and 2s.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="go">[1, 1, 2, 2, 2, 1]</span>
</pre></div>
</div>
<p>Now we've created our background. It's not going to be very exciting
unless we also draw a player on the screen. We'll create a mighty hero
that looks like the number 8. Let's stick him near the middle of the map
and see what it looks like.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mi">8</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="go">[1, 1, 2, 8, 2, 1]</span>
</pre></div>
</div>
<p>This might have been as far as you've gotten if you jumped right in doing
some graphics programming with pygame. You've got some nice looking stuff
on the screen, but it cannot move anywhere. Perhaps now that our screen
is just a list of numbers, it's easier to see how to move him?</p>
</section>
<section id="making-the-hero-move">
<h3>Making The Hero Move<a class="headerlink" href="#making-the-hero-move" title="Permalink to this heading"></a></h3>
<p>Before we can start moving the character. We need to keep track of some
sort of position for him. In the last section when we drew him, we just picked
an arbitrary position. Let's do it a little more officially this time.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">playerpos</span> <span class="o">=</span> <span class="mi">3</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="p">[</span><span class="n">playerpos</span><span class="p">]</span> <span class="o">=</span> <span class="mi">8</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="go">[1, 1, 2, 8, 2, 1]</span>
</pre></div>
</div>
<p>Now it is pretty easy to move him to a new position. We simply change
the value of playerpos, and draw him on the screen again.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">playerpos</span> <span class="o">=</span> <span class="n">playerpos</span> <span class="o">-</span> <span class="mi">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="p">[</span><span class="n">playerpos</span><span class="p">]</span> <span class="o">=</span> <span class="mi">8</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="go">[1, 1, 8, 8, 2, 1]</span>
</pre></div>
</div>
<p>Whoops. Now we can see two heroes. One in the old position, and one
in his new position. This is exactly the reason we need to &quot;erase&quot; the hero
in his old position before we draw him in the new position. To erase him,
we need to change that value in the list back to what it was before the hero
was there. That means we need to keep track of the values on the screen before
the hero replaced them. There's several way you could do this, but the easiest
is usually to keep a separate copy of the screen background. This means
we need to make some changes to our little game.</p>
</section>
<section id="creating-a-map">
<h3>Creating A Map<a class="headerlink" href="#creating-a-map" title="Permalink to this heading"></a></h3>
<p>What we want to do is create a separate list we will call our background.
We will create the background so it looks like our original screen did,
with 1s and 2s. Then we will copy each item from the background to the screen.
After that we can finally draw our hero back onto the screen.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">background</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="mi">6</span> <span class="c1">#a new blank screen</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">6</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">screen</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">background</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="go">[1, 1, 2, 2, 2, 1]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">playerpos</span> <span class="o">=</span> <span class="mi">3</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="p">[</span><span class="n">playerpos</span><span class="p">]</span> <span class="o">=</span> <span class="mi">8</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="go">[1, 1, 2, 8, 2, 1]</span>
</pre></div>
</div>
<p>It may seem like a lot of extra work. We're no farther off than we were
before the last time we tried to make him move. But this time we have the
extra information we need to move him properly.</p>
</section>
<section id="making-the-hero-move-take-2">
<h3>Making The Hero Move (Take 2)<a class="headerlink" href="#making-the-hero-move-take-2" title="Permalink to this heading"></a></h3>
<p>This time it will be easy to move the hero around. First we will erase
the hero from his old position. We do this by copying the correct value
from the background onto the screen. Then we will draw the character in his
new position on the screen</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="go">[1, 1, 2, 8, 2, 1]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="p">[</span><span class="n">playerpos</span><span class="p">]</span> <span class="o">=</span> <span class="n">background</span><span class="p">[</span><span class="n">playerpos</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">playerpos</span> <span class="o">=</span> <span class="n">playerpos</span> <span class="o">-</span> <span class="mi">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="p">[</span><span class="n">playerpos</span><span class="p">]</span> <span class="o">=</span> <span class="mi">8</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="go">[1, 1, 8, 2, 2, 1]</span>
</pre></div>
</div>
<p>There it is. The hero has moved one space to the left. We can use this
same code to move him to the left again.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="p">[</span><span class="n">playerpos</span><span class="p">]</span> <span class="o">=</span> <span class="n">background</span><span class="p">[</span><span class="n">playerpos</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">playerpos</span> <span class="o">=</span> <span class="n">playerpos</span> <span class="o">-</span> <span class="mi">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="p">[</span><span class="n">playerpos</span><span class="p">]</span> <span class="o">=</span> <span class="mi">8</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="go">[1, 8, 2, 2, 2, 1]</span>
</pre></div>
</div>
<p>Excellent! This isn't exactly what you'd call smooth animation. But with
a couple small changes, we'll make this work directly with graphics on
the screen.</p>
</section>
<section id="definition-blit">
<h3>Definition: &quot;blit&quot;<a class="headerlink" href="#definition-blit" title="Permalink to this heading"></a></h3>
<p>In the next sections we will transform our program from using lists to
using real graphics on the screen. When displaying the graphics we will
use the term <strong>blit</strong> frequently. If you are new to doing graphics
work, you are probably unfamiliar with this common term.</p>
<p>BLIT: Basically, blit means to copy graphics from one image
to another. A more formal definition is to copy an array of data
to a bitmapped array destination. You can think of blit as just
<em>&quot;assigning&quot;</em> pixels. Much like setting values in our screen-list
above, blitting assigns the color of pixels in our image.</p>
<p>Other graphics libraries will use the word <em>bitblt</em>, or just <em>blt</em>,
but they are talking about the same thing. It is basically copying
memory from one place to another. Actually, it is a bit more advanced than
straight copying of memory, since it needs to handle things like pixel
formats, clipping, and scanline pitches. Advanced blitters can also
handle things like transparency and other special effects.</p>
</section>
<section id="going-from-the-list-to-the-screen">
<h3>Going From The List To The Screen<a class="headerlink" href="#going-from-the-list-to-the-screen" title="Permalink to this heading"></a></h3>
<p>To take the code we see in the above to examples and make them work with
pygame is very straightforward. We'll pretend we have loaded some pretty
graphics and named them &quot;terrain1&quot;, &quot;terrain2&quot;, and &quot;hero&quot;. Where before
we assigned numbers to a list, we now blit graphics to the screen. Another
big change, instead of using positions as a single index (0 through 5), we
now need a two dimensional coordinate. We'll pretend each of the graphics
in our game is 10 pixels wide.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">background</span> <span class="o">=</span> <span class="p">[</span><span class="n">terrain1</span><span class="p">,</span> <span class="n">terrain1</span><span class="p">,</span> <span class="n">terrain2</span><span class="p">,</span> <span class="n">terrain2</span><span class="p">,</span> <span class="n">terrain2</span><span class="p">,</span> <span class="n">terrain1</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span> <span class="o">=</span> <span class="n">create_graphics_screen</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">6</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="p">(</span><span class="n">i</span><span class="o">*</span><span class="mi">10</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">playerpos</span> <span class="o">=</span> <span class="mi">3</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">playerimage</span><span class="p">,</span> <span class="p">(</span><span class="n">playerpos</span><span class="o">*</span><span class="mi">10</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
</pre></div>
</div>
<p>Hmm, that code should seem very familiar, and hopefully more importantly;
the code above should make a little sense. Hopefully my illustration of setting
simple values in a list shows the similarity of setting pixels on the screen
(with blit). The only part that's really extra work is converting the player position
into coordinates on the screen. For now we just use a crude <code class="code docutils literal notranslate"><span class="pre">(playerpos*10,</span> <span class="pre">0)</span></code> ,
but we can certainly do better than that. Now let's move the player
image over a space. This code should have no surprises.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">[</span><span class="n">playerpos</span><span class="p">],</span> <span class="p">(</span><span class="n">playerpos</span><span class="o">*</span><span class="mi">10</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">playerpos</span> <span class="o">=</span> <span class="n">playerpos</span> <span class="o">-</span> <span class="mi">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">playerimage</span><span class="p">,</span> <span class="p">(</span><span class="n">playerpos</span><span class="o">*</span><span class="mi">10</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
</pre></div>
</div>
<p>There you have it. With this code we've shown how to display a simple background
with a hero's image on it. Then we've properly moved that hero one space
to the left. So where do we go from here? Well for one the code is still
a little awkward. First thing we'll want to do is find a cleaner way to represent
the background and player position. Then perhaps a bit of smoother, real
animation.</p>
</section>
<section id="screen-coordinates">
<h3>Screen Coordinates<a class="headerlink" href="#screen-coordinates" title="Permalink to this heading"></a></h3>
<p>To position an object on the screen, we need to tell the blit() function
where to put the image. In pygame we always pass positions as an (X,Y) coordinate.
This represents the number of pixels to the right, and the number of pixels
down to place the image. The top-left corner of a Surface is coordinate (0,
0). Moving to the right a little would be (10, 0), and then moving down just
as much would be (10, 10). When blitting, the position argument represents
where the topleft corner of the source should be placed on the destination.</p>
<p>Pygame comes with a convenient container for these coordinates, it is a
Rect. The Rect basically represents a rectangular area in these coordinates.
It has topleft corner and a size. The Rect comes with a lot of convenient
methods which help you move and position them. In our next examples we will
represent the positions of our objects with the Rects.</p>
<p>Also know that many functions in pygame expect Rect arguments. All of these
functions can also accept a simple tuple of 4 elements (left, top, width,
height). You aren't always required to use these Rect objects, but you will
mainly want to. Also, the blit() function can accept a Rect as its position
argument, it simply uses the topleft corner of the Rect as the real position.</p>
</section>
<section id="changing-the-background">
<h3>Changing The Background<a class="headerlink" href="#changing-the-background" title="Permalink to this heading"></a></h3>
<p>In all our previous sections, we've been storing the background as a list
of different types of ground. That is a good way to create a tile-based game,
but we want smooth scrolling. To make that a little easier, we're going to
change the background into a single image that covers the whole screen. This
way, when we want to &quot;erase&quot; our objects (before redrawing them) we only need
to blit the section of the erased background onto the screen.</p>
<p>By passing an optional third Rect argument to blit, we tell blit to only
use that subsection of the source image. You'll see that in use below as we
erase the player image.</p>
<p>Also note, now when we finish drawing to the screen, we call pygame.display.update()
which will show everything we've drawn onto the screen.</p>
</section>
<section id="smooth-movement">
<h3>Smooth Movement<a class="headerlink" href="#smooth-movement" title="Permalink to this heading"></a></h3>
<p>To make something appear to move smoothly, we only want to move it a couple
pixels at a time. Here is the code to make an object move smoothly across
the screen. Based on what we already now know, this should look pretty simple.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span> <span class="o">=</span> <span class="n">create_screen</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">clock</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">Clock</span><span class="p">()</span> <span class="c1">#get a pygame clock object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">player</span> <span class="o">=</span> <span class="n">load_player_image</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">background</span> <span class="o">=</span> <span class="n">load_background_image</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="c1">#draw the background</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">position</span> <span class="o">=</span> <span class="n">player</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">player</span><span class="p">,</span> <span class="n">position</span><span class="p">)</span> <span class="c1">#draw the player</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">update</span><span class="p">()</span> <span class="c1">#and show it all</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span> <span class="c1">#animate 100 frames</span>
<span class="gp">... </span> <span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">position</span><span class="p">)</span> <span class="c1">#erase</span>
<span class="gp">... </span> <span class="n">position</span> <span class="o">=</span> <span class="n">position</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="c1">#move player</span>
<span class="gp">... </span> <span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">player</span><span class="p">,</span> <span class="n">position</span><span class="p">)</span> <span class="c1">#draw new player</span>
<span class="gp">... </span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">update</span><span class="p">()</span> <span class="c1">#and show it all</span>
<span class="gp">... </span> <span class="n">clock</span><span class="o">.</span><span class="n">tick</span><span class="p">(</span><span class="mi">60</span><span class="p">)</span> <span class="c1">#update 60 times per second</span>
</pre></div>
</div>
<p>There you have it. This is all the code that is needed to smoothly animate
an object across the screen. We can even use a pretty background character.
Another benefit of doing the background this way, the image for the player
can have transparency or cutout sections and it will still draw correctly
over the background (a free bonus).</p>
<p>We also throw in a call to pygame.time.Clock() to grab the clock element.
With it, we can call clock.tick() to set the framerate in frames per second.
This slows down our program a little, otherwise it might run so fast you might
not see it.</p>
</section>
<section id="so-what-next">
<h3>So, What Next?<a class="headerlink" href="#so-what-next" title="Permalink to this heading"></a></h3>
<p>Well there we have it. Hopefully this article has done everything it promised
to do. But, at this point the code really isn't ready for the next best-selling
game. How do we easily have multiple moving objects? What exactly are those
mysterious functions like load_player_image()? We also need a way to get simple
user input, and loop for more than 100 frames. We'll take the example we
have here, and turn it into an object oriented creation that would make momma
proud.</p>
</section>
<section id="first-the-mystery-functions">
<h3>First, The Mystery Functions<a class="headerlink" href="#first-the-mystery-functions" title="Permalink to this heading"></a></h3>
<p>Full information on these types of functions can be found in other tutorials
and reference. The pygame.image module has a load() function which will do
what we want. The lines to load the images should become this.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">player</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;player.bmp&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">background</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;liquid.bmp&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
</pre></div>
</div>
<p>We can see that's pretty simple, the load function just takes a filename
and returns a new Surface with the loaded image. After loading we make a call
to the Surface method, convert(). Convert returns us a new Surface of the
image, but now converted to the same pixel format as our display. Since the
images will be the same format at the screen, they will blit very quickly.
If we did not convert, the blit() function is slower, since it has to convert
from one type of pixel to another as it goes.</p>
<p>You may also have noticed that both the load() and convert() return new
Surfaces. This means we're really creating two Surfaces on each of these
lines. In other programming languages, this results in a memory leak (not
a good thing). Fortunately Python is smart enough to handle this, and pygame
will properly clean up the Surface we end up not using.</p>
<p>The other mystery function we saw in the above example was create_screen().
In pygame it is simple to create a new window for graphics. The code to create
a 640x480 surface is below. By passing no other arguments, pygame will just
pick the best color depth and pixel format for us.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">))</span>
</pre></div>
</div>
</section>
<section id="handling-some-input">
<h3>Handling Some Input<a class="headerlink" href="#handling-some-input" title="Permalink to this heading"></a></h3>
<p>We desperately need to change the main loop to look for any user input, (like
when the user closes the window). We need to add &quot;event handling&quot; to our
program. All graphical programs use this Event Based design. The program
gets events like &quot;keyboard pressed&quot; or &quot;mouse moved&quot; from the computer. Then
the program responds to the different events. Here's what the code should
look like. Instead of looping for 100 frames, we'll keep looping until the
user asks us to stop.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pygame</span><span class="o">.</span><span class="n">QUIT</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">move_and_draw_all_game_objects</span><span class="p">()</span>
</pre></div>
</div>
<p>What this code simply does is, first loop forever, then check if there are
any events from the user. We exit the program if the user presses the close
button on the window. After we've checked all the events we move and draw
our game objects. (We'll also erase them before they move, too)</p>
</section>
<section id="moving-multiple-images">
<h3>Moving Multiple Images<a class="headerlink" href="#moving-multiple-images" title="Permalink to this heading"></a></h3>
<p>Here's the part where we're really going to change things around. Let's
say we want 10 different images moving around on the screen. A good way to
handle this is to use python's classes. We'll create a class that represents
our game object. This object will have a function to move itself, and then
we can create as many as we like. The functions to draw and move the object
need to work in a way where they only move one frame (or one step) at a time.
Here's the python code to create our class.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">GameObject</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">image</span><span class="p">,</span> <span class="n">height</span><span class="p">,</span> <span class="n">speed</span><span class="p">):</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">speed</span> <span class="o">=</span> <span class="n">speed</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">image</span> <span class="o">=</span> <span class="n">image</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">height</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">move</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">speed</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">right</span> <span class="o">&gt;</span> <span class="mi">600</span><span class="p">:</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">left</span> <span class="o">=</span> <span class="mi">0</span>
</pre></div>
</div>
<p>So we have two functions in our class. The init function constructs our object.
It positions the object and sets its speed. The move method moves the object
one step. If it's gone too far, it moves the object back to the left.</p>
</section>
<section id="putting-it-all-together">
<h3>Putting It All Together<a class="headerlink" href="#putting-it-all-together" title="Permalink to this heading"></a></h3>
<p>Now with our new object class, we can put together the entire game. Here
is what the main function for our program will look like.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">clock</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">Clock</span><span class="p">()</span> <span class="c1">#get a pygame clock object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">player</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;player.bmp&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">background</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;background.bmp&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">objects</span> <span class="o">=</span> <span class="p">[]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span> <span class="c1">#create 10 objects&lt;/i&gt;</span>
<span class="gp">... </span> <span class="n">o</span> <span class="o">=</span> <span class="n">GameObject</span><span class="p">(</span><span class="n">player</span><span class="p">,</span> <span class="n">x</span><span class="o">*</span><span class="mi">40</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">objects</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">o</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pygame</span><span class="o">.</span><span class="n">QUIT</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">o</span> <span class="ow">in</span> <span class="n">objects</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">pos</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">pos</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">o</span> <span class="ow">in</span> <span class="n">objects</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">o</span><span class="o">.</span><span class="n">move</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">o</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">pos</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">clock</span><span class="o">.</span><span class="n">tick</span><span class="p">(</span><span class="mi">60</span><span class="p">)</span>
</pre></div>
</div>
<p>And there it is. This is the code we need to animate 10 objects on the screen.
The only point that might need explaining is the two loops we use to clear
all the objects and draw all the objects. In order to do things properly,
we need to erase all the objects before drawing any of them. In our sample
here it may not matter, but when objects are overlapping, using two loops
like this becomes important.</p>
</section>
<section id="preparing-for-improved-user-input">
<h3>Preparing for Improved User Input<a class="headerlink" href="#preparing-for-improved-user-input" title="Permalink to this heading"></a></h3>
<p>With all keyboard input terminating the program, that's not very interactive.
Let's add some extra user input!</p>
<p>First we should create a unique character that the player will control. We
can do that in much the same way we created the other movable entities. Let's
call the player object p. We can already move any object, but, a player should
have more input than simply moving right. To accommodate this, let's revamp
our move function under our GameObject class.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">move</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">up</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">down</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">left</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">right</span><span class="p">:</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">right</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">speed</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">left</span><span class="p">:</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">right</span> <span class="o">-=</span> <span class="bp">self</span><span class="o">.</span><span class="n">speed</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">down</span><span class="p">:</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">top</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">speed</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">up</span><span class="p">:</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">top</span> <span class="o">-=</span> <span class="bp">self</span><span class="o">.</span><span class="n">speed</span>
<span class="gp">... </span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">WIDTH</span><span class="p">:</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">left</span> <span class="o">=</span> <span class="mi">0</span>
<span class="gp">... </span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">top</span> <span class="o">&gt;</span> <span class="n">HEIGHT</span><span class="o">-</span><span class="n">SPRITE_HEIGHT</span><span class="p">:</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">top</span> <span class="o">=</span> <span class="mi">0</span>
<span class="gp">... </span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">right</span> <span class="o">&lt;</span> <span class="n">SPRITE_WIDTH</span><span class="p">:</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">right</span> <span class="o">=</span> <span class="n">WIDTH</span>
<span class="gp">... </span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">top</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">pos</span><span class="o">.</span><span class="n">top</span> <span class="o">=</span> <span class="n">HEIGHT</span><span class="o">-</span><span class="n">SPRITE_HEIGHT</span>
</pre></div>
</div>
<p>There's certainly a lot more going on here, so let's take it one step at a time.
First, we've added some default values into the move function, declared as up,
down, left, and right. These booleans will allow us to specifically select a
direction that the object is moving in. The first part, where we go through and
check True for each variable, is where we will add to the position of the object,
much like before. Right controls horizontal, and top controls vertical positions.</p>
<p>Additionally, we've removed the magic number present previously, and replaced it
with the constants WIDTH, HEIGHT, SPRITE_WIDTH, and SPRITE_HEIGHT. These values
represent the screen width and height, along with the width and height of the object
displayed on the screen.</p>
<p>The second part, where the position is being checked, ensures that the position
is within the confines of our screen. With this in place, we need to make sure that
when one of our other objects calls move, we set right to true.</p>
</section>
<section id="adding-the-user-input">
<h3>Adding the User Input<a class="headerlink" href="#adding-the-user-input" title="Permalink to this heading"></a></h3>
<p>We've already seen that pygame has event handling, and we know that KEYDOWN is
an event in this loop. We could, under KEYDOWN, assert the key press matches an
arrow key, where we would then call move. However, this movement will only occur
once every time a key is pressed, and it therefore will be extremely choppy and
unpleasant.</p>
<p>For this, we can use pygame.key.get_pressed(), which returns a list of all keys,
and whether or not they are currently pressed. Since we want these key presses
to be maintained whether an event is currently happening or not, we should put
it outside of the main event handling loop, but still within our game loop.
Our functionality will look like this.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">keys</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">get_pressed</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">if</span> <span class="n">keys</span><span class="p">[</span><span class="n">pygame</span><span class="o">.</span><span class="n">K_UP</span><span class="p">]:</span>
<span class="gp">... </span> <span class="n">p</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">up</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">if</span> <span class="n">keys</span><span class="p">[</span><span class="n">pygame</span><span class="o">.</span><span class="n">K_DOWN</span><span class="p">]:</span>
<span class="gp">... </span> <span class="n">p</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">down</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">if</span> <span class="n">keys</span><span class="p">[</span><span class="n">pygame</span><span class="o">.</span><span class="n">K_LEFT</span><span class="p">]:</span>
<span class="gp">... </span> <span class="n">p</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">left</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">if</span> <span class="n">keys</span><span class="p">[</span><span class="n">pygame</span><span class="o">.</span><span class="n">K_RIGHT</span><span class="p">]:</span>
<span class="gp">... </span> <span class="n">p</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">right</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</div>
<p>We simply get our list of keys pressed, called keys. We can then check the index
at the key code position to see if it is held down. For more key codes, I recommend
checking out the documentation on pygame.key.</p>
<p>When up is held, we move our object, p, up. When down is held, we move down. Rinse and
repeat for all cases, and we're good to go!</p>
</section>
<section id="putting-it-all-together-one-more-time">
<h3>Putting it all Together One More time<a class="headerlink" href="#putting-it-all-together-one-more-time" title="Permalink to this heading"></a></h3>
<p>Now that we're finished with the player functionality, let's take one last look to make
sure we understand everything.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">clock</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">Clock</span><span class="p">()</span> <span class="c1">#get a pygame clock object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">player</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;player.bmp&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">entity</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;alien1.bmp&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">background</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;background.bmp&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">objects</span> <span class="o">=</span> <span class="p">[]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">GameObject</span><span class="p">(</span><span class="n">player</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="c1">#create the player object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span> <span class="c1">#create 10 objects&lt;/i&gt;</span>
<span class="gp">... </span> <span class="n">o</span> <span class="o">=</span> <span class="n">GameObject</span><span class="p">(</span><span class="n">entity</span><span class="p">,</span> <span class="n">x</span><span class="o">*</span><span class="mi">40</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">objects</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">o</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">pos</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">pos</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">o</span> <span class="ow">in</span> <span class="n">objects</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">pos</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">pos</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">keys</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">get_pressed</span><span class="p">()</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">keys</span><span class="p">[</span><span class="n">pygame</span><span class="o">.</span><span class="n">K_UP</span><span class="p">]:</span>
<span class="gp">... </span> <span class="n">p</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">up</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">keys</span><span class="p">[</span><span class="n">pygame</span><span class="o">.</span><span class="n">K_DOWN</span><span class="p">]:</span>
<span class="gp">... </span> <span class="n">p</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">down</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">keys</span><span class="p">[</span><span class="n">pygame</span><span class="o">.</span><span class="n">K_LEFT</span><span class="p">]:</span>
<span class="gp">... </span> <span class="n">p</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">left</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">keys</span><span class="p">[</span><span class="n">pygame</span><span class="o">.</span><span class="n">K_RIGHT</span><span class="p">]:</span>
<span class="gp">... </span> <span class="n">p</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">right</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pygame</span><span class="o">.</span><span class="n">QUIT</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">pos</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">o</span> <span class="ow">in</span> <span class="n">objects</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">o</span><span class="o">.</span><span class="n">move</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">o</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">pos</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">clock</span><span class="o">.</span><span class="n">tick</span><span class="p">(</span><span class="mi">60</span><span class="p">)</span>
</pre></div>
</div>
<p>A few things not mentioned earlier: we load in a second image and call it entity,
and we use that for all objects that aren't the player, which uses the player
image defined earlier.</p>
<p>And that's all there is to it! Now we have a fully functional player object that
is controlled using the arrow keys!</p>
</section>
<section id="you-are-on-your-own-from-here">
<h3>You Are On Your Own From Here<a class="headerlink" href="#you-are-on-your-own-from-here" title="Permalink to this heading"></a></h3>
<p>So what would be next on your road to learning? Well first playing around
with this example a bit. The full running version of this example is available
in the pygame examples directory. It is the example named
<a class="reference internal" href="../ref/examples.html#pygame.examples.moveit.main" title="pygame.examples.moveit.main"><code class="xref py py-func docutils literal notranslate"><span class="pre">moveit.py</span></code></a> .
Take a look at the code and play with it, run it, learn it.</p>
<p>Things you may want to work on is maybe having more than one type of object.
Finding a way to cleanly &quot;delete&quot; objects when you don't want to show them
any more. Also updating the display.update() call to pass a list of the areas
on-screen that have changed.</p>
<p>There are also other tutorials and examples in pygame that cover these
issues. So when you're ready to keep learning, keep on reading. :-)</p>
<p>Lastly, you can feel free to come to the pygame mailing list or chatroom
with any questions on this stuff. There's always folks on hand who can help
you out with this sort of business.</p>
<p>Lastly, have fun, that's what games are for!</p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/MoveIt.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="PygameIntro.html" title="Pygame Intro"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="tom_games6.html" title="Putting it all together"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Pygame Tutorials - Help! How Do I Move An Image?</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,419 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pygame Intro &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Pygame Tutorials - Sprite Module Introduction" href="SpriteIntro.html" />
<link rel="prev" title="Pygame Tutorials - Help! How Do I Move An Image?" href="MoveIt.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="pygame-intro">
<section id="python-pygame-introduction">
<h2>Python Pygame Introduction<a class="headerlink" href="#python-pygame-introduction" title="Permalink to this heading"></a></h2>
<dl class="docinfo field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Pete Shinners</p>
</dd>
<dt class="field-even">Contact<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="mailto:pete&#37;&#52;&#48;shinners&#46;org">pete<span>&#64;</span>shinners<span>&#46;</span>org</a></p>
</dd>
</dl>
<p>This article is an introduction to the <a class="reference external" href="http://www.pygame.org">pygame library</a>
for <a class="reference external" href="https://www.python.org/">Python programmers</a>.
The original version appeared in the <a class="reference external" href="https://web.archive.org/web/20030810011958/http://store.pyzine.com:80/article.phtml?a=2">PyZine volume 1 issue 3</a>.
This version contains minor revisions, to
create an all-around better article. Pygame is a Python extension
library that wraps the <a class="reference external" href="http://www.libsdl.org">SDL</a> library
and its helpers.</p>
<section id="history">
<h3>HISTORY<a class="headerlink" href="#history" title="Permalink to this heading"></a></h3>
<p>Pygame started in the summer of 2000. Being a C programmer of many
years, I discovered both Python and SDL at about the same time. You are
already familiar with Python, which was at version 1.5.2. You may need
an introduction to SDL, which is the Simple DirectMedia Layer.
Created by Sam Lantinga, SDL is a cross-platform C library for
controlling multimedia, comparable to DirectX. It has been used for
hundreds of commercial and open source games. I was impressed at how clean
and straightforward both projects were and it wasn't long before I
realized mixing Python and SDL was an interesting proposal.</p>
<p>I discovered a small project already under-way with exactly the same
idea, PySDL. Created by Mark Baker, PySDL was a straightforward
implementation of SDL as a Python extension. The interface was cleaner
than a generic SWIG wrapping, but I felt it forced a &quot;C style&quot; of code.
The sudden death of PySDL prompted me to take on a new project of my
own.</p>
<p>I wanted to put together a project that really took advantage of
Python. My goal was to make it easy to do the simple things, and
straightforward to do the difficult things. Pygame was started in
October, 2000. Six months later pygame version 1.0 was released.</p>
</section>
<section id="taste">
<h3>TASTE<a class="headerlink" href="#taste" title="Permalink to this heading"></a></h3>
<p>I find the best way to understand a new library is to jump straight
into an example. In the early days of pygame, I created a bouncing ball
animation with 7 lines of code. Let's take a look at a friendlier
version of that same thing. This should be simple enough to follow
along, and a complete breakdown follows.</p>
<img alt="../_images/intro_ball.gif" class="inlined-right" src="../_images/intro_ball.gif" />
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">pygame</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="n">size</span> <span class="o">=</span> <span class="n">width</span><span class="p">,</span> <span class="n">height</span> <span class="o">=</span> <span class="mi">320</span><span class="p">,</span> <span class="mi">240</span>
<span class="n">speed</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="n">black</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">(</span><span class="n">size</span><span class="p">)</span>
<span class="n">ball</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s2">&quot;intro_ball.gif&quot;</span><span class="p">)</span>
<span class="n">ballrect</span> <span class="o">=</span> <span class="n">ball</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pygame</span><span class="o">.</span><span class="n">QUIT</span><span class="p">:</span> <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
<span class="n">ballrect</span> <span class="o">=</span> <span class="n">ballrect</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">speed</span><span class="p">)</span>
<span class="k">if</span> <span class="n">ballrect</span><span class="o">.</span><span class="n">left</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">ballrect</span><span class="o">.</span><span class="n">right</span> <span class="o">&gt;</span> <span class="n">width</span><span class="p">:</span>
<span class="n">speed</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">speed</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="n">ballrect</span><span class="o">.</span><span class="n">top</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">ballrect</span><span class="o">.</span><span class="n">bottom</span> <span class="o">&gt;</span> <span class="n">height</span><span class="p">:</span>
<span class="n">speed</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">speed</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">screen</span><span class="o">.</span><span class="n">fill</span><span class="p">(</span><span class="n">black</span><span class="p">)</span>
<span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">ball</span><span class="p">,</span> <span class="n">ballrect</span><span class="p">)</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
</pre></div>
</div>
<p>This is as simple as you can get for a bouncing animation.
First we see importing and initializing pygame is nothing noteworthy.
The <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">pygame</span></code> imports the package with all the available
pygame modules.
The call to <code class="docutils literal notranslate"><span class="pre">pygame.init()</span></code> initializes each of these modules.
Make sure the gif file of the bouncing ball is in the same folder
as the code block.
On <span class="codelineref">line 4</span> we set the size of the display window, for best
results yo can change these numbers to match your own monitor's
resolution.
On <span class="codelineref">line 8</span> we create a
graphical window with the call to <code class="docutils literal notranslate"><span class="pre">pygame.display.set_mode()</span></code>.
Pygame and SDL make this easy by defaulting to the best graphics modes
for the graphics hardware. You can override the mode and SDL will
compensate for anything the hardware cannot do. Pygame represents
images as <em>Surface</em> objects.
The <code class="docutils literal notranslate"><span class="pre">display.set_mode()</span></code> function creates a new <em>Surface</em>
object that represents the actual displayed graphics. Any drawing you
do to this Surface will become visible on the monitor.</p>
<p>At <span class="codelineref">line 10</span> we load
our ball image. Pygame supports a variety of image formats through the
SDL_image library, including BMP, JPG, PNG, TGA, and GIF.
The <code class="docutils literal notranslate"><span class="pre">pygame.image.load()</span></code> function
returns us a Surface with the ball data. The Surface will keep any
colorkey or alpha transparency from the file. After loading the ball
image we create a variable named ballrect. Pygame comes with a
convenient utility object type named <a class="reference internal" href="../ref/rect.html#pygame.Rect" title="pygame.Rect"><code class="xref py py-class docutils literal notranslate"><span class="pre">Rect</span></code></a>,
which represents a rectangular area. Later, in the animation part of
the code, we will see what the <em>Rect</em> objects can do.</p>
<p>At this point, <span class="codelineref">line 13</span>,
our program is initialized and ready to run. Inside an infinite loop we
check for user input, move the ball, and then draw the ball. If you are
familiar with GUI programming, you have had experience with events and
event loops. In pygame this is no different,
we check if a <em>QUIT</em> event has happened. If so we
simply exit the program, pygame will ensure everything is cleanly
shutdown.</p>
<p>It is time to update our position for the ball.
<span class="codelineref">Lines 17</span> moves the ballrect variable by the current speed.
<span class="codelineref">Lines 18 thru 21</span> reverse the speed if the ball has moved outside the screen.
Not exactly Newtonian physics, but it is all we need.</p>
<p>On <span class="codelineref">line 23</span> we erase
the screen by filling it with a black RGB color. If you have never
worked with animations this may seem strange. You may be asking &quot;Why do
we need to erase anything, why don't we just move the ball on the
screen?&quot; That is not quite the way computer animation works. Animation
is nothing more than a series of single images, which when displayed in
sequence do a very good job of fooling the human eye into seeing
motion. The screen is just a single image that the user sees. If we did
not take the time to erase the ball from the screen, we would actually
see a &quot;trail&quot; of the ball as we continuously draw the ball in its new
positions.</p>
<p>On <span class="codelineref">line 24</span> we draw the ball image onto the screen.
Drawing of images is handled by the
<a class="reference internal" href="../ref/surface.html#pygame.Surface.blit" title="pygame.Surface.blit"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Surface.blit()</span></code></a> method.
A blit basically means copying pixel colors from one image to another.
We pass the blit method a source <a class="reference internal" href="../ref/surface.html#pygame.Surface" title="pygame.Surface"><code class="xref py py-class docutils literal notranslate"><span class="pre">Surface</span></code></a>
to copy from, and a position to place the source onto the destination.</p>
<p>The last thing we need to do is actually update the visible display.
Pygame manages the display with a double buffer. When we are finished
drawing we call the <a class="tooltip reference internal" href="../ref/display.html#pygame.display.flip" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.flip()</span></code><span class="tooltip-content">Update the full display Surface to the screen</span></a> method.
This makes everything we have drawn on the screen Surface
become visible. This buffering makes sure we only see completely drawn
frames on the screen. Without it, the user would see the half completed
parts of the screen as they are being created.</p>
<p>That concludes this short introduction to pygame. Pygame also has
modules to do things like input handling for the keyboard, mouse, and
joystick. It can mix audio and decode streaming music.
With the <em>Surfaces</em> you can draw simple
shapes, rotate and scale the picture, and even manipulate the pixels of
an image in realtime as numpy arrays.
Pygame also has the ability to act as a
cross platform display layer for PyOpenGL. Most of the pygame modules
are written in C, few are actually done in Python.</p>
<p>The pygame website has full reference documentation for every pygame
function and tutorials for all ranges of users. The pygame source comes
with many examples of things like monkey punching and UFO shooting.</p>
</section>
<section id="python-and-gaming">
<h3>PYTHON AND GAMING<a class="headerlink" href="#python-and-gaming" title="Permalink to this heading"></a></h3>
<p>&quot;Is Python suitable for gaming?&quot; The answer is, &quot;It depends on the
game.&quot;</p>
<p>Python is actually quite capable at running games. It will likely even
surprise you how much is possible in under 30 milliseconds. Still, it
is not hard to reach the ceiling once your game begins to get more
complex. Any game running in realtime will be making full use of the
computer.</p>
<img alt="../_images/intro_blade.jpg" class="inlined-right" src="../_images/intro_blade.jpg" />
<p>Over the past several years there has been an interesting trend in game development,
the move towards higher level languages. Usually a game is split into
two major parts. The game engine, which must be as fast as possible,
and the game logic, which makes the engine actually do something. It
wasn't long ago when the engine of a game was written in assembly, with
portions written in C. Nowadays, C has moved to the game engine, while
often the game itself is written in higher level scripting languages.
Games like Quake3 and Unreal run these scripts as portable bytecode.</p>
<p>In early 2001, developer Rebel Act Studios finished their game,
Severance: Blade of Darkness. Using their own custom 3D engine, the
rest of the game is written with Python. The game is a bloody action
3rd person perspective fighter. You control medieval warriors into
intricate decapitating combination attacks while exploring dungeons and
castles. You can download third party add-ons for this game, and find
they are nothing more than Python source files.</p>
<p>More recently, Python has been used in a variety of games like Freedom
Force, and Humungous' Backyard Sports Series.</p>
<img alt="../_images/intro_freedom.jpg" class="inlined-right" src="../_images/intro_freedom.jpg" />
<p>Pygame and SDL serve as an excellent C engine for 2D games.
Games will still find the largest part of their runtime is spent
inside SDL handling the graphics.
SDL can take advantage of graphics hardware acceleration.
Enabling this can change a game from running around 40 frames per
second to over 200 frames per second. When you see your Python game
running at 200 frames per second, you realize that Python and games can
work together.</p>
<p>It is impressive how well both Python and SDL work on multiple
platforms. For example, in May of 2001 I released my own full pygame
project, SolarWolf, an arcade style action game. One thing that has
surprised me is that one year later there has been no need for any
patches, bug fixes, or updates. The game was developed entirely on
windows, but runs on Linux, Mac OSX, and many Unixes without any extra
work on my end.</p>
<p>Still, there are very clear limitations. The best way to manage
hardware accelerated graphics is not always the way to get fastest
results from software rendering. Hardware support is not available on
all platforms. When a game gets more complex, it often must commit to
one or the other. SDL has some other design limitations, things like
full screen scrolling graphics can quickly bring your game down to
unplayable speeds. While SDL is not suitable for all types of games,
remember companies like Loki have used SDL to run a wide variety of
retail quality titles.</p>
<p>Pygame is fairly low-level when it comes to writing games. You'll
quickly find yourself needing to wrap common functions into your own
game environment. The great thing about this is there is nothing inside
pygame to get in your way. Your program is in full control of
everything. The side effect of that is you will find yourself borrowing
a lot of code to get a more advanced framework put together. You'll
need a better understanding of what you are doing.</p>
</section>
<section id="closing">
<h3>CLOSING<a class="headerlink" href="#closing" title="Permalink to this heading"></a></h3>
<p>Developing games is very rewarding, there is something exciting about
being able to see and interact with the code you've written. Pygame
currently has almost 30 other projects using it. Several of them are
ready to play now. You may be surprised to visit the pygame website,
and see what other users have been able to do with Python.</p>
<p>One thing that has caught my attention is the amount of people coming
to Python for the first time to try game development. I can see why
games are a draw for new programmers, but it can be difficult since
creating games requires a firmer understanding of the language. I've
tried to support this group of users by writing many examples and
pygame tutorials for people new to these concepts.</p>
<p>In the end, my advice is to keep it simple. I cannot stress this
enough. If you are planning to create your first game, there is a
lot to learn. Even a simpler game will challenge your designs, and
complex games don't necessarily mean fun games. When you understand
Python, you can use pygame to create a simple game in only one or two
weeks. From there you'll need a surprising amount of time to add
the polish to make that into a full presentable game.</p>
<section id="pygame-modules-overview">
<h4>Pygame Modules Overview<a class="headerlink" href="#pygame-modules-overview" title="Permalink to this heading"></a></h4>
<table class="more-to-explore docutils align-default">
<colgroup>
<col style="width: 28.6%" />
<col style="width: 71.4%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><a class="reference internal" href="../ref/cdrom.html#module-pygame.cdrom" title="pygame.cdrom: pygame module for audio cdrom control"><code class="xref py py-mod docutils literal notranslate"><span class="pre">cdrom</span></code></a></p></td>
<td><p>playback</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../ref/cursors.html#module-pygame.cursors" title="pygame.cursors: pygame module for cursor resources"><code class="xref py py-mod docutils literal notranslate"><span class="pre">cursors</span></code></a></p></td>
<td><p>load cursor images, includes standard cursors</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../ref/display.html#module-pygame.display" title="pygame.display: pygame module to control the display window and screen"><code class="xref py py-mod docutils literal notranslate"><span class="pre">display</span></code></a></p></td>
<td><p>control the display window or screen</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../ref/draw.html#module-pygame.draw" title="pygame.draw: pygame module for drawing shapes"><code class="xref py py-mod docutils literal notranslate"><span class="pre">draw</span></code></a></p></td>
<td><p>draw simple shapes onto a Surface</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../ref/event.html#module-pygame.event" title="pygame.event: pygame module for interacting with events and queues"><code class="xref py py-mod docutils literal notranslate"><span class="pre">event</span></code></a></p></td>
<td><p>manage events and the event queue</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../ref/font.html#module-pygame.font" title="pygame.font: pygame module for loading and rendering fonts"><code class="xref py py-mod docutils literal notranslate"><span class="pre">font</span></code></a></p></td>
<td><p>create and render TrueType fonts</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../ref/image.html#module-pygame.image" title="pygame.image: pygame module for loading and saving images"><code class="xref py py-mod docutils literal notranslate"><span class="pre">image</span></code></a></p></td>
<td><p>save and load images</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../ref/joystick.html#module-pygame.joystick" title="pygame.joystick: Pygame module for interacting with joysticks, gamepads, and trackballs."><code class="xref py py-mod docutils literal notranslate"><span class="pre">joystick</span></code></a></p></td>
<td><p>manage joystick devices</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../ref/key.html#module-pygame.key" title="pygame.key: pygame module to work with the keyboard"><code class="xref py py-mod docutils literal notranslate"><span class="pre">key</span></code></a></p></td>
<td><p>manage the keyboard</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../ref/mouse.html#module-pygame.mouse" title="pygame.mouse: pygame module to work with the mouse"><code class="xref py py-mod docutils literal notranslate"><span class="pre">mouse</span></code></a></p></td>
<td><p>manage the mouse</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../ref/sndarray.html#module-pygame.sndarray" title="pygame.sndarray: pygame module for accessing sound sample data"><code class="xref py py-mod docutils literal notranslate"><span class="pre">sndarray</span></code></a></p></td>
<td><p>manipulate sounds with numpy</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../ref/surfarray.html#module-pygame.surfarray" title="pygame.surfarray: pygame module for accessing surface pixel data using array interfaces"><code class="xref py py-mod docutils literal notranslate"><span class="pre">surfarray</span></code></a></p></td>
<td><p>manipulate images with numpy</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../ref/time.html#module-pygame.time" title="pygame.time: pygame module for monitoring time"><code class="xref py py-mod docutils literal notranslate"><span class="pre">time</span></code></a></p></td>
<td><p>control timing</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../ref/transform.html#module-pygame.transform" title="pygame.transform: pygame module to transform surfaces"><code class="xref py py-mod docutils literal notranslate"><span class="pre">transform</span></code></a></p></td>
<td><p>scale, rotate, and flip images</p></td>
</tr>
</tbody>
</table>
</section>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/PygameIntro.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="SpriteIntro.html" title="Pygame Tutorials - Sprite Module Introduction"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="MoveIt.html" title="Pygame Tutorials - Help! How Do I Move An Image?"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Pygame Intro</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,494 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pygame Tutorials - Sprite Module Introduction &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Pygame Tutorials - Surfarray Introduction" href="SurfarrayIntro.html" />
<link rel="prev" title="Pygame Intro" href="PygameIntro.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="pygame-tutorials-sprite-module-introduction">
<section id="sprite-module-introduction">
<h2>Sprite Module Introduction<a class="headerlink" href="#sprite-module-introduction" title="Permalink to this heading"></a></h2>
<dl class="docinfo field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Pete Shinners</p>
</dd>
<dt class="field-even">Contact<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="mailto:pete&#37;&#52;&#48;shinners&#46;org">pete<span>&#64;</span>shinners<span>&#46;</span>org</a></p>
</dd>
</dl>
<p>Pygame version 1.3 comes with a new module, <code class="docutils literal notranslate"><span class="pre">pygame.sprite</span></code>. This module is
written in Python and includes some higher-level classes to manage your game
objects. By using this module to its full potential, you can easily manage and
draw your game objects. The sprite classes are very optimized, so it's likely
your game will run faster with the sprite module than without.</p>
<p>The sprite module is also meant to be very generic. It turns out you can use it
with nearly any type of gameplay. All this flexibility comes with a slight
penalty, it needs a little understanding to properly use it. The
<a class="reference internal" href="../ref/sprite.html#module-pygame.sprite" title="pygame.sprite: pygame module with basic game object classes"><code class="xref py py-mod docutils literal notranslate"><span class="pre">reference</span> <span class="pre">documentation</span></code></a> for the sprite module can keep
you running, but you'll probably need a bit more explanation of how to use
<code class="docutils literal notranslate"><span class="pre">pygame.sprite</span></code> in your own game.</p>
<p>Several of the pygame examples (like &quot;chimp&quot; and &quot;aliens&quot;) have been updated to
use the sprite module. You may want to look into those first to see what this
sprite module is all about. The chimp module even has its own line-by-line
tutorial, which may help get more an understanding of programming with python
and pygame.</p>
<p>Note that this introduction will assume you have a bit of experience
programming with python, and are somewhat familiar with the different parts of
creating a simple game. In this tutorial the word &quot;reference&quot; is occasionally
used. This represents a python variable. Variables in python are references,
so you can have several variables all pointing to the same object.</p>
<section id="history-lesson">
<h3>History Lesson<a class="headerlink" href="#history-lesson" title="Permalink to this heading"></a></h3>
<p>The term &quot;sprite&quot; is a holdover from older computer and game machines. These
older boxes were unable to draw and erase normal graphics fast enough for them
to work as games. These machines had special hardware to handle game like
objects that needed to animate very quickly. These objects were called
&quot;sprites&quot; and had special limitations, but could be drawn and updated very
fast. They usually existed in special overlay buffers in the video. These days
computers have become generally fast enough to handle sprite like objects
without dedicated hardware. The term sprite is still used to represent just
about anything in a 2D game that is animated.</p>
</section>
<section id="the-classes">
<h3>The Classes<a class="headerlink" href="#the-classes" title="Permalink to this heading"></a></h3>
<p>The sprite module comes with two main classes. The first is <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Sprite" title="pygame.sprite.Sprite"><code class="xref py py-class docutils literal notranslate"><span class="pre">Sprite</span></code></a>, which should be used as a base class for all your game
objects. This class doesn't really do anything on its own, it just includes
several functions to help manage the game object. The other type of class is
<a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group" title="pygame.sprite.Group"><code class="xref py py-class docutils literal notranslate"><span class="pre">Group</span></code></a>. The <code class="docutils literal notranslate"><span class="pre">Group</span></code> class is a container for
different <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> objects. There are actually several different types of
group classes. Some of the <code class="docutils literal notranslate"><span class="pre">Groups</span></code> can draw all the elements they contain,
for example.</p>
<p>This is all there really is to it. We'll start with a description of what each
type of class does, and then discuss the proper ways to use these two classes.</p>
</section>
<section id="the-sprite-class">
<h3>The Sprite Class<a class="headerlink" href="#the-sprite-class" title="Permalink to this heading"></a></h3>
<p>As mentioned before, the Sprite class is designed to be a base class for all
your game objects. You cannot really use it on its own, as it only has several
methods to help it work with the different <code class="docutils literal notranslate"><span class="pre">Group</span></code> classes. The sprite keeps
track of which groups it belongs to.
The class constructor (<code class="docutils literal notranslate"><span class="pre">__init__</span></code> method) takes an argument of a
<code class="docutils literal notranslate"><span class="pre">Group</span></code> (or list of <code class="docutils literal notranslate"><span class="pre">Groups</span></code>) the <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> instance should belong to.
You can also change the <code class="docutils literal notranslate"><span class="pre">Group</span></code> membership for the <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> with the
<a class="reference internal" href="../ref/sprite.html#pygame.sprite.Sprite.add" title="pygame.sprite.Sprite.add"><code class="xref py py-meth docutils literal notranslate"><span class="pre">add()</span></code></a> and
<a class="reference internal" href="../ref/sprite.html#pygame.sprite.Sprite.remove" title="pygame.sprite.Sprite.remove"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remove()</span></code></a> methods.
There is also a <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Sprite.groups" title="pygame.sprite.Sprite.groups"><code class="xref py py-meth docutils literal notranslate"><span class="pre">groups()</span></code></a> method,
which returns a list of the current groups containing the sprite.</p>
<p>When using the your Sprite classes it's best to think of them as &quot;valid&quot; or
&quot;alive&quot; when they are belonging to one or more <code class="docutils literal notranslate"><span class="pre">Groups</span></code>. When you remove the
instance from all groups pygame will clean up the object. (Unless you have your
own references to the instance somewhere else.) The <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Sprite.kill" title="pygame.sprite.Sprite.kill"><code class="xref py py-meth docutils literal notranslate"><span class="pre">kill()</span></code></a> method removes the sprite from all groups it
belongs to. This will cleanly delete the sprite object. If you've put some
little games together, you'll know sometimes cleanly deleting a game object can
be tricky. The sprite also comes with an <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Sprite.alive" title="pygame.sprite.Sprite.alive"><code class="xref py py-meth docutils literal notranslate"><span class="pre">alive()</span></code></a> method, which returns true if it is still a
member of any groups.</p>
</section>
<section id="the-group-class">
<h3>The Group Class<a class="headerlink" href="#the-group-class" title="Permalink to this heading"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">Group</span></code> class is just a simple container. Similar to the sprite, it has
an <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group.add" title="pygame.sprite.Group.add"><code class="xref py py-meth docutils literal notranslate"><span class="pre">add()</span></code></a> and <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group.remove" title="pygame.sprite.Group.remove"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remove()</span></code></a> method which can change which sprites belong to
the group. You also can pass a sprite or list of sprites to the constructor
(<code class="docutils literal notranslate"><span class="pre">__init__()</span></code> method) to create a <code class="docutils literal notranslate"><span class="pre">Group</span></code> instance that contains some
initial sprites.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">Group</span></code> has a few other methods like <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group.empty" title="pygame.sprite.Group.empty"><code class="xref py py-meth docutils literal notranslate"><span class="pre">empty()</span></code></a> to remove all sprites from the group and
<a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group.copy" title="pygame.sprite.Group.copy"><code class="xref py py-meth docutils literal notranslate"><span class="pre">copy()</span></code></a> which will return a copy of the group
with all the same members. Also the <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group.has" title="pygame.sprite.Group.has"><code class="xref py py-meth docutils literal notranslate"><span class="pre">has()</span></code></a>
method will quickly check if the <code class="docutils literal notranslate"><span class="pre">Group</span></code> contains a sprite or list of
sprites.</p>
<p>The other function you will use frequently is the <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group.sprites" title="pygame.sprite.Group.sprites"><code class="xref py py-meth docutils literal notranslate"><span class="pre">sprites()</span></code></a> method. This returns an object that can be
looped on to access every sprite the group contains. Currently this is just a
list of the sprites, but in later version of python this will likely use
iterators for better performance.</p>
<p>As a shortcut, the <code class="docutils literal notranslate"><span class="pre">Group</span></code> also has an <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group.update" title="pygame.sprite.Group.update"><code class="xref py py-meth docutils literal notranslate"><span class="pre">update()</span></code></a> method, which will call an <code class="docutils literal notranslate"><span class="pre">update()</span></code> method on
every sprite in the group. Passing the same arguments to each one. Usually in a
game you need some function that updates the state of a game object. It's very
easy to call your own methods using the <code class="docutils literal notranslate"><span class="pre">Group.sprites()</span></code> method, but this is
a shortcut that's used enough to be included. Also note that the base
<code class="docutils literal notranslate"><span class="pre">Sprite</span></code> class has a &quot;dummy&quot; <code class="docutils literal notranslate"><span class="pre">update()</span></code> method that takes any sort of
arguments and does nothing.</p>
<p>Lastly, the Group has a couple other methods that allow you to use it with
the builtin <code class="docutils literal notranslate"><span class="pre">len()</span></code> function, getting the number of sprites it contains, and
the &quot;truth&quot; operator, which allows you to do &quot;if mygroup:&quot; to check if the
group has any sprites.</p>
</section>
<section id="mixing-them-together">
<h3>Mixing Them Together<a class="headerlink" href="#mixing-them-together" title="Permalink to this heading"></a></h3>
<p>At this point the two classes seem pretty basic. Not doing a lot more than you
can do with a simple list and your own class of game objects. But there are
some big advantages to using the <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> and <code class="docutils literal notranslate"><span class="pre">Group</span></code> together. A sprite
can belong to as many groups as you want. Remember as soon as it belongs to no
groups, it will usually be cleared up (unless you have other &quot;non-group&quot;
references to that object).</p>
<p>The first big thing is a fast simple way to categorize sprites. For example,
say we had a Pacman-like game. We could make separate groups for the different
types of objects in the game. Ghosts, Pac, and Pellets. When Pac eats a power
pellet, we can change the state for all ghost objects by effecting everything
in the Ghost group. This is quicker and simpler than looping through a list
of all the game objects and checking which ones are ghosts.</p>
<p>Adding and removing groups and sprites from each other is a very fast
operation, quicker than using lists to store everything. Therefore you can very
efficiently change group memberships. Groups can be used to work like simple
attributes for each game object. Instead of tracking some attribute like
&quot;close_to_player&quot; for a bunch of enemy objects, you could add them to a
separate group. Then when you need to access all the enemies that are near the
player, you already have a list of them, instead of going through a list of all
the enemies, checking for the &quot;close_to_player&quot; flag. Later on your game could
add multiple players, and instead of adding more &quot;close_to_player2&quot;,
&quot;close_to_player3&quot; attributes, you can easily add them to different groups for
each player.</p>
<p>Another important benefit of using the <code class="docutils literal notranslate"><span class="pre">Sprites</span></code> and <code class="docutils literal notranslate"><span class="pre">Groups</span></code> is that the groups
cleanly handle the deleting (or killing) of game objects. In a game where many
objects are referencing other objects, sometimes deleting an object can be the
hardest part, since it can't go away until it is not referenced by anyone. Say
we have an object that is &quot;chasing&quot; another object. The chaser can keep a
simple Group that references the object (or objects) it is chasing. If the
object being chased happens to be destroyed, we don't need to worry about
notifying the chaser to stop chasing. The chaser can see for itself that its
group is now empty, and perhaps find a new target.</p>
<p>Again, the thing to remember is that adding and removing sprites from groups is
a very cheap/fast operation. You may be best off by adding many groups to
contain and organize your game objects. Some could even be empty for large
portions of the game, there isn't any penalties for managing your game like
this.</p>
</section>
<section id="the-many-group-types">
<h3>The Many Group Types<a class="headerlink" href="#the-many-group-types" title="Permalink to this heading"></a></h3>
<p>The above examples and reasons to use <code class="docutils literal notranslate"><span class="pre">Sprites</span></code> and <code class="docutils literal notranslate"><span class="pre">Groups</span></code> are only a tip
of the iceberg. Another advantage is that the sprite module comes with several
different types of <code class="docutils literal notranslate"><span class="pre">Groups</span></code>. These groups all work just like a regular old
<code class="docutils literal notranslate"><span class="pre">Group</span></code>, but they also have added functionality (or slightly different
functionality). Here's a list of the <code class="docutils literal notranslate"><span class="pre">Group</span></code> classes included with the
sprite module.</p>
<blockquote>
<div><p><a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group" title="pygame.sprite.Group"><code class="xref py py-class docutils literal notranslate"><span class="pre">Group</span></code></a></p>
<blockquote>
<div><p>This is the standard &quot;no frills&quot; group mainly explained above. Most of the
other <code class="docutils literal notranslate"><span class="pre">Groups</span></code> are derived from this one, but not all.</p>
</div></blockquote>
<p><a class="reference internal" href="../ref/sprite.html#pygame.sprite.GroupSingle" title="pygame.sprite.GroupSingle"><code class="xref py py-class docutils literal notranslate"><span class="pre">GroupSingle</span></code></a></p>
<blockquote>
<div><p>This works exactly like the regular <code class="docutils literal notranslate"><span class="pre">Group</span></code> class, but it only contains
the most recently added sprite. Therefore when you add a sprite to this group,
it &quot;forgets&quot; about any previous sprites it had. Therefore it always contains
only one or zero sprites.</p>
</div></blockquote>
<p><a class="reference internal" href="../ref/sprite.html#pygame.sprite.RenderPlain" title="pygame.sprite.RenderPlain"><code class="xref py py-class docutils literal notranslate"><span class="pre">RenderPlain</span></code></a></p>
<blockquote>
<div><p>This is a standard group derived from <code class="docutils literal notranslate"><span class="pre">Group</span></code>. It has a draw() method
that draws all the sprites it contains to the screen (or any <code class="docutils literal notranslate"><span class="pre">Surface</span></code>). For
this to work, it requires all sprites it contains to have a &quot;image&quot; and &quot;rect&quot;
attributes. It uses these to know what to blit, and where to blit it.</p>
</div></blockquote>
<p><a class="reference internal" href="../ref/sprite.html#pygame.sprite.RenderClear" title="pygame.sprite.RenderClear"><code class="xref py py-class docutils literal notranslate"><span class="pre">RenderClear</span></code></a></p>
<blockquote>
<div><p>This is derived from the <code class="docutils literal notranslate"><span class="pre">RenderPlain</span></code> group, and adds a method named
<code class="docutils literal notranslate"><span class="pre">clear()</span></code>. This will erase the previous position of all drawn sprites. It
uses a background image to fill in the areas where the sprite were. It is smart
enough to handle deleted sprites and properly clear them from the screen when
the <code class="docutils literal notranslate"><span class="pre">clear()</span></code> method is called.</p>
</div></blockquote>
<p><a class="reference internal" href="../ref/sprite.html#pygame.sprite.RenderUpdates" title="pygame.sprite.RenderUpdates"><code class="xref py py-class docutils literal notranslate"><span class="pre">RenderUpdates</span></code></a></p>
<blockquote>
<div><p>This is the Cadillac of rendering <code class="docutils literal notranslate"><span class="pre">Groups</span></code>. It is inherited from
<code class="docutils literal notranslate"><span class="pre">RenderClear</span></code>, but changes the <code class="docutils literal notranslate"><span class="pre">draw()</span></code> method to also return a list of
pygame <code class="docutils literal notranslate"><span class="pre">Rects</span></code>, which represent all the areas on screen that have been
changed.</p>
</div></blockquote>
</div></blockquote>
<p>That is the list of different groups available We'll discuss more about these
rendering groups in the next section. There's nothing stopping you from
creating your own Group classes as well. They are just python code, so you can
inherit from one of these and add/change whatever you want. In the future I
hope we can add a couple more <code class="docutils literal notranslate"><span class="pre">Groups</span></code> to this list. A <code class="docutils literal notranslate"><span class="pre">GroupMulti</span></code> which
is like the <code class="docutils literal notranslate"><span class="pre">GroupSingle</span></code>, but can hold up to a given number of sprites (in
some sort of circular buffer?). Also a super-render group that can clear the
position of the old sprites without needing a background image to do it (by
grabbing a copy of the screen before blitting). Who knows really, but in the
future we can add more useful classes to this list.</p>
</section>
<section id="the-rendering-groups">
<h3>The Rendering Groups<a class="headerlink" href="#the-rendering-groups" title="Permalink to this heading"></a></h3>
<p>From above we can see there are three different rendering groups. We could
probably just get away with the <code class="docutils literal notranslate"><span class="pre">RenderUpdates</span></code> one, but it adds overhead not
really needed for something like a scrolling game. So we have a couple tools
here, pick the right one for the right job.</p>
<p>For a scrolling type game, where the background completely changes every frame,
we obviously don't need to worry about python's update rectangles in the call
to <code class="docutils literal notranslate"><span class="pre">display.update()</span></code>. You should definitely go with the <code class="docutils literal notranslate"><span class="pre">RenderPlain</span></code>
group here to manage your rendering.</p>
<p>For games where the background is more stationary, you definitely don't want
pygame updating the entire screen (since it doesn't need to). This type of game
usually involves erasing the old position of each object, then drawing it in a
new place for each frame. This way we are only changing what is necessary.
Most of the time you will just want to use the <code class="docutils literal notranslate"><span class="pre">RenderUpdates</span></code> class here.
Since you will also want to pass this list of changes to the
<code class="docutils literal notranslate"><span class="pre">display.update()</span></code> function.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">RenderUpdates</span></code> class also does a good job at minimizing overlapping
areas in the list of updated rectangles. If the previous position and current
position of an object overlap, it will merge them into a single rectangle.
Combined with the fact that it properly handles deleted objects, this is
one powerful <code class="docutils literal notranslate"><span class="pre">Group</span></code> class. If you've written a game that manages the changed
rectangles for the objects in a game, you know this the cause for a lot of
messy code in your game. Especially once you start to throw in objects that can
be deleted at any time. All this work is reduced to a <code class="docutils literal notranslate"><span class="pre">clear()</span></code> and
<code class="docutils literal notranslate"><span class="pre">draw()</span></code> method with this monster class. Plus with the overlap checking, it
is likely faster than when you did it manually.</p>
<p>Also note that there's nothing stopping you from mixing and matching these
render groups in your game. You should definitely use multiple rendering groups
when you want to do layering with your sprites. Also if the screen is split
into multiple sections, perhaps each section of the screen should use an
appropriate render group?</p>
</section>
<section id="collision-detection">
<h3>Collision Detection<a class="headerlink" href="#collision-detection" title="Permalink to this heading"></a></h3>
<p>The sprite module also comes with two very generic collision detection
functions. For more complex games, these really won't work for you, but you
can easily grab the source code for them, and modify them as needed.</p>
<p>Here's a summary of what they are, and what they do.</p>
<blockquote>
<div><p><a class="reference internal" href="../ref/sprite.html#pygame.sprite.spritecollide" title="pygame.sprite.spritecollide"><code class="xref py py-func docutils literal notranslate"><span class="pre">spritecollide(sprite,</span> <span class="pre">group,</span> <span class="pre">dokill)</span> <span class="pre">-&gt;</span> <span class="pre">list</span></code></a></p>
<blockquote>
<div><p>This checks for collisions between a single sprite and the sprites in a group.
It requires a &quot;rect&quot; attribute for all the sprites used. It returns a list of
all the sprites that overlap with the first sprite. The &quot;dokill&quot; argument is a
boolean argument. If it is true, the function will call the <code class="docutils literal notranslate"><span class="pre">kill()</span></code> method
on all the sprites. This means the last reference to each sprite is probably in
the returned list. Once the list goes away so do the sprites. A quick example
of using this in a loop</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">bomb</span> <span class="ow">in</span> <span class="n">sprite</span><span class="o">.</span><span class="n">spritecollide</span><span class="p">(</span><span class="n">player</span><span class="p">,</span> <span class="n">bombs</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">boom_sound</span><span class="o">.</span><span class="n">play</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">Explosion</span><span class="p">(</span><span class="n">bomb</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</pre></div>
</div>
<p>This finds all the sprites in the &quot;bomb&quot; group that collide with the player.
Because of the &quot;dokill&quot; argument it deletes all the crashed bombs. For each
bomb that did collide, it plays a &quot;boom&quot; sound effect, and creates a new
<code class="docutils literal notranslate"><span class="pre">Explosion</span></code> where the bomb was. (Note, the <code class="docutils literal notranslate"><span class="pre">Explosion</span></code> class here knows to
add each instance to the appropriate class, so we don't need to store it in a
variable, that last line might feel a little &quot;funny&quot; to you python programmers.)</p>
</div></blockquote>
<p><a class="reference internal" href="../ref/sprite.html#pygame.sprite.groupcollide" title="pygame.sprite.groupcollide"><code class="xref py py-func docutils literal notranslate"><span class="pre">groupcollide(group1,</span> <span class="pre">group2,</span> <span class="pre">dokill1,</span> <span class="pre">dokill2)</span> <span class="pre">-&gt;</span> <span class="pre">dictionary</span></code></a></p>
<blockquote>
<div><p>This is similar to the <code class="docutils literal notranslate"><span class="pre">spritecollide</span></code> function, but a little more complex.
It checks for collisions for all the sprites in one group, to the sprites in
another. There is a <code class="docutils literal notranslate"><span class="pre">dokill</span></code> argument for the sprites in each list. When
<code class="docutils literal notranslate"><span class="pre">dokill1</span></code> is true, the colliding sprites in <code class="docutils literal notranslate"><span class="pre">group1</span></code> will be <code class="docutils literal notranslate"><span class="pre">kill()``ed.</span>
<span class="pre">When</span> <span class="pre">``dokill2</span></code> is true, we get the same results for <code class="docutils literal notranslate"><span class="pre">group2</span></code>. The
dictionary it returns works like this; each key in the dictionary is a sprite
from <code class="docutils literal notranslate"><span class="pre">group1</span></code> that had a collision. The value for that key is a list of the
sprites that it collided with. Perhaps another quick code sample explains it
best</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">alien</span> <span class="ow">in</span> <span class="n">sprite</span><span class="o">.</span><span class="n">groupcollide</span><span class="p">(</span><span class="n">aliens</span><span class="p">,</span> <span class="n">shots</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">boom_sound</span><span class="o">.</span><span class="n">play</span><span class="p">()</span>
<span class="gp">... </span> <span class="n">Explosion</span><span class="p">(</span><span class="n">alien</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">kills</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>
</div>
<p>This code checks for the collisions between player bullets and all the aliens
they might intersect. In this case we only loop over the dictionary keys, but
we could loop over the <code class="docutils literal notranslate"><span class="pre">values()</span></code> or <code class="docutils literal notranslate"><span class="pre">items()</span></code> if we wanted to do something
to the specific shots that collided with aliens. If we did loop over the
<code class="docutils literal notranslate"><span class="pre">values()</span></code> we would be looping through lists that contain sprites. The same
sprite may even appear more than once in these different loops, since the same
&quot;shot&quot; could have collided against multiple &quot;aliens&quot;.</p>
</div></blockquote>
</div></blockquote>
<p>Those are the basic collision functions that come with pygame. It should be
easy to roll your own that perhaps use something different than the &quot;rect&quot;
attribute. Or maybe try to fine-tweak your code a little more by directly
effecting the collision object, instead of building a list of the collision?
The code in the sprite collision functions is very optimized, but you could
speed it up slightly by taking out some functionality you don't need.</p>
</section>
<section id="common-problems">
<h3>Common Problems<a class="headerlink" href="#common-problems" title="Permalink to this heading"></a></h3>
<p>Currently there is one main problem that catches new users. When you derive
your new sprite class with the Sprite base, you <strong>must</strong> call the
<code class="docutils literal notranslate"><span class="pre">Sprite.__init__()</span></code> method from your own class <code class="docutils literal notranslate"><span class="pre">__init__()</span></code> method. If you
forget to call the <code class="docutils literal notranslate"><span class="pre">Sprite.__init__()</span></code> method, you get a cryptic error, like
this</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="ne">AttributeError</span><span class="p">:</span> <span class="s1">&#39;mysprite&#39;</span> <span class="n">instance</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="s1">&#39;_Sprite__g&#39;</span>
</pre></div>
</div>
</section>
<section id="extending-your-own-classes-advanced">
<h3>Extending Your Own Classes <em>(Advanced)</em><a class="headerlink" href="#extending-your-own-classes-advanced" title="Permalink to this heading"></a></h3>
<p>Because of speed concerns, the current <code class="docutils literal notranslate"><span class="pre">Group</span></code> classes try to only do exactly
what they need, and not handle a lot of general situations. If you decide you
need extra features, you may want to create your own <code class="docutils literal notranslate"><span class="pre">Group</span></code> class.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> and <code class="docutils literal notranslate"><span class="pre">Group</span></code> classes were designed to be extended, so feel free
to create your own <code class="docutils literal notranslate"><span class="pre">Group</span></code> classes to do specialized things. The best place
to start is probably the actual python source code for the sprite module.
Looking at the current <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> groups should be enough example on how to
create your own.</p>
<p>For example, here is the source code for a rendering <code class="docutils literal notranslate"><span class="pre">Group</span></code> that calls a
<code class="docutils literal notranslate"><span class="pre">render()</span></code> method for each sprite, instead of just blitting an &quot;image&quot;
variable from it. Since we want it to also handle updated areas, we will start
with a copy of the original <code class="docutils literal notranslate"><span class="pre">RenderUpdates</span></code> group, here is the code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">RenderUpdatesDraw</span><span class="p">(</span><span class="n">RenderClear</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;call sprite.draw(screen) to render sprites&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="nf">draw</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">surface</span><span class="p">):</span>
<span class="n">dirty</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">lostsprites</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lostsprites</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">s</span><span class="p">,</span> <span class="n">r</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">spritedict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="n">newrect</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">draw</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span> <span class="c1">#Here&#39;s the big change</span>
<span class="k">if</span> <span class="n">r</span> <span class="ow">is</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">dirty</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">newrect</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">dirty</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">newrect</span><span class="o">.</span><span class="n">union</span><span class="p">(</span><span class="n">r</span><span class="p">))</span>
<span class="bp">self</span><span class="o">.</span><span class="n">spritedict</span><span class="p">[</span><span class="n">s</span><span class="p">]</span> <span class="o">=</span> <span class="n">newrect</span>
<span class="k">return</span> <span class="n">dirty</span>
</pre></div>
</div>
<p>Following is more information on how you could create your own <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> and
<code class="docutils literal notranslate"><span class="pre">Group</span></code> objects from scratch.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> objects only &quot;require&quot; two methods. &quot;add_internal()&quot; and
&quot;remove_internal()&quot;. These are called by the <code class="docutils literal notranslate"><span class="pre">Group</span></code> classes when they are
removing a sprite from themselves. The <code class="docutils literal notranslate"><span class="pre">add_internal()</span></code> and
<code class="docutils literal notranslate"><span class="pre">remove_internal()</span></code> have a single argument which is a group. Your <code class="docutils literal notranslate"><span class="pre">Sprite</span></code>
will need some way to also keep track of the <code class="docutils literal notranslate"><span class="pre">Groups</span></code> it belongs to. You will
likely want to try to match the other methods and arguments to the real
<code class="docutils literal notranslate"><span class="pre">Sprite</span></code> class, but if you're not going to use those methods, you sure don't
need them.</p>
<p>It is almost the same requirements for creating your own <code class="docutils literal notranslate"><span class="pre">Group</span></code>. In fact, if
you look at the source you'll see the <code class="docutils literal notranslate"><span class="pre">GroupSingle</span></code> isn't derived from the
<code class="docutils literal notranslate"><span class="pre">Group</span></code> class, it just implements the same methods so you can't really tell
the difference. Again you need an &quot;add_internal()&quot; and &quot;remove_internal()&quot;
method that the sprites call when they want to belong or remove themselves from
the group. The <code class="docutils literal notranslate"><span class="pre">add_internal()</span></code> and <code class="docutils literal notranslate"><span class="pre">remove_internal()</span></code> have a single
argument which is a sprite. The only other requirement for the <code class="docutils literal notranslate"><span class="pre">Group</span></code>
classes is they have a dummy attribute named &quot;_spritegroup&quot;. It doesn't matter
what the value is, as long as the attribute is present. The Sprite classes can
look for this attribute to determine the difference between a &quot;group&quot; and any
ordinary python container. (This is important, because several sprite methods
can take an argument of a single group, or a sequence of groups. Since they
both look similar, this is the most flexible way to &quot;see&quot; the difference.)</p>
<p>You should go through the code for the sprite module. While the code is a bit
&quot;tuned&quot;, it's got enough comments to help you follow along. There's even a
TODO section in the source if you feel like contributing.</p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/SpriteIntro.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="SurfarrayIntro.html" title="Pygame Tutorials - Surfarray Introduction"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="PygameIntro.html" title="Pygame Intro"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Pygame Tutorials - Sprite Module Introduction</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,656 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pygame Tutorials - Surfarray Introduction &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Newbie Guide to Pygame" href="newbieguide.html" />
<link rel="prev" title="Pygame Tutorials - Sprite Module Introduction" href="SpriteIntro.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="pygame-tutorials-surfarray-introduction">
<section id="surfarray-introduction">
<h2>Surfarray Introduction<a class="headerlink" href="#surfarray-introduction" title="Permalink to this heading"></a></h2>
<dl class="docinfo field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Pete Shinners</p>
</dd>
<dt class="field-even">Contact<span class="colon">:</span></dt>
<dd class="field-even"><p><a class="reference external" href="mailto:pete&#37;&#52;&#48;shinners&#46;org">pete<span>&#64;</span>shinners<span>&#46;</span>org</a></p>
</dd>
</dl>
<section id="introduction">
<h3>Introduction<a class="headerlink" href="#introduction" title="Permalink to this heading"></a></h3>
<p>This tutorial will attempt to introduce users to both NumPy and the pygame
surfarray module. To beginners, the code that uses surfarray can be quite
intimidating. But actually there are only a few concepts to understand and
you will be up and running. Using the surfarray module, it becomes possible
to perform pixel level operations from straight python code. The performance
can become quite close to the level of doing the code in C.</p>
<p>You may just want to jump down to the <em>&quot;Examples&quot;</em> section to get an
idea of what is possible with this module, then start at the beginning here
to work your way up.</p>
<p>Now I won't try to fool you into thinking everything is very easy. To get
more advanced effects by modifying pixel values is very tricky. Just mastering
Numeric Python (SciPy's original array package was Numeric, the predecessor of NumPy)
takes a lot of learning. In this tutorial I'll be sticking with
the basics and using a lot of examples in an attempt to plant seeds of wisdom.
After finishing the tutorial you should have a basic handle on how the surfarray
works.</p>
</section>
<section id="numeric-python">
<h3>Numeric Python<a class="headerlink" href="#numeric-python" title="Permalink to this heading"></a></h3>
<p>If you do not have the python NumPy package installed,
you will need to do that now, by following the
<a class="reference external" href="https://numpy.org/install/">NumPy Installation Guide</a>.
To make sure NumPy is working for you,
you should get something like this from the interactive python prompt.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">numpy</span> <span class="kn">import</span> <span class="o">*</span> <span class="c1">#import numeric</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="n">array</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">))</span> <span class="c1">#create an array</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="c1">#display the array</span>
<span class="go">array([1, 2, 3, 4, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="c1">#index into the array</span>
<span class="go">3</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="o">*</span><span class="mi">2</span> <span class="c1">#new array with twiced values</span>
<span class="go">array([ 2, 4, 6, 8, 10])</span>
</pre></div>
</div>
<p>As you can see, the NumPy module gives us a new data type, the <em>array</em>.
This object holds an array of fixed size, and all values inside are of the same
type. The arrays can also be multidimensional, which is how we will use them
with images. There's a bit more to it than this, but it is enough to get us
started.</p>
<p>If you look at the last command above, you'll see that mathematical operations
on NumPy arrays apply to all values in the array. This is called &quot;element-wise
operations&quot;. These arrays can also be sliced like normal lists. The slicing
syntax is the same as used on standard python objects.
<em>(so study up if you need to :] )</em>.
Here are some more examples of working with arrays.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="c1">#get array size</span>
<span class="go">5</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">:]</span> <span class="c1">#elements 2 and up</span>
<span class="go">array([3, 4, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="c1">#all except last 2</span>
<span class="go">array([1, 2, 3])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">:]</span> <span class="o">+</span> <span class="n">a</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="c1">#add first and last</span>
<span class="go">array([4, 6, 8])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">array</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">))</span> <span class="o">+</span> <span class="n">array</span><span class="p">((</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">))</span> <span class="c1">#add arrays of wrong sizes</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">ValueError</span>: <span class="n">operands could not be broadcast together with shapes (3,) (2,)</span>
</pre></div>
</div>
<p>We get an error on the last command, because we try add together two arrays
that are different sizes. In order for two arrays two operate with each other,
including comparisons and assignment, they must have the same dimensions. It is
very important to know that the new arrays created from slicing the original all
reference the same values. So changing the values in a slice also changes the
original values. It is important how this is done.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="c1">#show our starting array</span>
<span class="go">array([1, 2, 3, 4, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">aa</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">3</span><span class="p">]</span> <span class="c1">#slice middle 2 elements</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">aa</span> <span class="c1">#show the slice</span>
<span class="go">array([2, 3])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">aa</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">13</span> <span class="c1">#chance value in slice</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="c1">#show change in original</span>
<span class="go">array([ 1, 2, 13, 4, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">aaa</span> <span class="o">=</span> <span class="n">array</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="c1">#make copy of array</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">aaa</span> <span class="c1">#show copy</span>
<span class="go">array([ 1, 2, 13, 4, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">aaa</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1">#set middle values to 0</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">aaa</span> <span class="c1">#show copy</span>
<span class="go">array([1, 0, 0, 0, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="c1">#show original again</span>
<span class="go">array([ 1, 2, 13, 4, 5])</span>
</pre></div>
</div>
<p>Now we will look at small arrays with two
dimensions. Don't be too worried, getting started it is the same as having a
two dimensional tuple <em>(a tuple inside a tuple)</em>. Let's get started with
two dimensional arrays.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">row1</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span> <span class="c1">#create a tuple of vals</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">row2</span> <span class="o">=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">)</span> <span class="c1">#another tuple</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">(</span><span class="n">row1</span><span class="p">,</span><span class="n">row2</span><span class="p">)</span> <span class="c1">#show as a 2D tuple</span>
<span class="go">((1, 2, 3), (3, 4, 5))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span> <span class="o">=</span> <span class="n">array</span><span class="p">((</span><span class="n">row1</span><span class="p">,</span> <span class="n">row2</span><span class="p">))</span> <span class="c1">#create a 2D array</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span> <span class="c1">#show the array</span>
<span class="go">array([[1, 2, 3],</span>
<span class="go"> [3, 4, 5]])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">array</span><span class="p">(((</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">),(</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">),(</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">)))</span> <span class="c1">#show a new 2D array</span>
<span class="go">array([[1, 2],</span>
<span class="go"> [3, 4],</span>
<span class="go"> [5, 6]])</span>
</pre></div>
</div>
<p>Now with this two
dimensional array <em>(from now on as &quot;2D&quot;)</em> we can index specific values
and do slicing on both dimensions. Simply using a comma to separate the indices
allows us to lookup/slice in multiple dimensions. Just using &quot;<code class="docutils literal notranslate"><span class="pre">:</span></code>&quot; as an
index <em>(or not supplying enough indices)</em> gives us all the values in
that dimension. Let's see how this works.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">b</span> <span class="c1">#show our array from above</span>
<span class="go">array([[1, 2, 3],</span>
<span class="go"> [3, 4, 5]])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span> <span class="c1">#index a single value</span>
<span class="go">2</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">,:]</span> <span class="c1">#slice second row</span>
<span class="go">array([3, 4, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="c1">#slice second row (same as above)</span>
<span class="go">array([3, 4, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span><span class="p">[:,</span><span class="mi">2</span><span class="p">]</span> <span class="c1">#slice last column</span>
<span class="go">array([3, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span><span class="p">[:,:</span><span class="mi">2</span><span class="p">]</span> <span class="c1">#slice into a 2x2 array</span>
<span class="go">array([[1, 2],</span>
<span class="go"> [3, 4]])</span>
</pre></div>
</div>
<p>Ok, stay with me here, this is about as hard as it gets. When using NumPy
there is one more feature to slicing. Slicing arrays also allow you to specify
a <em>slice increment</em>. The syntax for a slice with increment is
<code class="docutils literal notranslate"><span class="pre">start_index</span> <span class="pre">:</span> <span class="pre">end_index</span> <span class="pre">:</span> <span class="pre">increment</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span> <span class="o">=</span> <span class="n">arange</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="c1">#like range, but makes an array</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span> <span class="c1">#show the array</span>
<span class="go">array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">6</span><span class="p">:</span><span class="mi">2</span><span class="p">]</span> <span class="c1">#slice odd values from 1 to 6</span>
<span class="go">array([1, 3, 5])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="p">[</span><span class="mi">4</span><span class="p">::</span><span class="mi">4</span><span class="p">]</span> <span class="c1">#slice every 4th val starting at 4</span>
<span class="go">array([4, 8])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="p">[</span><span class="mi">8</span><span class="p">:</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="c1">#slice 1 to 8, reversed</span>
<span class="go">array([8, 7, 6, 5, 4, 3, 2])</span>
</pre></div>
</div>
<p>Well that is it. There's enough information there to get you started using
NumPy with the surfarray module. There's certainly a lot more to NumPy, but
this is only an introduction. Besides, we want to get on to the fun stuff,
correct?</p>
</section>
<section id="import-surfarray">
<h3>Import Surfarray<a class="headerlink" href="#import-surfarray" title="Permalink to this heading"></a></h3>
<p>In order to use the surfarray module we need to import it. Since both surfarray
and NumPy are optional components for pygame, it is nice to make sure they
import correctly before using them. In these examples I'm going to import
NumPy into a variable named <em>N</em>. This will let you know which functions
I'm using are from the NumPy package.
<em>(and is a lot shorter than typing NumPy before each function)</em></p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">N</span>
<span class="kn">import</span> <span class="nn">pygame.surfarray</span> <span class="k">as</span> <span class="nn">surfarray</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">,</span> <span class="s2">&quot;NumPy and Surfarray are required.&quot;</span>
</pre></div>
</div>
</section>
<section id="id1">
<h3>Surfarray Introduction<a class="headerlink" href="#id1" title="Permalink to this heading"></a></h3>
<p>There are two main types of functions in surfarray. One set of functions for
creating an array that is a copy of a surface pixel data. The other functions
create a referenced copy of the array pixel data, so that changes to the array
directly affect the original surface. There are other functions that allow you
to access any per-pixel alpha values as arrays along with a few other helpful
functions. We will look at these other functions later on.</p>
<p>When working with these surface arrays, there are two ways of representing the
pixel values. First, they can be represented as mapped integers. This type of
array is a simple 2D array with a single integer representing the surface's
mapped color value. This type of array is good for moving parts of an image
around. The other type of array uses three RGB values to represent each pixel
color. This type of array makes it extremely simple to do types of effects that
change the color of each pixel. This type of array is also a little trickier to
deal with, since it is essentially a 3D numeric array. Still, once you get your
mind into the right mode, it is not much harder than using the normal 2D arrays.</p>
<p>The NumPy module uses a machine's natural number types to represent the data
values, so a NumPy array can consist of integers that are 8-bits, 16-bits, and 32-bits.
<em>(the arrays can also use other types like floats and doubles, but for our image
manipulation we mainly need to worry about the integer types)</em>.
Because of this limitation of integer sizes, you must take a little extra care
that the type of arrays that reference pixel data can be properly mapped to a
proper type of data. The functions create these arrays from surfaces are:</p>
<dl class="py function definition">
<dt class="sig sig-object py title">
<span class="sig-prename descclassname"><span class="pre">surfarray.</span></span><span class="sig-name descname"><span class="pre">pixels2d</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">surface</span></span></em><span class="sig-paren">)</span></dt>
<dd><p>Creates a 2D array <em>(integer pixel values)</em> that reference the original surface data.
This will work for all surface formats except 24-bit.</p>
</dd></dl>
<dl class="py function definition">
<dt class="sig sig-object py title">
<span class="sig-prename descclassname"><span class="pre">surfarray.</span></span><span class="sig-name descname"><span class="pre">array2d</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">surface</span></span></em><span class="sig-paren">)</span></dt>
<dd><p>Creates a 2D array <em>(integer pixel values)</em> that is copied from any type of surface.</p>
</dd></dl>
<dl class="py function definition">
<dt class="sig sig-object py title">
<span class="sig-prename descclassname"><span class="pre">surfarray.</span></span><span class="sig-name descname"><span class="pre">pixels3d</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">surface</span></span></em><span class="sig-paren">)</span></dt>
<dd><p>Creates a 3D array <em>(RGB pixel values)</em> that reference the original surface data.
This will only work on 24-bit and 32-bit surfaces that have RGB or BGR formatting.</p>
</dd></dl>
<dl class="py function definition">
<dt class="sig sig-object py title">
<span class="sig-prename descclassname"><span class="pre">surfarray.</span></span><span class="sig-name descname"><span class="pre">array3d</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">surface</span></span></em><span class="sig-paren">)</span></dt>
<dd><p>Creates a 3D array <em>(RGB pixel values)</em> that is copied from any type of surface.</p>
</dd></dl>
<p>Here is a small chart that might better illustrate what types of functions
should be used on which surfaces. As you can see, both the arrayXD functions
will work with any type of surface.</p>
<table class="matrix docutils align-default">
<colgroup>
<col style="width: 20.0%" />
<col style="width: 20.0%" />
<col style="width: 20.0%" />
<col style="width: 20.0%" />
<col style="width: 20.0%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head stub"></th>
<th class="head"><p>32-bit</p></th>
<th class="head"><p>24-bit</p></th>
<th class="head"><p>16-bit</p></th>
<th class="head"><p>8-bit(c-map)</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><th class="stub"><p>pixel2d</p></th>
<td><p>yes</p></td>
<td></td>
<td><p>yes</p></td>
<td><p>yes</p></td>
</tr>
<tr class="row-odd"><th class="stub"><p>array2d</p></th>
<td><p>yes</p></td>
<td><p>yes</p></td>
<td><p>yes</p></td>
<td><p>yes</p></td>
</tr>
<tr class="row-even"><th class="stub"><p>pixel3d</p></th>
<td><p>yes</p></td>
<td><p>yes</p></td>
<td></td>
<td></td>
</tr>
<tr class="row-odd"><th class="stub"><p>array3d</p></th>
<td><p>yes</p></td>
<td><p>yes</p></td>
<td><p>yes</p></td>
<td><p>yes</p></td>
</tr>
</tbody>
</table>
</section>
<section id="examples">
<h3>Examples<a class="headerlink" href="#examples" title="Permalink to this heading"></a></h3>
<p>With this information, we are equipped to start trying things with surface
arrays. The following are short little demonstrations that create a NumPy
array and display them in pygame. These different tests are found in the
<em>arraydemo.py</em> example. There is a simple function named <em>surfdemo_show</em>
that displays an array on the screen.</p>
<div class="examples docutils container">
<div class="example docutils container">
<img alt="allblack" src="../_images/surfarray_allblack.png" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">allblack</span> <span class="o">=</span> <span class="n">N</span><span class="o">.</span><span class="n">zeros</span><span class="p">((</span><span class="mi">128</span><span class="p">,</span> <span class="mi">128</span><span class="p">))</span>
<span class="n">surfdemo_show</span><span class="p">(</span><span class="n">allblack</span><span class="p">,</span> <span class="s1">&#39;allblack&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Our first example creates an all black array. Whenever you need
to create a new numeric array of a specific size, it is best to use the
<code class="docutils literal notranslate"><span class="pre">zeros</span></code> function. Here we create a 2D array of all zeros and display
it.</p>
<div class="break docutils container">
</div>
</div>
<div class="example docutils container">
<img alt="striped" src="../_images/surfarray_striped.png" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">striped</span> <span class="o">=</span> <span class="n">N</span><span class="o">.</span><span class="n">zeros</span><span class="p">((</span><span class="mi">128</span><span class="p">,</span> <span class="mi">128</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="n">striped</span><span class="p">[:]</span> <span class="o">=</span> <span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">striped</span><span class="p">[:,::</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">)</span>
<span class="n">surfdemo_show</span><span class="p">(</span><span class="n">striped</span><span class="p">,</span> <span class="s1">&#39;striped&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Here we are dealing with a 3D array. We start by creating an all red image.
Then we slice out every third row and assign it to a blue/green color. As you
can see, we can treat the 3D arrays almost exactly the same as 2D arrays, just
be sure to assign them 3 values instead of a single mapped integer.</p>
<div class="break docutils container">
</div>
</div>
<div class="example docutils container">
<img alt="rgbarray" src="../_images/surfarray_rgbarray.png" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">imgsurface</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;surfarray.png&#39;</span><span class="p">)</span>
<span class="n">rgbarray</span> <span class="o">=</span> <span class="n">surfarray</span><span class="o">.</span><span class="n">array3d</span><span class="p">(</span><span class="n">imgsurface</span><span class="p">)</span>
<span class="n">surfdemo_show</span><span class="p">(</span><span class="n">rgbarray</span><span class="p">,</span> <span class="s1">&#39;rgbarray&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Here we load an image with the image module, then convert it to a 3D
array of integer RGB color elements. An RGB copy of a surface always
has the colors arranged as a[r,c,0] for the red component,
a[r,c,1] for the green component, and a[r,c,2] for blue. This can then
be used without caring how the pixels of the actual surface are configured,
unlike a 2D array which is a copy of the <a class="reference internal" href="../ref/surface.html#pygame.Surface.map_rgb" title="pygame.Surface.map_rgb"><code class="xref py py-meth docutils literal notranslate"><span class="pre">mapped</span></code></a>
(raw) surface pixels. We will use this image in the rest of the samples.</p>
<div class="break docutils container">
</div>
</div>
<div class="example docutils container">
<img alt="flipped" src="../_images/surfarray_flipped.png" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">flipped</span> <span class="o">=</span> <span class="n">rgbarray</span><span class="p">[:,::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">surfdemo_show</span><span class="p">(</span><span class="n">flipped</span><span class="p">,</span> <span class="s1">&#39;flipped&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Here we flip the image vertically. All we need to do is take the original
image array and slice it using a negative increment.</p>
<div class="break docutils container">
</div>
</div>
<div class="example docutils container">
<img alt="scaledown" src="../_images/surfarray_scaledown.png" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">scaledown</span> <span class="o">=</span> <span class="n">rgbarray</span><span class="p">[::</span><span class="mi">2</span><span class="p">,::</span><span class="mi">2</span><span class="p">]</span>
<span class="n">surfdemo_show</span><span class="p">(</span><span class="n">scaledown</span><span class="p">,</span> <span class="s1">&#39;scaledown&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Based on the last example, scaling an image down is pretty logical. We just
slice out all the pixels using an increment of 2 vertically and horizontally.</p>
<div class="break docutils container">
</div>
</div>
<div class="example docutils container">
<img alt="scaleup" src="../_images/surfarray_scaleup.png" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">shape</span> <span class="o">=</span> <span class="n">rgbarray</span><span class="o">.</span><span class="n">shape</span>
<span class="n">scaleup</span> <span class="o">=</span> <span class="n">N</span><span class="o">.</span><span class="n">zeros</span><span class="p">((</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="mi">2</span><span class="p">,</span> <span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">*</span><span class="mi">2</span><span class="p">,</span> <span class="n">shape</span><span class="p">[</span><span class="mi">2</span><span class="p">]))</span>
<span class="n">scaleup</span><span class="p">[::</span><span class="mi">2</span><span class="p">,::</span><span class="mi">2</span><span class="p">,:]</span> <span class="o">=</span> <span class="n">rgbarray</span>
<span class="n">scaleup</span><span class="p">[</span><span class="mi">1</span><span class="p">::</span><span class="mi">2</span><span class="p">,::</span><span class="mi">2</span><span class="p">,:]</span> <span class="o">=</span> <span class="n">rgbarray</span>
<span class="n">scaleup</span><span class="p">[:,</span><span class="mi">1</span><span class="p">::</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">scaleup</span><span class="p">[:,::</span><span class="mi">2</span><span class="p">]</span>
<span class="n">surfdemo_show</span><span class="p">(</span><span class="n">scaleup</span><span class="p">,</span> <span class="s1">&#39;scaleup&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Scaling the image up is a little more work, but is similar to the previous
scaling down, we do it all with slicing. First we create an array that is
double the size of our original. First we copy the original array into every
other pixel of the new array. Then we do it again for every other pixel doing
the odd columns. At this point we have the image scaled properly going across,
but every other row is black, so we simply need to copy each row to the one
underneath it. Then we have an image doubled in size.</p>
<div class="break docutils container">
</div>
</div>
<div class="example docutils container">
<img alt="redimg" src="../_images/surfarray_redimg.png" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">redimg</span> <span class="o">=</span> <span class="n">N</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">rgbarray</span><span class="p">)</span>
<span class="n">redimg</span><span class="p">[:,:,</span><span class="mi">1</span><span class="p">:]</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">surfdemo_show</span><span class="p">(</span><span class="n">redimg</span><span class="p">,</span> <span class="s1">&#39;redimg&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Now we are using 3D arrays to change the colors. Here we
set all the values in green and blue to zero.
This leaves us with just the red channel.</p>
<div class="break docutils container">
</div>
</div>
<div class="example docutils container">
<img alt="soften" src="../_images/surfarray_soften.png" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">factor</span> <span class="o">=</span> <span class="n">N</span><span class="o">.</span><span class="n">array</span><span class="p">((</span><span class="mi">8</span><span class="p">,),</span> <span class="n">N</span><span class="o">.</span><span class="n">int32</span><span class="p">)</span>
<span class="n">soften</span> <span class="o">=</span> <span class="n">N</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">rgbarray</span><span class="p">,</span> <span class="n">N</span><span class="o">.</span><span class="n">int32</span><span class="p">)</span>
<span class="n">soften</span><span class="p">[</span><span class="mi">1</span><span class="p">:,:]</span> <span class="o">+=</span> <span class="n">rgbarray</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">,:]</span> <span class="o">*</span> <span class="n">factor</span>
<span class="n">soften</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">,:]</span> <span class="o">+=</span> <span class="n">rgbarray</span><span class="p">[</span><span class="mi">1</span><span class="p">:,:]</span> <span class="o">*</span> <span class="n">factor</span>
<span class="n">soften</span><span class="p">[:,</span><span class="mi">1</span><span class="p">:]</span> <span class="o">+=</span> <span class="n">rgbarray</span><span class="p">[:,:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="n">factor</span>
<span class="n">soften</span><span class="p">[:,:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+=</span> <span class="n">rgbarray</span><span class="p">[:,</span><span class="mi">1</span><span class="p">:]</span> <span class="o">*</span> <span class="n">factor</span>
<span class="n">soften</span> <span class="o">//=</span> <span class="mi">33</span>
<span class="n">surfdemo_show</span><span class="p">(</span><span class="n">soften</span><span class="p">,</span> <span class="s1">&#39;soften&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Here we perform a 3x3 convolution filter that will soften our image.
It looks like a lot of steps here, but what we are doing is shifting
the image 1 pixel in each direction and adding them all together (with some
multiplication for weighting). Then average all the values. It's no Gaussian,
but it's fast. One point with NumPy arrays, the precision of arithmetic
operations is determined by the array with the largest data type.
So if factor was not declared as a 1 element array of type numpy.int32,
the multiplications would be performed using numpy.int8, the 8 bit integer
type of each rgbarray element. This will cause value truncation. The soften
array must also be declared to have a larger integer size than rgbarray to
avoid truncation.</p>
<div class="break docutils container">
</div>
</div>
<div class="example docutils container">
<img alt="xfade" src="../_images/surfarray_xfade.png" />
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">src</span> <span class="o">=</span> <span class="n">N</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">rgbarray</span><span class="p">)</span>
<span class="n">dest</span> <span class="o">=</span> <span class="n">N</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="n">rgbarray</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>
<span class="n">dest</span><span class="p">[:]</span> <span class="o">=</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">50</span><span class="p">,</span> <span class="mi">100</span>
<span class="n">diff</span> <span class="o">=</span> <span class="p">(</span><span class="n">dest</span> <span class="o">-</span> <span class="n">src</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.50</span>
<span class="n">xfade</span> <span class="o">=</span> <span class="n">src</span> <span class="o">+</span> <span class="n">diff</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="n">N</span><span class="o">.</span><span class="n">uint</span><span class="p">)</span>
<span class="n">surfdemo_show</span><span class="p">(</span><span class="n">xfade</span><span class="p">,</span> <span class="s1">&#39;xfade&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Lastly, we are cross fading between the original image and a solid bluish
image. Not exciting, but the dest image could be anything, and changing the 0.50
multiplier will let you choose any step in a linear crossfade between two images.</p>
<div class="break docutils container">
</div>
</div>
</div>
<p>Hopefully by this point you are starting to see how surfarray can be used to
perform special effects and transformations that are only possible at the pixel
level. At the very least, you can use the surfarray to do a lot of Surface.set_at()
Surface.get_at() type operations very quickly. But don't think you are finished
yet, there is still much to learn.</p>
</section>
<section id="surface-locking">
<h3>Surface Locking<a class="headerlink" href="#surface-locking" title="Permalink to this heading"></a></h3>
<p>Like the rest of pygame, surfarray will lock any Surfaces it needs to
automatically when accessing pixel data. There is one extra thing to be aware
of though. When creating the <em>pixel</em> arrays, the original surface will
be locked during the lifetime of that pixel array. This is important to remember.
Be sure to <em>&quot;del&quot;</em> the pixel array or let it go out of scope
<em>(ie, when the function returns, etc)</em>.</p>
<p>Also be aware that you really don't want to be doing much <em>(if any)</em>
direct pixel access on hardware surfaces <em>(HWSURFACE)</em>. This is because
the actual surface data lives on the graphics card, and transferring pixel
changes over the PCI/AGP bus is not fast.</p>
</section>
<section id="transparency">
<h3>Transparency<a class="headerlink" href="#transparency" title="Permalink to this heading"></a></h3>
<p>The surfarray module has several methods for accessing a Surface's alpha/colorkey
values. None of the alpha functions are affected by overall transparency of a
Surface, just the pixel alpha values. Here's the list of those functions.</p>
<dl class="py function definition">
<dt class="sig sig-object py title">
<span class="sig-prename descclassname"><span class="pre">surfarray.</span></span><span class="sig-name descname"><span class="pre">pixels_alpha</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">surface</span></span></em><span class="sig-paren">)</span></dt>
<dd><p>Creates a 2D array <em>(integer pixel values)</em> that references the original
surface alpha data.
This will only work on 32-bit images with an 8-bit alpha component.</p>
</dd></dl>
<dl class="py function definition">
<dt class="sig sig-object py title">
<span class="sig-prename descclassname"><span class="pre">surfarray.</span></span><span class="sig-name descname"><span class="pre">array_alpha</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">surface</span></span></em><span class="sig-paren">)</span></dt>
<dd><p>Creates a 2D array <em>(integer pixel values)</em> that is copied from any
type of surface.
If the surface has no alpha values,
the array will be fully opaque values <em>(255)</em>.</p>
</dd></dl>
<dl class="py function definition">
<dt class="sig sig-object py title">
<span class="sig-prename descclassname"><span class="pre">surfarray.</span></span><span class="sig-name descname"><span class="pre">array_colorkey</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">surface</span></span></em><span class="sig-paren">)</span></dt>
<dd><p>Creates a 2D array <em>(integer pixel values)</em> that is set to transparent
<em>(0)</em> wherever that pixel color matches the Surface colorkey.</p>
</dd></dl>
</section>
<section id="other-surfarray-functions">
<h3>Other Surfarray Functions<a class="headerlink" href="#other-surfarray-functions" title="Permalink to this heading"></a></h3>
<p>There are only a few other functions available in surfarray. You can get a better
list with more documentation on the
<a class="reference internal" href="../ref/surfarray.html#module-pygame.surfarray" title="pygame.surfarray: pygame module for accessing surface pixel data using array interfaces"><code class="xref py py-mod docutils literal notranslate"><span class="pre">surfarray</span> <span class="pre">reference</span> <span class="pre">page</span></code></a>.
There is one very useful function though.</p>
<dl class="py function definition">
<dt class="sig sig-object py title">
<span class="sig-prename descclassname"><span class="pre">surfarray.</span></span><span class="sig-name descname"><span class="pre">blit_array</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">surface</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">array</span></span></em><span class="sig-paren">)</span></dt>
<dd><p>This will transfer any type of 2D or 3D surface array onto a Surface
of the same dimensions.
This surfarray blit will generally be faster than assigning an array to a
referenced pixel array.
Still, it should not be as fast as normal Surface blitting,
since those are very optimized.</p>
</dd></dl>
</section>
<section id="more-advanced-numpy">
<h3>More Advanced NumPy<a class="headerlink" href="#more-advanced-numpy" title="Permalink to this heading"></a></h3>
<p>There's a couple last things you should know about NumPy arrays. When dealing
with very large arrays, like the kind that are 640x480 big, there are some extra
things you should be careful about. Mainly, while using the operators like + and
* on the arrays makes them easy to use, it is also very expensive on big arrays.
These operators must make new temporary copies of the array, that are then
usually copied into another array. This can get very time consuming. Fortunately,
all the NumPy operators come with special functions that can perform the
operation <em>&quot;in place&quot;</em>. For example, you would want to replace
<code class="docutils literal notranslate"><span class="pre">screen[:]</span> <span class="pre">=</span> <span class="pre">screen</span> <span class="pre">+</span> <span class="pre">brightmap</span></code> with the much faster
<code class="docutils literal notranslate"><span class="pre">add(screen,</span> <span class="pre">brightmap,</span> <span class="pre">screen)</span></code>.
Anyway, you'll want to read up on the NumPy UFunc
documentation for more about this.
It is important when dealing with the arrays.</p>
<p>Another thing to be aware of when working with NumPy arrays is the datatype
of the array. Some of the arrays (especially the mapped pixel type) often return
arrays with an unsigned 8-bit value. These arrays will easily overflow if you are
not careful. NumPy will use the same coercion that you find in C programs, so
mixing an operation with 8-bit numbers and 32-bit numbers will give a result as
32-bit numbers. You can convert the datatype of an array, but definitely be
aware of what types of arrays you have, if NumPy gets in a situation where
precision would be ruined, it will raise an exception.</p>
<p>Lastly, be aware that when assigning values into the 3D arrays, they must be
between 0 and 255, or you will get some undefined truncating.</p>
</section>
<section id="graduation">
<h3>Graduation<a class="headerlink" href="#graduation" title="Permalink to this heading"></a></h3>
<p>Well there you have it. My quick primer on Numeric Python and surfarray.
Hopefully now you see what is possible, and even if you never use them for
yourself, you do not have to be afraid when you see code that does. Look into
the vgrade example for more numeric array action. There are also some <em>&quot;flame&quot;</em>
demos floating around that use surfarray to create a realtime fire effect.</p>
<p>Best of all, try some things on your own. Take it slow at first and build up,
I've seen some great things with surfarray already like radial gradients and
more. Good Luck.</p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/SurfarrayIntro.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="newbieguide.html" title="Newbie Guide to Pygame"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="SpriteIntro.html" title="Pygame Tutorials - Sprite Module Introduction"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Pygame Tutorials - Surfarray Introduction</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,338 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>pygame/examples/chimp.py &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Pygame Tutorials - Setting Display Modes" href="DisplayModes.html" />
<link rel="prev" title="Pygame Tutorials - Line By Line Chimp Example" href="ChimpLineByLine.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="pygame-examples-chimp-py">
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/env python</span>
<span class="sd">&quot;&quot;&quot; pygame.examples.chimp</span>
<span class="sd">This simple example is used for the line-by-line tutorial</span>
<span class="sd">that comes with pygame. It is based on a &#39;popular&#39; web banner.</span>
<span class="sd">Note there are comments here, but for the full explanation,</span>
<span class="sd">follow along in the tutorial.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="c1"># Import Modules</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">pygame</span> <span class="k">as</span> <span class="nn">pg</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">pg</span><span class="o">.</span><span class="n">font</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Warning, fonts disabled&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">pg</span><span class="o">.</span><span class="n">mixer</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Warning, sound disabled&quot;</span><span class="p">)</span>
<span class="n">main_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="vm">__file__</span><span class="p">))[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">data_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">main_dir</span><span class="p">,</span> <span class="s2">&quot;data&quot;</span><span class="p">)</span>
<span class="c1"># functions to create our resources</span>
<span class="k">def</span> <span class="nf">load_image</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">colorkey</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="n">fullname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">data_dir</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="n">size</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">get_size</span><span class="p">()</span>
<span class="n">size</span> <span class="o">=</span> <span class="p">(</span><span class="n">size</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">scale</span><span class="p">,</span> <span class="n">size</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="n">scale</span><span class="p">)</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">scale</span><span class="p">(</span><span class="n">image</span><span class="p">,</span> <span class="n">size</span><span class="p">)</span>
<span class="k">if</span> <span class="n">colorkey</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">if</span> <span class="n">colorkey</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="n">colorkey</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">get_at</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="n">image</span><span class="o">.</span><span class="n">set_colorkey</span><span class="p">(</span><span class="n">colorkey</span><span class="p">,</span> <span class="n">pg</span><span class="o">.</span><span class="n">RLEACCEL</span><span class="p">)</span>
<span class="k">return</span> <span class="n">image</span><span class="p">,</span> <span class="n">image</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">load_sound</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="k">class</span> <span class="nc">NoneSound</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">play</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">pg</span><span class="o">.</span><span class="n">mixer</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">pg</span><span class="o">.</span><span class="n">mixer</span><span class="o">.</span><span class="n">get_init</span><span class="p">():</span>
<span class="k">return</span> <span class="n">NoneSound</span><span class="p">()</span>
<span class="n">fullname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">data_dir</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="n">sound</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">mixer</span><span class="o">.</span><span class="n">Sound</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="k">return</span> <span class="n">sound</span>
<span class="c1"># classes for our game objects</span>
<span class="k">class</span> <span class="nc">Fist</span><span class="p">(</span><span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;moves a clenched fist on the screen, following the mouse&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="c1"># call Sprite initializer</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">load_image</span><span class="p">(</span><span class="s2">&quot;fist.png&quot;</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">fist_offset</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">235</span><span class="p">,</span> <span class="o">-</span><span class="mi">80</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">punching</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;move the fist based on the mouse position&quot;&quot;&quot;</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">mouse</span><span class="o">.</span><span class="n">get_pos</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">topleft</span> <span class="o">=</span> <span class="n">pos</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move_ip</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fist_offset</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">punching</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move_ip</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">25</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">punch</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;returns true if the fist collides with the target&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">punching</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">punching</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">hitbox</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">inflate</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="p">,</span> <span class="o">-</span><span class="mi">5</span><span class="p">)</span>
<span class="k">return</span> <span class="n">hitbox</span><span class="o">.</span><span class="n">colliderect</span><span class="p">(</span><span class="n">target</span><span class="o">.</span><span class="n">rect</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">unpunch</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;called to pull the fist back&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">punching</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">class</span> <span class="nc">Chimp</span><span class="p">(</span><span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;moves a monkey critter across the screen. it can spin the</span>
<span class="sd"> monkey when it is punched.&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="c1"># call Sprite initializer</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">load_image</span><span class="p">(</span><span class="s2">&quot;chimp.png&quot;</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">get_surface</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">area</span> <span class="o">=</span> <span class="n">screen</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">topleft</span> <span class="o">=</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">90</span>
<span class="bp">self</span><span class="o">.</span><span class="n">move</span> <span class="o">=</span> <span class="mi">18</span>
<span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;walk or spin, depending on the monkeys state&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_spin</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_walk</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">_walk</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;move the monkey across the screen, and turn at the ends&quot;&quot;&quot;</span>
<span class="n">newpos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">move</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">contains</span><span class="p">(</span><span class="n">newpos</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">left</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">left</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">right</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">right</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">move</span> <span class="o">=</span> <span class="o">-</span><span class="bp">self</span><span class="o">.</span><span class="n">move</span>
<span class="n">newpos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">move</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">flip</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="kc">True</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">newpos</span>
<span class="k">def</span> <span class="nf">_spin</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;spin the monkey image&quot;&quot;&quot;</span>
<span class="n">center</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">center</span>
<span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">+</span> <span class="mi">12</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">&gt;=</span> <span class="mi">360</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">=</span> <span class="kc">False</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">original</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">rotate</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">rotate</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span> <span class="o">=</span> <span class="n">rotate</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">original</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">get_rect</span><span class="p">(</span><span class="n">center</span><span class="o">=</span><span class="n">center</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">punched</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;this will cause the monkey to start spinning&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">dizzy</span> <span class="o">=</span> <span class="kc">True</span>
<span class="bp">self</span><span class="o">.</span><span class="n">original</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">image</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;this function is called when the program starts.</span>
<span class="sd"> it initializes everything it needs, then runs in</span>
<span class="sd"> a loop until the function returns.&quot;&quot;&quot;</span>
<span class="c1"># Initialize Everything</span>
<span class="n">pg</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">1280</span><span class="p">,</span> <span class="mi">480</span><span class="p">),</span> <span class="n">pg</span><span class="o">.</span><span class="n">SCALED</span><span class="p">)</span>
<span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_caption</span><span class="p">(</span><span class="s2">&quot;Monkey Fever&quot;</span><span class="p">)</span>
<span class="n">pg</span><span class="o">.</span><span class="n">mouse</span><span class="o">.</span><span class="n">set_visible</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
<span class="c1"># Create The Background</span>
<span class="n">background</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">Surface</span><span class="p">(</span><span class="n">screen</span><span class="o">.</span><span class="n">get_size</span><span class="p">())</span>
<span class="n">background</span> <span class="o">=</span> <span class="n">background</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="n">background</span><span class="o">.</span><span class="n">fill</span><span class="p">((</span><span class="mi">170</span><span class="p">,</span> <span class="mi">238</span><span class="p">,</span> <span class="mi">187</span><span class="p">))</span>
<span class="c1"># Put Text On The Background, Centered</span>
<span class="k">if</span> <span class="n">pg</span><span class="o">.</span><span class="n">font</span><span class="p">:</span>
<span class="n">font</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">font</span><span class="o">.</span><span class="n">Font</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">64</span><span class="p">)</span>
<span class="n">text</span> <span class="o">=</span> <span class="n">font</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s2">&quot;Pummel The Chimp, And Win $$$&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">,</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
<span class="n">textpos</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">get_rect</span><span class="p">(</span><span class="n">centerx</span><span class="o">=</span><span class="n">background</span><span class="o">.</span><span class="n">get_width</span><span class="p">()</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="n">background</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">textpos</span><span class="p">)</span>
<span class="c1"># Display The Background</span>
<span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
<span class="c1"># Prepare Game Objects</span>
<span class="n">whiff_sound</span> <span class="o">=</span> <span class="n">load_sound</span><span class="p">(</span><span class="s2">&quot;whiff.wav&quot;</span><span class="p">)</span>
<span class="n">punch_sound</span> <span class="o">=</span> <span class="n">load_sound</span><span class="p">(</span><span class="s2">&quot;punch.wav&quot;</span><span class="p">)</span>
<span class="n">chimp</span> <span class="o">=</span> <span class="n">Chimp</span><span class="p">()</span>
<span class="n">fist</span> <span class="o">=</span> <span class="n">Fist</span><span class="p">()</span>
<span class="n">allsprites</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">RenderPlain</span><span class="p">((</span><span class="n">chimp</span><span class="p">,</span> <span class="n">fist</span><span class="p">))</span>
<span class="n">clock</span> <span class="o">=</span> <span class="n">pg</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">Clock</span><span class="p">()</span>
<span class="c1"># Main Loop</span>
<span class="n">going</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">while</span> <span class="n">going</span><span class="p">:</span>
<span class="n">clock</span><span class="o">.</span><span class="n">tick</span><span class="p">(</span><span class="mi">60</span><span class="p">)</span>
<span class="c1"># Handle Input Events</span>
<span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pg</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">QUIT</span><span class="p">:</span>
<span class="n">going</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">KEYDOWN</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">K_ESCAPE</span><span class="p">:</span>
<span class="n">going</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">MOUSEBUTTONDOWN</span><span class="p">:</span>
<span class="k">if</span> <span class="n">fist</span><span class="o">.</span><span class="n">punch</span><span class="p">(</span><span class="n">chimp</span><span class="p">):</span>
<span class="n">punch_sound</span><span class="o">.</span><span class="n">play</span><span class="p">()</span> <span class="c1"># punch</span>
<span class="n">chimp</span><span class="o">.</span><span class="n">punched</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">whiff_sound</span><span class="o">.</span><span class="n">play</span><span class="p">()</span> <span class="c1"># miss</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pg</span><span class="o">.</span><span class="n">MOUSEBUTTONUP</span><span class="p">:</span>
<span class="n">fist</span><span class="o">.</span><span class="n">unpunch</span><span class="p">()</span>
<span class="n">allsprites</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
<span class="c1"># Draw Everything</span>
<span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="n">allsprites</span><span class="o">.</span><span class="n">draw</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="n">pg</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
<span class="n">pg</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
<span class="c1"># Game Over</span>
<span class="c1"># this calls the &#39;main&#39; function when this script is executed</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/chimp.py.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="DisplayModes.html" title="Pygame Tutorials - Setting Display Modes"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="ChimpLineByLine.html" title="Pygame Tutorials - Line By Line Chimp Example"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="ChimpLineByLine.html" accesskey="U">Pygame Tutorials - Line By Line Chimp Example</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">pygame/examples/chimp.py</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,542 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>A Newbie Guide to pygame &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Author: Youngwook Kim (Korean)" href="en/Red_or_Black/1.Prolog/introduction.html" />
<link rel="prev" title="Pygame Tutorials - Surfarray Introduction" href="SurfarrayIntro.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="newbie-guide-to-pygame">
<section id="a-newbie-guide-to-pygame">
<h2>A Newbie Guide to pygame<a class="headerlink" href="#a-newbie-guide-to-pygame" title="Permalink to this heading"></a></h2>
<p>or <strong>Things I learned by trial and error so you don't have to,</strong></p>
<p>or <strong>How I learned to stop worrying and love the blit.</strong></p>
<p><a class="reference external" href="https://www.pygame.org/">Pygame</a> is a python wrapper for <a class="reference external" href="http://libsdl.org">SDL</a>, written by Pete Shinners. What this
means is that, using pygame, you can write games or other multimedia
applications in Python that will run unaltered on any of SDL's supported
platforms (Windows, Linux, Mac, and others).</p>
<p>Pygame may be easy to learn, but the world of graphics programming can be
pretty confusing to the newcomer. I wrote this to try to distill the practical
knowledge I've gained over the past year or so of working with pygame, and its
predecessor, PySDL. I've tried to rank these suggestions in order of
importance, but how relevant any particular hint is will depend on your own
background and the details of your project.</p>
<section id="get-comfortable-working-in-python">
<h3>Get comfortable working in Python.<a class="headerlink" href="#get-comfortable-working-in-python" title="Permalink to this heading"></a></h3>
<p>The most important thing is to feel confident using python. Learning something
as potentially complicated as graphics programming will be a real chore if
you're also unfamiliar with the language you're using. Write a few sizable
non-graphical programs in python -- parse some text files, write a guessing
game or a journal-entry program or something. Get comfortable with string and
list manipulation -- know how to split, slice and combine strings and lists.
Know how <code class="docutils literal notranslate"><span class="pre">import</span></code> works -- try writing a program that is spread across
several source files. Write your own functions, and practice manipulating
numbers and characters; know how to convert between the two. Get to the point
where the syntax for using lists and dictionaries is second-nature -- you don't
want to have to run to the documentation every time you need to slice a list or
sort a set of keys. Get comfortable using file paths -- this will come in handy
later when you start loading assets and creating save files.</p>
<p>Resist the temptation to ask for direct help online when
you run into trouble. Instead, fire up the interpreter and play with the
problem for a few hours, or use print statements and debugging tools to find out
what's going wrong in your code. Get into the habit of looking things up in the
official <a class="reference external" href="https://docs.python.org/3/">Python documentation</a>, and Googling error messages to figure out what
they mean.</p>
<p>This may sound incredibly dull, but the confidence you'll gain through your
familiarity with python will work wonders when it comes time to write your
game. The time you spend making python code second-nature will be nothing
compared to the time you'll save when you're writing real code.</p>
</section>
<section id="recognize-which-parts-of-pygame-you-really-need">
<h3>Recognize which parts of pygame you really need.<a class="headerlink" href="#recognize-which-parts-of-pygame-you-really-need" title="Permalink to this heading"></a></h3>
<p>Looking at the jumble of classes at the top of the pygame documentation index
may be confusing. The important thing is to realize that you can do a great
deal with only a tiny subset of functions. Many classes you'll probably never
use -- in a year, I haven't touched the <code class="docutils literal notranslate"><span class="pre">Channel</span></code>, <code class="docutils literal notranslate"><span class="pre">Joystick</span></code>, <code class="docutils literal notranslate"><span class="pre">cursors</span></code>,
<code class="docutils literal notranslate"><span class="pre">surfarray</span></code> or <code class="docutils literal notranslate"><span class="pre">version</span></code> functions.</p>
</section>
<section id="know-what-a-surface-is">
<h3>Know what a surface is.<a class="headerlink" href="#know-what-a-surface-is" title="Permalink to this heading"></a></h3>
<p>The most important part of pygame is the surface. Just think of a surface as a
blank piece of paper. You can do a lot of things with a surface -- you can
draw lines on it, fill parts of it with color, copy images to and from it, and
set or read individual pixel colors on it. A surface can be any size (within
reason) and you can have as many of them as you like (again, within reason).
One surface is special -- the one you create with
<a class="tooltip reference internal" href="../ref/display.html#pygame.display.set_mode" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.set_mode()</span></code><span class="tooltip-content">Initialize a window or screen for display</span></a>. This 'display surface' represents the screen;
whatever you do to it will appear on the user's screen.</p>
<p>So how do you create surfaces? As mentioned above, you create the special
'display surface' with <code class="docutils literal notranslate"><span class="pre">pygame.display.set_mode()</span></code>. You can create a surface
that contains an image by using <a class="tooltip reference internal" href="../ref/image.html#pygame.image.load" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.image.load()</span></code><span class="tooltip-content">load new image from a file (or file-like object)</span></a>, or you can make a surface
that contains text with <a class="tooltip reference internal" href="../ref/font.html#pygame.font.Font.render" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.font.Font.render()</span></code><span class="tooltip-content">draw text on a new Surface</span></a>. You can even create a surface that
contains nothing at all with <a class="tooltip reference internal" href="../ref/surface.html#pygame.Surface" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.Surface()</span></code><span class="tooltip-content">pygame object for representing images</span></a>.</p>
<p>Most of the surface functions are not critical. Just learn <a class="reference internal" href="../ref/surface.html#pygame.Surface.blit" title="pygame.Surface.blit"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Surface.blit()</span></code></a>,
<a class="reference internal" href="../ref/surface.html#pygame.Surface.fill" title="pygame.Surface.fill"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Surface.fill()</span></code></a>, <a class="reference internal" href="../ref/surface.html#pygame.Surface.set_at" title="pygame.Surface.set_at"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Surface.set_at()</span></code></a> and <a class="reference internal" href="../ref/surface.html#pygame.Surface.get_at" title="pygame.Surface.get_at"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Surface.get_at()</span></code></a>, and you'll be fine.</p>
</section>
<section id="use-surface-convert">
<h3>Use Surface.convert().<a class="headerlink" href="#use-surface-convert" title="Permalink to this heading"></a></h3>
<p>When I first read the documentation for <a class="reference internal" href="../ref/surface.html#pygame.Surface.convert" title="pygame.Surface.convert"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Surface.convert()</span></code></a>, I didn't think
it was something I had to worry about. 'I only use PNGs, therefore everything I
do will be in the same format. So I don't need <code class="docutils literal notranslate"><span class="pre">convert()</span></code>';. It turns out I
was very, very wrong.</p>
<p>The 'format' that <code class="docutils literal notranslate"><span class="pre">convert()</span></code> refers to isn't the <em>file</em> format (i.e. PNG,
JPEG, GIF), it's what's called the 'pixel format'. This refers to the
particular way that a surface records individual colors in a specific pixel.
If the surface format isn't the same as the display format, SDL will have to
convert it on-the-fly for every blit -- a fairly time-consuming process. Don't
worry too much about the explanation; just note that <code class="docutils literal notranslate"><span class="pre">convert()</span></code> is necessary
if you want to get any kind of speed out of your blits.</p>
<p>How do you use convert? Just call it after creating a surface with the
<a class="reference internal" href="../ref/image.html#pygame.image.load" title="pygame.image.load"><code class="xref py py-func docutils literal notranslate"><span class="pre">image.load()</span></code></a> function. Instead of just doing:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">surface</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;foo.png&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Do:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">surface</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s1">&#39;foo.png&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
</pre></div>
</div>
<p>It's that easy. You just need to call it once per surface, when you load an
image off the disk. You'll be pleased with the results; I see about a 6x
increase in blitting speed by calling <code class="docutils literal notranslate"><span class="pre">convert()</span></code>.</p>
<p>The only times you don't want to use <code class="docutils literal notranslate"><span class="pre">convert()</span></code> is when you really need to
have absolute control over an image's internal format -- say you were writing
an image conversion program or something, and you needed to ensure that the
output file had the same pixel format as the input file. If you're writing a
game, you need speed. Use <code class="docutils literal notranslate"><span class="pre">convert()</span></code>.</p>
</section>
<section id="be-wary-of-outdated-obsolete-and-optional-advice">
<h3>Be wary of outdated, obsolete, and optional advice.<a class="headerlink" href="#be-wary-of-outdated-obsolete-and-optional-advice" title="Permalink to this heading"></a></h3>
<p>Pygame has been around since the early 2000s, and a lot has changed since then --
both within the framework itself and within the broader computing landscape as a
whole. Make sure to check the dates on materials you read (including this guide!),
and take older advice with a grain of salt. Here are some common things that
stick out to me:</p>
<p><strong>Dirty Rects &amp; performance 'tricks'</strong></p>
<p>When you read older bits of pygame documentation or guides online, you may see
some emphasis on only updating portions of the screen that are dirty, for the
sake of performance (in this context, &quot;dirty&quot; means the region has changed since
the previous frame was drawn).</p>
<p>Generally this entails calling <a class="tooltip reference internal" href="../ref/display.html#pygame.display.update" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.update()</span></code><span class="tooltip-content">Update portions of the screen for software displays</span></a> (with a list of
rects) instead of <a class="tooltip reference internal" href="../ref/display.html#pygame.display.flip" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.display.flip()</span></code><span class="tooltip-content">Update the full display Surface to the screen</span></a>, not having scrolling backgrounds,
or even not filling the screen with a background color every frame because pygame
supposedly can't handle it. Some of pygame's API is designed to support this
paradigm as well (e.g. <a class="tooltip reference internal" href="../ref/sprite.html#pygame.sprite.RenderUpdates" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.sprite.RenderUpdates()</span></code><span class="tooltip-content">Group sub-class that tracks dirty updates.</span></a>), which made a lot of
sense in the early years of pygame.</p>
<p>In the present day (2022) though, most modest desktop computers are powerful enough to
refresh the entire display once per frame at 60 FPS and beyond. You can have a moving
camera, or dynamic backgrounds and your game should run totally fine at 60 FPS. CPUs are
more powerful nowadays, and you can use <code class="docutils literal notranslate"><span class="pre">display.flip()</span></code> without fear.</p>
<p>That being said there are still some times when this old technique is still useful
for squeezing out a few extra FPS. For example, with a single screen game like
an Asteroids or Space Invaders. Here is the rough process for how it works:</p>
<p>Instead of updating the whole screen every frame, only the parts that changed since
the last frame are updated. You do this by keeping track of those rectangles in a list,
then calling <code class="docutils literal notranslate"><span class="pre">update(the_dirty_rectangles)</span></code> at the end of the frame. In detail
for a moving sprite:</p>
<blockquote>
<div><ul class="simple">
<li><p>Blit a piece of the background over the sprite's current location, erasing it.</p></li>
<li><p>Append the sprite's current location rectangle to a list called dirty_rects.</p></li>
<li><p>Move the sprite.</p></li>
<li><p>Draw the sprite at its new location.</p></li>
<li><p>Append the sprite's new location to my dirty_rects list.</p></li>
<li><p>Call <code class="docutils literal notranslate"><span class="pre">display.update(dirty_rects)</span></code></p></li>
</ul>
</div></blockquote>
<p>Even though this technique is not required for making performant 2D games with
modern CPUs, it is still useful to be aware of. There are also still plenty of other ways
to accidentally tank your game's performance with poorly optimized rendering logic.
For example, even on modern hardware it's probably too slow to call <code class="docutils literal notranslate"><span class="pre">set_at</span></code> once per pixel
on the display surface. Being mindful of performance is still something you'll have to
do.</p>
<p>There just aren't that many 'one neat trick to fix your code performance' tips. Every game
is different and there are different problems and different algorithms to solve them
efficiently in each type of game. Pretty much every time your 2D game code is failing to hit a
reasonable frame rate the underlying cause turns out to be bad algorithm or a misunderstanding
of fundamental game design patterns.</p>
<p>If you are having performance problems, first make sure you aren't loading files repeatedly in your
game loop, then use one of the many options for profiling your code to find out what is taking up the
most time. Once you are armed with at least some knowledge on why your game is slow, try asking the
internet (via google), or the pygame community if they've got some better algorithms to help you out.</p>
<p><strong>HWSURFACE and DOUBLEBUF</strong></p>
<p>The HWSURFACE <a class="reference internal" href="../ref/display.html#pygame.display.set_mode" title="pygame.display.set_mode"><code class="xref py py-func docutils literal notranslate"><span class="pre">display.set_mode()</span></code></a> flag does nothing in pygame versions 2.0.0 and
later (you can check the docs if you don't believe me)! There's no reason to
use it anymore. Even in pygame 1, its effect is pretty nuanced and
generally misunderstood by most pygame users. It was never a magic speed-up
flag, unfortunately.</p>
<p>DOUBLEBUF still has some use, but is also not a magic speed up flag.</p>
<p><strong>The Sprite class</strong></p>
<p>You don't need to use the built-in <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Sprite" title="pygame.sprite.Sprite"><code class="xref py py-class docutils literal notranslate"><span class="pre">Sprite</span></code></a> or <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Group" title="pygame.sprite.Group"><code class="xref py py-class docutils literal notranslate"><span class="pre">Group</span></code></a> classes
if you don't want to. In a lot of tutorials, it may seem like <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> is the
fundamental &quot;GameObject&quot; of pygame, from which all other objects must derive,
but in reality it's pretty much just a wrapper around a <code class="docutils literal notranslate"><span class="pre">Rect</span></code> and a
<code class="docutils literal notranslate"><span class="pre">Surface</span></code>, with some additional convenience methods. You may find it
more intuitive (and fun) to write your game's core logic and classes from
scratch.</p>
</section>
<section id="there-is-no-rule-six">
<h3>There is NO rule six.<a class="headerlink" href="#there-is-no-rule-six" title="Permalink to this heading"></a></h3>
</section>
<section id="don-t-get-distracted-by-side-issues">
<h3>Don't get distracted by side issues.<a class="headerlink" href="#don-t-get-distracted-by-side-issues" title="Permalink to this heading"></a></h3>
<p>Sometimes, new game programmers spend too much time worrying about issues that
aren't really critical to their game's success. The desire to get secondary
issues 'right' is understandable, but early in the process of creating a game,
you cannot even know what the important questions are, let alone what answers
you should choose. The result can be a lot of needless prevarication.</p>
<p>For example, consider the question of how to organize your graphics files.
Should each frame have its own graphics file, or each sprite? Perhaps all the
graphics should be zipped up into one archive? A great deal of time has been
wasted on a lot of projects, asking these questions on mailing lists, debating
the answers, profiling, etc, etc. This is a secondary issue; any time spent
discussing it should have been spent coding the actual game.</p>
<p>The insight here is that it is far better to have a 'pretty good' solution that
was actually implemented, than a perfect solution that you never got around to
writing.</p>
</section>
<section id="rects-are-your-friends">
<h3>Rects are your friends.<a class="headerlink" href="#rects-are-your-friends" title="Permalink to this heading"></a></h3>
<p>Pete Shinners' wrapper may have cool alpha effects and fast blitting speeds,
but I have to admit my favorite part of pygame is the lowly <a class="reference internal" href="../ref/rect.html#pygame.Rect" title="pygame.Rect"><code class="xref py py-class docutils literal notranslate"><span class="pre">Rect</span></code></a> class.
A rect is simply a rectangle -- defined only by the position of its top left
corner, its width, and its height. Many pygame functions take rects as
arguments, and they also take 'rectstyles', a sequence that has the same values
as a rect. So if I need a rectangle that defines the area between 10, 20 and
40, 50, I can do any of the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">rect</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">Rect</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span>
<span class="n">rect</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">Rect</span><span class="p">((</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">30</span><span class="p">))</span>
<span class="n">rect</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">Rect</span><span class="p">((</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">),</span> <span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="mi">30</span><span class="p">))</span>
<span class="n">rect</span> <span class="o">=</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span>
<span class="n">rect</span> <span class="o">=</span> <span class="p">((</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">30</span><span class="p">))</span>
</pre></div>
</div>
<p>If you use any of the first three versions, however, you get access to Rect's
utility functions. These include functions to move, shrink and inflate rects,
find the union of two rects, and a variety of collision-detection functions.</p>
<p>For example, suppose I'd like to get a list of all the sprites that contain a
point (x, y) -- maybe the player clicked there, or maybe that's the current
location of a bullet. It's simple if each sprite has a .rect member -- I just
do:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">sprites_clicked</span> <span class="o">=</span> <span class="p">[</span><span class="n">sprite</span> <span class="k">for</span> <span class="n">sprite</span> <span class="ow">in</span> <span class="n">all_my_sprites_list</span> <span class="k">if</span> <span class="n">sprite</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">collidepoint</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span>
</pre></div>
</div>
<p>Rects have no other relation to surfaces or graphics functions, other than the
fact that you can use them as arguments. You can also use them in places that
have nothing to do with graphics, but still need to be defined as rectangles.
Every project I discover a few new places to use rects where I never thought
I'd need them.</p>
</section>
<section id="don-t-bother-with-pixel-perfect-collision-detection">
<h3>Don't bother with pixel-perfect collision detection.<a class="headerlink" href="#don-t-bother-with-pixel-perfect-collision-detection" title="Permalink to this heading"></a></h3>
<p>So you've got your sprites moving around, and you need to know whether or not
they're bumping into one another. It's tempting to write something like the
following:</p>
<blockquote>
<div><ul class="simple">
<li><p>Check to see if the rects are in collision. If they aren't, ignore them.</p></li>
<li><p>For each pixel in the overlapping area, see if the corresponding pixels from both sprites are opaque. If so, there's a collision.</p></li>
</ul>
</div></blockquote>
<p>There are other ways to do this, with ANDing sprite masks and so on, but any
way you do it in pygame, it's probably going to be too slow. For most games,
it's probably better just to do 'sub-rect collision' -- create a rect for each
sprite that's a little smaller than the actual image, and use that for
collisions instead. It will be much faster, and in most cases the player won't
notice the imprecision.</p>
</section>
<section id="managing-the-event-subsystem">
<h3>Managing the event subsystem.<a class="headerlink" href="#managing-the-event-subsystem" title="Permalink to this heading"></a></h3>
<p>Pygame's event system is kind of tricky. There are actually two different ways
to find out what an input device (keyboard, mouse or joystick) is doing.</p>
<p>The first is by directly checking the state of the device. You do this by
calling, say, <a class="tooltip reference internal" href="../ref/mouse.html#pygame.mouse.get_pos" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.mouse.get_pos()</span></code><span class="tooltip-content">get the mouse cursor position</span></a> or <a class="tooltip reference internal" href="../ref/key.html#pygame.key.get_pressed" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.key.get_pressed()</span></code><span class="tooltip-content">get the state of all keyboard buttons</span></a>.
This will tell you the state of that device <em>at the moment you call the
function.</em></p>
<p>The second method uses the SDL event queue. This queue is a list of events --
events are added to the list as they're detected, and they're deleted from the
queue as they're read off.</p>
<p>There are advantages and disadvantages to each system. State-checking (system
1) gives you precision -- you know exactly when a given input was made -- if
<code class="docutils literal notranslate"><span class="pre">mouse.get_pressed([0])</span></code> is 1, that means that the left mouse button is
down <em>right at this moment</em>. The event queue merely reports that the
mouse was down at some time in the past; if you check the queue fairly often,
that can be ok, but if you're delayed from checking it by other code, input
latency can grow. Another advantage of the state-checking system is that it
detects &quot;chording&quot; easily; that is, several states at the same time. If you
want to know whether the <code class="docutils literal notranslate"><span class="pre">t</span></code> and <code class="docutils literal notranslate"><span class="pre">f</span></code> keys are down at the same time, just
check:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">key</span><span class="o">.</span><span class="n">get_pressed</span><span class="p">[</span><span class="n">K_t</span><span class="p">]</span> <span class="ow">and</span> <span class="n">key</span><span class="o">.</span><span class="n">get_pressed</span><span class="p">[</span><span class="n">K_f</span><span class="p">]:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Yup!&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>In the queue system, however, each keypress arrives in the queue as a
completely separate event, so you'd need to remember that the <code class="docutils literal notranslate"><span class="pre">t</span></code> key was
down, and hadn't come up yet, while checking for the <code class="docutils literal notranslate"><span class="pre">f</span></code> key. A little more
complicated.</p>
<p>The state system has one great weakness, however. It only reports what the
state of the device is at the moment it's called; if the user hits a mouse
button then releases it just before a call to <code class="docutils literal notranslate"><span class="pre">mouse.get_pressed()</span></code>, the
mouse button will return 0 -- <code class="docutils literal notranslate"><span class="pre">get_pressed()</span></code> missed the mouse button press
completely. The two events, <code class="docutils literal notranslate"><span class="pre">MOUSEBUTTONDOWN</span></code> and <code class="docutils literal notranslate"><span class="pre">MOUSEBUTTONUP</span></code>, will
still be sitting in the event queue, however, waiting to be retrieved and
processed.</p>
<p>The lesson is: choose the system that meets your requirements. If you don't
have much going on in your loop -- say you're just sitting in a <code class="docutils literal notranslate"><span class="pre">while</span> <span class="pre">True</span></code>
loop, waiting for input, use <code class="docutils literal notranslate"><span class="pre">get_pressed()</span></code> or another state function; the
latency will be lower. On the other hand, if every keypress is crucial, but
latency isn't as important -- say your user is typing something in an editbox,
use the event queue. Some key presses may be slightly late, but at least you'll
get them all.</p>
<p>A note about <code class="docutils literal notranslate"><span class="pre">event.poll()</span></code> vs. <code class="docutils literal notranslate"><span class="pre">wait()</span></code> -- <code class="docutils literal notranslate"><span class="pre">poll()</span></code> may seem better,
since it doesn't block your program from doing anything while it's waiting for
input -- <code class="docutils literal notranslate"><span class="pre">wait()</span></code> suspends the program until an event is received.
However, <code class="docutils literal notranslate"><span class="pre">poll()</span></code> will consume 100% of available CPU time while it runs,
and it will fill the event queue with <code class="docutils literal notranslate"><span class="pre">NOEVENTS</span></code>. Use <code class="docutils literal notranslate"><span class="pre">set_blocked()</span></code> to
select just those event types you're interested in -- your queue will be much
more manageable.</p>
<p>Another note about the event queue -- even if you don't want to use it, you must
still clear it periodically because it's still going to be filling up with events
in the background as the user presses keys and mouses over the window. On Windows,
if your game goes too long without clearing the queue, the operating system will
think it has frozen and show a &quot;The application is not responding&quot; message.
Iterating over <code class="docutils literal notranslate"><span class="pre">event.get()</span></code> or simply calling <code class="docutils literal notranslate"><span class="pre">event.clear()</span></code> once per frame
will avoid this.</p>
</section>
<section id="colorkey-vs-alpha">
<h3>Colorkey vs. Alpha.<a class="headerlink" href="#colorkey-vs-alpha" title="Permalink to this heading"></a></h3>
<p>There's a lot of confusion around these two techniques, and much of it comes
from the terminology used.</p>
<p>'Colorkey blitting' involves telling pygame that all pixels of a certain color
in a certain image are transparent instead of whatever color they happen to be.
These transparent pixels are not blitted when the rest of the image is blitted,
and so don't obscure the background. This is how we make sprites that aren't
rectangular in shape. Simply call <a class="reference internal" href="../ref/surface.html#pygame.Surface.set_colorkey" title="pygame.Surface.set_colorkey"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Surface.set_colorkey()</span></code></a>, and pass in
an RGB tuple -- say (0,0,0). This would make every pixel in the source image
transparent instead of black.</p>
<p>'Alpha' is different, and it comes in two flavors. 'Image alpha' applies to the
whole image, and is probably what you want. Properly known as 'translucency',
alpha causes each pixel in the source image to be only <em>partially</em> opaque.
For example, if you set a surface's alpha to 192 and then blitted it onto a
background, 3/4 of each pixel's color would come from the source image, and 1/4
from the background. Alpha is measured from 255 to 0, where 0 is completely
transparent, and 255 is completely opaque. Note that colorkey and alpha
blitting can be combined -- this produces an image that is fully transparent in
some spots, and semi-transparent in others.</p>
<p>'Per-pixel alpha' is the other flavor of alpha, and it's more complicated.
Basically, each pixel in the source image has its own alpha value, from 0 to
255. Each pixel, therefore, can have a different opacity when blitted onto a
background. This type of alpha can't be mixed with colorkey blitting,
and it overrides per-image alpha. Per-pixel alpha is rarely used in
games, and to use it you have to save your source image in a graphic
editor with a special <em>alpha channel</em>. It's complicated -- don't use it
yet.</p>
</section>
<section id="software-architecture-design-patterns-and-games">
<h3>Software architecture, design patterns, and games.<a class="headerlink" href="#software-architecture-design-patterns-and-games" title="Permalink to this heading"></a></h3>
<p>You may reach a point where you're comfortable writing code, you're able to solve
complex problems without assistance, you understand how to use most of pygame's
modules, and yet, as you work on larger projects they always seem to get messier
and harder to maintain as time goes on. This can manifest in many ways -- for
example, fixing bugs in one place might always seem to create new bugs elsewhere,
figuring out <em>where</em> code should go might become a challenge, adding new
things might frequently require you to rewrite many other things, and so on.
Finally, you decide to cut your losses and start fresh on something new.</p>
<p>This is a common issue and it can be frustrating -- on the one hand, your
programming skills are improving, and yet you aren't able to finish the games
you start due to somewhat nebulous organizational problems.</p>
<p>This brings us to the concept of software architecture and design patterns. You
may be familiar with pygame's &quot;standard&quot; base template (there are many equivalent
variations of this, so don't stress about the small details too much):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pygame</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">1280</span><span class="p">,</span><span class="mi">720</span><span class="p">))</span>
<span class="n">clock</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">Clock</span><span class="p">()</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="c1"># Process player inputs.</span>
<span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">pygame</span><span class="o">.</span><span class="n">QUIT</span><span class="p">:</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
<span class="k">raise</span> <span class="ne">SystemExit</span>
<span class="c1"># Do logical updates here.</span>
<span class="c1"># ...</span>
<span class="n">screen</span><span class="o">.</span><span class="n">fill</span><span class="p">(</span><span class="s2">&quot;purple&quot;</span><span class="p">)</span> <span class="c1"># Fill the display with a solid color</span>
<span class="c1"># Render the graphics here.</span>
<span class="c1"># ...</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span> <span class="c1"># Refresh on-screen display</span>
<span class="n">clock</span><span class="o">.</span><span class="n">tick</span><span class="p">(</span><span class="mi">60</span><span class="p">)</span> <span class="c1"># wait until next frame (at 60 FPS)</span>
</pre></div>
</div>
<p>It does some initial setup, starts a loop, and then proceeds to repeatedly
collect input, handle the game's logic, and draw the current frame forever until
the program ends. The update, render, wait loop shown here is actually a design
pattern that serves as the skeleton of most games -- it's prolific because it's
clean, it's organized, and it works. (There's also an important but easy-to-miss
design feature here in the form of a strict division between the game's logic
and rendering routines. This decision alone prevents a whole category of potential
bugs related to objects updating and rendering concurrently, which is nice).</p>
<p>It turns out that there are many design patterns like this that are used frequently
in games and in software development at large. For a great resource on this
specifically for games, I highly recommend <a class="reference external" href="https://gameprogrammingpatterns.com/contents.html">Game Programming Patterns</a>, a short
free, e-book on the topic. It covers a bunch of useful patterns and concrete situations
where you might want to employ them. It won't instantly make you a better coder,
but learning some theory about software architecture can go a long way towards
helping you escape plateaus and tackle larger projects more confidently.</p>
</section>
<section id="do-things-the-pythony-way">
<h3>Do things the pythony way.<a class="headerlink" href="#do-things-the-pythony-way" title="Permalink to this heading"></a></h3>
<p>A final note (this isn't the least important one; it just comes at the end).
Pygame is a pretty lightweight wrapper around SDL, which is in turn a pretty
lightweight wrapper around your native OS graphics calls. Chances are pretty
good that if your code is still slow, and you've done the things I've mentioned
above, then the problem lies in the way you're addressing your data in python.
Certain idioms are just going to be slow in python no matter what you do.
Luckily, python is a very clear language -- if a piece of code looks awkward or
unwieldy, chances are its speed can be improved, too. Read over <a class="reference external" href="https://blubberquark.tumblr.com/post/630054903238262784/why-pygame-is-slow">Why Pygame is
Slow</a> for some deeper insight into why pygame might be considered slower than
other frameworks/engines, and what that actually means in practice.
And if you're truly stumped by performance problems, profilers like <a class="reference external" href="https://docs.python.org/3/library/profile.html">cProfile</a>
(or <a class="reference external" href="https://jiffyclub.github.io/snakeviz/">SnakeViz</a>, a visualizer for cProfile) can help identify bottlenecks (they'll
tell you which parts of the code are taking the longest to execute). That said,
premature optimisation is the root of all evil; if it's already fast enough,
don't torture the code trying to make it faster. If it's fast enough, let it
be :)</p>
<p>There you go. Now you know practically everything I know about using pygame.
Now, go write that game!</p>
<hr class="docutils" />
<p><em>David Clark is an avid pygame user and the editor of the Pygame Code
Repository, a showcase for community-submitted python game code. He is also
the author of Twitch, an entirely average pygame arcade game.</em></p>
<p><em>This guide was substantially updated in 2022.</em></p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/newbieguide.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="en/Red_or_Black/1.Prolog/introduction.html" title="Author: Youngwook Kim (Korean)"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="SurfarrayIntro.html" title="Pygame Tutorials - Surfarray Introduction"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">A Newbie Guide to pygame</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,236 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Revision: Pygame fundamentals &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Kicking things off" href="tom_games3.html" />
<link rel="prev" title="Making Games With Pygame" href="MakeGames.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="revision-pygame-fundamentals">
<section id="makegames-2">
<span id="id1"></span><h2>2. Revision: Pygame fundamentals<a class="headerlink" href="#makegames-2" title="Permalink to this heading"></a></h2>
<section id="the-basic-pygame-game">
<span id="makegames-2-1"></span><h3>2.1. The basic Pygame game<a class="headerlink" href="#the-basic-pygame-game" title="Permalink to this heading"></a></h3>
<p>For the sake of revision, and to ensure that you are familiar with the basic structure of a Pygame program, I'll briefly run through
a basic Pygame program, which will display no more than a window with some text in it, that should, by the end, look something like
this (though of course the window decoration will probably be different on your system):</p>
<img alt="../_images/tom_basic.png" src="../_images/tom_basic.png" />
<p>The full code for this example looks like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/python</span>
<span class="kn">import</span> <span class="nn">pygame</span>
<span class="kn">from</span> <span class="nn">pygame.locals</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1"># Initialise screen</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">150</span><span class="p">,</span> <span class="mi">50</span><span class="p">))</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_caption</span><span class="p">(</span><span class="s1">&#39;Basic Pygame program&#39;</span><span class="p">)</span>
<span class="c1"># Fill background</span>
<span class="n">background</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">Surface</span><span class="p">(</span><span class="n">screen</span><span class="o">.</span><span class="n">get_size</span><span class="p">())</span>
<span class="n">background</span> <span class="o">=</span> <span class="n">background</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="n">background</span><span class="o">.</span><span class="n">fill</span><span class="p">((</span><span class="mi">250</span><span class="p">,</span> <span class="mi">250</span><span class="p">,</span> <span class="mi">250</span><span class="p">))</span>
<span class="c1"># Display some text</span>
<span class="n">font</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">font</span><span class="o">.</span><span class="n">Font</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">36</span><span class="p">)</span>
<span class="n">text</span> <span class="o">=</span> <span class="n">font</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s2">&quot;Hello There&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
<span class="n">textpos</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="n">textpos</span><span class="o">.</span><span class="n">centerx</span> <span class="o">=</span> <span class="n">background</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span><span class="o">.</span><span class="n">centerx</span>
<span class="n">background</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">textpos</span><span class="p">)</span>
<span class="c1"># Blit everything to the screen</span>
<span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
<span class="c1"># Event loop</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">QUIT</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span> <span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
</section>
<section id="basic-pygame-objects">
<span id="makegames-2-2"></span><h3>2.2. Basic Pygame objects<a class="headerlink" href="#basic-pygame-objects" title="Permalink to this heading"></a></h3>
<p>As you can see, the code consists of three main objects: the screen, the background, and the text. Each of these objects is created
by first calling an instance of an in-built Pygame object, and then modifying it to fit our needs. The screen is a slightly special
case, because we still modify the display through Pygame calls, rather than calling methods belonging to the screen object. But for
all other Pygame objects, we first create the object as a copy of a Pygame object, giving it some attributes, and build our game
objects from them.</p>
<p>With the background, we first create a Pygame Surface object, and make it the size of the screen. We then perform the convert()
operation to convert the Surface to a single pixel format. This is more obviously necessary when we have several images and surfaces,
all of different pixel formats, which makes rendering them quite slow. By converting all the surfaces, we can drastically speed up
rendering times. Finally, we fill the background surface with white (255, 255, 255). These values are <em class="firstterm">RGB</em> (Red Green
Blue), and can be worked out from any good paint program.</p>
<p>With the text, we require more than one object. First, we create a font object, which defines which font to use, and the size of the
font. Then we create a text object, by using the <code class="docutils literal notranslate"><span class="pre">render</span></code> method that belongs to our font object, supplying three arguments:
the text to be rendered, whether or not it should be anti-aliased (1=yes, 0=no), and the color of the text (again in RGB format). Next
we create a third text object, which gets the rectangle for the text. The easiest way to understand this is to imagine drawing a
rectangle that will surround all of the text; you can then use this rectangle to get/set the position of the text on the screen. So
in this example we get the rectangle, set its <code class="docutils literal notranslate"><span class="pre">centerx</span></code> attribute to be the <code class="docutils literal notranslate"><span class="pre">centerx</span></code> attribute of the
background (so the text's center will be the same as the background's center, i.e. the text will be centered on the screen on the x
axis). We could also set the y coordinate, but it's not any different so I left the text at the top of the screen. As the screen is
small anyway, it didn't seem necessary.</p>
</section>
<section id="blitting">
<span id="makegames-2-3"></span><h3>2.3. Blitting<a class="headerlink" href="#blitting" title="Permalink to this heading"></a></h3>
<p>Now we have created our game objects, we need to actually render them. If we didn't and we ran the program, we'd just see a
blank window, and the objects would remain invisible. The term used for rendering objects is <em class="firstterm">blitting</em>, which is where
you copy the pixels belonging to said object onto the destination object. So to render the background object, you blit it onto the
screen. In this example, to make things simple, we blit the text onto the background (so the background will now have a copy of the
text on it), and then blit the background onto the screen.</p>
<p>Blitting is one of the slowest operations in any game, so you need to be careful not to blit too much onto the screen in every frame.
If you have a background image, and a ball flying around the screen, then you could blit the background and then the ball in every
frame, which would cover up the ball's previous position and render the new ball, but this would be pretty slow. A better solution is
to blit the background onto the area that the ball previously occupied, which can be found by the ball's previous rectangle, and then
blitting the ball, so that you are only blitting two small areas.</p>
</section>
<section id="the-event-loop">
<span id="makegames-2-4"></span><h3>2.4. The event loop<a class="headerlink" href="#the-event-loop" title="Permalink to this heading"></a></h3>
<p>Once you've set the game up, you need to put it into a loop so that it will continuously run until the user signals that he/she wants
to exit. So you start an open <code class="docutils literal notranslate"><span class="pre">while</span></code> loop, and then for each iteration of the loop, which will be each frame of the game,
update the game. The first thing is to check for any Pygame events, which will be the user hitting the keyboard, clicking a mouse
button, moving a joystick, resizing the window, or trying to close it. In this case, we simply want to watch out for for user trying
to quit the game by closing the window, in which case the game should <code class="docutils literal notranslate"><span class="pre">return</span></code>, which will end the <code class="docutils literal notranslate"><span class="pre">while</span></code> loop.
Then we simply need to re-blit the background, and flip (update) the display to have everything drawn. OK, as nothing moves or happens
in this example, we don't strictly speaking need to re-blit the background in every iteration, but I put it in because when things are
moving around on the screen, you will need to do all your blitting here.</p>
</section>
<section id="ta-da">
<span id="makegames-2-5"></span><h3>2.5. Ta-da!<a class="headerlink" href="#ta-da" title="Permalink to this heading"></a></h3>
<p>And that's it - your most basic Pygame game! All games will take a form similar to this, but with lots more code for the actual game
functions themselves, which are more to do your with programming, and less guided in structure by the workings of Pygame. This is what
this tutorial is really about, and will now go onto.</p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/tom_games2.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="tom_games3.html" title="Kicking things off"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="MakeGames.html" title="Making Games With Pygame"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Revision: Pygame fundamentals</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,216 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Kicking things off &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Game object classes" href="tom_games4.html" />
<link rel="prev" title="Revision: Pygame fundamentals" href="tom_games2.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="kicking-things-off">
<section id="makegames-3">
<span id="id1"></span><h2>3. Kicking things off<a class="headerlink" href="#makegames-3" title="Permalink to this heading"></a></h2>
<p>The first sections of code are relatively simple, and, once written, can usually be reused in every game you consequently make. They
will do all of the boring, generic tasks like loading modules, loading images, opening networking connections, playing music, and so
on. They will also include some simple but effective error handling, and any customisation you wish to provide on top of functions
provided by modules like <code class="docutils literal notranslate"><span class="pre">sys</span></code> and <code class="docutils literal notranslate"><span class="pre">pygame</span></code>.</p>
<section id="the-first-lines-and-loading-modules">
<span id="makegames-3-1"></span><h3>3.1. The first lines, and loading modules<a class="headerlink" href="#the-first-lines-and-loading-modules" title="Permalink to this heading"></a></h3>
<p>First off, you need to start off your game and load up your modules. It's always a good idea to set a few things straight at the top of
the main source file, such as the name of the file, what it contains, the license it is under, and any other helpful info you might
want to give those who will be looking at it. Then you can load modules, with some error checking so that Python doesn't print out
a nasty traceback, which non-programmers won't understand. The code is fairly simple, so I won't bother explaining any of it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/env python</span>
<span class="c1">#</span>
<span class="c1"># Tom&#39;s Pong</span>
<span class="c1"># A simple pong game with realistic physics and AI</span>
<span class="c1"># http://tomchance.org.uk/projects/pong</span>
<span class="c1">#</span>
<span class="c1"># Released under the GNU General Public License</span>
<span class="n">VERSION</span> <span class="o">=</span> <span class="s2">&quot;0.4&quot;</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">math</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">getopt</span>
<span class="kn">import</span> <span class="nn">pygame</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">pygame.locals</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">,</span> <span class="n">err</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;couldn&#39;t load module. </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="resource-handling-functions">
<span id="makegames-3-2"></span><h3>3.2. Resource handling functions<a class="headerlink" href="#resource-handling-functions" title="Permalink to this heading"></a></h3>
<p>In the <a class="reference internal" href="ChimpLineByLine.html"><span class="doc">Line By Line Chimp</span></a> example, the first code to be written was for loading images and sounds. As these
were totally independent of any game logic or game objects, they were written as separate functions, and were written first so
that later code could make use of them. I generally put all my code of this nature first, in their own, classless functions; these
will, generally speaking, be resource handling functions. You can of course create classes for these, so that you can group them
together, and maybe have an object with which you can control all of your resources. As with any good programming environment, it's up
to you to develop your own best practice and style.</p>
<p>It's always a good idea to write your own resource handling functions,
because although Pygame has methods for opening images and sounds, and other modules will have their methods of opening other
resources, those methods can take up more than one line, they can require consistent modification by yourself, and they often don't
provide satisfactory error handling. Writing resource handling functions gives you sophisticated, reusable code, and gives you more
control over your resources. Take this example of an image loading function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">load_png</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot; Load image and return image object&quot;&quot;&quot;</span>
<span class="n">fullname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s2">&quot;data&quot;</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="k">if</span> <span class="n">image</span><span class="o">.</span><span class="n">get_alpha</span><span class="p">()</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">convert_alpha</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">FileNotFoundError</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Cannot load image: </span><span class="si">{</span><span class="n">fullname</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">raise</span> <span class="ne">SystemExit</span>
<span class="k">return</span> <span class="n">image</span><span class="p">,</span> <span class="n">image</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
</pre></div>
</div>
<p>Here we make a more sophisticated image loading function than the one provided by <a class="tooltip reference internal" href="../ref/image.html#pygame.image.load" title=""><code class="xref py py-func docutils literal notranslate"><span class="pre">pygame.image.load()</span></code><span class="tooltip-content">load new image from a file (or file-like object)</span></a>. Note that
the first line of the function is a documentation string describing what the function does, and what object(s) it returns. The
function assumes that all of your images are in a directory called data, and so it takes the filename and creates the full pathname,
for example <code class="docutils literal notranslate"><span class="pre">data/ball.png</span></code>, using the <em class="citetitle">os</em> module to ensure cross-platform compatibility. Then it
tries to load the image, and convert any alpha regions so you can achieve transparency, and it returns a more human-readable error
if there's a problem. Finally it returns the image object, and its <a class="reference internal" href="../ref/rect.html#pygame.Rect" title="pygame.Rect"><code class="xref py py-class docutils literal notranslate"><span class="pre">rect</span></code></a>.</p>
<p>You can make similar functions for loading any other resources, such as loading sounds. You can also make resource handling classes,
to give you more flexibility with more complex resources. For example, you could make a music class, with an <code class="docutils literal notranslate"><span class="pre">__init__</span></code>
function that loads the sound (perhaps borrowing from a <code class="docutils literal notranslate"><span class="pre">load_sound()</span></code> function), a function to pause the music, and a
function to restart. Another handy resource handling class is for network connections. Functions to open sockets, pass data with
suitable security and error checking, close sockets, finger addresses, and other network tasks, can make writing a game with network
capabilities relatively painless.</p>
<p>Remember the chief task of these functions/classes is to ensure that by the time you get around to writing game object classes,
and the main loop, there's almost nothing left to do. Class inheritance can make these basic classes especially handy. Don't go
overboard though; functions which will only be used by one class should be written as part of that class, not as a global
function.</p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/tom_games3.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="tom_games4.html" title="Game object classes"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="tom_games2.html" title="Revision: Pygame fundamentals"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Kicking things off</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,245 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Game object classes &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="User-controllable objects" href="tom_games5.html" />
<link rel="prev" title="Kicking things off" href="tom_games3.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="game-object-classes">
<section id="makegames-4">
<span id="id1"></span><h2>4. Game object classes<a class="headerlink" href="#makegames-4" title="Permalink to this heading"></a></h2>
<p>Once you've loaded your modules, and written your resource handling functions, you'll want to get on to writing some game objects.
The way this is done is fairly simple, though it can seem complex at first. You write a class for each type of object in the game,
and then create an instance of those classes for the objects. You can then use those classes' methods to manipulate the objects,
giving objects some motion and interactive capabilities. So your game, in pseudo-code, will look like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/python</span>
<span class="c1"># [load modules here]</span>
<span class="c1"># [resource handling functions here]</span>
<span class="k">class</span> <span class="nc">Ball</span><span class="p">:</span>
<span class="c1"># [ball functions (methods) here]</span>
<span class="c1"># [e.g. a function to calculate new position]</span>
<span class="c1"># [and a function to check if it hits the side]</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">:</span>
<span class="c1"># [initiate game environment here]</span>
<span class="c1"># [create new object as instance of ball class]</span>
<span class="n">ball</span> <span class="o">=</span> <span class="n">Ball</span><span class="p">()</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="c1"># [check for user input]</span>
<span class="c1"># [call ball&#39;s update function]</span>
<span class="n">ball</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
</pre></div>
</div>
<p>This is, of course, a very simple example, and you'd need to put in all the code, instead of those little bracketed comments. But
you should get the basic idea. You create a class, into which you put all the functions for a ball, including <code class="docutils literal notranslate"><span class="pre">__init__</span></code>,
which would create all the ball's attributes, and <code class="docutils literal notranslate"><span class="pre">update</span></code>, which would move the ball to its new position, before blitting
it onto the screen in this position.</p>
<p>You can then create more classes for all of your other game objects, and then create instances of them so that you can handle them
easily in the <code class="docutils literal notranslate"><span class="pre">main</span></code> function and the main program loop. Contrast this with initiating the ball in the <code class="docutils literal notranslate"><span class="pre">main</span></code>
function, and then having lots of classless functions to manipulate a set ball object, and you'll hopefully see why using classes is
an advantage: It allows you to put all of the code for each object in one place; it makes using objects easier; it makes adding new
objects, and manipulating them, more flexible. Rather than adding more code for each new ball object, you could simply create new
instances of the <code class="docutils literal notranslate"><span class="pre">Ball</span></code> class for each new ball object. Magic!</p>
<section id="a-simple-ball-class">
<span id="makegames-4-1"></span><h3>4.1. A simple ball class<a class="headerlink" href="#a-simple-ball-class" title="Permalink to this heading"></a></h3>
<p>Here is a simple class with the functions necessary for creating a ball object that will, if the <code class="docutils literal notranslate"><span class="pre">update</span></code> function is called
in the main loop, move across the screen:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Ball</span><span class="p">(</span><span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;A ball that will move across the screen</span>
<span class="sd"> Returns: ball object</span>
<span class="sd"> Functions: update, calcnewpos</span>
<span class="sd"> Attributes: area, vector&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">vector</span><span class="p">):</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">load_png</span><span class="p">(</span><span class="s1">&#39;ball.png&#39;</span><span class="p">)</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">get_surface</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">area</span> <span class="o">=</span> <span class="n">screen</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">vector</span> <span class="o">=</span> <span class="n">vector</span>
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">newpos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">calcnewpos</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="p">,</span><span class="bp">self</span><span class="o">.</span><span class="n">vector</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">newpos</span>
<span class="k">def</span> <span class="nf">calcnewpos</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">rect</span><span class="p">,</span><span class="n">vector</span><span class="p">):</span>
<span class="p">(</span><span class="n">angle</span><span class="p">,</span><span class="n">z</span><span class="p">)</span> <span class="o">=</span> <span class="n">vector</span>
<span class="p">(</span><span class="n">dx</span><span class="p">,</span><span class="n">dy</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="n">z</span><span class="o">*</span><span class="n">math</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">angle</span><span class="p">),</span><span class="n">z</span><span class="o">*</span><span class="n">math</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">angle</span><span class="p">))</span>
<span class="k">return</span> <span class="n">rect</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">dx</span><span class="p">,</span><span class="n">dy</span><span class="p">)</span>
</pre></div>
</div>
<p>Here we have the <code class="docutils literal notranslate"><span class="pre">Ball</span></code> class, with an <code class="docutils literal notranslate"><span class="pre">__init__</span></code> function that sets the ball up, an <code class="docutils literal notranslate"><span class="pre">update</span></code>
function that changes the ball's rectangle to be in the new position, and a <code class="docutils literal notranslate"><span class="pre">calcnewpos</span></code> function to calculate the ball's
new position based on its current position, and the vector by which it is moving. I'll explain the physics in a moment. The one other
thing to note is the documentation string, which is a little bit longer this time, and explains the basics of the class. These strings
are handy not only to yourself and other programmers looking at the code, but also for tools to parse your code and document it. They
won't make much of a difference in small programs, but with large ones they're invaluable, so it's a good habit to get into.</p>
<section id="diversion-1-sprites">
<span id="makegames-4-1-1"></span><h4>4.1.1. Diversion 1: Sprites<a class="headerlink" href="#diversion-1-sprites" title="Permalink to this heading"></a></h4>
<p>The other reason for creating a class for each object is sprites. Each image you render in your game will be a sprite object, and so
to begin with, the class for each object should inherit the <a class="reference internal" href="../ref/sprite.html#pygame.sprite.Sprite" title="pygame.sprite.Sprite"><code class="xref py py-class docutils literal notranslate"><span class="pre">Sprite</span></code></a> class.
This is a really nice feature of Python - class
inheritance. Now the <code class="docutils literal notranslate"><span class="pre">Ball</span></code> class has all of the functions that come with the <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> class, and any object
instances of the <code class="docutils literal notranslate"><span class="pre">Ball</span></code> class will be registered by Pygame as sprites. Whereas with text and the background, which don't
move, it's OK to blit the object onto the background, Pygame handles sprite objects in a different manner, which you'll see when we
look at the whole program's code.</p>
<p>Basically, you create both a ball object, and a sprite object for that ball, and you then call the ball's update function on the
sprite object, thus updating the sprite. Sprites also give you sophisticated ways of determining if two objects have collided.
Normally you might just check in the main loop to see if their rectangles overlap, but that would involve a lot of code, which would
be a waste because the <code class="docutils literal notranslate"><span class="pre">Sprite</span></code> class provides two functions (<code class="docutils literal notranslate"><span class="pre">spritecollide</span></code> and <code class="docutils literal notranslate"><span class="pre">groupcollide</span></code>)
to do this for you.</p>
</section>
<section id="diversion-2-vector-physics">
<span id="makegames-4-1-2"></span><h4>4.1.2. Diversion 2: Vector physics<a class="headerlink" href="#diversion-2-vector-physics" title="Permalink to this heading"></a></h4>
<p>Other than the structure of the <code class="docutils literal notranslate"><span class="pre">Ball</span></code> class, the notable thing about this code is the vector physics, used to calculate
the ball's movement. With any game involving angular movement, you won't get very far unless you're comfortable with trigonometry, so
I'll just introduce the basics you need to know to make sense of the <code class="docutils literal notranslate"><span class="pre">calcnewpos</span></code> function.</p>
<p>To begin with, you'll notice that the ball has an attribute <code class="docutils literal notranslate"><span class="pre">vector</span></code>, which is made up of <code class="docutils literal notranslate"><span class="pre">angle</span></code> and <code class="docutils literal notranslate"><span class="pre">z</span></code>.
The angle is measured in radians, and will give you the direction in which the ball is moving. Z is the speed at which the ball
moves. So by using this vector, we can determine the direction and speed of the ball, and therefore how much it will move on the x and
y axes:</p>
<img alt="../_images/tom_radians.png" src="../_images/tom_radians.png" />
<p>The diagram above illustrates the basic maths behind vectors. In the left hand diagram, you can see the ball's projected movement
represented by the blue line. The length of that line (z) represents its speed, and the angle is the direction in which
it will move. The angle for the ball's movement will always be taken from the x axis on the right, and it is measured clockwise from
that line, as shown in the diagram.</p>
<p>From the angle and speed of the ball, we can then work out how much it has moved along the x and y axes. We need to do this because
Pygame doesn't support vectors itself, and we can only move the ball by moving its rectangle along the two axes. So we need to
<em class="firstterm">resolve</em> the angle and speed into its movement on the x axis (dx) and on the y axis (dy). This is a simple matter of
trigonometry, and can be done with the formulae shown in the diagram.</p>
<p>If you've studied elementary trigonometry before, none of this should be news to you. But just in case you're forgetful, here are some
useful formulae to remember, that will help you visualise the angles (I find it easier to visualise angles in degrees than in radians!)</p>
<img alt="../_images/tom_formulae.png" src="../_images/tom_formulae.png" />
</section>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/tom_games4.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="tom_games5.html" title="User-controllable objects"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="tom_games3.html" title="Kicking things off"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Game object classes</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,234 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>User-controllable objects &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Putting it all together" href="tom_games6.html" />
<link rel="prev" title="Game object classes" href="tom_games4.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="user-controllable-objects">
<section id="makegames-5">
<span id="id1"></span><h2>5. User-controllable objects<a class="headerlink" href="#makegames-5" title="Permalink to this heading"></a></h2>
<p>So far you can create a Pygame window, and render a ball that will fly across the screen. The next step is to make some bats which
the user can control. This is potentially far more simple than the ball, because it requires no physics (unless your user-controlled
object will move in ways more complex than up and down, e.g. a platform character like Mario, in which case you'll need more physics).
User-controllable objects are pretty easy to create, thanks to Pygame's event queue system, as you'll see.</p>
<section id="a-simple-bat-class">
<span id="makegames-5-1"></span><h3>5.1. A simple bat class<a class="headerlink" href="#a-simple-bat-class" title="Permalink to this heading"></a></h3>
<p>The principle behind the bat class is similar to that of the ball class. You need an <code class="docutils literal notranslate"><span class="pre">__init__</span></code> function to initialise the
ball (so you can create object instances for each bat), an <code class="docutils literal notranslate"><span class="pre">update</span></code> function to perform per-frame changes on the bat before
it is blitted the bat to the screen, and the functions that will define what this class will actually do. Here's some sample code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Bat</span><span class="p">(</span><span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Movable tennis &#39;bat&#39; with which one hits the ball</span>
<span class="sd"> Returns: bat object</span>
<span class="sd"> Functions: reinit, update, moveup, movedown</span>
<span class="sd"> Attributes: which, speed&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">side</span><span class="p">):</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">load_png</span><span class="p">(</span><span class="s2">&quot;bat.png&quot;</span><span class="p">)</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">get_surface</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">area</span> <span class="o">=</span> <span class="n">screen</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">side</span> <span class="o">=</span> <span class="n">side</span>
<span class="bp">self</span><span class="o">.</span><span class="n">speed</span> <span class="o">=</span> <span class="mi">10</span>
<span class="bp">self</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;still&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">reinit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">reinit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;still&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">movepos</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">side</span> <span class="o">==</span> <span class="s2">&quot;left&quot;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">midleft</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">midleft</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">side</span> <span class="o">==</span> <span class="s2">&quot;right&quot;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">midright</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">midright</span>
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">newpos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">contains</span><span class="p">(</span><span class="n">newpos</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">newpos</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">pump</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">moveup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">speed</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;moveup&quot;</span>
<span class="k">def</span> <span class="nf">movedown</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">speed</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;movedown&quot;</span>
</pre></div>
</div>
<p>As you can see, this class is very similar to the ball class in its structure. But there are differences in what each function does.
First of all, there is a reinit function, which is used when a round ends, and the bat needs to be set back in its starting place,
with any attributes set back to their necessary values. Next, the way in which the bat is moved is a little more complex than with the
ball, because here its movement is simple (up/down), but it relies on the user telling it to move, unlike the ball which just keeps
moving in every frame. To make sense of how the bat moves, it is helpful to look at a quick diagram to show the sequence of events:</p>
<img alt="../_images/tom_event-flowchart.png" src="../_images/tom_event-flowchart.png" />
<p>What happens here is that the person controlling the bat pushes down on the key that moves the bat up. For each iteration of the main
game loop (for every frame), if the key is still held down, then the <code class="docutils literal notranslate"><span class="pre">state</span></code> attribute of that bat object will be set to
&quot;moving&quot;, and the <code class="docutils literal notranslate"><span class="pre">moveup</span></code> function will be called, causing the ball's y position to be reduced by the value of the
<code class="docutils literal notranslate"><span class="pre">speed</span></code> attribute (in this example, 10). In other words, so long as the key is held down, the bat will move up the screen
by 10 pixels per frame. The <code class="docutils literal notranslate"><span class="pre">state</span></code> attribute isn't used here yet, but it's useful to know if you're dealing with spin, or
would like some useful debugging output.</p>
<p>As soon as the player lets go of that key, the second set of boxes is invoked, and the <code class="docutils literal notranslate"><span class="pre">state</span></code> attribute of the bat object
will be set back to &quot;still&quot;, and the <code class="docutils literal notranslate"><span class="pre">movepos</span></code> attribute will be set back to [0,0], meaning that when the <code class="docutils literal notranslate"><span class="pre">update</span></code> function is called, it won't move the bat any more. So when the player lets go of the key, the bat stops moving. Simple!</p>
<section id="diversion-3-pygame-events">
<span id="makegames-5-1-1"></span><h4>5.1.1. Diversion 3: Pygame events<a class="headerlink" href="#diversion-3-pygame-events" title="Permalink to this heading"></a></h4>
<p>So how do we know when the player is pushing keys down, and then releasing them? With the Pygame event queue system, dummy! It's a
really easy system to use and understand, so this shouldn't take long :) You've already seen the event queue in action in the basic
Pygame program, where it was used to check if the user was quitting the application. The code for moving the bat is about as simple
as that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">QUIT</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">KEYDOWN</span><span class="p">:</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_UP</span><span class="p">:</span>
<span class="n">player</span><span class="o">.</span><span class="n">moveup</span><span class="p">()</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_DOWN</span><span class="p">:</span>
<span class="n">player</span><span class="o">.</span><span class="n">movedown</span><span class="p">()</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">KEYUP</span><span class="p">:</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_UP</span> <span class="ow">or</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_DOWN</span><span class="p">:</span>
<span class="n">player</span><span class="o">.</span><span class="n">movepos</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span>
<span class="n">player</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;still&quot;</span>
</pre></div>
</div>
<p>Here assume that you've already created an instance of a bat, and called the object <code class="docutils literal notranslate"><span class="pre">player</span></code>. You can see the familiar
layout of the <code class="docutils literal notranslate"><span class="pre">for</span></code> structure, which iterates through each event found in the Pygame event queue, which is retrieved with
the <a class="reference internal" href="../ref/event.html#pygame.event.get" title="pygame.event.get"><code class="xref py py-mod docutils literal notranslate"><span class="pre">event.get()</span></code></a> function. As the user hits keys, pushes mouse buttons and moves the joystick about, those actions are
pumped into the Pygame event queue, and left there until dealt with. So in each iteration of the main game loop, you go through
these events, checking if they're ones you want to deal with, and then dealing with them appropriately. The <a class="reference internal" href="../ref/event.html#pygame.event.pump" title="pygame.event.pump"><code class="xref py py-func docutils literal notranslate"><span class="pre">event.pump()</span></code></a>
function that was in the <code class="docutils literal notranslate"><span class="pre">Bat.update</span></code> function is then called in every iteration to pump out old events, and keep the queue
current.</p>
<p>First we check if the user is quitting the program, and quit it if they are. Then we check if any keys are being pushed down, and if
they are, we check if they're the designated keys for moving the bat up and down. If they are, then we call the appropriate moving
function, and set the player state appropriately (though the states moveup and movedown and changed in the <code class="docutils literal notranslate"><span class="pre">moveup()</span></code> and
<code class="docutils literal notranslate"><span class="pre">movedown()</span></code> functions, which makes for neater code, and doesn't break <em>encapsulation</em>, which means that you
assign attributes to the object itself, without referring to the name of the instance of that object). Notice here we have three
states: still, moveup, and movedown. Again, these come in handy if you want to debug or calculate spin. We also check if any keys have
been &quot;let go&quot; (i.e. are no longer being held down), and again if they're the right keys, we stop the bat from moving.</p>
</section>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/tom_games5.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="tom_games6.html" title="Putting it all together"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="tom_games4.html" title="Game object classes"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">User-controllable objects</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>

View File

@@ -0,0 +1,433 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Putting it all together &#8212; pygame v2.5.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pygame.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<link rel="icon" href="../_static/pygame.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Pygame Tutorials - Help! How Do I Move An Image?" href="MoveIt.html" />
<link rel="prev" title="User-controllable objects" href="tom_games5.html" />
</head><body>
<div class="document">
<div class="header">
<div class="flex-container">
<div class="logo">
<a href="https://www.pygame.org/">
<img src="../_static/pygame_tiny.png"/>
</a>
<h5>pygame documentation</h5>
</div>
<div class="pagelinks">
<div class="top">
<a href="https://www.pygame.org/">Pygame Home</a> ||
<a href="../index.html">Help Contents</a> ||
<a href="../genindex.html">Reference Index</a>
<form action="../search.html" method="get" style="display:inline;float:right;">
<input name="q" value="" type="text">
<input value="search" type="submit">
</form>
</div>
<hr style="color:black;border-bottom:none;border-style: dotted;border-bottom-style:none;">
<p class="bottom"><b>Most useful stuff</b>:
<a href="../ref/color.html">Color</a> |
<a href="../ref/display.html">display</a> |
<a href="../ref/draw.html">draw</a> |
<a href="../ref/event.html">event</a> |
<a href="../ref/font.html">font</a> |
<a href="../ref/image.html">image</a> |
<a href="../ref/key.html">key</a> |
<a href="../ref/locals.html">locals</a> |
<a href="../ref/mixer.html">mixer</a> |
<a href="../ref/mouse.html">mouse</a> |
<a href="../ref/rect.html">Rect</a> |
<a href="../ref/surface.html">Surface</a> |
<a href="../ref/time.html">time</a> |
<a href="../ref/music.html">music</a> |
<a href="../ref/pygame.html">pygame</a>
</p>
<p class="bottom"><b>Advanced stuff</b>:
<a href="../ref/cursors.html">cursors</a> |
<a href="../ref/joystick.html">joystick</a> |
<a href="../ref/mask.html">mask</a> |
<a href="../ref/sprite.html">sprite</a> |
<a href="../ref/transform.html">transform</a> |
<a href="../ref/bufferproxy.html">BufferProxy</a> |
<a href="../ref/freetype.html">freetype</a> |
<a href="../ref/gfxdraw.html">gfxdraw</a> |
<a href="../ref/midi.html">midi</a> |
<a href="../ref/pixelarray.html">PixelArray</a> |
<a href="../ref/pixelcopy.html">pixelcopy</a> |
<a href="../ref/sndarray.html">sndarray</a> |
<a href="../ref/surfarray.html">surfarray</a> |
<a href="../ref/math.html">math</a>
</p>
<p class="bottom"><b>Other</b>:
<a href="../ref/camera.html">camera</a> |
<a href="../ref/sdl2_controller.html#module-pygame._sdl2.controller">controller</a> |
<a href="../ref/examples.html">examples</a> |
<a href="../ref/fastevent.html">fastevent</a> |
<a href="../ref/scrap.html">scrap</a> |
<a href="../ref/tests.html">tests</a> |
<a href="../ref/touch.html">touch</a> |
<a href="../ref/pygame.html#module-pygame.version">version</a>
</p>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="body" role="main">
<section id="putting-it-all-together">
<section id="makegames-6">
<span id="id1"></span><h2>6. Putting it all together<a class="headerlink" href="#makegames-6" title="Permalink to this heading"></a></h2>
<p>So far you've learnt all the basics necessary to build a simple game. You should understand how to create Pygame objects, how Pygame
displays objects, how it handles events, and how you can use physics to introduce some motion into your game. Now I'll just show how
you can take all those chunks of code and put them together into a working game. What we need first is to let the ball hit the sides
of the screen, and for the bat to be able to hit the ball, otherwise there's not going to be much gameplay involved. We do this
using Pygame's <a class="reference internal" href="../ref/rect.html#pygame.Rect.collidepoint" title="pygame.Rect.collidepoint"><code class="xref py py-meth docutils literal notranslate"><span class="pre">collision</span></code></a> methods.</p>
<section id="let-the-ball-hit-sides">
<span id="makegames-6-1"></span><h3>6.1. Let the ball hit sides<a class="headerlink" href="#let-the-ball-hit-sides" title="Permalink to this heading"></a></h3>
<p>The basic principle behind making it bounce of the sides is easy to grasp. You grab the coordinates of the four corners of the ball,
and check to see if they correspond with the x or y coordinate of the edge of the screen. So if the top right and top left corners both
have a y coordinate of zero, you know that the ball is currently on the top edge of the screen. We do all this in the <code class="docutils literal notranslate"><span class="pre">update</span></code> function,
after we've worked out the new position of the ball.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">contains</span><span class="p">(</span><span class="n">newpos</span><span class="p">):</span>
<span class="n">tl</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">collidepoint</span><span class="p">(</span><span class="n">newpos</span><span class="o">.</span><span class="n">topleft</span><span class="p">)</span>
<span class="n">tr</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">collidepoint</span><span class="p">(</span><span class="n">newpos</span><span class="o">.</span><span class="n">topright</span><span class="p">)</span>
<span class="n">bl</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">collidepoint</span><span class="p">(</span><span class="n">newpos</span><span class="o">.</span><span class="n">bottomleft</span><span class="p">)</span>
<span class="n">br</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">collidepoint</span><span class="p">(</span><span class="n">newpos</span><span class="o">.</span><span class="n">bottomright</span><span class="p">)</span>
<span class="k">if</span> <span class="n">tr</span> <span class="ow">and</span> <span class="n">tl</span> <span class="ow">or</span> <span class="p">(</span><span class="n">br</span> <span class="ow">and</span> <span class="n">bl</span><span class="p">):</span>
<span class="n">angle</span> <span class="o">=</span> <span class="o">-</span><span class="n">angle</span>
<span class="k">if</span> <span class="n">tl</span> <span class="ow">and</span> <span class="n">bl</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">offcourt</span><span class="p">(</span><span class="n">player</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="k">if</span> <span class="n">tr</span> <span class="ow">and</span> <span class="n">br</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">offcourt</span><span class="p">(</span><span class="n">player</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">vector</span> <span class="o">=</span> <span class="p">(</span><span class="n">angle</span><span class="p">,</span><span class="n">z</span><span class="p">)</span>
</pre></div>
</div>
<p>Here we check to see if the <code class="docutils literal notranslate"><span class="pre">area</span></code>
contains the new position of the ball (it always should, so we needn't have an <code class="docutils literal notranslate"><span class="pre">else</span></code> clause,
though in other circumstances you might want to consider it). We then check if the coordinates for the four corners
are <em>colliding</em> with the area's edges, and create objects for each result. If they are, the objects will have a value of 1,
or <code class="docutils literal notranslate"><span class="pre">True</span></code>. If they don't, then the value will be <code class="docutils literal notranslate"><span class="pre">None</span></code>, or <code class="docutils literal notranslate"><span class="pre">False</span></code>. We then see if it has hit the top or bottom, and if it
has we change the ball's direction. Handily, using radians we can do this by simply reversing its positive/negative value.
We also check to see if the ball has gone off the sides, and if it has we call the <code class="docutils literal notranslate"><span class="pre">offcourt</span></code> function.
This, in my game, resets the ball, adds 1 point to the score of the player specified when calling the function, and displays the new score.</p>
<p>Finally, we recompile the vector based on the new angle. And that is it. The ball will now merrily bounce off the walls and go
offcourt with good grace.</p>
</section>
<section id="let-the-ball-hit-bats">
<span id="makegames-6-2"></span><h3>6.2. Let the ball hit bats<a class="headerlink" href="#let-the-ball-hit-bats" title="Permalink to this heading"></a></h3>
<p>Making the ball hit the bats is very similar to making it hit the sides of the screen. We still use the collide method, but this time
we check to see if the rectangles for the ball and either bat collide. In this code I've also put in some extra code to avoid various
glitches. You'll find that you'll have to put all sorts of extra code in to avoid glitches and bugs, so it's good to get used to seeing
it.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">else</span><span class="p">:</span>
<span class="c1"># Deflate the rectangles so you can&#39;t catch a ball behind the bat</span>
<span class="n">player1</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">inflate</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">)</span>
<span class="n">player2</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">inflate</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">)</span>
<span class="c1"># Do ball and bat collide?</span>
<span class="c1"># Note I put in an odd rule that sets self.hit to 1 when they collide, and unsets it in the next</span>
<span class="c1"># iteration. this is to stop odd ball behaviour where it finds a collision *inside* the</span>
<span class="c1"># bat, the ball reverses, and is still inside the bat, so bounces around inside.</span>
<span class="c1"># This way, the ball can always escape and bounce away cleanly</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">colliderect</span><span class="p">(</span><span class="n">player1</span><span class="o">.</span><span class="n">rect</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span><span class="p">:</span>
<span class="n">angle</span> <span class="o">=</span> <span class="n">math</span><span class="o">.</span><span class="n">pi</span> <span class="o">-</span> <span class="n">angle</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hit</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">colliderect</span><span class="p">(</span><span class="n">player2</span><span class="o">.</span><span class="n">rect</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span><span class="p">:</span>
<span class="n">angle</span> <span class="o">=</span> <span class="n">math</span><span class="o">.</span><span class="n">pi</span> <span class="o">-</span> <span class="n">angle</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hit</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hit</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span>
<span class="bp">self</span><span class="o">.</span><span class="n">vector</span> <span class="o">=</span> <span class="p">(</span><span class="n">angle</span><span class="p">,</span><span class="n">z</span><span class="p">)</span>
</pre></div>
</div>
<p>We start this section with an <code class="docutils literal notranslate"><span class="pre">else</span></code> statement, because this carries on from the previous chunk of code to check if the ball
hits the sides. It makes sense that if it doesn't hit the sides, it might hit a bat, so we carry on the conditional statement. The
first glitch to fix is to shrink the players' rectangles by 3 pixels in both dimensions, to stop the bat catching a ball that goes
behind them (if you imagine you just move the bat so that as the ball travels behind it, the rectangles overlap, and so normally the
ball would then have been &quot;hit&quot; - this prevents that).</p>
<p>Next we check if the rectangles collide, with one more glitch fix. Notice that I've commented on these odd bits of code - it's always
good to explain bits of code that are abnormal, both for others who look at your code, and so you understand it when you come back to
it. The without the fix, the ball might hit a corner of the bat, change direction, and one frame later still find itself inside the
bat. Then it would again think it has been hit, and change its direction. This can happen several times, making the ball's motion
completely unrealistic. So we have a variable, <code class="docutils literal notranslate"><span class="pre">self.hit</span></code>, which we set to <code class="docutils literal notranslate"><span class="pre">True</span></code> when it has been hit, and <code class="docutils literal notranslate"><span class="pre">False</span></code> one frame
later. When we check if the rectangles have collided, we also check if <code class="docutils literal notranslate"><span class="pre">self.hit</span></code> is <code class="docutils literal notranslate"><span class="pre">True</span></code>/<code class="docutils literal notranslate"><span class="pre">False</span></code>, to stop internal bouncing.</p>
<p>The important code here is pretty easy to understand. All rectangles have a <a class="reference internal" href="../ref/rect.html#pygame.Rect.colliderect" title="pygame.Rect.colliderect"><code class="xref py py-meth docutils literal notranslate"><span class="pre">colliderect</span></code></a>
function, into which you feed the rectangle of another object, which returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if the rectangles do overlap, and <code class="docutils literal notranslate"><span class="pre">False</span></code> if not.
If they do, we can change the direction by subtracting the current angle from <code class="docutils literal notranslate"><span class="pre">pi</span></code> (again, a handy trick you can do with radians,
which will adjust the angle by 90 degrees and send it off in the right direction; you might find at this point that a thorough
understanding of radians is in order!). Just to finish the glitch checking, we switch <code class="docutils literal notranslate"><span class="pre">self.hit</span></code> back to <code class="docutils literal notranslate"><span class="pre">False</span></code> if it's the frame
after they were hit.</p>
<p>We also then recompile the vector. You would of course want to remove the same line in the previous chunk of code, so that you only do
this once after the <code class="docutils literal notranslate"><span class="pre">if-else</span></code> conditional statement. And that's it! The combined code will now allow the ball to hit sides and bats.</p>
</section>
<section id="the-finished-product">
<span id="makegames-6-3"></span><h3>6.3. The Finished product<a class="headerlink" href="#the-finished-product" title="Permalink to this heading"></a></h3>
<p>The final product, with all the bits of code thrown together, as well as some other bits ofcode to glue it all together, will look
like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">#</span>
<span class="c1"># Tom&#39;s Pong</span>
<span class="c1"># A simple pong game with realistic physics and AI</span>
<span class="c1"># http://tomchance.org.uk/projects/pong</span>
<span class="c1">#</span>
<span class="c1"># Released under the GNU General Public License</span>
<span class="n">VERSION</span> <span class="o">=</span> <span class="s2">&quot;0.4&quot;</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">math</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">getopt</span>
<span class="kn">import</span> <span class="nn">pygame</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">pygame.locals</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">,</span> <span class="n">err</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;couldn&#39;t load module. </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">load_png</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot; Load image and return image object&quot;&quot;&quot;</span>
<span class="n">fullname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s2">&quot;data&quot;</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="k">if</span> <span class="n">image</span><span class="o">.</span><span class="n">get_alpha</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">convert_alpha</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">FileNotFoundError</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Cannot load image: </span><span class="si">{</span><span class="n">fullname</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">raise</span> <span class="ne">SystemExit</span>
<span class="k">return</span> <span class="n">image</span><span class="p">,</span> <span class="n">image</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="k">class</span> <span class="nc">Ball</span><span class="p">(</span><span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;A ball that will move across the screen</span>
<span class="sd"> Returns: ball object</span>
<span class="sd"> Functions: update, calcnewpos</span>
<span class="sd"> Attributes: area, vector&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="p">(</span><span class="n">xy</span><span class="p">),</span> <span class="n">vector</span><span class="p">):</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">load_png</span><span class="p">(</span><span class="s2">&quot;ball.png&quot;</span><span class="p">)</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">get_surface</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">area</span> <span class="o">=</span> <span class="n">screen</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">vector</span> <span class="o">=</span> <span class="n">vector</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hit</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">newpos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">calcnewpos</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="p">,</span><span class="bp">self</span><span class="o">.</span><span class="n">vector</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">newpos</span>
<span class="p">(</span><span class="n">angle</span><span class="p">,</span><span class="n">z</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">vector</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">contains</span><span class="p">(</span><span class="n">newpos</span><span class="p">):</span>
<span class="n">tl</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">collidepoint</span><span class="p">(</span><span class="n">newpos</span><span class="o">.</span><span class="n">topleft</span><span class="p">)</span>
<span class="n">tr</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">collidepoint</span><span class="p">(</span><span class="n">newpos</span><span class="o">.</span><span class="n">topright</span><span class="p">)</span>
<span class="n">bl</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">collidepoint</span><span class="p">(</span><span class="n">newpos</span><span class="o">.</span><span class="n">bottomleft</span><span class="p">)</span>
<span class="n">br</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">collidepoint</span><span class="p">(</span><span class="n">newpos</span><span class="o">.</span><span class="n">bottomright</span><span class="p">)</span>
<span class="k">if</span> <span class="n">tr</span> <span class="ow">and</span> <span class="n">tl</span> <span class="ow">or</span> <span class="p">(</span><span class="n">br</span> <span class="ow">and</span> <span class="n">bl</span><span class="p">):</span>
<span class="n">angle</span> <span class="o">=</span> <span class="o">-</span><span class="n">angle</span>
<span class="k">if</span> <span class="n">tl</span> <span class="ow">and</span> <span class="n">bl</span><span class="p">:</span>
<span class="c1">#self.offcourt()</span>
<span class="n">angle</span> <span class="o">=</span> <span class="n">math</span><span class="o">.</span><span class="n">pi</span> <span class="o">-</span> <span class="n">angle</span>
<span class="k">if</span> <span class="n">tr</span> <span class="ow">and</span> <span class="n">br</span><span class="p">:</span>
<span class="n">angle</span> <span class="o">=</span> <span class="n">math</span><span class="o">.</span><span class="n">pi</span> <span class="o">-</span> <span class="n">angle</span>
<span class="c1">#self.offcourt()</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Deflate the rectangles so you can&#39;t catch a ball behind the bat</span>
<span class="n">player1</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">inflate</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">)</span>
<span class="n">player2</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">inflate</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">)</span>
<span class="c1"># Do ball and bat collide?</span>
<span class="c1"># Note I put in an odd rule that sets self.hit to 1 when they collide, and unsets it in the next</span>
<span class="c1"># iteration. this is to stop odd ball behaviour where it finds a collision *inside* the</span>
<span class="c1"># bat, the ball reverses, and is still inside the bat, so bounces around inside.</span>
<span class="c1"># This way, the ball can always escape and bounce away cleanly</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">colliderect</span><span class="p">(</span><span class="n">player1</span><span class="o">.</span><span class="n">rect</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span><span class="p">:</span>
<span class="n">angle</span> <span class="o">=</span> <span class="n">math</span><span class="o">.</span><span class="n">pi</span> <span class="o">-</span> <span class="n">angle</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hit</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">colliderect</span><span class="p">(</span><span class="n">player2</span><span class="o">.</span><span class="n">rect</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span><span class="p">:</span>
<span class="n">angle</span> <span class="o">=</span> <span class="n">math</span><span class="o">.</span><span class="n">pi</span> <span class="o">-</span> <span class="n">angle</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hit</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hit</span> <span class="o">=</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">hit</span>
<span class="bp">self</span><span class="o">.</span><span class="n">vector</span> <span class="o">=</span> <span class="p">(</span><span class="n">angle</span><span class="p">,</span><span class="n">z</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">calcnewpos</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">rect</span><span class="p">,</span><span class="n">vector</span><span class="p">):</span>
<span class="p">(</span><span class="n">angle</span><span class="p">,</span><span class="n">z</span><span class="p">)</span> <span class="o">=</span> <span class="n">vector</span>
<span class="p">(</span><span class="n">dx</span><span class="p">,</span><span class="n">dy</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="n">z</span><span class="o">*</span><span class="n">math</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">angle</span><span class="p">),</span><span class="n">z</span><span class="o">*</span><span class="n">math</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">angle</span><span class="p">))</span>
<span class="k">return</span> <span class="n">rect</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">dx</span><span class="p">,</span><span class="n">dy</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Bat</span><span class="p">(</span><span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Movable tennis &#39;bat&#39; with which one hits the ball</span>
<span class="sd"> Returns: bat object</span>
<span class="sd"> Functions: reinit, update, moveup, movedown</span>
<span class="sd"> Attributes: which, speed&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">side</span><span class="p">):</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">Sprite</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">image</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">load_png</span><span class="p">(</span><span class="s2">&quot;bat.png&quot;</span><span class="p">)</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">get_surface</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">area</span> <span class="o">=</span> <span class="n">screen</span><span class="o">.</span><span class="n">get_rect</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">side</span> <span class="o">=</span> <span class="n">side</span>
<span class="bp">self</span><span class="o">.</span><span class="n">speed</span> <span class="o">=</span> <span class="mi">10</span>
<span class="bp">self</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;still&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">reinit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">reinit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;still&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">movepos</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">side</span> <span class="o">==</span> <span class="s2">&quot;left&quot;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">midleft</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">midleft</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">side</span> <span class="o">==</span> <span class="s2">&quot;right&quot;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">midright</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">midright</span>
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">newpos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rect</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="o">.</span><span class="n">contains</span><span class="p">(</span><span class="n">newpos</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rect</span> <span class="o">=</span> <span class="n">newpos</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">pump</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">moveup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">speed</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;moveup&quot;</span>
<span class="k">def</span> <span class="nf">movedown</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">movepos</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">speed</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;movedown&quot;</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1"># Initialise screen</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="n">screen</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">((</span><span class="mi">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">))</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_caption</span><span class="p">(</span><span class="s2">&quot;Basic Pong&quot;</span><span class="p">)</span>
<span class="c1"># Fill background</span>
<span class="n">background</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">Surface</span><span class="p">(</span><span class="n">screen</span><span class="o">.</span><span class="n">get_size</span><span class="p">())</span>
<span class="n">background</span> <span class="o">=</span> <span class="n">background</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
<span class="n">background</span><span class="o">.</span><span class="n">fill</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="c1"># Initialise players</span>
<span class="k">global</span> <span class="n">player1</span>
<span class="k">global</span> <span class="n">player2</span>
<span class="n">player1</span> <span class="o">=</span> <span class="n">Bat</span><span class="p">(</span><span class="s2">&quot;left&quot;</span><span class="p">)</span>
<span class="n">player2</span> <span class="o">=</span> <span class="n">Bat</span><span class="p">(</span><span class="s2">&quot;right&quot;</span><span class="p">)</span>
<span class="c1"># Initialise ball</span>
<span class="n">speed</span> <span class="o">=</span> <span class="mi">13</span>
<span class="n">rand</span> <span class="o">=</span> <span class="p">((</span><span class="mf">0.1</span> <span class="o">*</span> <span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="mi">8</span><span class="p">))))</span>
<span class="n">ball</span> <span class="o">=</span> <span class="n">Ball</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">),(</span><span class="mf">0.47</span><span class="p">,</span><span class="n">speed</span><span class="p">))</span>
<span class="c1"># Initialise sprites</span>
<span class="n">playersprites</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">RenderPlain</span><span class="p">((</span><span class="n">player1</span><span class="p">,</span> <span class="n">player2</span><span class="p">))</span>
<span class="n">ballsprite</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">sprite</span><span class="o">.</span><span class="n">RenderPlain</span><span class="p">(</span><span class="n">ball</span><span class="p">)</span>
<span class="c1"># Blit everything to the screen</span>
<span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
<span class="c1"># Initialise clock</span>
<span class="n">clock</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">Clock</span><span class="p">()</span>
<span class="c1"># Event loop</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="c1"># Make sure game doesn&#39;t run at more than 60 frames per second</span>
<span class="n">clock</span><span class="o">.</span><span class="n">tick</span><span class="p">(</span><span class="mi">60</span><span class="p">)</span>
<span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">QUIT</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">KEYDOWN</span><span class="p">:</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_a</span><span class="p">:</span>
<span class="n">player1</span><span class="o">.</span><span class="n">moveup</span><span class="p">()</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_z</span><span class="p">:</span>
<span class="n">player1</span><span class="o">.</span><span class="n">movedown</span><span class="p">()</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_UP</span><span class="p">:</span>
<span class="n">player2</span><span class="o">.</span><span class="n">moveup</span><span class="p">()</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_DOWN</span><span class="p">:</span>
<span class="n">player2</span><span class="o">.</span><span class="n">movedown</span><span class="p">()</span>
<span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">KEYUP</span><span class="p">:</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_a</span> <span class="ow">or</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_z</span><span class="p">:</span>
<span class="n">player1</span><span class="o">.</span><span class="n">movepos</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span>
<span class="n">player1</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;still&quot;</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_UP</span> <span class="ow">or</span> <span class="n">event</span><span class="o">.</span><span class="n">key</span> <span class="o">==</span> <span class="n">K_DOWN</span><span class="p">:</span>
<span class="n">player2</span><span class="o">.</span><span class="n">movepos</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span>
<span class="n">player2</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;still&quot;</span>
<span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="n">ball</span><span class="o">.</span><span class="n">rect</span><span class="p">,</span> <span class="n">ball</span><span class="o">.</span><span class="n">rect</span><span class="p">)</span>
<span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="n">player1</span><span class="o">.</span><span class="n">rect</span><span class="p">,</span> <span class="n">player1</span><span class="o">.</span><span class="n">rect</span><span class="p">)</span>
<span class="n">screen</span><span class="o">.</span><span class="n">blit</span><span class="p">(</span><span class="n">background</span><span class="p">,</span> <span class="n">player2</span><span class="o">.</span><span class="n">rect</span><span class="p">,</span> <span class="n">player2</span><span class="o">.</span><span class="n">rect</span><span class="p">)</span>
<span class="n">ballsprite</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
<span class="n">playersprites</span><span class="o">.</span><span class="n">update</span><span class="p">()</span>
<span class="n">ballsprite</span><span class="o">.</span><span class="n">draw</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="n">playersprites</span><span class="o">.</span><span class="n">draw</span><span class="p">(</span><span class="n">screen</span><span class="p">)</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<p>As well as showing you the final product, I'll point you back to TomPong, upon which all of this is based. Download it, have a look
at the source code, and you'll see a full implementation of pong using all of the code you've seen in this tutorial, as well as lots of
other code I've added in various versions, such as some extra physics for spinning, and various other bug and glitch fixes.</p>
<p>Oh, find TomPong at <a class="reference external" href="http://tomchance.org.uk/projects/pong">http://tomchance.org.uk/projects/pong</a>.</p>
</section>
</section>
</section>
<br /><br />
<hr />
<a href="https://github.com/pygame/pygame/edit/main/docs/reST/tut/tom_games6.rst" rel="nofollow">Edit on GitHub</a>
<div class="clearer"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="MoveIt.html" title="Pygame Tutorials - Help! How Do I Move An Image?"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="tom_games5.html" title="User-controllable objects"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">pygame v2.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Putting it all together</a></li>
<script type="text/javascript" src="https://www.pygame.org/comment/jquery.plugin.docscomments.js"></script>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2000-2023, pygame developers.
</div>
</body>
</html>