一组 Sprite Kit 辅助类和函数。其中最有趣的是 SKTEffects,它可以让您的游戏变得更 有趣。
Sprite Kit 有一个名为 actions 的便利功能,可以让您非常容易地移动、旋转和缩放精灵。然而,一个很大的缺点是超出了标准 ease in 和 ease out 的计时函数。本包中提供的 SKTEffects
类添加了对更多 easing 函数的支持,以便于 Sprite Kit。
它允许您仅使用几行代码就做到以下事情
此代码最初是为iOS Games by Tutorials这本书编写的,该书由raywenderlich.com出版。
SKTEffects
存在的唯一原因是 SKAction
不允许任意的计时函数,只有标准的 ease-in 和 ease-out 函数。SKTEffect
子类是对 SKAction
已经执行的操作的重新实现,增加了自定义的计时函数。这是一个相当曲折的方法来实现最应该内置到 Sprite Kit 中的东西。
目前有三种 SKTEffect
子类
SKTMoveEffect
SKTRotateEffect
SKTScaleEffect
您可以使用如下方式使用它们
SKTMoveEffect *moveEffect = [SKTMoveEffect effectWithNode:node
duration:1.0
startPosition:startPosition
endPosition:endPosition];
moveEffect.timingFunction = SKTTimingFunctionBounceEaseOut;
[node runAction:[SKAction actionWithEffect:moveEffect]];
首先创建一个 SKTMoveEffect
对象,并将应该动画的节点、动画持续时间的秒数,以及节点的起始和结束位置传递给它。
然后(可选的),设置效果对象上的计时函数。您可以使用提供的计时函数——例如,弹性、反弹等其他许多函数——或者创建自己的。参见 SKTTimingFunctions.h 获取完整列表。
最后,您将效果对象包装在一个常规的 SKAction
内部,并在节点上运行此动作。
SKTRotateEffect
和 SKTScaleEffect
的过程是相同的,但分别指定旋转角度和缩放向量。
您可以同时组合多个效果,例如,有多个缩放效果同时作用于同一个节点。
目前效果没有“相对”版本。您必须始终提供绝对的起始和结束位置,旋转角度或缩放。大多数情况下这没问题,但这确实意味着您不能将它们放入重复的动作中。
例如,演示项目每秒旋转节点 45 度的操作如下:
[barrierNode runAction:[SKAction repeatActionForever:[SKAction sequence:@[
[SKAction waitForDuration:0.75],
[SKAction runBlock:^{
SKTRotateEffect *effect = [SKTRotateEffect
effectWithNode:barrierNode
duration:0.25
startAngle:barrierNode.zRotation
endAngle:barrierNode.zRotation + M_PI_4];
effect.timingFunction = SKTTimingFunctionBackEaseInOut;
[barrierNode runAction:[SKAction actionWithEffect:effect]];
}]]]]];
如果效果有一个相对版本,这可以简单地写成:
SKTRotateEffect *effect = [SKTRotateEffect effectWithNode:barrierNode duration:0.25 byAngle:M_PI_4];
effect.timingFunction = SKTTimingFunctionBackEaseInOut;
[barrierNode runAction:[SKAction repeatActionForever:[SKAction sequence:@[
[SKAction waitForDuration:0.75],
[SKAction actionWithEffect:effect]]]]];
这不仅更容易阅读,还能让您免于为每次重复创建一个新的效果实例。然而,在当前库版本中这行不通。
效果保持状态(与SKActions
不同),因此您不应在多个动作中重复使用相同的效果实例。
如果您长时间使用大量效果,可能会遇到内存碎片问题,因为您需要为每个效果分配一个新的对象。目前,效果无法重置,因此将它们放入对象池以重复使用有些棘手。
由于动作保持状态,如果在同一时间节点移动,则延迟后您无法将其放入动作中。换句话说,这样做可能或可能不起作用
SKTMoveEffect *effect = ...;
SKAction *action = [SKAction sequence:@[
[SKAction waitForDuration:5.0],
[SKAction actionWithEffect:effect]]];
如果节点在延迟期间通过另一个SKAction
、物理效应或应用程序更改节点的position
属性进行移动,则效果将从错误的位置开始。
Examples/Effects文件夹包含一个小型示例项目,展示了如何使用更有趣的时间函数进行动画。此应用程序使用物理运动球并检测碰撞。
它具有以下特殊效果:
大多数效果都是累积的;也就是说,如果连续发生多次碰撞,则屏幕震动运动会是这些击打的和。
所有的乐趣都在MyScene.m中。顶部有几个#define
语句,您可以启用或关闭效果。
触摸屏幕以向球体添加随机冲量。
如果您认为自定义时间函数是Sprite Kit中内置的重要特性,请访问bugreport.apple.com并提交以下特性请求。收到越多越好!谢谢! :)
Title: SKActionTimingModes are insufficient
The SKAction class from Sprite Kit allows you to specify a timing mode, using an enum with the following values: Linear, Ease In, Ease Out, Ease In + Out.
Unfortunately, a lot of the common timing modes that are used in games are missing (bounce, elastic, etc). More importantly, there is no easy way to add your own timing modes.
This is an example of what I'd like to see. You define a block that takes a float and returns a float:
typedef float (^SKActionTimingFunction)(float t);
The value of t is always between 0 and 1 and describes how far along the animation is. The block returns a modified value of t that curves the timing.
Some examples:
SKActionTimingFunction SKActionTimingFunctionLinear = ^(float t) {
return t;
};
SKActionTimingFunction SKActionTimingFunctionQuadraticEaseIn = ^(float t) {
return t * t;
};
SKActionTimingFunction SKActionTimingFunctionQuadraticEaseOut = ^(float t) {
return t * (2.0f - t);
};
SKActionTimingFunction SKActionTimingFunctionQuadraticEaseInOut = ^(float t) {
if (t < 0.5f) {
return 2.0f * t * t;
} else {
const float f = t - 1.0f;
return 1.0f - 2.0f * f * f;
}
};
But beyond the standard ease in & out, it easily allows users of Sprite Kit to extend this with more interesting effects, such as:
SKActionTimingFunction SKActionTimingFunctionBackEaseInOut = ^(float t) {
const float s = 1.70158f;
if (t < 0.5f) {
const float f = 2.0f * t;
return 0.5f * ((s + 1.0f) * f - s) * f * f;
} else {
const float f = 2.0f * (1.0f - t);
return 1.0f - 0.5f * ((s + 1.0f) * f - s) * f * f;
}
};
These kinds of timing curves are available in many other gaming toolkits. Not having this kind of flexibility makes Sprite Kit a lot less useful. Users of Sprite Kit need to be able to supply their own timing functions.
Note: Core Animation allows you to specify a timing function using a bezier path and 4 control points. That would be useful but by itself it is not enough. Having a block that takes a t value between 0 and 1, and can do any custom transformation on that, is a must.