Vgagames: Film functions:
=========================

 

Overview
--------

   With film functions you can put together a lot of graphics, put them into
   different graphical sequences and give all out step by step as a film.

   *****
   A film is not needed while playing actively a game, but only for
   non-interactive sequences (e.g. for introducing).
   *****

   You can imagine a film as a matrix of pictures.
   E.g. when you have 3 sequences, then your film might look as following:
     seq 1: <picture 1> <picture 2> <picture 3> ...
     seq 2: <picture 1> <picture 2> <picture 3> ...
     seq 3: <picture 1> <picture 2> <picture 3> ...

   Each picture (bild) has additional information:
     how long to be seen, relative coordinates, sound
   Each sequence is independed of other sequences.

   E.g. one sequence is a dog running from left to right,
        another sequence a flying bird, sometimes whistling.
        Each picture is an image of the dog/bird with info, where to be put,
        how many loops staying, and whether playing a sound.

   For extended use you can declare and use a "film subcall" (see below).


The functions
-------------


film * create_film(int arg1):
   create a new film

   Arguments:
    - arg1: number of sequences

   Return value: pointer to created film
                 NULL=error

   Example:
     film * flm;
     // create a film with 3 sequences
     if ((flm=create_film(3))==NULL) { [...error...] }




void free_film(film * arg1):
   destroy a film and free memory

   Arguments:
    - arg1: created film

   Example:
     film * flm;
     if ((flm=create_film(3))==NULL) { [...error...] }
     free_film(flm);




int add_bild_to_film(film * arg1,film_bild * arg2,int arg3):
   append a picture (bild) to a film at a certain sequence
   (graphics are duplicated, see argument pic at SET_FILM_BILD)

   Arguments:
    - arg1: created film
    - arg2: picture filled with SET_FILM_BILD()
    - arg3: sequence number

   Return value: position of picture in the sequence
                 -1=error

   Example:
     film * flm;
     film_bild bld;
     if ((flm=create_film(3))==NULL) { [...error...] }
     [ ... ]
     add_bild_to_film(flm,&bld,1)  /* append at sequence number 1 */
     [ ... ]
     add_bild_to_film(flm,&bld,1)  /* append at sequence number 1 */




void reset_film(film * arg1,void * arg2,int arg3):
   rewind a film

   Arguments:
    - arg1: created film
    - arg2: a pointer of your choice (only used by a "film subcall") or NULL
    - arg3: a number other than 0 (only used by a "film subcall")

   Example:
     film * flm;
     if ((flm=create_film(3))==NULL) { [...error...] }
     [ ... ]
     reset_film(flm,NULL,1);




unsigned long copy_film(grafik * arg1,film * arg2,void * arg3):
   give out the next step of a film to a graphic or backbuffer

   Arguments:
    - arg1: output to graphic or NULL=backbuffer
    - arg2: created film
    - arg3: a pointer of your choice (only used by a "film subcall") or NULL

   Return value: current step number of film

   Example:
     film * flm;
     unsigned long l1;
     if ((flm=create_film(3))==NULL) { [...error...] }
     [ ... ]
     reset_film(flm,NULL,1);
     // give out 320 steps
     do {
       CLEAR_BOX(NULL,RGB_BLACK);
       l1=copy_film(NULL,flm,NULL);  /* next step */
       flush_window();
       wait_time(40);
     } while (l1<320UL);




void SET_FILM(film * flm,int id,int x,int y,void (*func)(film *,void *,int)):
   Macro to set global values of a film

   Arguments:
    - flm: created film
    - id: ID of the film, what you want
    - x,y: absolute x/y coordinates to put film out to graphic
    - func: "film subcall" or NULL
            The "film subcall" must be declared as
              void function(film *,void *,int);
            Every time you call copy_film(), this function is called, too.
            See below for more details.

   Example:
     film * flm;
     if ((flm=create_film(3))==NULL) { [...error...] }
     SET_FILM(flm,1,0,0,NULL);




void SET_FILM_BILD(film_bild * bld,grafik * pic,int x,int y,int ft,int count_to,int wnr,int wch,short wvol):
   Macro to set a picture of a sequence of a film

   Arguments:
    - bld: address to picture (bild)
    - pic: graphic of this picture or NULL=no graphic
           this graphic is as a copy duplicated, so you can free it after call to add_bild_to_film()
    - x,y: relative x/y coordinates to them to the film (see SET_FILM())
    - ft: graphic output: RGB_FULL or RGB_TRANS
    - count_to: steps how long graphic is shown
    - wnr: wave number got with load_wave()
           or 0=no sound
           or -1=stop sound
    - wch: channel(s) to play/stop sound (see arg2 of play_wave()) or 0
    - wvol: time to in/decrease volume (see arg4 of play_wave()) or 0

   Example:
     film_bild bld;
     grafik * grf=load_grafik("test.vga");
     // set picture: graphic is "test.vga",
     //   coordinates are +10/+10 relative to film coordinates
     //   graphic shall be shown 5 steps
     SET_FILM_BILD(&bld,grf,10,10,RGB_TRANS,5,0,0,0);



