ARKIT

SpriteKit(4) - 动作

2017-07-28  本文已影响74人  li_礼光

动作

let actionMoveToPoint = SKAction.move(to: CGPoint(x: 100, y: 100), duration: 5)
let actionMoveToX = SKAction.moveTo(x: 700, duration: 2)
let actionMoveToY = SKAction.moveTo(y: 500, duration: 2)
let actionMoveByPoint = SKAction.moveBy(x: 100, y: 100, duration: 5)
let actionMoveByV = SKAction.move(by: CGVector(dx: 100, dy: 100), duration: 5)

动作序列 (以let scene = GameAction()方式创建)

import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        let sprite : SKSpriteNode = SKSpriteNode(imageNamed: "1.png")
        sprite.position = CGPoint(x: size.width * 0.5,
                                  y: size.height * 0.5)
        sprite.setScale(1)
        self.addChild(sprite)
        
        //创建并设置节点移动的动作,即斜向下移动(100,-100)
        let actionMidMove = SKAction.move(to: CGPoint(x: size.width * 0.5 + 100,y: size.height * 0.5 - 100),  duration: 2.5)
        //创建并设置节点移动的动作,即斜向上移动(200,0)
        let actionMove = SKAction.move(to: CGPoint(x: size.width * 0.5 + 200,y: size.height * 0.5),duration: 2.5)
        
        //创建序列动作
        let squence = SKAction.sequence([actionMidMove,actionMove])
        sprite.run(squence)
    }
}

重复动作

        //创建序列动作
        let squence = SKAction.sequence([actionMidMove,actionMove])
//        sprite.run(squence)

        //重复动作
        let repeatAction = SKAction.repeat(squence, count: 5)
        sprite.run(repeatAction)

重复动作的注意点 : 注意设计具体需要重复的路线就好

延迟动作


import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        
        let node1 = SKSpriteNode()
        node1.position = CGPoint(x: 0, y: size.height * 0.5)
        node1.anchorPoint = CGPoint(x: 0, y: 0)
        node1.color = UIColor.red
        node1.size = CGSize(width: 100, height: 100)
        self.addChild(node1)
        
        let node2 = SKSpriteNode()
        node2.position = CGPoint(x: 0, y: size.height * 0.5)
        node2.anchorPoint = CGPoint(x: 0, y: 1)
        node2.color = UIColor.blue
        node2.size = CGSize(width: 100, height: 100)
        self.addChild(node2)
        
        //创建并设置节点移动的动作,向前300
        let actionMoveForward = SKAction.move(to: CGPoint(x:300,y: size.height * 0.5),  duration: 1.0)
        //创建并设置节点移动的动作,回到原点
        let actionMoveBackward = SKAction.move(to: CGPoint(x: 0,y: size.height * 0.5),duration: 1.0)
        
        let waitAction1 = SKAction.wait(forDuration: 1)
        let squence1 = SKAction.sequence([actionMoveForward,waitAction1,actionMoveBackward])
        let repeatAction1 = SKAction.repeat(squence1, count: 5)
        node1.run(repeatAction1)
        
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.0) {
            let waitAction2 = SKAction.wait(forDuration: 1.0)
            let squence2 = SKAction.sequence([actionMoveForward,waitAction2,actionMoveBackward])
            let repeatAction2 = SKAction.repeat(squence2, count: 5)
            node2.run(repeatAction2)
        }
    }
}
延时动作

缩放动作

import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        
        let node = SKSpriteNode()
        node.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
        node.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        node.color = UIColor.red
        node.size = CGSize(width: 100, height: 100)
        self.addChild(node)
        
        let zoom = SKAction.scale(by: 2, duration: 0.5)
        let skrink = SKAction.scale(by: 0.5, duration: 0.5)
        let squence = SKAction.sequence([zoom,skrink])
        let repeatAction = SKAction.repeat(squence, count: 5)
        
        node.run(repeatAction)
    }
}
缩放

PS : 这里要注意的是缩放的比例的控制

旋转动作

import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        
        let node = SKSpriteNode()
        node.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
        node.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        node.color = UIColor.red
        node.size = CGSize(width: 100, height: 100)
        self.addChild(node)
        
        let rotate = SKAction.rotate(byAngle: CGFloat.pi/4.0, duration: 0.25)
        let repeatAction = SKAction.repeat(rotate, count: 10)
        
        node.run(repeatAction)
    }
}
旋转

