Buried in Glimmr Drawing Commands, the bedrock Glimmr extension responsible for drawing images directly to the screen, is a set of commands for drawing lines using an angle plus a distance. This allows us to, for example, specify a line by saying “draw a line 20 pixels long from (0,0) on a heading of 30°.” I personally haven’t made much of use of this feature; I just thought that it might be useful given the emphasis of IF on compass directions–north being 0°, east 90°, and so on–and decided to throw it in. Something else this kind of thing is good for, though, is clocks. Since I’ve been thinking a little bit about timed events in IF lately, I thought I’d throw together a quick demo of an an analog clock face with sweep second hand (that’s it above). Downloads:
Glulx games don’t yet have access to the system clock (though this is in progress), but of course an analog clock in an IF game will most often need to show game time rather than real-world time. Inform 7 tracks game time very simply by default–1 turn equals 1 minute–but this can be customized, and there are extensions to help. This analog clock demo, though, doesn’t change anything in Inform’s default handling. Instead, it overlays real-time on top of game time; in other words, each turn takes one minute, unless you spend one minute thinking about, in which case 2 minutes will pass. This probably isn’t a solution that would be appropriate for most games, but it’s convenient for demonstration purposes!
Why does the clock look like it’s from the early 1990s? Well, Glimmr draws lines by coloring each pixel individually. This can be slow enough as it (depending on a variety of factors), and I haven’t attempted to incorporate antialiasing to soften the edges of the lines. Once support for Glulx floating point math is added to Inform, I may experiment to see whether antialiased line-drawing is feasible. Until then, the only way to get nice, smooth lines will be to use individual images for each tick of each hand of the clock (Glulx doesn’t support dynamic rotation of PNG images). For a clock like this one, this would require at least 180 individual PNG images: 60 for each hand, all the way around the dial; optimally, though, the hour hand should have even more, since there ought to be 30 hour-hand positions (one for each integer degree) between each numeral on the dial. Building a clock out of 181 images is certainly doable, and on the programming side it’s not very hard. But unless you have a method of automating the process of creating the images in the first place, that part sounds to me like an exercise in crushing boredom…
Creating the Clock
While the basic drawing commands are implemented, as mentioned above, in the Drawing Commands extension, the window-managing Glimmr Canvas-Based Drawing extension does not have a corresponding graphic element to handle angle+distance lines. Graphic elements (g-elements) are objects that control drawing to a graphics window: specify a few properties for the element (such as the coordinates where it should be drawn), and it will be automatically scaled to fit and drawn to the window. So, the first order of business was to create a type of g-element that would have all the properties of lines (such as line-weight and color), but also have an angle and a length that could be specified. This required just a few lines of code; see the source code for the demo to see how it was done (link above).
Once this new “ray primitive” type was defined, the next step was to define three rays, one for each hand; differing lengths, line-weights, and colors serve to distinguish the hands from one another, like so:
Table of Hands
|an hour hand||23||g-Black||2||2|
|a minute hand||30||g-Black||2||2|
|a second hand||38||g-Red||1||3|
Note the display-layer property: elements on lower layers are drawn first, so this indicates that the hour and minute hands are drawn on layer 2, with the second hand superimposed on them (layer 3). Layer 1 is the clock face itself, which is simply defined by a PNG image, since it doesn’t need to change. (I made it without antialiasing so that it would match the look of the hands.)
The elements will be displayed with these parameters in the window whenever it is redrawn without any further work from the author. To update the clock is thus pretty simple: we just need to set each hand to the appropriate angle for the time we need to display. Each digit on the clock is separated by 30 degrees (360° ÷ 12 digits = 30°), and each minute/second is separated by 6° (360° ÷ 60). Knowing this, it’s not difficult to write a routine to update the hands:
To update clock: let H be the hours part of the time of day; let M be the minutes part of the time of day; if H > 12, let H be H - 12; let Hh be H * 30; let Hh be Hh + (M / 2); let Mh be M * 6; now the angle of the hour hand is Hh; now the angle of the minute hand is Mh; now the angle of the second hand is seconds passed * 6; follow the window-drawing rules for the graphics-window.
Note that we advance the hour hand in 1° increments, roughly once every two minutes, to reflect the hour hand’s geared relationship to the movement of the minute hand.
Finally, because Inform’s implementation of the time of day doesn’t include seconds, we need to advance the “seconds passed” variable used above according to a 1 second (1000 millisecond) timer. For each tick of the timer, we increment the seconds count, and when it moves above 60, reset it to 1 while also advancing the time of day by one minute. To see the sweep second hand moving we also need to update the clock every second. This routine runs every time the timer ticks and takes care of all of these:
Glulx timed activity rule (this is the seconds increment rule): increment seconds passed; if seconds passed > 60: now the time of day is the time of day + 1 minute; now seconds passed is 1; update the status line; update clock.
And that’s really all there is to it. One thing that might be of interest is that, in the demo, the clock’s hands are both objects in the world and graphic elements; the player can see and refer to them even though their primary purpose is to bundle properties for drawing. The demo also implements a few commands for messing around with the clock. Please see the demo’s source code for all of the details (linked at the top of the post).
NOTE: The demo game file is a gblorb file. To play it, you will need a Glulx interpreter, such as Gargoyle, Windows Glulxe, or Zoom (see links at right). Mac users: a long-standing bug in Zoom screws up the colors; Gargoyle is preferred.