SpriteKit框架之最全动作介绍 没有之一

斩断自己的退路,才能更好地赢得出路。在很多时候,我们都需要一种斩断自己退路的勇气。


SKAction简介


在先前的博客中就说过,动作是一个游戏中不可缺少的,比如移动,形状的变换等等.比如"超级马里奥"中的马里奥的移动,以及蘑菇,怪兽的移动都是需要动作的支持的.

在SpriteKit框架中是用SKAction类来实现动作.一个SKAction实例是一个动作,通过SKScene场景中的节点来执行。动作可以绑定到节点上,用以改变节点的结构和内容,有时也可以改变场景。当场景处理其子节点的时候,与这些节点相关联的动作将被计算。由于SKAction动作类型过多,所以我就先用下图进行了分类.


SKAction分类


准备工作

下面所有的动作前提准备都是一样的,我们就以微信打飞机的场景为实例,具体代发如下


-(instancetype)initWithSize:(CGSize)size{

    if (self = [super initWithSize:size]) {
        
        self.backgroundColor = [SKColor whiteColor];
        
    }

    return self;

}

-(void)didMoveToView:(SKView *)view{

    [super didMoveToView:view];

    [self backgroundNode];
    
    [self planeNode];

    
}

#pragma mark ----创建背景----

-(void)backgroundNode{

    SKSpriteNode *backgroundNode = [SKSpriteNode spriteNodeWithImageNamed:@"bg_02.jpg"];

    backgroundNode.position = CGPointZero;
    
    backgroundNode.zPosition = 0;
    
    backgroundNode.anchorPoint = CGPointZero;
    
    backgroundNode.size = self.size;
    
    [self addChild:backgroundNode];
    
    
    
}

#pragma mark ---- 创建飞船 ----

-(void)planeNode{

    SKSpriteNode *planeNode = [SKSpriteNode spriteNodeWithImageNamed:@"飞机.png"];
    
    planeNode.position = CGPointMake(self.size.width/2, self.size.height/2);
    
    planeNode.anchorPoint = CGPointMake(0.5, 0.5);
    
    planeNode.zPosition = 1;
    
    planeNode.name = @"plane";
    
    [self addChild:planeNode];

}

场景示意图


移动动作

移动动作在一个游戏中是最常见的动作了.移动动作主要分为以点的形式移动和以偏移量的形式移动.且听我慢慢道来.

其中以点的形式移动的主要有三个SKAction类方法来创建.

+ (SKAction *)moveTo:(CGPoint)location duration:(NSTimeInterval)sec;

location: 用来指定节点移动到的位置.
sec:用来指定移动动作所需要的时间.

+ (SKAction *)moveToX:(CGFloat)x duration:(NSTimeInterval)sec;

x: 用来指定节点的x轴上移动到的位置.节点的y轴上的值不变化.
sec:用来指定移动动作所需要的时间.

+ (SKAction *)moveToY:(CGFloat)y duration:(NSTimeInterval)sec;

y: 用来指定节点的y轴上移动到的位置.节点的x轴上的值不变化.
sec:用来指定移动动作所需要的时间.

以偏移量的形式移动主要有两种两种类方法.

+ (SKAction *)moveBy:(CGVector)delta duration:(NSTimeInterval)sec;

delta:是一个矢量,用力啊指定偏移量,类型为CGVector,CGVector是一个很简单的结构体,有dx和dy组成.dx表示x轴上的偏移量,dy表示y轴上的偏移量.结构体形式如下.

struct CGVector {
    CGFloat dx;
    CGFloat dy;
};

sec:用来指定移动动作所需要的时间.

+ (SKAction *)moveByX:(CGFloat)deltaX y:(CGFloat)deltaY duration:(NSTimeInterval)sec;

deltaX:表示在x轴上的偏移量.
deltaY:表示在y轴上的偏移量.
sec:用来指定移动动作所需要的时间.

示例:

#pragma mark ---- 以点的形式移动飞船 ----

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    
    UITouch *touch = [touches anyObject];
    
    CGPoint  position = [touch locationInNode:self];
    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];

    SKAction * moveAction =  [SKAction moveTo:position duration:1];
    
    [planeNode runAction:moveAction];
    
    
}
 
