The Ronin Sprite Engine
Overview
The sprite engine display is a canvas that represents a virtual rectangular
window into a 2D plane. The sprite engine is responsible for maintaining
a list of sprites, clipping them against the view window, and displaying
them correctly. The sprite engine uses a hybrid dirty rectangle technique
that takes advantage of Java's features while avoiding its pitfalls. In
particular, the following considerations are made:
-
no pixel operations - Since Java is unlikely
to support speedy pixel operations at the bytecode level, it is important
to let the native libraries do all low-level graphics work. All pixel changes
will be done by moving rectangles of pixels between images. This is especially
important when dealing with transparency.
-
no flicker - Never is a pixel drawn to
the screen unless it is intended to be viewed on that frame. This
includes erasing procedures.
-
only one extra buffer - Since an off-screen
buffer can be quite costly ( 512x512x4 = 1M ) only one will be used (it's
hard to avoid using one but tempting to use two).
-
minimal pixel pushing - Only the minimum
amount of pixel blitting will be performed, given the other constraints.
-
static background - In Ronin the background
will not change very often (relative to the animation rate).
Operation
Sprite engine updates occur in 5 steps:
-
Move the sprites that overlap with the view window onto a visible sprite
list.
-
Sort the visible sprite list according to Z order.
-
Draw the visible sprites onto the offscreen buffer.
-
Update the canvas by copying pixels from the offscreen buffer.
The union of all rectangles from steps 3 (of this update) and 5 (of the
last update) must be copied.
-
Erase the sprites from the offscreen buffer by drawing over the bounding
rectangle with pixels from a special background object (rather than another
offscreen buffer). Unlike in step 4, only the rectangles from step
3 must be copied.
Unfortunately, the obvious optimizations to steps 4 and 5 (like only redrawing
changed sprites or only erasing uncovered areas) fail due to our inability
to handle transparency manually. However, the native libraries should
be fast enough to make up for it. The sprite engine does not worry
about time or motion; it simply draws the sprites where they desire to
be drawn. It is up to the user of the sprite engine to place the
sprites and then request the sprite engine to update. This will make
it flexible for a variety of tasks.
Classes and Interfaces
Sprites are abstract so that Ronin characters can be sprites with custom
positioning and Z ordering.
public interface Sprite
{
public int GetX();
public int GetY();
public int GetZ();
public Image GetImage(); //
the image holds the width and height
}
The PixelArray interface is implemented to provide a tiled (or otherwise)
backdrop for the sprite engine.
public interface PixelArray
{
public void CopyOut( Image
aImage, Point p, Dimension d );
}
The SpriteCanvas class is the sprite engine.
public class SpriteCanvas extends Canvas
{
private Image mOffscreenBuffer;
private PixelArray mBackdrop;
private DoubleLinkedList mSpriteList;
// sorted by
public SpriteCanvas( PixelArray
aBackdrop, Dimension aSize );
public void AddSprite( Sprite
s );
public void RemoveSprite(
Sprite s );
public void Update();
public void SetPosition( Point
p ); // allows the virtual window to be moved
}
Using the Sprite Engine for Ronin Battle Visualization
The sprite engine is meant to be of general use but also easily usable
for visualizing Ronin battles. The following tasks must be performed
by the Ronin battle visualization unit between sprite updates:
-
Decide which sprites are active and add and remove sprites from the
SpriteCanvas.
-
Move sprites according to their trajectories.
-
Change the images in use by active sprites according to their animation
characteristics.
-
Set the Z order of the active sprites, probably according to screen
Y due to tile overlap or altitude.
Technical Notes
-
Java will probably automatically provide clipping to the canvas, but
rough culling of sprites according to overlap with the virtual window should
probably be handled by the sprite engine (see step 5 of Operation).
-
It may be unnecessary to worry about spatial sorting of the sprites.
If the number of sprites becomes unwieldy, the sprite engine can be augmented
to be smarter about figuring out which sprites are within the view window.