dmd Submodule

The dmd submodule provides classes and functions to facilitate generating both text and graphics for on the dot matrix display:

Overview

The pyprocgame display system is designed specifically to take advantage of the mode queue architecture. This provides the game developer with a relatively simple means to supply the player with the most relevant information at all times.

The DisplayController class is the glue that makes this architecture work. If you wish to implement a different architecture you can certainly ignore DisplayController but most developers will want to take advantage of it.

When integrated within your GameController subclass, DisplayController‘s update() method is called whenever the DMD is ready for a new frame. update() iterates over the mode queue in search of modes that have a layer attribute. This attribute should be an instance of a subclass of Layer, which provides a sequence of frames, one at a time, via its next_frame() method. If a mode does not provide this layer attribute it is ignored; otherwise the next frame is obtained and the frames are composited from bottom to top (lowest priority modes being at the bottom).

All layers have an Layer.opaque attribute, which defaults to False. If a layer is opaque, no layers below that one (with lower priority) will be fetched or composited. Also, if a layer’s next_frame() method returns None it is considered to be transparent.

By using this mode-layer arrangement the developer has a direct connection between modes and what’s being displayed, without having to manage a separate display queue. For example, the score display might be a layer associated with a low-priority mode. If the game enters a hurry-up mode, which has a higher priority due to its interest in switch events, the hurry-up mode can supply its own layer which is automatically displayed above the score layer.

Core Classes

Animation

class procgame.dmd.Animation

An ordered collection of Frame objects.

frames

Ordered collection of Frame objects.

height

Height of each of the animation frames in dots.

load(filename, allow_cache=True)

Loads filename from disk. The native animation format is the DMD File Format Specification, which can be created using dmdconvert, or DMDAnimator.

This method also supports loading common image formats such as PNG, GIF, and so forth using Python Imaging Library. Note that loading such images can be time-consuming. As such, a caching facility is provided. To enable animation caching, provide a path using the dmd_cache_path key in System Configuration File. Note that only non-native images are cached (.dmd files are not cached).

filename can be a string or a list. If it is a list, the images pointed to will be appended to the animation.

save(filename)

Saves the animation as a .dmd file at the given location, filename.

width

Width of each of the animation frames in dots.

DisplayController

class procgame.dmd.DisplayController(game, width=128, height=32, message_font=None)

Manages the process of obtaining DMD frames from active modes and compositing them together for display on the DMD.

Using DisplayController

  1. Add a DisplayController instance to your GameController subclass:

    class Game(game.GameController):
      def __init__(self, machine_type):
        super(Game, self).__init__(machine_type)
        self.dmd = dmd.DisplayController(self, width=128, height=32,
                                         message_font=font_tiny7)
    
  2. In your subclass’s dmd_event() call DisplayController.update():

    def dmd_event(self):
        self.dmd.update()
    
frame_handlers

If set, frames obtained by update() will be sent to the functions in this list with the frame as the only parameter.

This list is initialized to contain only self.game.proc.dmd_draw.

update()

Iterates over procgame.game.GameController.modes from lowest to highest and composites a DMD image for this point in time by checking for a layer attribute on each Mode. If the mode has a layer attribute, that layer’s composite_next() method is called to apply that layer’s next frame to the frame in progress.

The resulting frame is sent to the frame_handlers and then returned from this method.

Font

class procgame.dmd.Font(filename=None)

Variable-width bitmap font.

Fonts can be loaded manually, using load(), or with the font_named() utility function which supports searching a font path.

char_widths

Array of dot widths for each character, 0-indexed from <space>. This array is populated by load(). You may alter this array in order to update the font and then save() it.

composite_op

Composite operation used by draw() when calling copy_rect().

draw(frame, text, x, y)

Uses this font’s characters to draw the given string at the given position.

draw_in_rect(frame, text, rect=(0, 0, 128, 32), anchor=0)

Draw text on frame within the given rect, aligned in accordance with anchor.

rect is a tuple of length 4: (origin_x, origin_y, height, width). 0,0 is in the upper left (NW) corner.

anchor is one of: AnchorN, AnchorE, AnchorS, AnchorW, AnchorNE, AnchorNW, AnchorSE, AnchorSW, or AnchorCenter (the default).

load(filename)

Loads the font from a .dmd file (see Animation.load()). Fonts are stored in .dmd files with frame 0 containing the bitmap data and frame 1 containing the character widths. 96 characters (32..127, ASCII printables) are stored in a 10x10 grid, starting with space (' ') in the upper left at 0, 0. The character widths are stored in the second frame within the ‘raw’ bitmap data in bytes 0-95.

save(filename)

Save the font to the given path.

size(text)

Returns a tuple of the width and height of this text as rendered with this font.

tracking

Number of dots to adjust the horizontal position between characters, in addition to the last character’s width.

Frame

class procgame.dmd.Frame(width, height)

DMD frame/bitmap.

Subclass of pinproc.DMDBuffer.

ascii()

Returns an ASCII representation of itself.

copy()

Returns a copy of itself.

static copy_rect(dst, dst_x, dst_y, src, src_x, src_y, width, height, op='copy')

Static method which performs some type checking before calling pinproc.DMDBuffer.copy_to_rect().

static create_with_text(lines, palette={' ': 0, '*': 15})

Create a frame based on text.

This class method can be used to generate small sprites within the game’s source code:

frame = Frame.create_with_text(lines=[ \
    '*+++*', \
    ' *+* ', \
    '  *  '], palette={' ':0, '+':7, '*':15})
height

Height of the frame in dots.

subframe(x, y, width, height)

Generates a new frame based on a sub rectangle of this frame.