Short example
-------------

We want to show a clock which makes to one side "tick" and to the other "tack"
Our graphics:
 - a clock:       +----+
                  | \_ |
                  |    |
                  |    |
                  +----+
 - a pendulum right and left:             /     \
                                         /       \
                                        O         O
to get:    +----+  and  +----+
           | \_ |       | \_ |
           | /  |       |  \ |
           |/   |       |   \|
           O----+       +----O
program:
  film * flm;
  film_bild bld;
  grafik * grf;
  int wv[2];
  unsigned long l1;

  [ ... ]  // initialization
  wv[0]=load_wave("tick.wav",TYP_IS_WAVE);
  wv[1]=load_wave("tack.wav",TYP_IS_WAVE);

  // we need 2 seqences, 1 for the clock, 1 for the two pendulums
  if ((flm=create_film(2))==NULL) { [...error...] }
  SET_FILM(flm,1,0,0,NULL);  /* put the clock to coordinates 0/0 */

  // set the 1. sequence only with the clock
  grf=load_grafik("clock.vga");
  // step value 100, but could be any other, because in 1.seq is only 1 picture
  // and after sequence is over it begins again
  SET_FILM_BILD(&bld,grf,0,0,RGB_FULL,100,0,0,0);
  add_bild_to_film(flm,&bld,1);  /* to 1.seq */
  free_grafik(grf);

  // set the 2. sequence with the two pendulums
  grf=load_grafik("tick.vga");
  // we assume relative coordinates to be at 0,20
  // and want to show "tick" 10 steps
  // and want to play sound "tick.wav" at channel 1
  SET_FILM_BILD(&bld,grf,0,20,RGB_TRANS,10,wv[0],CN_(1),0);
  add_bild_to_film(flm,&bld,2);  /* to 2.seq */
  free_grafik(grf);

  grf=load_grafik("tack.vga");
  // we assume relative coordinates to be at 30,20
  // and want to show "tack" 10 steps
  // and want to play sound "tack.wav" at channel 1
  SET_FILM_BILD(&bld,grf,30,20,RGB_TRANS,10,wv[1],CN_(1),0);
  add_bild_to_film(flm,&bld,2);  /* again to 2.seq */
  free_grafik(grf);

  // film is ready, now output
  reset_film(flm,NULL,1);  /* here not needed */
  // give out 1000 steps: that is 50 x tick and 50 x tack
  do {
    CLEAR_BOX(NULL,RGB_BLACK);
    l1=copy_film(NULL,flm,NULL);  /* next step out to backbuffer */
    flush_window();
    wait_time(50);
  } while (l1<1000UL);

  // free film
  free_film(flm);



Example with a "film subcall"
-----------------------------

We want the same as in the short example above, but after 10 "tacks"
(200 steps), the pendulum shall be twice as fast.
And after 400 steps we don't want to show the clock any more, only
the pendulum.

From the program above we have to change:
  SET_FILM(flm,1,0,0,filmfunc);

Then we have to write the "film subcall":
  void filmfunc(film * flm,void * data,int flag) {
    if (flag==1) {  /* reset_film() called, we had set arg3 to 1 */
      // now we have to set the struct (see vgagames.h) manually
      // 2.sequence - 1.picture:  flm->bild[2][1]
      flm->bild[2][1]->count_to=10;
      // 2.sequence - 2.picture:  flm->bild[2][2]
      flm->bild[2][2]->count_to=10;
    } else if (flag==0) {  /* always 0 when called from copy_film() */
      if (flm->step==200UL) {  /* 200 steps gone */
        // increase the pendulum at 2.sequence
        flm->bild[2][1]->count_to/=2;  // 1.picture
        flm->bild[2][2]->count_to/=2;  // 2.picture
      } else if (flm->step==400UL) {  /* 400 steps gone */
        // don't show the clock any more
        // we have to set the element "aktiv" to another value:
        // 1.sequence:  flm->aktiv[1]
        flm->aktiv[1]=FILM_ACT_DEAD;
        // now reset 1.sequence (only for demonstration purpose)
        flm->bildnr[1]=1;  // set pointer of 1.sequence to 1.picture
        flm->bild[1][1]->count=0;  // 1.sequence + 1.picture: count=0
      }
    }
  }


Note:
  Each copy_film():
   - increments the step of a film (flm->step)
   - increments the count value of the current picture in each sequence
     (flm->bild[<sequence>-1][<picture>-1]->count),
     (unless a sequence is set inactive (flm->aktiv[<sequence>-1]!=FILM_ACT_OK))
   - if the count value is equal to the maximum count value (count_to),
     the next picture is taken (flm->bildnr[<sequence>-1]++), but if it was
     the last picture of this sequence, again the first picture is taken
   - now all values are set, but now at first the "film subcall" ist called,
     you may change these values (be careful!)
   - then the pictures of the current values are drawn:
       at first of the 1.sequence, then of the 2.sequence and so on
       (unless a sequence is set dead (flm->aktiv[<sequence>-1]=FILM_ACT_DEAD))


 

Home | Previous: Color functions | Next: Key and mouse functions