根据教程,我们应学习ClutterAnimation,但是在这里我碰到了一些问题,我不确定是否是Clutter1.0的问题,从某种意义上看,Clutter0.9比Clutter1.0更为稳定。我们已经一而再地讨论了clutter的兼容,但是我想仍需要再三讨论这个问题。现在,我们学习类似的处理效果ClutterBehaviour,我认为所有ClutterAnmation均可以通过ClutterBehaviour来进行处理。消灭问题或者绕开问题,一直是中国传统哲学的一个特点。

  学习资料来源: Using BehaviourExample ,以及clutter 1.0的联机文档。

  在ClutterTimeline中,可以根据new-frame触发来进行动态图像处理,但是new-frame的触发频率依赖于monitor,我们不能精确地控制动作发生的时间过程。而ClutterBehaviour提供一种在指定时间内完成某个动作的方式。

  下面是一个例子,我们去除了具体的动作效果,先讨论ClutterBehaviour如何工作。我们提供了两个动态效果,例如如果图像从大到小,那么另一个效果就是从小到大,已是的整个动作连贯。

#include <clutter/clutter.h>
 #include <stdlib.h> int main(int argc,char * argv[]){
     ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff };
     clutter_init (&argc, &argv);     /* Get the stage and set its size and color: */
     ClutterActor *stage = clutter_stage_get_default ();
     clutter_actor_set_size (stage, 800, 600);
     clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);     /* Add a rectangle to the stage: */
     ClutterActor * rect  = clutter_texture_new_from_file("4.png",NULL);
     clutter_actor_set_position (rect, 200, 200);
     clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
     clutter_actor_show (rect);     /* Show the stage: */
     clutter_actor_show (stage); /* 加两个顺序执行的timeline,周期均为10秒 */ 
     ClutterScore * score = clutter_score_new();
     clutter_score_set_loop(score,TRUE); 
     ClutterTimeline *timeline1 = clutter_timeline_new(10000);
     ClutterTimeline *timeline2 = clutter_timeline_new(10000);
     clutter_score_append(score,NULL,timeline1);
     clutter_score_append(score,timeline1,timeline2);/* ClutterAlpha是个很有趣的参数,简单说他将某个运动的模式和timeline进行捆绑,例如我们定义在某个timeline的有效时间内,动态的效果是线性的。如果这个效果作用于一个移动的动作(在下面定义),则表示匀速运动,如果亮度的渐变方式,表示均速变化。Clutter提供了丰富的模式,详细可以参见联机文档:/usr/share/gtk-doc/html/clutter/clutter-Implicit-Animations.html#CLUTTER-LINEAR--CAPS。*/ 
     ClutterAlpha *alpha1 = clutter_alpha_new_full (timeline1, CLUTTER_LEANAR ); 
     ClutterAlpha *alpha2 = clutter_alpha_new_full (timeline2, CLUTTER_EASE_OUT_BOUNCE);
     g_object_unref (timeline1);
     g_object_unref (timeline2);    /* … …,这里我们创建两个动作behaviour1和behaviour2,具体在后面讨论,先略去*/ 
    /* 将某个动作和具体的actor关联。这个actor将在timeline的有效时间内,根据运动模型,进行具体的动作*/ 
     clutter_behaviour_apply (behaviour1, rect);  
     clutter_behaviour_apply (behaviour2, rect);
     clutter_score_start(score);     clutter_main (); 
    return EXIT_SUCCESS;
 }

Clutter提供了六种的动作方式,具体的可以参见联机文档,我们在下面分别讨论:

这里给出两种动作,一种是椭圆运动方式。如果我们想使用逆时针旋转,方向设置为CLUTTER_ROTATE_CCW,但是初始角度要大于最后角度,应设置为……,CLUTTER_ROTATE_CCW,360.0,0);请注意角度是不能超过360度,如果需要连续旋转两周,可以设置两个timeline,分别旋转1周。后一种是Z轴的depth,但是在平面的图像中,我确实比较难理解Z的变化,从现在上看类似于Scale,而且不会小于图像本上大小。

