added completly new version for haslach 2025
This commit is contained in:
@@ -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 — 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%40eclecti.cc">nrp<span>@</span>eclecti<span>.</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">"/dev/video0"</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">"Sorry, no cameras detected."</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'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">"RGB"</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">"YUV"</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">"HSV"</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'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">></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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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%40shinners.org">pete<span>@</span>shinners<span>.</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 "chimp".
|
||||
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">"Warning, fonts disabled"</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">"Warning, sound disabled"</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">"data"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>First, we import the standard "os" 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 "data" 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">"""moves a clenched fist on the screen, following the mouse"""</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">"fist.png"</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">"""move the fist based on the mouse position"""</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">"""returns true if the fist collides with the target"""</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">"""called to pull the fist back"""</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 "image" and "rect" 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 "punching" 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">"""moves a monkey critter across the screen. it can spin the</span>
|
||||
<span class="sd"> monkey when it is punched."""</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">"chimp.png"</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">"""walk or spin, depending on the monkeys state"""</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">"""move the monkey across the screen, and turn at the ends"""</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"><</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">></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">"""spin the monkey image"""</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">>=</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">"""this will cause the monkey to start spinning"""</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 "area" to be the size of the display screen.</p>
|
||||
<p>The <cite>update</cite> function for the chimp simply looks at the current "dizzy"
|
||||
state, which is true when the monkey is spinning from a punch. It calls either
|
||||
the <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 "dizzy". The dizzy
|
||||
attribute is used to store the current amount of rotation. When the monkey
|
||||
has rotated all the way around (360 degrees) it resets the monkey image
|
||||
back to the original, non-rotated version. Before calling the
|
||||
<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 "rotate". There is no need to do that
|
||||
for this example, it is just done here to keep the following line's length a
|
||||
little shorter. Note that when calling the <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 "original".</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">"Monkey Fever"</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">"Pummel The Chimp, And Win $$$"</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 "Rect" 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">"whiff.wav"</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">"punch.wav"</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 "allsprites" by passing a list with all the sprites that
|
||||
should belong in the group. We could later on add or remove sprites from this
|
||||
group, but in this game we won't need to.</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 "RenderPlain"
|
||||
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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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%40shinners.org">pete<span>@</span>shinners<span>.</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
|
||||
"real" 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">>>> </span><span class="kn">import</span> <span class="nn">pygame.display</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">init</span><span class="p">()</span>
|
||||
<span class="gp">>>> </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">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">info</span><span class="p">)</span>
|
||||
<span class="go"><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">></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">>>> </span><span class="c1"># give me the best depth with a 640 x 480 windowed display</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">640</span><span class="p">,</span> <span class="mi">480</span><span class="p">))</span>
|
||||
|
||||
<span class="gp">>>> </span><span class="c1"># give me the biggest 16-bit display available</span>
|
||||
<span class="gp">>>> </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">>>> </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">'16-bit not supported'</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">'Found Resolution:'</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">>>> </span><span class="c1"># need an 8-bit surface, nothing else will do</span>
|
||||
<span class="gp">>>> </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">'Can only work with an 8-bit display, sorry'</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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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%40shinners.org">pete<span>@</span>shinners<span>.</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 "import pygame", pygame
|
||||
will check to see if the font module is available. If the font module is available
|
||||
it will be imported as "pygame.font". If the module is not available, "pygame.font"
|
||||
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 "pygame.init()", 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 "get_init()" 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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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 "game", 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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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? — 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%40shinners.org">pete<span>@</span>shinners<span>.</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 "move" 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 "erase" 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 "illusion" 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
|
||||
"erase" 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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </span><span class="n">playerpos</span> <span class="o">=</span> <span class="mi">3</span>
|
||||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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 "erase" 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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </span><span class="n">playerpos</span> <span class="o">=</span> <span class="mi">3</span>
|
||||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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: "blit"<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>"assigning"</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 "terrain1", "terrain2", and "hero". 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">>>> </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">>>> </span><span class="n">screen</span> <span class="o">=</span> <span class="n">create_graphics_screen</span><span class="p">()</span>
|
||||
<span class="gp">>>> </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">>>> </span><span class="n">playerpos</span> <span class="o">=</span> <span class="mi">3</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">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">>>> </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">>>> </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">>>> </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 "erase" 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">>>> </span><span class="n">screen</span> <span class="o">=</span> <span class="n">create_screen</span><span class="p">()</span>
|
||||
<span class="gp">>>> </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">>>> </span><span class="n">player</span> <span class="o">=</span> <span class="n">load_player_image</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">background</span> <span class="o">=</span> <span class="n">load_background_image</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="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">>>> </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">>>> </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">>>> </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="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">>>> </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">'player.bmp'</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
|
||||
<span class="gp">>>> </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">'liquid.bmp'</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">>>> </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 "event handling" to our
|
||||
program. All graphical programs use this Event Based design. The program
|
||||
gets events like "keyboard pressed" or "mouse moved" 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">>>> </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">>>> </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">></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">>>> </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">>>> </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">>>> </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">'player.bmp'</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
|
||||
<span class="gp">>>> </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">'background.bmp'</span><span class="p">)</span><span class="o">.</span><span class="n">convert</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="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
|
||||
<span class="gp">>>> </span><span class="n">objects</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="gp">>>> </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</i></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">>>> </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">>>> </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">></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">></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"><</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"><</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">>>> </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>
|
||||
</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">>>> </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">>>> </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">>>> </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">'player.bmp'</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
|
||||
<span class="gp">>>> </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">'alien1.bmp'</span><span class="p">)</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
|
||||
<span class="gp">>>> </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">'background.bmp'</span><span class="p">)</span><span class="o">.</span><span class="n">convert</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="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
|
||||
<span class="gp">>>> </span><span class="n">objects</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="gp">>>> </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">>>> </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</i></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">>>> </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 "delete" 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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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%40shinners.org">pete<span>@</span>shinners<span>.</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 "C style" 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">"intro_ball.gif"</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"><</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">></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"><</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">></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 "Why do
|
||||
we need to erase anything, why don't we just move the ball on the
|
||||
screen?" 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 "trail" 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>"Is Python suitable for gaming?" The answer is, "It depends on the
|
||||
game."</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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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%40shinners.org">pete<span>@</span>shinners<span>.</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 "chimp" and "aliens") 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 "reference" 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 "sprite" 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
|
||||
"sprites" 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 "valid" or
|
||||
"alive" 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 "dummy" <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 "truth" operator, which allows you to do "if mygroup:" 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 "non-group"
|
||||
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
|
||||
"close_to_player" 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 "close_to_player" flag. Later on your game could
|
||||
add multiple players, and instead of adding more "close_to_player2",
|
||||
"close_to_player3" 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 "chasing" 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 "no frills" 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 "forgets" 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 "image" and "rect"
|
||||
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">-></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 "rect" attribute for all the sprites used. It returns a list of
|
||||
all the sprites that overlap with the first sprite. The "dokill" 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">>>> </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 "bomb" group that collide with the player.
|
||||
Because of the "dokill" argument it deletes all the crashed bombs. For each
|
||||
bomb that did collide, it plays a "boom" 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 "funny" 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">-></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">>>> </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
|
||||
"shot" could have collided against multiple "aliens".</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 "rect"
|
||||
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">'mysprite'</span> <span class="n">instance</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="s1">'_Sprite__g'</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 "image"
|
||||
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">"""call sprite.draw(screen) to render sprites"""</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'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 "require" two methods. "add_internal()" and
|
||||
"remove_internal()". 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 "add_internal()" and "remove_internal()"
|
||||
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 "_spritegroup". 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 "group" 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 "see" the difference.)</p>
|
||||
<p>You should go through the code for the sprite module. While the code is a bit
|
||||
"tuned", 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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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%40shinners.org">pete<span>@</span>shinners<span>.</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>"Examples"</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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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 "element-wise
|
||||
operations". 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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></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">>>> </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">>>> </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">>>> </span><span class="n">aa</span> <span class="c1">#show the slice</span>
|
||||
<span class="go">array([2, 3])</span>
|
||||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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 "2D")</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 "<code class="docutils literal notranslate"><span class="pre">:</span></code>" 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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">"NumPy and Surfarray are required."</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">'allblack'</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">'striped'</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">'surfarray.png'</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">'rgbarray'</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">'flipped'</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">'scaledown'</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">'scaleup'</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">'redimg'</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">'soften'</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">'xfade'</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>"del"</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>"in place"</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>"flame"</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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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">""" 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 'popular' 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">"""</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">"Warning, fonts disabled"</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">"Warning, sound disabled"</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">"data"</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">"""moves a clenched fist on the screen, following the mouse"""</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">"fist.png"</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">"""move the fist based on the mouse position"""</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">"""returns true if the fist collides with the target"""</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">"""called to pull the fist back"""</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">"""moves a monkey critter across the screen. it can spin the</span>
|
||||
<span class="sd"> monkey when it is punched."""</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">"chimp.png"</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">"""walk or spin, depending on the monkeys state"""</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">"""move the monkey across the screen, and turn at the ends"""</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"><</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">></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">"""spin the monkey image"""</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">>=</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">"""this will cause the monkey to start spinning"""</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">"""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."""</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">"Monkey Fever"</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">"Pummel The Chimp, And Win $$$"</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">"whiff.wav"</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">"punch.wav"</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 'main' function when this script is executed</span>
|
||||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</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> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="ChimpLineByLine.html" accesskey="U">Pygame Tutorials - Line By Line Chimp Example</a> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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">'foo.png'</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">'foo.png'</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 & 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, "dirty" 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 "GameObject" 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 "chording" 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">"Yup!"</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 "The application is not responding" 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 "standard" 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">"purple"</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> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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">'Basic Pygame program'</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">"Hello There"</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">'__main__'</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> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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'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">"0.4"</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">"couldn't load module. </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s2">"</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">""" Load image and return image object"""</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">"data"</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">"Cannot load image: </span><span class="si">{</span><span class="n">fullname</span><span class="si">}</span><span class="s2">"</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> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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'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">"""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"""</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">'ball.png'</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> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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">"""Movable tennis 'bat' 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"""</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">"bat.png"</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">"still"</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">"still"</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">"left"</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">"right"</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">"moveup"</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">"movedown"</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
|
||||
"moving", 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 "still", 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">"still"</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 "let go" (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> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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 — 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'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 "hit" - 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'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">"0.4"</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">"couldn't load module. </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s2">"</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">""" Load image and return image object"""</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">"data"</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">"Cannot load image: </span><span class="si">{</span><span class="n">fullname</span><span class="si">}</span><span class="s2">"</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">"""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"""</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">"ball.png"</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'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">"""Movable tennis 'bat' 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"""</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">"bat.png"</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">"still"</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">"still"</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">"left"</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">"right"</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">"moveup"</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">"movedown"</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">"Basic Pong"</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">"left"</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">"right"</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'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">"still"</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">"still"</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">"__main__"</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> »</li>
|
||||
<li class="nav-item nav-item-1"><a href="MakeGames.html" accesskey="U">Making Games With Pygame</a> »</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">
|
||||
© Copyright 2000-2023, pygame developers.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user