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.
-
minimal flicker - When possible, a pixel
should not be drawn to the screen unless it is intended to be viewed on
that frame.
-
minimal offscreen buffers - Since an off-screen
buffer can be quite costly ( 512x512x4 = 1M ) at most one will be used.
-
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
For single buffering (no offscreen buffer) an update requires the following
steps:
-
Move the sprites that overlap with the view window onto a visible sprite
list.
-
Sort the visible sprite list according to Z order.
-
Erase the sprites that were drawn on the previous update from the canvas.
-
Draw the visible sprites on the canvas.
-
Empty the dirty rectangle list.
-
Update the dirty rectangle list with the bounding rectangles of the
visible sprites.
For double buffering there are a few changes.
-
Steps 3 and 4 above are performed on the offscreen buffer instead of
the canvas.
-
After step 4, a new step is added. All rectangles in the current
dirty rectangle list as well as all those about to be put on the new dirty
rectangle list must be copied from the offscreen buffer to the canvas.
This can be handled smartly by building the new list before destroying
the old list, using both if double buffering, and then storing the new
list for next time.
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 aSrc, Point aDest, Dimension d );
public void CopyOut( Canvas
aCanvas, Point aSrc, Point aDest, Dimension d );
}
The SpriteCanvas class is the sprite engine.
public class SpriteCanvas extends Canvas
{
private Image mOffscreenBuffer;
private PixelArray mBackdrop;
private LinkedList mSpriteList;
private LinkedList mDirtyRectangleList;
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.
-
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.
-
Since the SpriteCanvas is a Canvas, it should have it's paint() method
overridden to cause a complete refresh. The SpriteCanvas should use
this mechanism to cause a refresh when the virtual window position changes.