ClutterBehaviour *behaviour1 = clutter_behaviour_ellipse_new ( alpha1,
      300,               /* center x */
      200,               /* center y */
      400,               /* width */
      300,               /* height */
      CLUTTER_ROTATE_CW, /* direction */
      0.0,               /* initial angle */
      360.0);            /* final angle */ ClutterBehaviour *behaviour2 = clutter_behaviour_depth_new ( alpha2,
 200,
 20
 );

一个clutter的可能bug的处理如果我们不是要求马上进行动态运动,即我们不在main中调用clutter_score_start(),而是在程序的其他地方,例如某个回调函数,在检测到用户某个实现后触发,我们会发现actor并不在我们期待的位置。不在我们创建actor时指定的问题,也不在我们运动要求的初始位置。对于运动,clutter的默认初始位置为(0,0),如果是椭圆运动,默认运动中心为(0,0),根据我们运动范围和初始角度,将位置设置为(200,0),这显然不是我们所期待。在这种情况下,我们可以在 clutter_behaviour_apply后面加上clutter_actor_set_position(rect,500,200)来修正我们的位置。 我不实际了解depth动作的具体含义,这个不清除如何矫正。但是在这个例子中他的作用相当于scale,我们用scale的变化方式替代,scale是可以修正的。

下面是亮度渐变的方式。从暗到亮,在从亮到暗,循环进行。

ClutterBehaviour *behaviour1 = clutter_behaviour_opacity_new( alpha1,40,255);
 ClutterBehaviour *behaviour2 = clutter_behaviour_opacity_new( alpha2,255,40);

路径移动,可以进行直线移动,也可以进行曲线移动。请注意clutter_path_add_move_to是非常重要的。如果不设置,初始位置为(0,0)。这是耗费了小时计算的时间才找到的解决方法。

ClutterPath * path1 = clutter_path_new ();
clutter_path_add_move_to (path1,100,100);
clutter_path_add_line_to (path1,600,400);
 ClutterBehaviour *behaviour1 = clutter_behaviour_path_new(alpha1,path1);
 ClutterPath * path2 = clutter_path_new();
 clutter_path_add_move_to(path2,600,400);
 clutter_path_add_curve_to(path2,400,500,200,500,100,100);
 ClutterBehaviour *behaviour2 = clutter_behaviour_path_new( alpha2,path2);

指定移动的路线,可以设置多个点,移动的方式是直线

ClutterKnot knot1[3],knot2[2];
   knot1[0].x = 50;
   knot1[0].y = 50;
   knot1[1].x = 100;
   knot1[1].y = 300;
   knot1[2].x= 600;
   knot1[2].y= 400;
   knot2[0].x = 600;
   knot2[0].y = 400;
   knot2[1].x= 50;
   knot2[1].y= 50; ClutterBehaviour *behaviour1 = clutter_behaviour_path_new_with_knots( alpha1,knot1,3);
 ClutterBehaviour *behaviour2 = clutter_behaviour_path_new_with_knots( alpha2,knot2,2);

旋转,同样如果需要反时针转动,设置为CLUTTER_ROTATE_CCW,并且初始角度大于最终角度。

ClutterBehaviour *behaviour1 = clutter_behaviour_rotate_new( alpha1,CLUTTER_Y_AXIS,CLUTTER_ROTATE_CW,0,360.0);
 clutter_behaviour_rotate_set_center((ClutterBehaviourRotate *)behaviour1,20,0,50);
 ClutterBehaviour *behaviour2 = clutter_behaviour_rotate_new( alpha2,CLUTTER_X_AXIS,CLUTTER_ROTATE_CW,0,360.0);

大小变化,这个比较简单。

ClutterBehaviour *behaviour1 = clutter_behaviour_scale_new(alpha1,0.5,0.5,3,2);
 ClutterBehaviour *behaviour2 = clutter_behaviour_scale_new(alpha2,3,2,0.5,0.5);

关于动态效果

下面的这个图很好地表明的动态效果和时间轴的关系。

各类的动态效果,可以看下图,来自联机文档:

Clutter学习(十一):动态效果设置ClutterBehaviour_callback

 

