FLIC routines

There are two high level functions for playing FLI/FLC animations: play_fli(), which reads the data directly from disk, and play_memory_fli(), which uses data that has already been loaded into RAM. Apart from the different sources of the data, these two functions behave identically. They draw the animation onto the specified bitmap, which should normally be the screen. Frames will be aligned with the top left corner of the bitmap: if you want to position them somewhere else you will need to create a sub-bitmap for the FLI player to draw onto.

If the callback function is not NULL it will be called once for each frame, allowing you to perform background tasks of your own. This callback should normally return zero: if it returns non-zero the player will terminate (this is the only way to stop an animation that is playing in looped mode).

The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR if something went wrong, and the value returned by the callback function if that was what stopped it. If you need to distinguish between different return values, your callback should return positive integers, since FLI_OK is zero and FLI_ERROR is negative.

Note that the FLI player will only work when the timer module is installed, and that it will alter the palette according to whatever palette data is present in the animation file.

Occasionally you may need more detailed control over how an FLI is played, for example if you want to superimpose a text scroller on top of the animation, or to play it back at a different speed. You could do both of these with the lower level functions described below.


int play_fli(const char *filename, BITMAP *bmp, int loop, int (*callback)());

Plays an Autodesk Animator FLI or FLC animation file on the specified BITMAP, reading the data from disk as it is required. If `loop' is not zero, the player will cycle when it reaches the end of the file, otherwise it will play through the animation once and then return. Read the beginning of chapter "FLIC routines" for a description of the callback parameter. Example:
      /* Let users skip looped animations. */
      int check_escape_key(void)
      {
         if (key[KEY_ESC])
            return 1;
         else
            return 0;
      }
      ...
         int ret = play_fli("animlogo.fli", screen, 1,
                             check_escape_key);
         if (ret == FLI_ERROR)
            abort_on_error("Error playing intro!");

Return value: The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR if something went wrong, and the value returned by the callback function if that was what stopped it.

See also: play_memory_fli, install_timer, fli_frame.
int play_memory_fli(const void *fli_data, BITMAP *bmp, int loop, int (*callback)());

Plays an Autodesk Animator FLI or FLC animation on the specified BITMAP, reading the data from a copy of the file which is held in memory. You can obtain the `fli_data' pointer by allocating a block of memory and reading an FLI file into it, or by importing an FLI into a grabber datafile. If `loop' is not zero, the player will cycle when it reaches the end of the file, otherwise it will play through the animation once and then return. Read the beginning of chapter "FLIC routines" for a description of the callback parameter.

Playing animations from memory is obviously faster than cuing them directly from disk, and is particularly useful with short, looped FLI's. Animations can easily get very large, though, so in most cases you will probably be better just using play_fli(). You can think of this function as a wrapper on top of open_memory_fli(), next_fli_frame() and close_fli(). Example:

      int ret = play_memory_fli(anim_data, screen, 0, NULL);
      if (ret == FLI_ERROR)
         abort_on_error("Corrupted animation data?");

Return value: The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR if something went wrong, and the value returned by the callback function if that was what stopped it.

See also: play_fli, install_timer, fli_frame.
int open_fli(const char *filename);

int open_memory_fli(const void *fli_data);

Open FLI files ready for playing, reading the data from disk or memory respectively. Information about the current FLI is held in the global variables fli_bitmap and fli_palette, which you can use if this function succeeds. However, you can only have one animation open at a time. Example:
      if (open_fli("intro.fli") == FLI_ERROR)
         abort_on_error("Error playing intro");

Return value: Returns FLI_OK on success, FLI_ERROR if something went wrong, like trying to open another FLI file without closing the previous one.

See also: close_fli, next_fli_frame, fli_bitmap, fli_palette.
void close_fli();

Closes an FLI file when you have finished reading from it. Remember to do this to avoid having memory leaks in your program.
See also: open_fli.
int next_fli_frame(int loop);

