Introduction to gaffe

HO - Mar 2002


What is the Gaffe ?

What is Gaffe? What is Anim?

Anim is a tool for making 2D animated cartoons. It compiles a script and generates from it a series of pictures (or 'frames'). The script itself is readable text and uses that "gaffe" language. This language is designed to describe motion in an easy way.

To simplify this document a bit, we use "gaffe" to indicate both the language and its compiler.

History of gaffe

The idea of Gaffe was born as a side-effect of my working situation. I started working on a graphical toolkit for animation when the company I use to work for got bankrupt. I was without a job and this gave me some things to do. But in the early development stage, I managed to get another job, so it was very hard for me to continue this project.

I decided to split the development in a Gui part and a console part, with the first being 'cattoon' and the latter called 'gaffe', so I could more easily develop during some lost hours then that is possible with one big GUI application.

The name 'gaffe' came as a tribute to 'A. Franquin' with his 'Gaston Lagaffe' comics. Do away with the 'la' in 'lagaffe' and there you go. Voila!

Comparing gaffe to other languages

The only utility I know of that does 2D animation is Flash Media. However, Flash is mainly used for 2D interactive shows and gaffe is non-interactive. So I didn't study this further. The gaffe language concepts are derived from some well known constructs in programming: pipes for sequential execution, thread for parallel execution and critical sections are called "hold's". Beside that the gaffe language has some similarities with the C programming language, no knowledge of C is required to understand and use gaffe.

Concepts

File hierarchy

.g gaffe script Text file that describes animation. After compilation, it produces .ppm files. .ppm portable pixmap Image file. The basic P6 raw binary is used which can be viewed with most image viewers. .lst shot Contains extra information made while compilting the gaffe script. .lm region file File describing certain regions ('LedeMaten') that are animated The compilation process is as follows: One gaffe script and zero or more region files produces image files and one shot file.
.g [ { + .lm } ] ----> .lst { + .ppm }

Naming

ledemaat Ledemaat (mult. 'ledematen') is Dutch for 'body part or body member' (eg. your arm, your leg,...). I wanted a word that expressed a 'region' but also expressed motion of the region. A ledemaat is basicly a poolygon wit some extra attributes.
shot Sequence of images derived from one base image (the 'scenery') and one gaffe script.
scenery Background image of the shot
operation A basic operation is a function like 'rotate', 'move',... It's counter-part and nemesis is a 'compound'.
compound A compound is a queue which has two functions: (1) to collect operations in its queue, and, (2) if the size of the queue is larger than the number of operations, then the compound will divide the operations it collected in smaller pieces (2).
eg. a compound has collected two operations:
{ rotate( + 10 ); move( -6 ) }
However, it's queue size is 4: The compound will break up the operations to hold:
{ rotate( +5 ); rotate( +5 ); move(+3 ); move( +3 ); }.
There are several types of compounds that have different ways of dividing the operations: pipe, cycle, thread,loop and repeat. A compound can hold both operations and / or sub-compounds.
queue A collection of operations as used in a compound (infra). Compounds have a fixed size.
pipe A word about the naming. I pipe represents a pure sequential way of doing something. Why name it pipe? Because, a pipe is by definition a sequence of smaller pipes (...) get it?
thread A word about the naming. A thread is pars-pro-toto: a thread is woven into a fabric. This compound weaves it's operations by mixing them in an orderly fashion.

Syntax

Basic structure

1-  #Simple Example
2-  #
3-  scenery="hunter.ppm";
4-  anime jager("fires",250,180)
5-  {
6-    pipe(10) {
7-        pan(3,10,395,285,3,10,395,285);
8-    }
9-  }

Compiling

To compile a gaffe script you must open a command box, go to the directory containing the script and its related file (scenery, region files,...) and type:
Windows ME/95/2000/NT:
	C:\...> gaffe myscript.g

Unix:
	..$ gaffe myscript.g
Remarks:
  1. Be sure to examine the compiler output as it may contain references to problems.
  2. When the scriptname is omitted, the standard input will be used.

Syntax

Summary

Important:
  1. All operations and settings are followed by a semi-colon ( ';' ).
  2. The anime header and all compounds are followed by curly braces.

Anime

Indicate the beginning of the script.

Syntax:

anime( prefix , width, height ) { ... }

Parameters:

prefix string output frames are prefix'ed by this name. width integer width of the output frames height integer height of the output frames