#pragma mark ---- 以偏移量的形式移动飞船 ----

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];

    SKAction * moveAction =  [SKAction moveBy:CGVectorMake(50, 50) duration:1];
    
    [planeNode runAction:moveAction];
    
    
}

上面的分别以点的形式和偏移量的形式做出了示例,我们看一下效果图.当我们每一次点击屏幕的时候触发移动动作,下面我们就看一下两种形式的效果图有何不同.

以点形式移动效果图
以偏移量形式移动效果图


旋转动作

游戏中的物体的旋转大多需要用的旋转动作,旋转动作的创建方法只有一种,如下所示.

+ (SKAction *)rotateByAngle:(CGFloat)radians duration:(NSTimeInterval)sec;

sec:用来指定旋转动作所需要的时间.
radians:用来指定精灵或者其他节点的旋转量,以弧度为单位;下面所示的常用的角度(框架自带).

#define M_PI        3.14159265358979323846264338327950288   /* 180度             */
#define M_PI_2      1.57079632679489661923132169163975144   /* 90度           */
#define M_PI_4      0.785398163397448309615660845819875721  /* 45度          */

旋转示例:

#pragma mark --- 添加旋转动作 ---

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    SKSpriteNode *windmillNode = (SKSpriteNode *)[self childNodeWithName:@"windmillNode"];
    
    //删除所有的动作
    [windmillNode removeAllActions];
    
    SKAction *rotateAction = [SKAction rotateByAngle:M_PI*2 duration:0.3];
    
    [windmillNode runAction:rotateAction];

}

上面是以一个风车的精灵为例,做旋转动作,每当点击屏幕,精灵就会旋转360度.效果图如下.

旋转效果图
路径动作

在游戏过程中,经常会遇到一些怪物,它们会按照一定的路劲轨迹不断的行走,在SKAciton中就有对路径动作的创建形式,其常用语法形式如下

+ (SKAction *)followPath:(CGPathRef)path duration:(NSTimeInterval)sec;

path:用来指定一个CGPathRef路径,这个路径就是精灵的移动路径.
sec:指定这个路径动作完成所需要的时间.

相比于上面比较常用的方式之外,下面的语法形式则应该算的上他的增强版,其中包括对其路径的点相对性,以及Z轴的旋转属性都可以进行设置操作.

+ (SKAction *)followPath:(CGPathRef)path asOffset:(BOOL)offset orientToPath:(BOOL)orient duration:(NSTimeInterval)sec;

路径示例:

下面就以一个矩形路径为示例,给节点添加路径动作,让其进行移动.

#pragma mark ---- 以路径的形式移动飞船 ----

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
        
    CGRect createRect = CGRectMake(0, 0, 100, 100);
    
    CGPathRef path = CGPathCreateWithRect(createRect, nil);

    SKAction * moveAction =  [SKAction followPath:path duration:2];

    [planeNode runAction:moveAction];
    
}

通过下面的效果图我们就可以知道路径的点是相对路径.而且节点Z轴在旋转的时候属性也是发生改变的.

下面的则是完整版的路径动作创建.然后我们通过修改Offset(是否是相对路径),以及orientToPath(节点Z轴在旋转的时候属性是否发生改变).这两属性看看效果各有什么不同.

#pragma mark ---- 以路径的形式移动飞船 ----

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
        
    CGRect createRect = CGRectMake(0, 0, 100, 100);
    
    CGPathRef path = CGPathCreateWithRect(createRect, nil);

    SKAction * moveAction =  [SKAction followPath:path asOffset:YES orientToPath:YES duration:2];

    [planeNode runAction:moveAction];
    
    
}

在 *** + (SKAction *)followPath:(CGPathRef)path duration:(NSTimeInterval)sec; ** 这个方法中默认的offset是YES,orient也是YES,也就是说如果上面的代码执行的话,是跟最常用的方法的效果图一样的,现在我们就先只修改offset的值为NO.会发现节点是以绝对路径进行运动的,也就是一节点的父类坐标系为基准,进行动作的执行.

offset的值为NO

接下来我们只修改orient的值为NO,其他不变,我们会发现节点Z轴是没有发生任何改变的.


反向动作

反向动作就是场景中的节点原来往一个方向进行移动,但是在运行时这些节点却向相反的防线进行了运动,如果想要实现反向运动,就需要使用到反向运动,反向运动的创建方法为对象方法,是使用一个动作调用- (SKAction *)reversedAction;返回动作就会说这个动作的反向动作. 其语法形式如下所示.

