클러터(Clutter) 사용하기 (4)

클러터 튜토리얼 계속 이어집니다.

타임라인 (Timelines)

ClutterTimeline은 시간이 흐르는 동안 액터의 모양이나 위치를 자동으로 변경하는데 사용합니다. 다음에 설명할 효과(effect)나 움직임(behaviour)와 함께 사용할 수도 있지만 직접 사용할 수도 있습니다.

타임라인 객체는 지정한 초당 프레임 수를 기준으로 시간이 되면 각 프레임이 그려질 수 있도록 new-frame 시그널을 발생합니다. 그러면 시그널 핸들러에서 액터의 속성을 변경하면 됩니다. 물론 스테이지에 있는 여러 액터의 속성을 동시에 변경할 수도 있습니다. (물론 이외에도 몇 가지 시그널이 더 있습니다)

타임라인 객체를 만드는 clutter_timeline_new() 함수는 총 프레임 수(n_frames)와 초당 프레임 수(fps)를 인수로 받습니다. 따라서 이 값을 기준으로 전체 지속 시간을 예측할 수 있습니다. 타임라인은 clutter_timeline_start()를 호출해야 비로소 시작합니다. clutter_timeline_stop()을 호출하기 전까지 clutter_timeline_set_loop()를 이용하여 무한히 반복하게 할 수도 있습니다.

여러 타임라인을 동시에 시작하거나 정지, 또는 순서대로 실행하려면 ClutterScore 객체를 사용합니다. 일종의 타임라인 제어기 역할을 하는 셈입니다. clutter_score_append()는 두 개의 타임라인을 인수로 받는데, 첫번째는 부모(parent) 타임라인이고 두번째가 추가할 타임라인입니다. 추가되는 타임라인은 부모가 끝난 다음에 실행됩니다. 부모가 NULL인 타임라인은 clutter_timeline_start()을 호출하면 바로 시작합니다.

예를 들어 다음 예제는 timeline1이 끝난 다음에 timeline2, timeline3가 동시에 시작합니다.

  ClutterTimeline *timeline1, *timeline2, *timeline3;
  ClutterScore *score;
 
  timeline1 = clutter_timeline_new_for_duration (1000);
  timeline2 = clutter_timeline_new_for_duration (500);
  timeline3 = clutter_timeline_new_for_duration (500);
 
  score = clutter_score_new ();
 
  clutter_score_append (score, NULL,       timeline1);
  clutter_score_append (score, timeline1, timeline2);
  clutter_score_append (score, timeline1, timeline3);
 
  clutter_score_start (score);

클러터 액터와 달리 타임라인 객체는 부동 참조(floating reference)가 없기 때문에 사용이 끝난 다음에는 g_object_unref()로 리소스를 해제해야 합니다. 사용이 끝나는 시점이 모호할 경우 completed 시그널에 핸들러를 등록해서 처리해도 됩니다.

다음 예제는 하나가 끝난 뒤 다른 하나가 시작하는 두 개의 타임라인을 포함하는 하나의 스코어 객체를 보여줍니다. 이 스코어 객체는 무한히 반복하고, 첫번째 타임라인은 사각형을 회전시키며 두번째 타임라인은 사각형을 수평을 이동시킵니다.

#include <clutter/clutter.h>
#include <stdlib.h>
 
ClutterActor *rect = NULL;
 
gint rotation_angle = 0;
gint color_change_count = 0;
 
/* 사각형을 회전시키고 색상을 변경 */
void
on_timeline_rotation_new_frame (ClutterTimeline *timeline,
                                gint             frame_num,
                                gpointer         data)
{
  rotation_angle += 1;
  if(rotation_angle >= 360)
    rotation_angle = 0;
 
  /* X축을 기준으로 시계방향으로 회전시킵니다. */
  clutter_actor_set_rotation (rect, CLUTTER_X_AXIS,
    rotation_angle, 0, 0, 0);
 
  /* 색삭을 변경합니다.
   * (This is a silly example, making the rectangle flash):
   */
  ++color_change_count;
  if(color_change_count > 100)
    color_change_count = 0;
 
  if(color_change_count == 0)
  {
    ClutterColor rect_color = { 0xff, 0xff, 0xff, 0x99 };
    clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color);
  }
  else if (color_change_count == 50)
  {
    ClutterColor rect_color = { 0x10, 0x40, 0x90, 0xff };
    clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color);
  }
}
 
/* 사각형 움직이기 */
void
on_timeline_move_new_frame (ClutterTimeline *timeline,
                            gint             frame_num,
                            gpointer         data)
{
  gint x_position = clutter_actor_get_x (rect);
 
  x_position += 1;
  if (x_position >= 150)
    x_position = 0;
 
  clutter_actor_set_x (rect, x_position);
}
 
int main(int argc, char *argv[])
{
  ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff };
  ClutterColor rect_color = { 0xff, 0xff, 0xff, 0x99 };
 
  clutter_init (&argc, &argv);
 
  /* 스테이지를 얻어 크기와 색상을 정합니다. */
  ClutterActor *stage = clutter_stage_get_default ();
  clutter_actor_set_size (stage, 200, 200);
  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
 
  /* 스테이지에 사각형을 추가합니다. */
  rect = clutter_rectangle_new_with_color (&rect_color);
  clutter_actor_set_size (rect, 70, 70);
  clutter_actor_set_position (rect, 50, 100);
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
  clutter_actor_show (rect);
 
  /* 스테이지를 보이게 합니다. */
  clutter_actor_show (stage);
 
  /* 스코어 객체를 하나 만들어 타임라인 객체 두개를 추가합니다.
   * 두번째 타임라인은 첫번째가 멈춘 뒤에 시작합니다. */
  ClutterScore *score = clutter_score_new ();
  clutter_score_set_loop (score, TRUE);
 
  ClutterTimeline *timeline_rotation =
    clutter_timeline_new (200 /* 총프레임수 */, 120 /* 초당프레임수(fps) */);
  g_signal_connect (timeline_rotation, "new-frame",
                    G_CALLBACK (on_timeline_rotation_new_frame), NULL);
  clutter_score_append (score, NULL, timeline_rotation);
 
  ClutterTimeline *timeline_move =
    clutter_timeline_new (200 /* 총프레임수 */, 120 /* 초당프레임수(fps) */);
  g_signal_connect (timeline_move, "new-frame",
                    G_CALLBACK (on_timeline_move_new_frame), NULL);
  clutter_score_append (score,  timeline_rotation, timeline_move);
 
  clutter_score_start (score);
 
  /* 메인 이벤트 루프를 시작합니다. */
  clutter_main ();
 
  g_object_unref (timeline_rotation);
  g_object_unref (timeline_move);
  g_object_unref (score);
 
  return EXIT_SUCCESS;
}

이제 클러터를 이용한 기본적인 애니메이션 원리를 알게 되었군요.

Creative Commons License
This work, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 2.0 Korea License.
This entry was posted in 카스탈리엔 and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">