# Displaying images

Images should be drawn into a window in the window's on_draw event handler. Usually a "sprite" should be created for each appearance of the image on-screen. Images can also be drawn directly without creating a sprite.

# Sprites

A sprite is an instance of an image displayed in the window. Multiple sprites can share the same image; for example, hundreds of bullet sprites might share the same bullet image.

A sprite is constructed given an image or animation, and drawn with the Sprite.draw method:

    sprite = pyglet.sprite.Sprite(image)

    @window.event
    def on_draw():
        window.clear()
        sprite.draw()

Sprites have properties for setting the position, rotation, scale, opacity, color tint and visibility of the displayed image. Sprites automatically handle displaying the most up-to-date frame of an animation. The following example uses a scheduled function to gradually move the sprite across the screen:

    def update(dt):
        # Move 10 pixels per second
        sprite.x += dt * 10

    # Call update 60 times a second
    pyglet.clock.schedule_interval(update, 1/60.)

If you need to draw many sprites, use a Batch to draw them all at once. This is far more efficient than calling draw on each of them in a loop:

    batch = pyglet.graphics.Batch()

    sprites = [pyglet.sprite.Sprite(image, batch=batch),
               pyglet.sprite.Sprite(image, batch=batch),
               # ...  ]

    @window.event
    def on_draw():
        window.clear()
        batch.draw()

When sprites are collected into a batch, no guarantee is made about the order in which they will be drawn. If you need to ensure some sprites are drawn before others (for example, landscape tiles might be drawn before character sprites, which might be drawn before some particle effect sprites), use two or more OrderedGroup objects to specify the draw order:

    batch = pyglet.graphics.Batch()
    background = pyglet.graphics.OrderedGroup(0)
    foreground = pyglet.graphics.OrderedGroup(1)

    sprites = [pyglet.sprite.Sprite(image, batch=batch, group=background),
               pyglet.sprite.Sprite(image, batch=batch, group=background),
               pyglet.sprite.Sprite(image, batch=batch, group=foreground),
               pyglet.sprite.Sprite(image, batch=batch, group=foreground),
               # ...]

    @window.event
    def on_draw():
        window.clear()
        batch.draw()

See the Graphics section for more details on batch and group rendering.

For best performance, try to collect all batch images into as few textures as possible; for example, by loading images with pyglet.resource.image (see Application resources) or with Texture bins and atlases).

# Simple image blitting

A simple but less efficient way to draw an image directly into a window is with the blit method:

    @window.event
    def on_draw():
        window.clear()
        image.blit(x, y)

The x and y coordinates locate where to draw the anchor point of the image. For example, to center the image at `(x, y)`:

    kitten.anchor_x = kitten.width // 2
    kitten.anchor_y = kitten.height // 2
    kitten.blit(x, y)

You can also specify an optional z component to the blit method. This has no effect unless you have changed the default projection or enabled depth testing. In the following example, the second image is drawn behind the first, even though it is drawn after it:

    from pyglet.gl import *
    glEnable(GL_DEPTH_TEST)

    kitten.blit(x, y, 0)
    kitten.blit(x, y, -0.5)

The default pyglet projection has a depth range of (-1, 1) -- images drawn with a z value outside this range will not be visible, regardless of whether depth testing is enabled or not.

Images with an alpha channel can be blended with the existing framebuffer. To do this you need to supply OpenGL with a blend equation. The following code fragment implements the most common form of alpha blending, however other techniques are also possible:

    from pyglet.gl import *
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

You would only need to call the code above once during your program, before you draw any images (this is not necessary when using only sprites).