- (SKAction *)reversedAction;

反向示例:

就那上面的路径动作为例,我们创建它的反向动作,为了更加生动形象,我给动作的触发设置了一个BOOL,具体的示例代码如下.

#pragma mark ---- 以反向形式移动飞船 ----

BOOL isReversed = YES;//设置监控反向的BOOL值.

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    isReversed = ! isReversed;
    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
        
    CGRect createRect = CGRectMake(0, 0, 100, 100);
    
    CGPathRef path = CGPathCreateWithRect(createRect, nil);

    SKAction * moveAction =  [SKAction followPath:path duration:2];
    
    SKAction *reversedAction = [moveAction reversedAction];

    if (isReversed) {
        [planeNode runAction:moveAction];

    }else{
    
        [planeNode runAction:reversedAction];
    
    }
  
}

如下图所示,这就是反向动作的效果图

反向效果图.gif


速度动作

速度动作一般是配合着别的位置动作使用的,其实不但有速度动作还有速度属性,我们可以给定一定的速度值来改变场景中节点执行动作的速度.速度动作一个有两个创建方式,一个是设置一个恒定的速度,加速度为0.一个是设置恒定的加速度.即速度增量.语法形式如下.
</b>

+ (SKAction *)speedTo:(CGFloat)speed duration:(NSTimeInterval)sec;

speed:指定节点运动的速度.
sec:指定完成动作所需要的时间


+ (SKAction *)speedBy:(CGFloat)speed duration:(NSTimeInterval)sec;


speed:指定节点运动的加速度.即速度增量
sec:指定完成动作所需要的时间

速度示例:

首先是恒定的速度的代码示例,不过在此之前,+ (SKAction *)group:(NSArray<SKAction*> *)actions;要做一下接下,这是个组动作,可以把两个动作放在一起执行,主要的是两个动作是同时执行.下面我们会说到这个动作的.这里需要引用一下这个动作.

#pragma mark ---- 移动飞船 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    UITouch *touch = [touches anyObject];
    
    CGPoint position = [touch locationInNode:self];
    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    SKAction * moveAction =  [SKAction moveTo:position duration:3];
    
    SKAction *speedAction = [SKAction speedTo:5 duration:1];
    
    SKAction *groupAction = [SKAction group:@[
                                              moveAction,
                                              speedAction
                                              ]];
    
    [planeNode runAction:groupAction];
}

我们看一下效果图,发现节点整体都是以一个恒定的速度做完每一次移动的.

效果图.gif

接下来是以恒定的速度增量来来运动.示例代码如下

#pragma mark ---- 移动飞船 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    UITouch *touch = [touches anyObject];
    
    CGPoint position = [touch locationInNode:self];
    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    SKAction * moveAction =  [SKAction moveTo:position duration:3];
    
    SKAction *speedAction = [SKAction speedBy:5 duration:1];
    
    SKAction *groupAction = [SKAction group:@[
                                              moveAction,
                                              speedAction
                                              ]];
    
    [planeNode runAction:groupAction];
}

下面的这效果图和上面的效果图一对比,发现,节点的速度是不断增加的.



组动作

组动作,我们在上面的移动操作的示例中已经做了简单的示例,组合动作其实就是吧两个或者两个以上的动作放在一起同时执行,组合动作最大的特点就是同时性,不管几个动作都是同时执行的.其语法形式如下:

+ (SKAction *)group:(NSArray<SKAction*> *)actions;

actions:是一个数组类型,数组中的元素是SKAction.

组动作示例:

组动作示例的示例代码就不多解释了,大家就参考着上面的速度动作的示例代码就可以了,当然了,组动作是可以其他的动作配合使用的.


序列动作

序列动作跟组动作一样,是一个组合动作,序列动作从字面上来看,最大的特点就是顺序.序列动作的使用场景是多个动作需要一个一个顺序执行,这时候就需要用到序列动作.

+ (SKAction *)sequence:(NSArray<SKAction*> *)actions;

actions:是一个数组类型,数组中的元素是SKAction.

序列动作示例:

序列动作的示例,我就用两个移动动作,当我点击屏幕的时候,飞船会飞到点击出,然后在回到初始位置.代码如下