附:可能的一些bug

  ClutterBehavior初始位置的设定可能存在bug。例如clutter_behaviour_ellipse_new,这是个椭圆运动,无论我们如何设置椭圆的中心,clutter会按照中心为(0,0),根据范围,和初始角度设置初始位置。同样对于直线运动方式,初始会设置在(0,0),都需要修正。
  如果我们将动作变化在main函数中触发貌似正常,但是如果我们屏蔽了时间轴(或者时间轴集)的启动,就很清楚地看到clutterBehavior设置的初始位置,显然不是我们预计的。
  如果我们在callback函数中设置clutterBehavior或者启动时间轴,就会在触发的时候,在clutter自认为的初始位置中闪现,除非我们在clutter_behaviour_apply后面用set_position来进行修正。这等于需要我们重新计算位置。
  如果变化不是位置的变化,例如depth的变化,那么在我们apply的时候就设置为会初始化,而不是在时间轴启动的时候才进行。这会影响我们的实现,因为变化可能是ClutterScore非第一个时间轴,例如是第二个时间轴,他将会在score启动的时候,在其初始状态上进行闪现。这会严重影响我们的效果。因此需要避免相关情况。
  这是一个测试的例子:

#include <clutter/clutter.h>
 #include <stdlib.h>

 ClutterActor *rect = NULL;
 ClutterBehaviour *behaviour1 = NULL , * behaviour2 = NULL;
 ClutterScore * score = NULL;

 void set_motion(){
         score = clutter_score_new();
         clutter_score_set_loop(score,TRUE);

         ClutterTimeline *timeline1 = clutter_timeline_new(10000);
         ClutterTimeline *timeline2 = clutter_timeline_new(10000);
         clutter_score_append(score,NULL,timeline1);
         //clutter_score_append(score,timeline1,timeline2);

         ClutterAlpha *alpha1 = clutter_alpha_new_full (timeline1,
          CLUTTER_EASE_IN_OUT_QUAD);//CLUTTER_EASE_IN_SINE);
         ClutterAlpha *alpha2 = clutter_alpha_new_full (timeline2,
          CLUTTER_EASE_OUT_BOUNCE);//CLUTTER_EASE_IN_SINE);
         g_object_unref (timeline1);
         //g_object_unref (timeline2);

         ClutterBehaviour *behaviour1 = clutter_behaviour_ellipse_new(
          alpha1,
          300,               /* center x */
          200,               /* center y */
          400,               /* width */
          300,               /* height */
          CLUTTER_ROTATE_CCW, /* direction */
          360.0,               /* initial angle */
          0.0);            /* final angle */

         ClutterBehaviour *behaviour2 = clutter_behaviour_depth_new(
          alpha2,
          200,
          20
          );
         clutter_behaviour_apply (behaviour1, rect);
         //clutter_behaviour_apply (behaviour2, rect);
         clutter_actor_set_position(rect,500,200);
         clutter_score_start(score);
 }

 static gboolean on_key_press(ClutterStage * stage ,
                 ClutterEvent * event,
                 gpointer *user_data){
         float x = 0;
         float y = 0;
         clutter_actor_get_position (rect, &x, &y);

         g_print ("rect  at (%f, %f)/n", x,y);
         set_motion();


         return TRUE;
 }

 int main(int argc,char * argv[]){
         ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff };
         //ClutterColor rect_color = { 0xff, 0xff, 0xff, 0x99 };

         clutter_init (&argc, &argv);

         /* Get the stage and set its size and color: */
         ClutterActor *stage = clutter_stage_get_default ();
         clutter_actor_set_size (stage, 800, 600);
         clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);

         /* Add a rectangle to the stage: */
         //rect = clutter_rectangle_new_with_color (&rect_color);
         //clutter_actor_set_size (rect, 40, 40);
         rect  = clutter_texture_new_from_file("4.png",NULL);
         clutter_actor_set_position (rect, 500, 200);
         clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
         clutter_actor_show (rect);

         /* Show the stage: */
         clutter_actor_show (stage);


         g_signal_connect(stage,"key_press_event",G_CALLBACK(on_key_press),NULL);


         //set_motion();

         clutter_main ();

         return EXIT_SUCCESS;
 }

相关链接:
我的Clutter相关博客

 

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6