# New features replacing standard practice

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.

# Importing pyglet

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()

# Application event loop

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 Window.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.

# Loading resources

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.