Remarks:

There can only be one 'anime' keyword in one script file. Only global settings or comments can precede this keyword.

See Also:

none.

Blit

operation. Paints a given image on the scenery

Syntax:

blit( image , x , y , delta_x , delta_y ); blit( image , x , y , delta_x , delta_y , z_order );

Parameters:

image string string indicating a portable pixmap image ( P6 binary ). x , y integer position where the image has to be painted delta_x , delta_y integer displacement during motion z_order float number indicating order when multiple blits have to be painted over each other

See Also:

none.

Cycle

compound. spreading queue that forwards motion untill the middle, then reverses the motion.

Syntax:

cycle( ) { ... }

Parameters:

size integer size of the queue

Remarks:

A queue divides its operations over its size. eg. If there are three operations in the cycle: { X Y Z } If the size parameter is nine, then the queue will look like this: { 1/2X 2/2X 1/2X 1/2Y 2/2Y 1/2Y 1/2Z 2/2Z 1/2Z } The ratio (1/2, 1/3, ... ) before the operation indicates the percentage of the operation that is executed (also called the 'motion').

Notes:

  1. A cycle reverses motion. The percentage in the above example grows untill the maximum and then decreases again.
  2. A cycle spreads each operation over its time-frame and than proceeds to the next.

See Also:

none.

Freeze

operation. hold the previous operation exactely like it was for N time.

Syntax:

freeze( );

Parameters:

size integer number of freeze operations

Remarks:

Freeze repeats the operation before this one. It 'freezes' the motion. 'Freeze' must be preceeded by an operation or else compiler error will occur.

See Also:

none.

Hold

compound. does not split its queue when a thread is made.

Syntax:

hold( ) { ... }

Remarks:

A thread compound will tear all of its sub-compounds apart, except the 'hold' compound. In short, the 'hold' compound ensures that its operations are executed one after the other.

See Also:

thread.

Loop

compound. a repetetive queue that reverses the motion in the middle of the queue.

Syntax:

cycle( ) { ... }

Parameters:

size integer size of the queue

Remarks:

A queue divides its operations over its size. eg. If there are three operations in the loop: { X Y Z } If the size parameter is nine, then the queue will look like this: { 1/2X 1/2Y 1/2Z 2/2X 2/2Y 2/2Z 1/2X 1/2Y 1/2Z } The ratio (1/2, 1/3, ... ) before the operation indicates the percentage of the operation that is executed. This percentage is called the 'motion'.

Notes:

  1. A loop reverses motion. The percentage in the above example grows untill the maximum and then decreases again.
  2. A loop repeats its operation tightly.

See Also:

none.

Move

operation. Move a ledemaat.

Syntax:

move( , , );

Parameters:

ledemaat string region identifier x integer horz. displacement y integer vert. displacement

Remarks:

The 'ledemaat' is set name of the region give by an '.lm' file. This file must be set by the 'scenery.regions' variable. This operation moves the region by and . This a vector operation. It doesn't paint anything but pushes the result on the stack so that paint can use it.

See Also:

stretch, rotate, paint

Nop

operation. does nothing for a specified amout of time.

Syntax:

nop( );

Parameters:

size integer the size indicates the number of operations that nothing must be done.

Remarks:

none.

See Also:

none.

Paint

operation. paint a ledemaat.

Syntax:

paint( , " " );

Parameters:

ledemaat string name of a region. specifier quoted string see remarks

Remarks:

The 'ledemaat' is set name of the region give by an '.lm' file. This file must be set by the 'scenery.regions' variable. The specifier can be: "background" paint with this region's background color "morph" pop's a the results of a vector operation from the stack and morphs the region to match it. "border" paint the border of this region black A specifier can contain one or more of the above words.

See Also:

none.

Pan

operation. take a panoramic 'shot' of the scenery image

Syntax:

pan( x1 , y1 , width1 , height1 , x2 , y2 , width2 , height2 );

Parameters:

x1,y1 integer x,y position x2,y2 integer id. width1,height1 width2,height2 integer width, height

Remarks:

Using pan-operations is a conditio-sine-qua-none for making a moves. It is used to take snapshots of the scenery. The (x1,y1,w1,h1) indicates starting camera postions and the second set (x2,y2,w2,h2) indicates to target camera position.

See Also:

none.

Pipe

compound. spreading queue.

Syntax:

