Chapter 19. Playing Movies and Cut Scenes

FLI is an animation format developed by Autodesk for creating and playing computer-generated animations at high resolutions using Autodesk Animator, while the FLC format was the standard format used in Autodesk Animator Pro. These two formats (FLI and FLC) are both referred to as the FLIC format. The original FLI format was limited to a resolution of 320 × 200, while FLC provided higher resolutions and file compression. This chapter focuses on the functions built into Allegro for reading and playing FLIC movies, which are especially useful as cut-scenes within a game or as the opening video often presented as a game begins.

Here is a breakdown of the major topics in this chapter:

Playing FLI Animation Files

Animated or rendered movies are often used in games to fill in a cut scene at a specified point in the game or to tell a story as the game starts. Of course, you can use an animation for any purpose within a game using Allegro's built-in support for FLI loading and playback (both from memory and from disk file). The only limitation is that you can only play one FLI at a time. If you need multiple animations to run at the same time, I recommend converting the FLI file to one or more bitmap images and treating the movie as an animated sprite—although I'll leave implementation of that concept up to you. (First you would need to convert the FLI to individual bitmap images.)

The easiest way to play an FLI animation file with Allegro is by using the play_fli function, which simply plays an FLI or FLC file directly to the screen or to another destination bitmap.

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

The first parameter is the FLI/FLC file to play; the second parameter is the destination bitmap where you would like the animation to play; and the third parameter, loop, determines whether the animation is looped at the end (1 is looped, 0 is not). In practice, however, you will want to intercept playback in the callback function and pass a return value of 1 from the callback to stop playback.

As you can see from the function definition, play_fli supports a callback function. The purpose for this is so that your game can continue running while the FLI is played; otherwise, playback would run without interruption. The callback function is very simple—it returns an int but accepts no parameters.

When you are playing back an animation file, keep in mind that play_fli draws each frame at the upper-left corner of the destination bitmap (which is usually the screen). If you want more control over the playback of an FLI, you can tell play_fli to draw the frames on a memory bitmap and then draw that bitmap to the screen yourself. (See the following section on using the callback function.)

The FLI Callback Function

The callback function makes it possible to do other things inside your program after each frame of the animation is displayed. Note that you should return from the callback function as quickly as possible or the playback timing will be off. When you want to use a callback function, simply declare a function like this:

int fli_callback(void)
{
}

You can then use play_fli to start playback of an FLI file, including the fli_callback function.

play_fli("particles.fli", screen, 1, fli_callback);

The PlayFlick Program

The play_fli function is not really very useful if you don't also use the callback function. I have written a test program called PlayFlick that demonstrates how to use play_fli along with the callback to play an animation with logistical information printed after each frame of the FLI is displayed on the screen. Figure 19.1 shows the output from the PlayFlick program.

The PlayFlick program demonstrates how to play an Autodesk Animator FLI/FLC file.

Figure 19.1. The PlayFlick program demonstrates how to play an Autodesk Animator FLI/FLC file.

If you are writing this program from scratch (as follows), you will of course need an FLI file to use for testing. You can copy one of the FLI files off the CD-ROM from the folder for this chapter and project, chapter19playflick. The sample file is called particles.fli, and there are several other sample FLI files in other project folders for this chapter.

#include <stdio.h>
#include "allegro.h"

#define WHITE makecol(255,255,255)

int fli_callback(void)
{
    //display some info after each frame
    textprintf_ex(screen, font, 0, 0, WHITE,0,
       "FLI resolution: %d x %d", fli_bitmap->w, fli_bitmap->h);
    textprintf_ex(screen, font, 0, 10, WHITE,0,
       "Current frame: %2d", fli_frame);

    //ESC key stops animation
    if (keypressed())
        return 1;
    else
        return 0;
}

int main(void)
{
    //initialize Allegro
    allegro_init();
    set_color_depth(16);
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
    install_timer();
    install_keyboard();

    //play fli with callback
    play_fli("particles.fli", screen, 1, fli_callback);

    //time to leave
    allegro_exit();
    return 0;
}
END_OF_MAIN()

Playing an FLI from a Memory Block

Allegro provides you with a way to play a raw FLI file that has been mass copied from disk into memory with header and all. The play_memory_fli function will play a memory FLI as if it were a disk file. The FLI routines must still work with only one file at a time, even if that file was loaded into a memory block (which you must create with malloc and read into memory using your own file input code). You would also use this function when you have stored an FLI inside a datafile. (For more information about datafiles, refer to Chapter 18.)

int play_memory_fli(const void *fli_data, BITMAP *bmp,
int loop, int (*callback)());

