mutter/doc/reference/clutter-animation.sgml
Matthew Allum a303847b02 2007-10-28 Matthew Allum <mallum@openedhand.com>
* clutter-animation.sgml:
        Fix missing func param (#583)
2007-10-28 22:01:25 +00:00

214 lines
5.9 KiB
Plaintext

<chapter id="clutter-animations">
<chapterinfo>
<author>
<firstname>Matthew</firstname>
<surname>Allum</surname>
<affiliation>
<address>
<email>mallum@openedhand.com</email>
</address>
</affiliation>
</author>
</chapterinfo>
<title>Creating Animations with Clutter</title>
<para>
Clutter has a powerful and flexible framework for animating
actors. The basis of which is the #ClutterTimeline class which
reprents a period of time in frames. A #ClutterTimeline takes two
parameters, a total number of frames and a frame rate (in frames per
second). Once created, a signal ("new-frame") can be attached and
then on starting (clutter_timeline_start()) the signal callback wil
be called every time a new frame is reached. With the callback also
receiving the current frame number this information can be used to
modify actor properties and thus produce an animation.
</para>
<example id="clutter-timeline-example">
<para>
The following example demonstrates rotating an actor with a timeline.
</para>
<programlisting>
#include &lt;clutter/clutter.h&gt;
void
on_new_frame (ClutterTimeline *timeline,
gint frame_num,
gpointer data)
{
ClutterActor *actor = CLUTTER_ACTOR(data);
clutter_actor_rotate_z (actor, (gdouble)frame_num,
clutter_actor_get_width (actor)/2,
clutter_actor_get_height (actor)/2);
}
int
main (int argc, char *argv[])
{
ClutterTimeline *timeline;
ClutterActor *stage, *actor;
GdkPixbuf *pixbuf;
clutter_init (&amp;argc, &amp;argv);
stage = clutter_stage_get_default ();
pixbuf = gdk_pixbuf_new_from_file ("an-image.png", NULL);
actor = clutter_texture_new_from_pixbuf (pixbuf);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
clutter_actor_set_position (actor, 100, 100);
timeline = clutter_timeline_new (360, 60); /* num frames, fps */
g_object_set(timeline, "loop", TRUE, NULL); /* have it loop */
g_signal_connect (timeline, "new-frame", G_CALLBACK (on_new_frame), actor);
clutter_actor_show_all (stage);
clutter_timeline_start (timeline);
clutter_main();
return 0;
}
</programlisting>
</example>
<para>
Timelines will 'drop' frames if it appears the application cannot
keep up with the requested framerate. The first and last frames are
guaranteed to be called however. Read the #ClutterTimeline
documentation for more information on how they can be manipulated.
</para>
<para>
Timelines on there own are useful for simple animations but can be
come very unweldy for more complex multiple actor animations. Also
they can lead to much code duplication. The #ClutterAlpha and
#ClutterBehaviour classes build on timelines to offer further
animation functionality and avoid these problems.
</para>
<para>
A #ClutterAlpha is a 'function if time' (note, not pixel alpha!). It is
created by passing both a #ClutterTimelime and a
#ClutterAlphaFunc. The Alpha then produces a value between 0 and
CLUTTER_ALPHA_MAX. This value is dependant on both the position of
the Alpha's supplied timeline and the supplied function used by the
Alpha.
</para>
<para>
Clutter comes with many predefined #ClutterAlphaFunc's including:
#CLUTTER_ALPHA_RAMP_INC - A rising alpha value over time,
#CLUTTER_ALPHA_RAMP_DEC - A decreasing alpha value over time,
#CLUTTER_ALPHA_SINE, A sinewave etc.
</para>
<para>
A #ClutterBehaviour is then 'driven' by a supplied #ClutterAlpha and
when then applied to an actor it will modify a visual property or
feature of the actor dependant on the Alpha's value. For example a
path based behaviour applied to an actor will alter its position
along the path dependant on the current alpha value over time. The
actual motion will depend on the chosen #ClutterAlphaFunc - a
#CLUTTER_ALPHA_RAMP_INC making it to move at constant speed along the
path, a #CLUTTER_ALPHA_SINE making it alternate from one end of the
path to the other with non constant speed.
</para>
<example id="clutter-timeline-example">
<para>
The following example demonstrates an ellipse behaviour in action.
</para>
<programlisting>
#include &lt;clutter/clutter.h&gt;
int
main (int argc, char *argv[])
{
ClutterTimeline *timeline;
ClutterBehaviour *behave;
ClutterAlpha *alpha;
ClutterActor *stage, *actor;
GdkPixbuf *pixbuf;
clutter_init (&amp;argc, &amp;argv);
stage = clutter_stage_get_default ();
pixbuf = gdk_pixbuf_new_from_file ("ohpowers.png", NULL);
actor = clutter_texture_new_from_pixbuf (pixbuf);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
timeline = clutter_timeline_new (100, 26); /* num frames, fps */
g_object_set(timeline, "loop", TRUE, NULL); /* have it loop */
/* Set an alpha func to power behaviour */
alpha = clutter_alpha_new_full (timeline,
CLUTTER_ALPHA_SINE,
NULL, NULL);
behave = clutter_behaviour_ellipse_new (alpha,
200, /* center x */
200, /* center y */
400, /* width */
300, /* height */
CLUTTER_ROTATE_CW, /* direction */
0.0, /* angle begin */
360.0); /* angle end */
clutter_behaviour_apply (behave, actor);
clutter_actor_show_all (stage);
clutter_timeline_start (timeline);
clutter_main();
return 0;
}
</programlisting>
</example>
<para>
Multiple behaviours can of course be applied to an actor as well as
a single behaviour being applied to multiple actors. The separation
of timelines, alphas and behaviours allows for a single timeline to
drive many behaviours each potentially using different alpha
functions.
</para>
<para>
Properties of the behaviour, alpha and timeline can be changed on
the fly making animations. Experiment!
</para>
<para>
ClutterEffects provide a simpler (but more limited) layer around the above.
FIXME.
</para>
</chapter>