#pragma mark ---- 移动飞船 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    UITouch *touch = [touches anyObject];
    
    CGPoint position = [touch locationInNode:self];
    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    SKAction * moveAction =  [SKAction moveTo:position duration:1];
    SKAction *moveZeroAction = [SKAction moveTo:CGPointMake(self.size.width/2, self.size.height/2) duration:1];

    SKAction *groupAction = [SKAction sequence:@[
                                                 moveAction,
                                                 moveZeroAction

                                              ]];
    
    [planeNode runAction:groupAction];
}

效果图如下


效果图.gif


重复动作

重复动作及一个动作运行多次或者无数次,其中重复动作分为无限重复和具有一定次数的重复.其中两种语法形式如下.

//无限重复
+ (SKAction *)repeatActionForever:(SKAction *)action;

//具有一定次数的重复
+ (SKAction *)repeatAction:(SKAction *)action count:(NSUInteger)count;

action:用来指定重复的动作.
count:用来指定重复的次数.

重复动作示例:

我们就拿上面的示例序列动作示例来添加在重复动作的中.如下代码所示.

#pragma mark ---- 移动飞船 ----

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    UITouch *touch = [touches anyObject];
    
    CGPoint position = [touch locationInNode:self];
    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    SKAction * moveAction =  [SKAction moveTo:position duration:1];
    SKAction *moveZeroAction = [SKAction moveTo:CGPointMake(self.size.width/2, self.size.height/2) duration:1];

    SKAction *groupAction = [SKAction sequence:@[
                                                 moveAction,
                                                 moveZeroAction

                                              ]];
    
    
    SKAction * repeatAction  = [SKAction  repeatActionForever:groupAction];
    
    [planeNode runAction:repeatAction];
}

效果图如下,当我们点击屏幕的一个位置的时候,飞船会不断的来回移动.


组合动作注意事项:
上面叙述的组动作,序列动作,重复动作是以子动作的方式包含其他动作:
一个序列动作中有多个子动作,序列中的每一个动作在前一个动作结束之前开始。
一个组动作中有多个子动作,动作组中的所有动作同时开始执行。
一个重复动作中只有一个子动作,当重复动作中的子动作完成时,重复动作将重新开始执行。
上面三种动作可以嵌套使用,这种使动作结合起来的能力可以帮你为节点添加非常复杂的动作。


块动作

块动作其实就是把动作的整个执行过程放到一个Block块中,其中语法形式主要有两种,一种是常用的,另外一种是带有线程的.其语法形式如下.


+ (SKAction *)runBlock:(dispatch_block_t)block;

带有GCD线程相关的语法形式如下.


+ (SKAction *)runBlock:(dispatch_block_t)block queue:(dispatch_queue_t)queue;

block:指定执行的block块的系列动作
queue:指定GCD线程

块动作示例代码

接在在上面的重复动作的示例代码基础上来开发,效果图就如上了,但是实际的实现过程是有区别的,示例代码如下.

#pragma mark ---- 移动飞船 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    UITouch *touch = [touches anyObject];
    
    CGPoint position = [touch locationInNode:self];
    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    SKAction *blockAction  = [SKAction runBlock:^{
        
        SKAction * moveAction =  [SKAction moveTo:position duration:1];
        SKAction *moveZeroAction = [SKAction moveTo:CGPointMake(self.size.width/2, self.size.height/2) duration:1];
        
        SKAction *groupAction = [SKAction sequence:@[
                                                     moveAction,
                                                     moveZeroAction
                                                     
                                                     ]];
        
        
        SKAction * repeatAction  = [SKAction  repeatActionForever:groupAction];
        
        [planeNode runAction:repeatAction];

    }];
    
    
    [planeNode runAction:blockAction];
}


透明度动作

透明度动作就是指定节点的透明度的动作,虽然看起来比较简单,但是语法形式比较多,下面就注意的说明各个语法形式.

下面的两个语法是不用指定alpha值的,一个alpha值为1,一个为0,我们只需要设定两者的动作时间就可以了.

//alpha值为1
+ (SKAction *)fadeInWithDuration:(NSTimeInterval)sec;

//alpha值为0
+ (SKAction *)fadeOutWithDuration:(NSTimeInterval)sec;

下面的语法是需要指定alpha值的.

+ (SKAction *)fadeAlphaTo:(CGFloat)alpha duration:(NSTimeInterval)sec;