Loading FLIs into Memory

The two functions covered thus far were designed for simple FLI playback with little to no control over the frames inside the animation. Fortunately, Allegro provides a low-level interface for FLI playback, allowing you to read an FLI file and manipulate it frame by frame, adjusting the palette and blitting the frame to the screen manually.

Opening and Closing FLI Files

To open an FLI file for low-level playback, you'll use the open_fli function.

int open_fli(const char *filename);

If you are using a data file (or you have loaded an entire FLI file into memory byte for byte), you'll use the open_memory_fli function to open it for low-level access.

int open_memory_fli(const void *fli_data);

If the file was opened successfully, a value of FLI_OK will be returned; otherwise, FLI_ERROR will be returned by these functions. Information about the current FLI is held in global variables, so you can only have one animation open at a time.

Note

The FLI routines make use of interrupts, so you must install the timer by calling install_timer at the start of the program.

After you have finished playing an FLI animation, you can close the file by calling close_fli.

void close_fli();

Processing Each Frame of the Animation

After you have opened the FLI file, you are ready to begin handling the low-level processing of the animation playback. Allegro provides a number of functions and global variables for dealing with each animation frame; you'll see that they are easy to use in practice.

For starters, take a look at the next_fli_frame function.

int next_fli_frame(int loop);

This function reads the next frame of the current animation file. If loop is set, the player will cycle when playback reaches the end of the file; otherwise, the function will return FLI_EOF. If no error occurs, this function will return FLI_OK, but if an error has occurred, it will return FLI_ERROR or FLI_NOT_OPEN. One useful return value is FLI_EOF, which tells you that the playback has reached the last frame of the file.

What about drawing each frame image? The frame is read into the global variables fli_bitmap (which contains the current frame image) and fli_palette (which contains the current frame's palette).

extern BITMAP *fli_bitmap;
extern PALETTE fli_palette;

Even if you are running a program in a high-color or true-color video mode, you will need to set the current palette to render the animation frames properly. (This at least applies to 8-bit FLI files; FLC files might not need a palette.)

After each call to next_fli_frame, Allegro sets a global variable indicating the current frame in the animation sequence of the FLI file, called fli_frame.

extern int fli_frame;

The current frame is helpful to know, but it doesn't help with timing, which will differ from one FLI file to another. Allegro takes care of the problem by automatically incrementing a global variable called fli_timer whenever a new frame should be displayed. This works regardless of the computer's speed because it is handled by an interrupt. It is important to pay attention to timing unless you are only concerned with the image of each frame and not playback speed.

extern volatile int fli_timer;

Each time you call next_fli_frame, the fli_timer variable is decremented, so if playback is in sync with timing, this variable will always be 0 unless a new frame is ready to be displayed. This makes it easy to determine when each frame should be drawn.

The LoadFlick Program

To demonstrate the low-level FLI animation routines, I've written a short program called LoadFlick. The output from this program is shown in Figure 19.2. LoadFlick pretty much demonstrates everything you need to know about the low-level FLI routines, including how to load an FLI file, keep track of each frame, manage timing, and blit the image to the screen.

The LoadFlick program handles each frame of the FLI animation individually.

Figure 19.2. The LoadFlick program handles each frame of the FLI animation individually.

#include <stdio.h>
#include <allegro.h>

#define WHITE makecol(255,255,255)

int main(void)
{
    int ret;

    //initialize Allegro
    allegro_init();
    set_color_depth(16);
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
    install_timer();
    install_keyboard();

    //load the fli movie file
    ret = open_fli("octahedron.fli");
    if (ret != FLI_OK)
    {
        allegro_message("Error loading octahedron.fli");
        allegro_exit();
        return 1;
    }

    //display movie resolution
    textprintf_ex(screen, font, 0, 0, WHITE,0,
        "FLI resolution: %d x %d", fli_bitmap->w, fli_bitmap->h);

    //main loop
    while (!keypressed())
    {
      //is it time for the next frame?
      if (fli_timer)
      {
          //open the next frame
          next_fli_frame(1);

          //adjust the palette
          set_palette(fli_palette);

         //copy the FLI frame to the screen
        blit(fli_bitmap, screen, 0, 0, 0, 30,
             fli_bitmap->w, fli_bitmap->h);

        //display current frame
        textprintf_ex(screen, font, 0, 10, WHITE,0,
            "Current frame: %4d", fli_frame);
      }
  }

  //remove fli from memory
  close_fli();
  //time to leave
  allegro_exit();
  return 0;
}
END_OF_MAIN()

The ResizeFlick Program

Let's do something fun just to see how useful the low-level FLI routines can be when you want full control over each frame in the animation. The ResizeFlick program is similar to LoadFlick in that it opens an FLI into memory before playback. The difference in this new program is that the resulting FLI frames are resized to fill the screen (using a proper ratio for the height). Note that the FLI file must be in landscape orientation—wider than it is tall—or the bottom of each frame image might be cropped. It's best to use FLI files with a resolution that is similar to one of the common screen resolutions, such as 320 × 240, 640 × 480, and so on.

Figure 19.3 shows the ResizeFlick program running with a short animation of a jet aircraft (the U.S. Air Force SR-71 Blackbird). Note the black area at the bottom of the screen—this is due to the fact that the original FLI animation was 320 × 200, so when it was scaled there were pixels left blank on the bottom. If you want to truly fill the entire screen, you can do away with the width and height variables and simply pass SCREEN_W-1 and SCREEN_H-1 as the last two parameters of stretch_blit, which will cause the FLI to be played back in true full-screen mode (although with image artifacts if the scaling is not a multiple of the original resolution).

The ResizeFlick program shows how to play an FLI at any scaled resolution.

Figure 19.3. The ResizeFlick program shows how to play an FLI at any scaled resolution.

#include "allegro.h"

#define WHITE makecol(255,255,255)
#define BLACK makecol(0,0,0)

int main(void)
{
  int ret,width,height;

  //initialize Allegro
  allegro_init();
  install_timer();
  install_keyboard();

  //set video mode--color depth defaults to 8-bit
  set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);

  //load the fli movie file
  ret = open_fli("particles.fli");
  if (ret != FLI_OK) {
     allegro_message("Error loading animation file");
     allegro_exit();
     return 1;
  }

  //main loop
  while (!keypressed())
  {
     //is it time for the next frame?
     if (fli_timer)
     {
         //open the next frame
         next_fli_frame(1);

         //adjust the palette
         set_palette(fli_palette);

         //calculate scale
         width = SCREEN_W;
         height = fli_bitmap->h * (SCREEN_W / fli_bitmap->w);

         //draw scaled FLI (note: screen must be in 8-bit mode)
         stretch_blit(fli_bitmap, screen, 0, 0, fli_bitmap->w,
             fli_bitmap->h, 0, 0, width, height);

         //display movie resolution
         textprintf_ex(screen, font, 0, 0, BLACK, 0,
            "FLI resolution: %d x %d", fli_bitmap->w, fli_bitmap->h);

         //display current frame
         textprintf_ex(screen, font, 0, 10, BLACK, 0,
           "Current frame: %4d", fli_frame);
     }
  }

  //remove fli from memory
  close_fli();

  allegro_exit();
  return 0;
}
END_OF_MAIN()

