Beginner's Guide to Egfx
by Bret Victor
Egfx is cool. I swear. When I first wrote it, I thought it was kinda neat,
nothing special... but when I actually used it for the first time
on my ditch day stack, I had an enormous amount of fun. I made a maze
game where the maze was many times the screen size and the screen panned
around the maze, "glowing" animations with things fading in and out, and
lots of other stuff. Egfx made it all really easy.
Egfx can be a little complicated at first (especially if you didn't
actually write it yourself), so hopefully I can explain how to use it...
What is Egfx?
Egfx
is what you use if you want to draw pictures on the LED screen, instead
of just text. It supports multiple, arbitrarily-sized drawing buffers,
multiple "colors" (shades of intensity) and real drawing objects such as
lines and rectangles. All the cool kids use Egfx, and that's why they
are constantly surrounded by beautiful scantily-clad women (or men, depending
on their tastes). Shouldn't you use Egfx too?
Starting Up
When you start up Egfx with Egfx_SetMode
, you specify how many colors you want
(numcolors) and what the screen refresh rate should be. There are
some trade-offs involved, because if the product of these two numbers is
too high, the processor will be slowed down or the screen will flicker
horribly. The refresh rate though
should be above 50 Hz or there will be a noticable flicker. The general
rule is to use the fewest colors and slowest refresh rate that still looks
good. I think that at 60 Hz, seven or eight colors is about the max, but
you can experiment.
Buffers and Colors
When you draw in Egfx, you draw into a "buffer", which is not necessarily
connected to the physical screen. The buffer is created with
Egfx_CreateBuffer and can
be of arbitrary size. A one-byte value
(the "pixel color") is associated with each pixel in the buffer. The
intensity of the pixel on the screen is determined by its color as well
as the baseline and numcolors.
baseline is a parameter
that you can set which determines what color is considered "off" or "black".
All colors that are baseline or less do not light up. Colors that are
(baseline + numcolors - 1) or greater are at full intensity.
Colors in between are proportionally dimmer. You can play neat tricks with
the baseline parameter, such as slowly increasing or decreasing it to
make the screen "fade out" or "fade in". baseline starts out set to
zero to make things simple, but it is recommended that you set it to a value
closer to midrange such as 128 (and then Wipe) to give yourself more
freedom.
Cursors and Drawing
The "cursor" is the position within the buffer where the next drawing command
will start drawing. There are a number of
commands that deal with moving
the cursor around. In addition, some of the drawing commands themselves move
the cursor while they draw. You often want the cursor to move in some
direction after a drawing command completes; for this, the
automove
parameter can be used to move the cursor in one of the four directions (or
execute a graphics script resource) after each drawing command. Whenever
the cursor is told to go past the edge of the buffer, it wraps around to the
other side.
A drawing command
changes the pixel color of the pixels it draws on. How
exactly it changes them depends on the
drawing mode. A drawing mode might
use the color parameter, the
delta parameter, or neither.
Putting It Onscreen
In order for anyone to see what's in the buffer, the buffer (or part of it)
has to be mapped to the physical screen. The easiest way to do this is
with ScreenSet, which maps the entire
screen to a chunk of the buffer. Note that the buffer appears to "wrap
around" in the horizontal direction; if the chunk is too close to the right
edge of the buffer, part of the left edge of the buffer will be shown on the
screen. And if the buffer's width is less than the width of the screen, you
will see identical pictures side-by-side. Note also that there is no
wrap around in the vertical direction -- you should avoid mapping the screen
off the bottom edge of the buffer.
You can also map a chunk of the buffer to only part of the screen, using
RangeSet.
This command lets you set a range of onscreen columns instead of all of them.
Once your buffer is mapped to the screen, you can make it appear it move
around using the Pan commands. These commands
shift the buffer mappings according to the
pan parameter.
For example, if the screen is mapped so that
the top-left corner is position (0,0) in the buffer and you pan right, the
top-left corner will now be at position (1,0) and the picture will appear to
have shifted left. You can implement quite a number of impressive effects
just by panning around. Many types of animations can be implemented with
panning or screen/range setting, and it is much quicker than redrawing.
Multiple Buffers
You can call Egfx_CreateBuffer as
much as you like to allocate more drawing buffers.
Use SetBuffer to set which buffer you
are drawing to, and use ScreenSet
or RangeSet to map it to the screen or
part of the screen. The
stored cursor positions are properties
of the current drawing buffer, and change when you switch buffers. All
other parameters stay the same though, including the cursor position
(although it might "wrap around" if it is out of the range of the buffer
being switched to). When a Pan command is
given, each range of the screen pans through whichever buffer it's been
set to.
Does this mean you can do "double-buffered" animations? Of course!
Also, some pretty interesting effects can be implemented by mapping
differently sized buffers to different parts of the screen and panning
through them.
Scripts
All Egfx commands are given in "scripts", which simply consist of the
command numbers, followed by their parameters if any, and ending with a
zero byte. Libcoke may generate graphics scripts for you, if it exists.
You can execute a graphics script directly with
Egfx_ScriptInline, or you can upload
a script as a resource. Resource scripts can be executed with
Egfx_ScriptResource, called
from within other scripts with the
ScriptResource graphics command,
used for AutoMove, or executed
periodically automatically using
Egfx_StartAutoScript.
Gfx and Egfx
Neither Gfx nor Egfx erase their buffers when you turn them on. Therefore,
it is conceivable to be, say, scrolling some text with Gfx while displaying
an animation with Egfx, and switching between them by calling
Gfx_SetMode and
Egfx_RestoreMode.
Note that when you enable
one graphics mode, it automatically turns the other one off, so you don't
have to worry about both of them accidently being enabled together.
Have fun!
As always, feel free to ask me anything that's on your mind:
bret@ugcs.caltech.edu.
And of course, if you feel like adding anything to Egfx or implementing
the commands that haven't been implemented yet, that would be great.