SpriteKit(4) - 動作

動作

  • 以點的方式移動
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)
    }
}
兩個動作同步一起做

改變透明度

  • 不需要指定alpha值
let fadeOut = SKAction.fadeOut(withDuration: 1)
let fadeIn = SKAction.fadeIn(withDuration: 1)
  • 指定alpha值
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)
    }
}
運動軌跡

路徑考慮 : 這里面的路徑考慮從錨點出發,錨點根據設置的路徑來執行.
這里有些比較有意思的考慮點

  • 矩形路徑 : 考慮的角度是紅色節點的錨點,也就是矩形參考紅色節點的錨點位置.x和y值為0,0,也就是初始點.每次路徑結束都會重新計算一次路徑.
  • 圓形路徑 : 考慮的角度是圓本身的路徑,也就是圓形參考場景坐標系.每次路徑計算都是固定的值.

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)
    }
}
速度動作
  • 動作的 speed 屬性改變動畫播放的速率。你可以在動畫默認計時上加速或減速。
  • speed 值為 1.0 是正常的速度。如果動作的 speed 屬性設置為 2.0,當節點執行動作時,
  • 它速度快了一倍。要暫停動作,將值設置為 0。 如果你調整那些包含其他動作(例如組、序列或重復動作)的動作的速率,速率會應用到所
    包含的動作。附加的動作也會受到它們自己的 speed 屬性的作用。
  • 節點的 speed 屬性與動作的 speed 屬性具有相同的效果,但該速率適用于該節點或景樹中的任意后代所處理的所有動作。

簡單粗暴的理解 :
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)
    }
}

理解 : 其實有點像動作塊,也還是一樣將自定義的動作打包.

動作屬性

  • 速度 speed
  • 時間 duration
  • 曲線方式 timingMode
    • SKActionTimingLinear 線性執行
    • SKActionTimingEaseIn 淡入
    • SKActionTimingEaseOut 淡出
    • SKActionTimingEaseInEaseOut 淡入淡出

刪除動作

let remove = SKAction.removeFromParent()

這個比較好理解,也就是刪除節點的動作.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,701評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,691評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,974評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,694評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,026評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,193評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,719評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,442評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,668評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,846評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,255評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,592評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,394評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,836評論 18 139
  • 斬斷自己的退路,才能更好地贏得出路。在很多時候,我們都需要一種斬斷自己退路的勇氣。 SKAction簡介 在先前的...
    神經騷棟閱讀 6,354評論 24 60
  • 國家電網公司企業標準(Q/GDW)- 面向對象的用電信息數據交換協議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 11,079評論 6 13
  • Dear 三大只: 當時光荏苒了歲月,歲月褪去了鉛華,我想我還是會一如既往地喜歡著你們、關注著你們,這是一種說...
    澄Ruan閱讀 332評論 0 3
  • 傳送門http://www.cnblogs.com/lucyjiayou/archive/2012/01/04/2...
    Fattyu閱讀 867評論 0 0