Summary

This chapter provided an overview of the FLIC animation routines available with Allegro. You learned how to play an FLI/FLC file directly from disk as well as how to load an FLI/FLC file into memory and manipulate the animation frame by frame. There were three sample programs in this chapter to demonstrate the routines available for playback of an FLIC file, including a program at the end of the chapter that displayed a movie scaled to the entire screen.

Chapter Quiz

You can find the answers to this chapter quiz in Appendix A, “Chapter Quiz Answers.”

1.

Which company developed the FLI/FLC file format?

  1. Autodesk

  2. Borland

  3. Microsoft

  4. Bungie

2.

Which product first used the FLI format?

  1. 3D Studio Max

  2. WordPerfect

  3. Animator

  4. PC Paintbrush

3.

Which product premiered the more advanced FLC format?

  1. Animator Pro

  2. PC Animation

  3. Dr. Halo

  4. CorelDRAW

4.

What is the common acronym used to describe both FLI and FLC files?

  1. FLICK

  2. FLICKS

  3. FLI/C

  4. FLIC

5.

Which function plays an FLIC file directly?

  1. play_fli

  2. direct_play

  3. play_animation

  4. play_flic

6.

How many FLIC files can be played back at a time by Allegro?

  1. 1

  2. 2

  3. 3

  4. 4

7.

Which function loads a FLIC file for low-level playback?

  1. load_fli

  2. read_fli

  3. open_fli

  4. shoo_fli

8.

Which function moves the animation to the next frame in an FLIC file?

  1. next_fli_frame

  2. get_next_frame

  3. move_frame

  4. next_fli

9.

What is the name of the variable used to set the timing of FLIC playback?

  1. flic_frames

  2. playback_timer

  3. fli_playback

  4. fli_timer

10.

What is the name of the variable that contains the bitmap of the current FLIC frame?

  1. fli_frame

  2. fli_bitmap

  3. fli_image

  4. current_fli

 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.126.199