节点动画
直接修改节点的属性会立即生效,体现不出时间的概念,也没有渐变的效果。想让一个精灵执行一段连贯的动画,需要用到 Action 动画类。
位移动画
MoveTo
动画可以使节点在一段时间内移动到另一个位置。
// 创建一个位移动画,2.5 秒后使节点移动到坐标 (100, 200) 处
auto moveTo = gcnew MoveTo(2.5f, Point(100, 200));
调用节点的 runAction
函数,可以让节点执行动画。如下面的代码执行后,无论精灵在什么位置,它都会在 2.5 秒内移动到坐标 (100, 200) 处。
// 创建一个精灵
auto sprite = gcnew Sprite();
// 让这个精灵执行位移动画
sprite->runAction(moveTo);
MoveBy
动画也是位移动画,它使节点朝一个方向移动一定的距离。
// 创建一个位移动画,2.5 秒内使节点移动横向移动 100 像素
auto moveBy = gcnew MoveBy(2.5f, Vector2(100, 0));
执行这个动画后,节点会从它的起始位置开始,在 2.5 秒内向正右方移动 100 像素。
透明度渐变动画
OpacityTo
动画可以使节点的透明度在一段时间内变化到另一个值(必须在 0 ~ 1 范围内,0 是完全透明,1 是完全不透明)。
// 创建一个透明度渐变动画,1 秒后透明度变为 0.2
auto opacityTo = gcnew OpacityTo(1, 0.2f);
执行这个动画后,无论节点本来的透明度如何,它的透明度都会在 1 秒内变成 0.2。
OpacityBy
动画也是透明度渐变动画,它使节点的透明度在一段时间内逐渐增加或减少。
// 创建一个透明度渐变动画,1 秒后透明度减少 0.5
auto opacityBy = gcnew OpacityBy(1, -0.5f);
例如下面的精灵的起始透明度是 0.5,执行这个动画后,它的透明度会在 1 秒内从 0.8 减少到 0.3。
// 创建一个精灵
auto sprite = gcnew Sprite();
// 设置精灵的透明度为 0.8
sprite->setOpacity(0.8f);
// 让这个精灵执行位移动画
sprite->runAction(opacityBy);
FadeIn
和 FadeOut
是淡入和淡出动画,让节点浮现或消失,你只需要指定这个动画的时长。
// 创建一个 1 秒的淡入动画
auto fadeIn = gcnew FadeIn(1);
// 创建一个 1 秒的淡出动画
auto fadeOut = gcnew FadeOut(1);
缩放动画
ScaleTo
动画可以使节点在一段时间内逐渐放大或缩小(大于 1 是放大,小于 1 大于 0 是缩小,小于 0 是反转)。
// 创建一个缩放动画,1 秒后缩放到原始大小的 0.5 倍
auto scaleTo = gcnew ScaleTo(1, 0.5f);
执行这个动画后,无论节点本来多大,它都会在 1 秒内逐渐变化成原始大小的 0.5 倍。
ScaleBy
动画也是缩放动画,它使节点的缩放倍数在一段时间内逐渐增加或减少。
// 创建一个缩放动画,1 秒后缩放倍数减少 0.3
auto scaleBy = gcnew ScaleBy(1, -0.3f);
例如下面的精灵的起始缩放倍数是 0.5,执行这个动画后,它会在 1 秒内逐渐缩小至原始大小的 0.2 倍。
// 创建一个精灵
auto sprite = gcnew Sprite();
// 设置精灵的缩放为原来的 0.5 倍
sprite->setScale(0.5f);
// 让这个精灵执行位移动画
sprite->runAction(scaleBy);
旋转动画
RotateTo
动画可以使节点在一段时间内逐渐旋转至某个角度。
// 创建一个旋转动画,1 秒后缩放至 180 度
auto rotateTo = gcnew RotateTo(1, 180);
执行这个动画后,无论节点原本的角度是多少,它都会在 1 秒内逐渐旋转至 180 度。
RotateBy
动画也是旋转动画,它使节点的旋转度数在一段时间内逐渐变化(正数表示顺时针旋转,负数表示逆时针旋转)。
// 创建一个旋转动画,1 秒内顺时针旋转 60 度
auto rotateBy = gcnew RotateBy(1, 60);
跳跃动画
JumpTo
动画可以使节点在一段时间内跳跃到另一个位置。
// 创建一个跳跃动画,2.5 秒后使节点移动到坐标 (100, 200) 处,跳跃高度为250
auto jumpTo = gcnew JumpTo(2.5f, Point(100, 200), 250);
// 创建一个跳跃动画,但跳跃3次
auto jumpTo = gcnew JumpTo(2.5f, Point(100, 200), 250, 3);
JumpBy
动画也是跳跃动画,但它可以跳跃到相对于当前的某个位置。
// 创建一个相对跳跃动画,2.5 秒内使节点跳跃后移动到它右侧 100 像素位置,跳跃高度为250
auto jumpBy = gcnew JumpBy(2.5f, Vector2(100, 0), 250);
帧动画
Animation
是帧动画,所谓帧动画就是每隔一个很短的时间,切换一次精灵的图片。当这个间隔非常短时,精灵就好像动了起来。
用 Image (图片类) 可以给精灵创建帧动画,下面是一段示例代码
// 创建帧动画的序列帧,每 0.1 秒切换一帧
auto seq = gcnew FrameSequence(0.1);
// 加载多个精灵帧
seq->add(Image::load("第一帧.png")); // 无裁剪的添加一张图片
seq->add(gcnew KeyFrame(Image::load("第二帧.png"))); // 无裁剪的指定图片为关键帧,和上一行写法没有区别
seq->add(gcnew KeyFrame(Image::load("第三帧.png"), Rect(Point(), Size(100, 50)))); // 指定图片为关键帧并进行裁剪
// 创建帧动画
auto animation = gcnew Animation(seq);
// 精灵执行帧动画
sprite->runAction(animation);
注意,只能由 Sprite 执行帧动画。
这个动画只执行一次就结束了,如果想让它循环执行帧动画,需要用 Loop 动画组合实现
// 把已建好的帧动画组合成循环动画
auto action = gcnew Loop(animation);
// 精灵执行循环的帧动画
sprite->runAction(action);
在动画中执行函数
CallFunc
在运行时立即执行一个函数。
void Test() { ... }
// 创建一个动画,这个动画立即执行 Test 函数
auto action = gcnew CallFunc(Test);
// 另外一种方法,执行 lambda 函数
auto action = gcnew CallFunc([]() {});
查看更多关于回调函数的内容
动画中的延时
Delay
是一段延时动画,它什么都不做,只是为了多个动画组合在一起时,起到间隔的作用。
// 创建一个延时动画,它延时 1 秒
auto delay = gcnew Delay(1);
顺序执行多个动画
Sequence
可以将多个动画组合成一个顺序执行的动画。
// 创建一个 1.5 秒的淡出动画
auto fadeOut = gcnew FadeOut(1.5f);
// 创建一个回调函数动画
auto callback = gcnew CallFunc([=]() {
sprite->setRotation(45); // 在回调函数中修改精灵的旋转角度
});
// 创建一个 0.5 秒的淡入动画
auto fadeIn = gcnew FadeIn(0.5f);
// 组合三个动画成顺序动画
auto sequence = gcnew Sequence({ fadeOut, callback, fadeIn });
// 执行顺序动画
sprite->runAction(sequence);
上面的代码将三个动画组合成一个顺序动画,精灵执行这个动画后,就会先慢慢消失,然后旋转 45 度,再慢慢浮现出来。
同时执行多个动画
Spawn
可以将多个动画组合在一起,并让它们同时开始运行。
// 创建一个 1.5 秒的淡出动画
auto fadeOut = gcnew FadeOut(1.5f);
// 创建一个 0.5 秒的旋转动画
auto rotateBy = gcnew RotateBy(0.5f, 60);
// 组合两个动画
auto two = gcnew Spawn({ fadeOut, rotateBy });
// 执行组合动画
sprite->runAction(two);
上面的代码将淡入和旋转动画组合成一个动画,精灵执行后就会一边慢慢消失,一边旋转 60 度。
循环执行动画
Loop
可以让一个动画循环执行,例如下面的代码,精灵执行动画后会持续不断的旋转
// 创建一个旋转动画,1 秒内顺时针旋转 60 度
auto rotateBy = gcnew RotateBy(1, 60);
// 创建一个循环动画
auto loop = gcnew Loop(rotateBy);
// 让一个精灵执行
sprite->runAction(loop);
配合组合动画,可以实现更复杂的动画循环,例如下面的代码,精灵执行动画后就会不断的消失,又浮现
// 创建一个 1.5 秒的淡出动画
auto fadeOut = gcnew FadeOut(1.5f);
// 创建一个 0.5 秒的淡入动画
auto fadeIn = gcnew FadeIn(0.5f);
// 组合两个动画
auto seq = gcnew Sequence({ fadeOut, fadeIn });
// 创建一个循环动画
auto loop = gcnew Loop(seq);
// 让一个精灵执行
sprite->runAction(loop);
循环动画可以设置它的构造函数的第二个参数,指定它的循环次数。例如下面的代码中,循环动画只会循环 3 次。
// 创建一个循环动画
auto loop = gcnew Loop(action, 3);
动画的停止、暂停和继续
节点执行动画后,可以在任何时候让这个动画停止、暂停或继续。
// 假设存在动画 action 和精灵 sprite
// 执行动画
sprite->runAction(action);
// 暂停动画
action->pause();
// 继续动画
action->resume();
// 停止动画
action->stop();
动作可以有自己的名称,然后你可以让所有相同名称的动画停止或继续
// 假设存在动画 action 和精灵 sprite
// 设置动画的名称
action->setName("旋转动画");
// 执行动画
sprite->runAction(action);
// 停止 sprite 的“旋转动画”
sprite->stopAction("旋转动画");
你也可以直接停止、暂停或继续一个节点的所有动画
// 暂停 sprite 的所有动画
sprite->pauseAllActions();
// 继续 sprite 的所有动画
sprite->resumeAllActions();
// 停止 sprite 的所有动画
sprite->stopAllActions();
动画的克隆
虽然一个精灵可以执行两个动画,但是两个精灵不能执行同一个动画,所以下面的代码是错误的
// 创建一个 1.5 秒的淡出动画
auto fadeOut = gcnew FadeOut(1.5f);
// 两个精灵执行同一个动画将出现错误
sprite->runAction(fadeOut);
sprite2->runAction(fadeOut);
这种情况应使用 clone
函数创建一个相同的动画,并让第二个精灵执行这个克隆后的动画
// 创建一个 1.5 秒的淡出动画
auto fadeOut = gcnew FadeOut(1.5f);
// 第一个精灵执行动画
sprite->runAction(fadeOut);
// 第二个精灵执行这个动画的克隆动画
sprite2->runAction(fadeOut->clone());