width

Width of the frame in dots.

Layer

class procgame.dmd.Layer(opaque=False)

The Layer class is the basis for the pyprocgame display architecture. Subclasses override next_frame() to provide a frame for the current moment in time. Handles compositing of provided frames and applying transitions within a DisplayController context.

composite_next(target)

Composites the next frame of this layer onto the given target buffer. Called by DisplayController.update(). Generally subclasses should not override this method; implementing next_frame() is recommended instead.

composite_op

Composite operation used by composite_next() when calling copy_rect().

enabled

If False, DisplayController will ignore this layer.

next_frame()

Returns an instance of a Frame object to be shown, or None if there is no frame. The default implementation returns None; subclasses should implement this method.

opaque

Determines whether layers below this one will be rendered. If True, the DisplayController will not render any layers after this one (such as from modes with lower priorities – see DisplayController for more information).

set_target_position(x, y)

Setter for target_x and target_y.

target_x

Base x component of the coordinates at which this layer will be composited upon a target buffer.

target_x_offset

Translation component used in addition to target_x as this layer’s final compositing position.

target_y

Base y component of the coordinates at which this layer will be composited upon a target buffer.

target_y_offset

Translation component used in addition to target_y as this layer’s final compositing position.

transition

Transition which composite_next() applies to the result of next_frame() prior to compositing upon the output.

Layer Subclasses

Subclasses of Layer that provide building blocks for sophisticated display effects.

AnimatedLayer

class procgame.dmd.AnimatedLayer(opaque=False, hold=True, repeat=False, frame_time=1, frames=None)

Collection of frames displayed sequentially, as an animation. Optionally holds the last frame on-screen.

add_frame_listener(frame_index, listener)

Registers a method (listener) to be called when a specific frame number (frame_index) in the animation has been reached. Negative numbers, like Python list indexes, indicate a number of frames from the last frame. That is, a frame_index of -1 will trigger on the last frame of the animation.

frame_pointer

Index of the next frame to display. Incremented by next_frame().

frame_time

Number of frame times each frame should be shown on screen before advancing to the next frame. The default is 1.

hold

True if the last frame of the animation should be held on-screen indefinitely.

next_frame()

Returns the frame to be shown, or None if there is no frame.

repeat

True if the animation should be repeated indefinitely.

reset()

Resets the animation back to the first frame.

FrameLayer

class procgame.dmd.FrameLayer(opaque=False, frame=None)

Displays a single frame.

GroupedLayer

class procgame.dmd.GroupedLayer(width, height, layers=None)

Layer subclass that composites several sublayers (members of its layers list attribute) together.

layers

List of layers to be composited together whenever this layer’s next_frame() is called.

Layers are composited first to last using each layer’s composite_next() method. Compositing is ended after a layer that returns non-None from composite_next() is opaque.

ScriptedLayer

class procgame.dmd.ScriptedLayer(width, height, script)

Displays a set of layers based on a simple script.

Script Format

The script is an list of dictionaries. Each dictionary contains two keys: seconds and layer. seconds is the number of seconds that layer will be displayed before advancing to the next script element.

If layer is None, no frame will be returned by this layer for the duration of that script element.

Example script:

[{'seconds':3.0, 'layer':self.game_over_layer}, {'seconds':3.0, 'layer':None}]
duration()

Returns the complete duration of the script.

force_next(forward=True)

Advances to the next script element in the given direction.

TextLayer

class procgame.dmd.TextLayer(x, y, font, justify='left', opaque=False, width=128, height=32, fill_color=None)

Layer that displays text.

fill_color

Dot value to fill the frame with. Requres that width and height be set. If None only the font characters will be drawn.

set_text(text, seconds=None, blink_frames=None)

Displays the given message for the given number of seconds.

Utilities

Font Utilities

procgame.dmd.font_named(name)

Searches the font_path for a font file of the given name and returns an instance of Font if it exists.

procgame.dmd.font_path

list() -> new empty list list(iterable) -> new list initialized from iterable’s items

MarkupFrameGenerator

class procgame.dmd.MarkupFrameGenerator(width=128, min_height=32)

Renders a Frame for given text-based markup.

The markup format presently uses three markup tokens: # (for headlines) and [ and ] for plain text. The markup tokens indicate justification. Lines with no markup or a leading # or [ will be left-justified. Lines with a trailing # or ] will be right- justified. Lines with both will be centered.

The width and min_height are specified with instantiation.

Fonts can be adjusted by assigning the font_plain and font_bold member variables.

font_bold

Font used for bold characters.

font_plain

Font used for plain, non-bold characters.

frame_for_markup(markup, y_offset=0)

Returns a Frame with the given markup rendered within it. The frame width is fixed, but the height will be adjusted to fit the contents while respecting min_height.

The Y offset can be configured supplying y_offset.

DMD File Format Specification

.dmd files are the native format for DMD animations in pyprocgame. The file format is as follows:

4 bytes - header data (unused)
4 bytes - frame_count
4 bytes - width of animation frames in pixels
4 bytes - height of animation frames in pixels
? bytes - Frames: frame_count * width * height bytes

Frame data is laid out row0..rowN. Byte values of each pixel are in two parts: the lower 4 bits are the dot “color”, 0x0 being black and 0xF being the brightest value and the upper 4 bits are alpha (0x0 is fully transparent, 0xF is fully opaque). Note that transparency is optional and only supported by the alpha blending modes in procgame.dmd.Frame.copy_rect(). Alpha values are ignored by pinproc.PinPROC.dmd_draw().

.dmd files are loaded using procgame.dmd.Animation.load().