pipe( ) { ... }

Parameters:

size integer size of the queue

Remarks:

A queue divides its operations over its size. eg. If there are three operations in the pipe: { X Y Z } If the size parameter is nine, then the queue will look like this: { 1/2X 2/3X 3/3X 1/3Y 2/3Y 3/3Y 1/3Z 2/3Z 3/3Z } The ratio (1/2, 1/3, ... ) before the operation indicates the percentage of the operation that is executed (also called the 'motion').

Notes:

  1. A pipe spreads each operation over its time-frame and than proceeds to the next.

See Also:

none.

Repeat

compound. repetetive queue.

Syntax:

repeat( ) { ... }

Parameters:

size integer size of the queue

Remarks:

A queue divides its operations over its size. eg. If there are three operations in the loop: { X Y Z } If the size parameter is nine, then the queue will look like this: { 1/3X 1/3Y 1/3Z 2/3X 2/3Y 2/3Z 3/3X 3/3Y 3/3Z } The ratio (1/2, 1/3, ... ) before the operation indicates the percentage of the operation that is executed. This percentage is called the 'motion'.

Notes:

  1. A repeat repeats its operations tightly.

See Also:

none.

Rotate

operation. Rotates a ledemaat.

Syntax:

rotate( , );

Parameters:

ledemaat string region identifier angle float angle in radians

Remarks:

The 'ledemaat' is set name of the region give by an '.lm' file. This file must be set by the 'scenery.regions' variable. This operation rotates the region by (range: 0 ... 3.14 ... 6.28 ...). The first point of the region is used as rotation point. The last point of the region remains fixed too. This a vector operation. It doesn't paint anything but pushes the result on the stack so that paint can use it.

See Also:

stretch, move, paint

Stretch

operation. Deforms a ledemaat.

Syntax:

stretch( , , );

Parameters:

ledemaat string region identifier x integer horz. displacement y integer vert. displacement

Remarks:

The 'ledemaat' is set name of the region give by an '.lm' file. This file must be set by the 'scenery.regions' variable. This operation deforms the region by and . All points, except the first and last point of the region will be moved with the displacement. This a vector operation. It doesn't paint anything but pushes the result on the stack so that paint can use it.

See Also:

move, rotate, paint

Thread

compound. Weaves a new queue from its sub-compounds.

Syntax:

thread( ) { ... } thread() { ... }

Parameters:

size integer size of the queue

Remarks:

This compound has a special kind of a queue. It is possible to specify the size of it, but when the second form is used then a queue will always use it's optimal size. A thread can only have sub-compound as its member. It will transvers it's sub-compounds: take the operation of the sub-compounds one by one and mix them. eg. If there are two sub-compounds and one sub-sub-compound with a total of three operations: { { X { Y } } { Z } } If the size parameter is nine, then the queue will look like this: { X Z Y } A thread tranverses it's every sub-compound one by one (first X, sub-compound 1, then Z, sub-compound 2). And then repeats this ( 'Y' , in the subsub-compound). A thread cannot traverse a hold-compound: { hold({ X { Y }) } { Z } } Results in: { hold({ X { Y }) } Z }

See Also:

none.

Settings

Global settings are: scenery string. the path to an image file (.ppm). shot.from integer. only the frames from this one on are included in the shot shot.to integer. only the frames untill this one on are included in the shot scenery.regions string. points to an '.lm' file containing regions.

File formats

Region file ( .lm )

Example:

#been.ppm - beschrijving van de vlakken
bil!5,41,98
knieholte!4,20,144
hiel,60,197
scheen!3,87,210
knie!0,112,143
lies!10,71,87

#ledematen - De eerst is het rotatiepunt
onderbeen!FEFEFE=knieholte,hiel,scheen,knie
bovenbeen!FEFEFE=bil,knieholte,hiel,scheen,knie,lies

Point are defined by: <name>[ !<width>],<x>,<y>

  • width pen width. pen width is used for painting the border of a ledemaat.
  • x,y horz/vert position

'Ledematen' are defined by: <name>!<colour>={ <point-name> , ... }

  • name region name as will be used by the script
  • colour RGB value of the colour. The colours are encoded in a double digits hex format ('00' to 'FF') first for red, then green, then blue. NOTE: The colour FFFFFF (pure white) is a reserved colour for transparancy (!). It is common to use FEFEFE (almost pure white) as a substitute for pure white.