调整尺寸

import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        
        let node = SKSpriteNode()
        node.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
        node.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        node.color = UIColor.red
        node.size = CGSize(width: 100, height: 100)
        self.addChild(node)
        
        let resizeWidth = SKAction.resize(toWidth: 300, duration: 1)
        let wait = SKAction.wait(forDuration: 1)
        let resizeHeight = SKAction.resize(toHeight: 300, duration: 1)
        let squence = SKAction.sequence([resizeWidth,wait,resizeHeight])
        
        node.run(squence)
    }
}
调整尺寸

调整尺寸和缩放有点类似,但是更精确

组合动作

组合动作就是在同时对两个或两个以上的动作进行执行.

import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        
        let node = SKSpriteNode()
        node.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
        node.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        node.color = UIColor.red
        node.size = CGSize(width: 100, height: 100)
        self.addChild(node)
        
        let resizeWidth = SKAction.resize(toWidth: 300, duration: 1)
        let wait = SKAction.wait(forDuration: 1)
        let resizeHeight = SKAction.resize(toHeight: 300, duration: 1)
        let squence = SKAction.sequence([resizeWidth,wait,resizeHeight])
        
        let rotate = SKAction.rotate(byAngle: CGFloat.pi/2, duration: 2)
        let group = SKAction.group([squence,rotate])
        
        node.run(group)
    }
}
两个动作同步一起做

改变透明度

let fadeOut = SKAction.fadeOut(withDuration: 1)
let fadeIn = SKAction.fadeIn(withDuration: 1)
let fadeAlphaTo1 = SKAction.fadeAlpha(to: 1, duration: 1)
let fadeAlphaTo2 = SKAction.fadeAlpha(by: 0.5, duration: 1)

可以通过这种做一些,加载时候的效果.

改变颜色

let color1 = SKAction.colorize(withColorBlendFactor: 0.3, duration: 1)
let color2 = SKAction.colorize(withColorBlendFactor: 0.8, duration: 1)
let color = SKAction.colorize(with: UIColor.blue, colorBlendFactor: 1.0, duration: 1)
原图 变换过程
最终过程

以动画的形式改变纹理的动作

        let f1 = SKTexture(imageNamed: "texture1.png")
        let f2 = SKTexture(imageNamed: "texture2.png")
        let f3 = SKTexture(imageNamed: "texture3.png")
        let f4 = SKTexture(imageNamed: "texture4.png")
        let textureArray = [f1,f2,f3,f4]
        let playerSprite = SKSpriteNode(texture: f1)
        playerSprite.position=CGPoint(x : 50,y :  170)
        self.addChild(playerSprite)
        let runRightAction = SKAction.animate(with: textureArray, timePerFrame: 0.1)
        let runForever = SKAction.repeatForever(runRightAction)
        let actionMove = SKAction.move(to: CGPoint(x: 100, y: playerSprite.position.y),duration: 5)
        let group = SKAction.group([runForever, actionMove])
        
        playerSprite.run(group)
移动1 移动2

以不断切换纹理图片的形式,做出节点在活动的假象.
不过感觉这里有个bug,有些时候切换纹理的时候会一闪一闪的,也就是切换第一张,正常,第二张就显示不出来,第三张又好了的样子.交错显示.但是呢,多运行几次又正常了.应该是一个bug.不知道是什么鬼情况.(先不要在意,跳过这里,知道有这个细节,看看后续能否悟出原因,我用的是Xcode9,和iOS11.0的版本,也有可能是新版本里面的bug)

动作路径