Reads the next frame of the current animation file. If `loop' is not zero, the player will cycle when it reaches the end of the file, otherwise it will return FLI_EOF. The frame is read into the global variables fli_bitmap and fli_palette. Example:
      while (next_fli_frame(0) == FLI_OK) {
         /* Do stuff, like play audio stream
            or check keys to skip animation. */
         /* Rest some time until next frame... */
      }

Return value: Returns FLI_OK on success, FLI_ERROR or FLI_NOT_OPEN on error, and FLI_EOF on reaching the end of the file.

See also: open_fli, fli_bitmap, fli_palette, fli_timer, fli_frame.
extern BITMAP *fli_bitmap;

Contains the current frame of the FLI/FLC animation. If there is no open animation, its value will be NULL.
See also: next_fli_frame, fli_bmp_dirty_from, fli_palette.
extern PALETTE fli_palette;

Contains the current FLI palette.
See also: next_fli_frame, fli_pal_dirty_from, fli_bitmap.
extern int fli_bmp_dirty_from;

extern int fli_bmp_dirty_to;

These variables are set by next_fli_frame() to indicate which part of the fli_bitmap has changed since the last call to reset_fli_variables(). If fli_bmp_dirty_from is greater than fli_bmp_dirty_to, the bitmap has not changed, otherwise lines fli_bmp_dirty_from to fli_bmp_dirty_to (inclusive) have altered. You can use these when copying the fli_bitmap onto the screen, to avoid moving data unnecessarily. Example:
      if (fli_bmp_dirty_from <= fli_bmp_dirty_to)
         blit(fli_bitmap, screen, 0, fli_bmp_dirty_from,
              0, fli_bmp_dirty_from, fli_bitmap->w,
              fli_bmp_dirty_to - fli_bmp_dirty_from + 1);
See also: fli_bitmap, reset_fli_variables.
extern int fli_pal_dirty_from;

extern int fli_pal_dirty_to;

These variables are set by next_fli_frame() to indicate which part of the fli_palette has changed since the last call to reset_fli_variables(). If fli_pal_dirty_from is greater than fli_pal_dirty_to, the palette has not changed, otherwise colors fli_pal_dirty_from to fli_pal_dirty_to (inclusive) have altered. You can use these when updating the hardware palette, to avoid unnecessary calls to set_palette(). Example:
      if (fli_pal_dirty_from <= fli_pal_dirty_to)
         set_palette_range(fli_palette, fli_pal_dirty_from,
                           fli_pal_dirty_to, 1);
See also: fli_palette, reset_fli_variables.
void reset_fli_variables();

Once you have done whatever you are going to do with the fli_bitmap and fli_palette, call this function to reset the fli_bmp_dirty_* and fli_pal_dirty_* variables.
See also: fli_bmp_dirty_from, fli_pal_dirty_from.
extern int fli_frame;

Global variable containing the current frame number in the FLI file. This is useful for synchronising other events with the animation, for instance you could check it in a play_fli() callback function and use it to trigger a sample at a particular point. Example:
      while (next_fli_frame(0) == FLI_OK) {
         if (fli_frame == 345)
            play_sample(trumpet_sound, 255, 128, 1000, 0);
         /* Rest some time until next frame... */
      }
See also: play_fli, play_memory_fli, next_fli_frame.
extern volatile int fli_timer;

Global variable for timing FLI playback. When you open an FLI file, a timer interrupt is installed which increments this variable every time a new frame should be displayed. Calling next_fli_frame() decrements it, so you can test it and know that it is time to display a new frame if it is greater than zero. Example:
      while (next_fli_frame(0) == FLI_OK) {
         /* Do stuff, like play audio stream
            or check keys to skip animation. */
         /* Rest some time until next frame... */
         while (fli_timer <= 0)
            rest(0);
      }
See also: install_timer, next_fli_frame.

Back to contents