下面的语法是需要指定alpha值的增量.

+ (SKAction *)fadeAlphaBy:(CGFloat)factor duration:(NSTimeInterval)sec;


透明度动作的示例

我就以简单的不用指定的透明度的动作为示例.

#pragma mark ---- 飞船的透明度 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{


    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    

    SKAction *alphaInAction  = [SKAction fadeInWithDuration:1];
    
    SKAction *alphaOutAction = [SKAction fadeOutWithDuration:1];
    
    SKAction *repeatAction = [SKAction repeatActionForever:[SKAction sequence:@[
                                                                                alphaOutAction,
                                                                                alphaInAction
                                                                                ]]];
    
    
    [planeNode runAction:repeatAction];
}

当我们点击屏幕的时候,效果图如下.


隐藏/显示动作

隐藏/显示动作和整体效果看起来和透明度的整体效果差不多,但是还是有一些区别的,透明度只是改变的是透明度,节点还是存在在场景上的,而隐藏/显示动作是真的隐藏了,节点是不存在与场景之中的.其语法形式如下.

//显示节点
+ (SKAction *)hide;

//隐藏节点
+ (SKAction *)unhide;

隐藏/显示动作示例:

isHide是我设置的一个监控的显示/隐藏的BOOL值.不多说,直接上代码.

#pragma mark ---- 隐藏/显示飞船 ----

BOOL isHide = YES;

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    isHide = !isHide;
    
    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    

    SKAction *hideAction  = [SKAction hide];
    
    SKAction *unhideAction = [SKAction unhide];
    
    if (isHide) {
        
        [planeNode runAction:unhideAction];


    }else{

        [planeNode runAction:hideAction];

    }
}

效果图如下所示,每当我点屏幕的时候,飞船的显示和隐藏状态就会发生改变.



尺寸动作

尺寸动作就是用来修改节点的尺寸的.其语法形式有以下几种,分别是以目标值调整尺寸,单独调节目标节点的高度或者宽度,以增量的形式调节整体的尺寸.具体语法形式如下.

以目标值调整尺寸

+ (SKAction *)resizeToWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration;

单独调节目标节点的高度或者宽度的两种形式语法如下


//调整宽度
+ (SKAction *)resizeToWidth:(CGFloat)width duration:(NSTimeInterval)duration;

//调整高度
+ (SKAction *)resizeToHeight:(CGFloat)height duration:(NSTimeInterval)duration;

以增量的形式调节整体的尺寸.

+ (SKAction *)resizeByWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration;

尺寸动作示例:

废话不多说,直接上代码.以以目标值调整尺寸为例.

#pragma mark ---- 改变尺寸飞船 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{


    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    SKAction  *sizeAction = [SKAction resizeToWidth:200 height:200 duration:0.5];
    
    [planeNode runAction:sizeAction];
}


效果图如下.


缩放动作

缩放动作就是对节点进行缩放操作.其语法形式与尺寸动作类似,一共有三种,语法形式如下.

以缩放倍数缩放如下.

+ (SKAction *)scaleTo:(CGFloat)scale duration:(NSTimeInterval)sec;

//对宽和高以不同的缩放比例缩放.
+ (SKAction *)scaleXTo:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec;

单独对宽和高进行缩放.

//宽度缩放
+ (SKAction *)scaleXTo:(CGFloat)scale duration:(NSTimeInterval)sec;

//高度缩放
+ (SKAction *)scaleYTo:(CGFloat)scale duration:(NSTimeInterval)sec;

以增量值进行缩放.

+ (SKAction *)scaleBy:(CGFloat)scale duration:(NSTimeInterval)sec;

//对宽和高以不同的缩放比例增量值缩放.
+ (SKAction *)scaleXBy:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec;

缩放动作示例:

下面就一最简单的缩放形式进行缩放,其他的缩放类似

#pragma mark ---- 缩放飞船 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{


    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    SKAction  *sizeAction = [SKAction scaleTo:2 duration:1];
    
    [planeNode runAction:sizeAction];
}

效果图如下



颜色动作

颜色动作其实是改变节点的颜色以及混合因子,语法形式总共有两种,一种是只改变混合因子,另外一种是改变颜色和混合因子,对于混合因子,类型为CGFloat类型,可以理解为颜色的深浅度.具体的语法形式如下.

