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

作者: 神经骚栋 | 来源:发表于2016-08-26 20:27 被阅读2476次

    </b>

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

    </b>


    </br>

    SKAction简介


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

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

    </br>

    SKAction分类


    </b>

    准备工作

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

    
    -(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];
    
    }
    
    

    </br>

    场景示意图

    </br>

    移动动作

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

    • 其中以点的形式移动的主要有三个SKAction类方法来创建.
    + (SKAction *)moveTo:(CGPoint)location duration:(NSTimeInterval)sec;
    
    

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

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

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

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

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

    • 以偏移量的形式移动主要有两种两种类方法.
    + (SKAction *)moveBy:(CGVector)delta duration:(NSTimeInterval)sec;
    
    

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

    struct CGVector {
        CGFloat dx;
        CGFloat dy;
    };
    

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

    + (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];
        
        
    }
    
    

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

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

    </br>

    旋转动作

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

    + (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度.效果图如下.

    旋转效果图

    </br>

    路径动作

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

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

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

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

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

    </br>

    • 路径示例:

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

    #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];
        
    }
    
    

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

    </br>

    下面的则是完整版的路径动作创建.然后我们通过修改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];
        
        
    }
    
    

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

    offset的值为NO

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


    </br>

    反向动作

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

    - (SKAction *)reversedAction;
    

    </br>

    • 反向示例:

    就那上面的路径动作为例,我们创建它的反向动作,为了更加生动形象,我给动作的触发设置了一个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];
        
        }
      
    }
    
    

    </br>

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


    反向效果图.gif

    </br>

    速度动作

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

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

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

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

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

    </br>

    • 速度示例:

    首先是恒定的速度的代码示例,不过在此之前,+ (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];
    }
    
    

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

    效果图.gif

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

    #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];
    }
    
    

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


    </br>

    组动作

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

    </b>

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

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

    </br>

    • 组动作示例:

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

    </br>

    序列动作

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

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

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

    </br>

    • 序列动作示例:

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

    #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];
    }
    

    </b>
    效果图如下


    效果图.gif

    </br>

    重复动作

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

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

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

    </br>

    • 重复动作示例:

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

    #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];
    }
    
    

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

    </br>

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

    </br>

    块动作

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

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

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

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

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

    </br>

    • 块动作示例代码

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

    #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];
    }
    
    

    </br>

    透明度动作

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

    </b>

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

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

    </b>

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

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

    </b>

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

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

    </br>

    • 透明度动作的示例

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

    #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];
    }
    
    

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

    </br>

    隐藏/显示动作

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

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

    </br>

    • 隐藏/显示动作示例.

    </b>
    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];
    
        }
    }
    
    

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


    </br>

    尺寸动作

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

    以目标值调整尺寸

    + (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;
    
    

    </br>

    • 尺寸动作示例:

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

    #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];
    }
    
    
    

    效果图如下.

    </br>

    缩放动作

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

    以缩放倍数缩放如下.

    + (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;
    
    

    </br>

    • 缩放动作示例:

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

    #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];
    }
    
    

    效果图如下


    </br>

    颜色动作

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

    只改变混合因子

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

    同时改变混合因子和颜色

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

    </br>

    • 颜色动作示例:

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

    #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];
    }
    

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

    </br>

    改变纹理的动作

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

    </br>

    等待动作

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

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

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

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

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

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

    </br>

    • 等待动作示例:

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

    #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秒之后.改变颜色动作才会执行.

    </br></br>

    自定义动作

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

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

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

    </br>

    • 自定义动作示例:

    废话不多说,直接上代码

    #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];
        
    }
    

    效果图如下.

    </br></br>

    删除动作.

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

    + (SKAction *)removeFromParent;
    
    

    </br>

    删除动作示例:

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

    
    #pragma mark ---- 删除飞船 ----
    
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    
        SKSpriteNode *planeNode = (SKSpriteNode *)[self childNodeWithName:@"plane"];
        
        
        [planeNode runAction: [SKAction removeFromParent]];
        
    }
    
    
    

    </br>
    </br>

    最后说两句


    </b>

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

    相关文章

      网友评论

      • 我只不过是出来写写代码:一直在找用OC写的spriteKit教程,受教了。谢谢
      • Double_Chen:你好,我有个问题想咨询一下,像怪物跟着主角走的移动功能可以如何实现?目前想到的一个办法是在update方法中进行怪物position的改变,但是这样实现明显不佳,请问有更好的办法吗?
      • _Mr遇_:大神我是初学者 我想请问一下 像超级玛丽这样的背景是用几张图拼接起来的吗? spritekit有镜头的概念吗
        FKSky:@神经骚栋 SpriteKit也有SKCameraNode类,比如这篇里面有介绍到https://www.raywenderlich.com/158961/introduction-spritekit-scene-editor
        神经骚栋:@sides camera是应该在3D中的概念吧?在sceneKit中 确实有camera,但是在spriteKit中没有这个概念
        FKSky:有camera这个Node
      • YorkSuo:赞:+1:🏻
      • Thebloodelves:必须支持,虽然不用这个技术了。。。。
        神经骚栋:@钱洋彪 老铁 自己玩的话 用苹果自己的框架就能玩 要是真想做 玩cocos2dx 或者unity3d 都行 这两个的脚本语言是c#和js
        转岗做JAVA:现在游戏开发用什么框架,做了好几年的企业应用,想找点新乐子做做游戏,还望大神指点。
      • 传闻中的饼干君:写得不错...
        神经骚栋: @传闻中的饼干君 谢谢
      • Tismagic:你干嘛不用swift写
        神经骚栋:@乖乖小宇宙 恩
        Tismagic:@神经骚栋 有人喜欢穿新鞋,有人喜欢穿旧鞋,我也没办法
        神经骚栋: @乖乖小宇宙 swift写的太多了,不想和他们一样,再说了,现在大部分人研究这个框架只是为了做几个小游戏,而大部分iOS人员都是用OC写代码,我用swift写,哥,你觉得合适吗?
      • YungFan:代码怎么没上呢 :stuck_out_tongue_closed_eyes:
        神经骚栋:@YungFan 哥 不是 我只有最后的那个了~~因为是一边做一边删除~ :sweat:
        YungFan:@神经骚栋 传给我研究下啊
        神经骚栋: @YungFan 哥,这么没法上,太多了…我光写这个,就用了三天…

      本文标题:SpriteKit框架之最全动作介绍 没有之一

      本文链接:https://www.haomeiwen.com/subject/knowsttx.html