Pauses and real time

Though IF is generally turn-based, it is possible -- and, if you've familiarized yourself with mouse input and hyperlinks, actually quite easy -- to incorporate real-time events into your game. This can be handy for, say, moving characters in and out of the room while the player is thinking about what command to try next, or for implementing a bomb that the player character really does have only a few seconds to defuse. It can also be used in tandem with the graphics suite to create animaations.

The command to kick off a real-time event is glk_request_timer_events(), with a number between the parentheses representing the number of milliseconds between calls to HandleGlkEvent(). That is to say, when the program reaches the line "glk_request_timer_events(1000);", it will go to the appropriate place in HandleGlkEvent() every 1000 milliseconds -- ie, every second -- and run the code it finds there. Placing the code is very much like it is for Mouse input or Hyperlinks -- simply conflate your HandleGlkEvent() routine with something that looks like this:

   [ HandleGlkEvent ev context;
      switch (ev-->0) {
            ! here would go the code to be run every so often

The one major difference from mouse events and hyperlinks is that you don't have to request a new timer event every time the N milliseconds are up: the program will keep going back to HandleGlkEvent() over and over until you explicitly tell it to stop with the line "glk_request_timer_events(0);".

So, how do you do animations? The key is to take advantage of the fact that if you list the frames of each animation sequentially in your Blorb resource file, the constants you choose will be assigned to sequential numbers. So if you have a seven-frame animation, your frames might be assigned Blorb resource numbers 3, 4, 5, 6, 7, 8, and 9. But you don't need to know what the numbers are -- instead, just create a global to count off the frames, and start it off assigned to the first one:

   frame_count = First_Frame;

Then put code like this in your HandleGlkEvent() routine:

   switch (ev-->0) {
         if (frame_count > Last_Frame) glk_request_timer_events(0);
         else {
            glk_image_draw(gg_moviewin, frame_count, 0, 0);

This code will show first frame one, then frame two, then frame three, etc., all the way up to frame seven, and then stop. It's up to you to make sure this happens at a reasonable speed -- try different numbers of milliseconds for your glk_request_timer_events() call and see what works best.

Now, if you just want to pause things until the player hits a key, that's much easier. There's a command called KeyCharPrimitive() that will read a keypress -- if you put the line "foo = KeyCharPrimitive();" into your code, the game will wait for the player to press a key, and then put the value of the key pressed into the variable "foo". A nifty side effect is that you can use KeyCharPrimitive() all by itself to cause the output stream to come to a halt and wait for the player to press a key before continuing. For example, let's say you wanted to put a pause before a dramatic revelation:

   print "~I have considered all the evidence,~ the detective
      says, ~and it at points in one direction. The murderer
   print " me! Sorry, won't happen again.~";

Some aren't satisfied by this type of pause, however, and demand that pauses be allowed to be deactivated by either keypress or mouse click. Ross Raszewski has come up with a Pause() routine that allows this:

   [ Pause;
      while(1) {
         if (gg_event-->0 == evtype_MouseInput or evtype_CharInput) {
            if (gg_event-->0 == evtype_MouseInput) glk_cancel_char_event(gg_mainwin);
         else HandleGlkEvent(gg_event, 1, gg_arguments);

That ought to satisfy the bastards— er, is this thing on?

Next section: File I/O
Or return to the table of contents