只改变混合因子

+ (SKAction *)colorizeWithColorBlendFactor:(CGFloat)colorBlendFactor duration:(NSTimeInterval)sec;

同时改变混合因子和颜色

+ (SKAction *)colorizeWithColor:(SKColor *)color colorBlendFactor:(CGFloat)colorBlendFactor duration:(NSTimeInterval)sec;


颜色动作示例:

下面以只改变混合因子为示例.

#pragma mark ---- 改变飞船的颜色 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{


    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    SKAction  *sizeAction = [SKAction colorizeWithColorBlendFactor:0.66 duration:1];
    
    [planeNode runAction:sizeAction];
}

效果图如下.通过效果图我们会发现飞机整体的颜色会变浅.


改变纹理的动作

改变纹理的动作,这个动作其实可以理解为是让一个游戏物体动起来,我们看到很多游戏都是这样的,例如下面的爆炸效果图.对于这个动作其实是要结合这纹理集进行实现的,改变纹理的动作也是比较常用的一个动作,具体内容查看SpriteKit框架之SKTextureAtlas这篇文章.
(重要等级:⭐️⭐️⭐️⭐️⭐️)


等待动作

等待动作也叫延时动作.也是在游戏中经常使用的一个动作,经常也其他动作配合使用.其语法形式一共有两种,比较特殊的哪一种形式是可以用力啊指定演示时间的范围的.代码如下.

这一种延时动作只能指定延时的时间

+ (SKAction *)waitForDuration:(NSTimeInterval)sec;

这一种延时动作是可以用来指定延时时间的范围.

+ (SKAction *)waitForDuration:(NSTimeInterval)sec withRange:(NSTimeInterval)durationRange;

sec:指定延时的时间.
durationRange:指定延时时间的范围.

等待动作示例:
我们就以上面的改变飞创的颜色的动作为基础进行等待动作的添加,代码如下.

#pragma mark ---- 改变飞船的颜色 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{


    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    SKAction  *sizeAction = [SKAction colorizeWithColorBlendFactor:0.66 duration:5];
    
    
    SKAction *waitAction  = [SKAction waitForDuration:1];

    [planeNode runAction:[SKAction sequence:@[
                                              waitAction,
                                              sizeAction
                                              ]]];
}



我们看一下效果图,当我点击完屏幕之后,移开鼠标,等待5秒之后.改变颜色动作才会执行.


自定义动作

如果系统的动作还不能满足我们的需求怎么办?这时候,我们可以自定义动作,自定义出我们想要实现的效果.其语法形式如下.

+ (SKAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(SKNode *node, CGFloat elapsedTime))block;

seconds:指定自定义动作完成所需要的时间
block:block块内指定自定义动作的内容.

自定义动作示例:

废话不多说,直接上代码

#pragma mark ---- 改变飞船的坐标 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    UITouch *touch = [touches anyObject];
    
    CGPoint position = [touch locationInNode:self];

    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    
    SKAction *myMoveAction = [SKAction customActionWithDuration:1 actionBlock:^(SKNode * _Nonnull node, CGFloat elapsedTime) {
        
        
        SKSpriteNode *plane= (SKSpriteNode *)node;
        
        plane.position= CGPointMake(position.x, position.y);
        
        
    }];
    
    [planeNode runAction: myMoveAction];
    
}

效果图如下.


删除动作.

删除动作就是删除动作,当我们不需要节点的时候,我们可以使用删除动作删除节点.其语法形式如下.

+ (SKAction *)removeFromParent;

删除动作示例:

废话不多说,直接上代码,效果图不就添加了,就是直接删除飞船了.


#pragma mark ---- 删除飞船 ----


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{


    SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
    
    
    [planeNode runAction: [SKAction removeFromParent]];
    
}



最后说两句


SpriteKit所有的动作都在这了,SKAction创建形式比较多.所以博客篇幅较长,这也没有办法,建议学习的时候每一个方法都测试一下,因为只有测试之后,你才能知道他的用途和注意事项,建议本篇博客学习时间为3天.好了,SKAction动作相关创建方式就说这么多了!如果您觉得这篇博客对你有所帮助就点赞支持一下呗,没帮助就不要点了,毕竟没帮到您是我最大的失败~~😂

推荐阅读更多精彩内容