import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        
        let node1 = SKSpriteNode()
        node1.position = CGPoint(x: 150, y: size.height * 0.5 - 50)
        node1.color = UIColor.red
        node1.size = CGSize(width: 50, height: 50)
        self.addChild(node1)
        
        let node2 = SKSpriteNode()
        node2.position = CGPoint(x: 200, y: size.height * 0.5)
        node2.color = UIColor.blue
        node2.size = CGSize(width: 50, height: 50)
        self.addChild(node2)
        
        //让node1以矩形路径运动
        let playRect = CGRect(x: 0, y: 0, width: 100, height: 100)
        let screenBorders = CGPath(rect: playRect, transform: nil)
        let followAction1 = SKAction.follow(screenBorders, duration: 3)
        let repeatAction1 = SKAction.repeatForever(followAction1)
        node1.run(repeatAction1)
        
        
        let node3 = SKSpriteNode()
        node3.position = CGPoint(x: 400, y: size.height * 0.5 - 50)
        node3.color = UIColor.red
        node3.size = CGSize(width: 50, height: 50)
        self.addChild(node3)
        
        let node4 = SKSpriteNode()
        node4.position = CGPoint(x: 450, y: size.height * 0.5)
        node4.color = UIColor.blue
        node4.size = CGSize(width: 50, height: 50)
        self.addChild(node4)
        
        //让node1以圆形路径运动
        let playRect2 = CGRect(x: 400, y: size.height * 0.5 - 50, width: 100, height: 100)
        let circle = CGPath(roundedRect: playRect2, cornerWidth: 50, cornerHeight: 50, transform: nil)
        let followAction2 = SKAction.follow(circle, asOffset: false, orientToPath: true, duration: 5)
        let repeatAction2 = SKAction.repeatForever(followAction2)
        node3.run(repeatAction2)
    }
}
运动轨迹

路径考虑 : 这里面的路径考虑从锚点出发,锚点根据设置的路径来执行.
这里有些比较有意思的考虑点

PS : 关于其他路劲,多尝试一下吧.

反向运动

let actionMove = SKAction.moveTo(x: 100, duration: 1)
let reversed = actionMove.reversed()

速度

可以通过一个给定的速度值来改变场景中精灵或者其他节点执行动作的速度.

import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        
        let node1 = SKSpriteNode()
        node1.position = CGPoint(x: 50, y: size.height * 0.5 - 50)
        node1.color = UIColor.red
        node1.size = CGSize(width: 50, height: 50)
        self.addChild(node1)

        let moveAction = SKAction.moveTo(x: 550, duration: 20)
        let scaleAction = SKAction.scale(to: 2.5, duration: 20)
        let speedAction = SKAction.speed(to: 5, duration: 1)
        let group = SKAction.group([speedAction,moveAction,scaleAction])
        node1.run(group)
    }
}
速度动作

简单粗暴的理解 :
let speedAction = SKAction.speed(to: 0, duration: 4)
在4秒钟之后,动作执行的速度变为0

显示或隐藏

let hide = SKAction.hide()
let unhide = SKAction.unhide()

动作块

有时候,开发者需要将一系列的动作放入到一个块中,此时就是需要使用动作块.

简单粗暴的理解 :
就是将某些固定的动作封装在一个动作块中,到时候直接调用就好了.

import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        
        let node1 = SKSpriteNode()
        node1.position = CGPoint(x: 50, y: size.height * 0.5 - 50)
        node1.color = UIColor.red
        node1.size = CGSize(width: 50, height: 50)
        self.addChild(node1)
        
        
        let block = SKAction.run {
            let rotate = SKAction.rotate(byAngle: CGFloat.pi, duration: 2)
            let runForever = SKAction.repeatForever(rotate)
            node1.run(runForever)
        }
        node1.run(block)
    }
}

自定义动作

import SpriteKit
import GameplayKit

class GameAction: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        
        let node1 = SKSpriteNode()
        node1.name = "node1"
        node1.position = CGPoint(x: 250, y: size.height * 0.5 - 50)
        node1.color = UIColor.red
        node1.size = CGSize(width: 50, height: 50)
        self.addChild(node1)
        
        let duration : TimeInterval = 2
        let blinkTimes = 2.0
        
        //node : 节点运行操作的节点。
        //elapsedTime : 在动画中传递的时间量。根据withDuration给定的参数
        let customAction1 = SKAction.customAction(withDuration: duration) { (node, elapsedTime) in
            let slice = duration / blinkTimes
            let remainder = elapsedTime.truncatingRemainder(dividingBy: 2)
            node.isHidden = remainder > CGFloat(slice) / 2.0
            print(elapsedTime)
        }
        let repeatAction = SKAction.repeatForever(customAction1)
        node1.run(repeatAction)

        //移动
        let customAction2 = SKAction.customAction(withDuration: duration) { (node, elapsedTime) in
            let moveAction = SKAction.moveTo(x: 500, duration: duration)
            node.run(moveAction)
        }
        node1.run(customAction2)
    }
}

理解 : 其实有点像动作块,也还是一样将自定义的动作打包.

动作属性

删除动作

let remove = SKAction.removeFromParent()

这个比较好理解,也就是删除节点的动作.

上一篇下一篇

猜你喜欢

热点阅读