pyglet 1.1 introduces new features for rendering high performance graphics and text, is more convenient to use, and integrates better with the operating system. Some of the existing interfaces have also been redesigned slightly to conform with standard Python practice or to fix design flaws.
pyglet 1.1 is backward compatible with pyglet 1.0. Any application that uses only public and documented methods of pyglet 1.0 will continue to work unchanged in pyglet 1.1. If you encounter an issue where this is not the case, please consider it a bug in pyglet and file an issue report.
Some methods have been marked deprecated in pyglet 1.1. These methods continue to work, but have been superceded by newer methods that are either more efficient or have a better design. The API reference has a complete list of deprecated methods; the main changes are described in the next section.
Deprecated methods will continue to be supported in all minor revisions of pyglet 1.x. A pyglet 2.0 release will no longer support these methods.
The following minor changes have been made for design or efficiency reasons. Applications which no longer need to support pyglet 1.0 should make the appropriate changes to ensure the deprecated methods are not called.
The dispatch_events
method on Player
and the equivalent function on the
pyglet.media module should no longer be called. In pyglet 1.1, media
objects schedule an update function on pyglet.clock at an appropriate
interval. New applications using media are required to call
pyglet.clock.tick periodically.
The AbstractImage
properties texture
, image_data
, and so on have
been replaced with equivalent methods get_texture
, get_image_data
,
etc.
The ImageData
properties data, format and pitch, which together were
used to extract pixel data from an image, have been replaced with a single
function get_data
. The format and pitch properties should now be used
only to determine the current format and pitch of the image.
The get_current_context function has been replaced with a global variable, current_context, for efficiency.
pyglet 1.1 introduces new features that make it easier to program with, so the standard practice as followed in many of the pyglet example programs has changed.
In pyglet 1.0, it was necessary to explicitly import each submodule required by the application; for example:
from pyglet import font
from pyglet import image
from pyglet import window
pyglet now lazily loads submodules on demand, so an application can get away
with importing just pyglet. This is especially handy for modules that are
typically only used once in an application, and frees up the names font
,
image
, window
and so on for the application developer. For example:
window = pyglet.window.Window()
Every application using pyglet 1.0 provides its own event loop, such as:
while not window.has_exit:
dt = clock.tick()
update(dt)
window.dispatch_events()
window.clear()
draw()
window.flip()
Besides being somewhat repetitious to type, this type of event loop is difficult to extend with more windows, and exausts all available system resources, even if the application is not doing anything.
The new pyglet.app
module provides an application event loop that is
less demanding of the CPU yet more responsive to user events. A complete
application that opens an empty window can be written with:
window = pyglet.window.Window()
@window.event
def on_draw():
window.clear()
pyglet.app.run()
Note the new on_draw()
event, which makes it easy to specify different drawing
functions for each window. The pyglet.app
event loop takes care of
dispatching events, ticking the clock, calling the draw function and flipping
the window buffer.
Update functions can be scheduled on the clock. To have an update function be called as often as possible, use clock.schedule (this effectively degenerates into the older dispatch_events practice of thrashing the CPU):
def update(dt):
pass
clock.schedule(update)
Usually applications can update at a less frequent interval. For example, a game that is designed to run at 60Hz can use clock.schedule_interval:
def update(dt):
pass
clock.schedule_interval(update, 1/60.0)
This also removes the need for clock.set_fps_limit.
Besides the advantages already listed, windows managed by the event loop will not block while being resized or moved; and the menu bar on OS X can be interacted with without blocking the application.
It is highly recommended that all applications use the event loop. The
loop can be extended if you need to add additional hooks or integrate with
another package. Applications continuing to use dispatch_events()
gain no advantage, but suffer from poorer response, increased CPU usage and
artifacts during window resizing and moving.
See The application event loop for more details.
Locating resources such as images, sound and video files, data files and fonts is difficult to do correctly across all platforms, considering the effects of a changing working directory and various distribution packages such as setuptools, py2exe and py2app.
The new pyglet.resource
module implements the correct logic for all these
cases, making it simple to load resources that belong to a specific module or
the application as a whole. A resource path can be set that is indexed once,
and can include filesystem directories, Python module paths and ZIP files.
For example, suppose your application ships with a logo.png
that needs to
be loaded on startup. In pyglet 1.0 you might have written:
import os.path
from pyglet import image
script_dir = os.path.dirname(__file__)
logo_filename = os.path.join(script_dir, 'logo.png')
logo = image.load(logo_filename)
In pyglet 1.1, you can write:
logo = pyglet.resource.image('logo.png')
And will actually work in more scenarios (such as within a setuptools egg file, py2exe and py2app).
The resource module efficiently packs multiple small images into larger textures, so there is less need for artists to create sprite sheets themselves for efficient rendering. Images and textures are also cached automatically.
See Application resources for more details.
The pyglet.graphics
module is a low-level abstraction of OpenGL vertex
arrays and buffer objects. It is intended for use by developers who are
already very familiar with OpenGL and are after the best performance possible.
pyglet uses this module internally to implement its new sprite module and the
new text rendering module. The Graphics chapter describes this module in
detail.
The pyglet.sprite module provide a fast, easy way to display 2D graphics on screen. Sprites can be moved, rotated, scaled and made translucent. Using the batch features of the new graphics API, multiple sprites can be drawn in one go very quickly. See Sprites for details.
The pyglet.image.load_animation function can load animated GIF images.
These are returned as an Animation
, which exposes the individual image
frames and timings. Animations can also be played directly on a sprite in
place of an image. The Animations
chapter describes how to use them.
The pyglet.image.atlas module packs multiple images into larger textures for
efficient rendering. The pyglet.resource
module uses this module for small
images automatically, but you can use it directly even if you’re not making
use of pyglet.resource
. See Texture bins and atlases for details.
Images now have anchor_x
and anchor_y
attributes, which specify a
point from which the image should be drawn. The sprite module also uses the
anchor point as the center of rotation.
Textures have a get_transform method for retrieving a TextureRegion
that
refers to the same texture data in video memory, but with optional horizontal
or vertical flipping, or 90-degree rotation.
The pyglet.text
module can render formatted text efficiently. A new class
Label supercedes the old pyglet.font.Text class (which is now actually
implemented in terms of Label()
). The “Hello, World” application can now be
written:
window = pyglet.window.Window()
label = pyglet.text.Label('Hello, world',
font_name='Times New Roman',
font_size=36,
x=window.width//2, y=window.height//2,
halign='center', valign='center')
@window.event
def on_draw():
window.clear()
label.draw()
pyglet.app.run()
You can also display multiple fonts and styles within one label, with HTMLLabel:
label = pyglet.text.HTMLLabel('<b>Hello</b>, <font color=red>world!</font>')
More advanced uses of the new text module permit applications to efficiently display large, scrolling, formatted documents (for example, HTML files with embedded images), and to allow the user to interactively edit text as in a WYSIWYG text editor.
EventDispatcher
now has a remove_handlers method which provides finer
control over the event stack than pop_handlers()
.
The @event
decorator has been fixed so that it no longer overrides
existing event handlers on the object, which fixes the common problem of
handling the on_resize()
event. For example, the following now works without
any surprises (in pyglet 1.0 this would override the default handler, which
sets up a default, necessary viewport and projection):
@window.event
def on_resize(width, height):
pass
A variant of clock.schedule_interval, clock.schedule_interval_soft has
been added. This is for functions that need to be called periodically at a
given interval, but do not need to schedule the period immediately. Soft
interval scheduling is used by the pyglet.media
module to distribute the
work of decoding video and audio data over time, rather than stalling the CPU
periodically. Games could use soft interval scheduling to spread the
regular computational requirements of multiple agents out over time.
In pyglet 1.0, font.load attempted to match the font resolution (DPI) with the operating system’s typical behaviour. For example, on Linux and Mac OS X the default DPI was typically set at 72, and on Windows at 96. While this would be useful for writing a word processor, it adds a burden on the application developer to ensure their fonts work at arbitrary resolutions. In pyglet 1.1 the default DPI is set at 96 across all platforms. It can still be overridden explicitly by the application if desired.
Video sources in pyglet.media
can now be stepped through frame-by-frame:
individual image frames can be extracted without needing to play back the
video in realtime.
For a complete list of new features and bug fixes, see the CHANGELOG
distributed with the source distribution.