ios Swift - 使用同步动画分组精灵

时间:2016-05-31 09:31:27

标签: ios swift animation sprite

我正在尝试制作一个同步动画(在分离的和较小的拼图拼图部分上由帧分解的大型视频)。这个游戏是一个视频拼图。以下是我通过示例分三部分使用的代码:

func Anim_Puzzle13 (Node13 : SKPuzzle) {

    let puzzle13 = SKAction.animateWithTextures(sheet_puzzle13.Puzzle13_(), timePerFrame: 0.066)
    NPuzzle13 = Node13
    NPuzzle13.runAction(SKAction.repeatActionForever(puzzle13))
    NPuzzle13.position = CGPoint(x: 500, y: 400)
    NPuzzle13.zPosition = 1

}

func Anim_Puzzle19 (Node19 : SKPuzzle) {


    let puzzle19 = SKAction.animateWithTextures(sheet_puzzle19.Puzzle19_(), timePerFrame: 0.066)
    NPuzzle19 = Node19
    NPuzzle19.runAction(SKAction.repeatActionForever(puzzle19))
    NPuzzle19.position = CGPoint(x: 600, y: 500)
    NPuzzle19.zPosition = 1

}

func Anim_Puzzle30 (Node30 : SKPuzzle) {


    let puzzle30 = SKAction.animateWithTextures(sheet_puzzle30.Puzzle30_(), timePerFrame: 0.066)
    NPuzzle30 = Node30
    NPuzzle30.runAction(SKAction.repeatActionForever(puzzle30))
    NPuzzle30.position = CGPoint(x: 700, y: 600)
    NPuzzle30.zPosition = 1

}

效果很好,但动画之间不同步,视频没有完整性。我搜索了很长时间的解决方案,使动画同步;我看到了两种可能性:首先是创建一个内部所有拼图部分的唯一SKNode(),但我希望能够独立移动每个拼图部分并且没有成功使用此方法获得同步动画。

另一种方式似乎是创建一个包含所有动画的组,但这不起作用,并导致应用程序停止。

以下是我使用的所有代码:

import SpriteKit
import UIKit
import AVFoundation
import AVKit
import CoreFoundation

private let kpuzzleNodeName = "puzzle"
private let kdancing = "dancing"


class SKPuzzle: SKSpriteNode {
var name2:String = "";
}

class GameScene: SKScene {



var background = SKVideoNode(videoFileNamed: "Video_Socle.mov")
var selectedNode = SKPuzzle()
var player:AVPlayer?
var videoNode:SKVideoNode?

var NPuzzle13 = SKPuzzle()
var NPuzzle19 = SKPuzzle()
var NPuzzle30 = SKPuzzle()
var NPuzzle11 = SKPuzzle()
var NPuzzle29 = SKPuzzle()
var NPuzzle35 = SKPuzzle()
var puzzle13 = SKAction()
var puzzle19 = SKAction()
var puzzle30 = SKAction()
var puzzle11 = SKAction()
var puzzle29 = SKAction()
var puzzle35 = SKAction()

let sheet_puzzle13 = Puzzle13()
let sheet_puzzle19 = Puzzle19()
let sheet_puzzle30 = Puzzle30()
let sheet_puzzle11 = Puzzle11()
let sheet_puzzle29 = Puzzle29()
let sheet_puzzle35 = Puzzle35()



override init(size: CGSize) {
    super.init(size: size)



    // 1
    self.background.name = kdancing
    self.background.anchorPoint = CGPointZero
    background.zPosition = 0
    self.addChild(background)


    // 2
    let sheet = Statiques()

    let sprite_dancing1 = SKSpriteNode(texture: sheet.Dancing1())
    let sprite_dancing2 = SKSpriteNode(texture: sheet.Dancing2())
    sprite_dancing1.name = kdancing
    sprite_dancing2.name = kdancing


    sprite_dancing1.position = CGPoint(x: 837, y: 752)
    sprite_dancing1.zPosition = 2
    sprite_dancing2.position = CGPoint(x: 1241, y: 752)
    sprite_dancing2.zPosition = 2

    background.addChild(sprite_dancing1)

    background.addChild(sprite_dancing2)



    let imageNames = [sheet.Puzzle13() , sheet.Puzzle19(), sheet.Puzzle30(), sheet.Puzzle11(), sheet.Puzzle29(), sheet.Puzzle35() ]

    for i in 0..<imageNames.count {
        let imageName = imageNames[i]

        let sprite = SKPuzzle(texture: imageName)

        sprite.name = kpuzzleNodeName
        sprite.name2 = "\(i)"

        let offsetFraction = (CGFloat(i) + 1.0)/(CGFloat(imageNames.count) + 1.0)

        sprite.position = CGPoint(x: size.width * offsetFraction, y: size.height / 2)
        sprite.zPosition = 3

        background.addChild(sprite)

    }



}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch: AnyObject in touches {
        let positionInScene = touch.locationInNode(self)
        selectNodeForTouch(positionInScene)
    }
}

override func didMoveToView(view: SKView) {

    let urlStr = NSBundle.mainBundle().pathForResource("Video_Socle", ofType: "mov")
    let url = NSURL(fileURLWithPath: urlStr!)

    player = AVPlayer(URL: url)
    NSNotificationCenter.defaultCenter().addObserverForName(AVPlayerItemDidPlayToEndTimeNotification, object: player!.currentItem, queue: nil)
    { notification in
        let t1 = CMTimeMake(5, 100);
        self.player!.seekToTime(t1)
        self.player!.play()
    }


    videoNode = SKVideoNode(AVPlayer: player!)
    videoNode!.position = CGPointMake(frame.size.width/2, frame.size.height/2)
    videoNode!.size = CGSize(width: 2048, height: 1536)
    videoNode!.zPosition = 0


    background.addChild(videoNode!)
    videoNode!.play()


    let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(GameScene.handlePanFrom(_:)))
    self.view!.addGestureRecognizer(gestureRecognizer)
}


func handlePanFrom(recognizer : UIPanGestureRecognizer) {
    if recognizer.state == .Began {
        var touchLocation = recognizer.locationInView(recognizer.view)
        touchLocation = self.convertPointFromView(touchLocation)

        self.selectNodeForTouch(touchLocation)
    } else if recognizer.state == .Changed {
        var translation = recognizer.translationInView(recognizer.view!)
        translation = CGPoint(x: translation.x, y: -translation.y)

        self.panForTranslation(translation)

        recognizer.setTranslation(CGPointZero, inView: recognizer.view)
    } else if recognizer.state == .Ended {

    }
}

func degToRad(degree: Double) -> CGFloat {
    return CGFloat(degree / 180.0 * M_PI)
}

func selectNodeForTouch(touchLocation : CGPoint) {
    // 1
    let touchedNode = self.nodeAtPoint(touchLocation)

    if touchedNode is SKPuzzle {
        // 2
        if !selectedNode.isEqual(touchedNode) {
            selectedNode.runAction(SKAction.rotateToAngle(0.0, duration: 0.1))

            selectedNode = touchedNode as! SKPuzzle

            // 3
            if touchedNode.name! == kpuzzleNodeName {
                let sequence = SKAction.sequence([SKAction.rotateByAngle(degToRad(-4.0), duration: 0.1),
                    SKAction.rotateByAngle(0.0, duration: 0.1),
                    SKAction.rotateByAngle(degToRad(4.0), duration: 0.1)])
                selectedNode.runAction(SKAction.repeatActionForever(sequence))
            }
        }
    }
}



func panForTranslation(translation : CGPoint) {
    let position = selectedNode.position

    if selectedNode.name! == kpuzzleNodeName {
        selectedNode.position = CGPoint(x: position.x + translation.x * 2, y: position.y + translation.y * 2)

        print (selectedNode.name)
        print (selectedNode.name2)
        if selectedNode.name2 == "0" {

            Anim_Puzzle13(selectedNode)
        }

        print (selectedNode.name2)
        if selectedNode.name2 == "1" {
            Anim_Puzzle19(selectedNode)
        }

        print (selectedNode.name2)
        if selectedNode.name2 == "2" {
            Anim_Puzzle30(selectedNode)
        }

        print (selectedNode.name2)
        if selectedNode.name2 == "3" {
            Anim_Puzzle11(selectedNode)
        }

        print (selectedNode.name2)
        if selectedNode.name2 == "4" {
            Anim_Puzzle29(selectedNode)
        }

        print (selectedNode.name2)
        if selectedNode.name2 == "5" {
            Anim_Puzzle35(selectedNode)
        }

    }

}


func Anim_Puzzle13 (Node13 : SKPuzzle) {

    let puzzle13 = SKAction.animateWithTextures(sheet_puzzle13.Puzzle13_(), timePerFrame: 0.066)
    NPuzzle13 = Node13
    NPuzzle13.runAction(SKAction.repeatActionForever(puzzle13))
    NPuzzle13.position = CGPoint(x: 500, y: 400)
    NPuzzle13.zPosition = 1

}

func Anim_Puzzle19 (Node19 : SKPuzzle) {


    let puzzle19 = SKAction.animateWithTextures(sheet_puzzle19.Puzzle19_(), timePerFrame: 0.066)
    NPuzzle19 = Node19
    NPuzzle19.runAction(SKAction.repeatActionForever(puzzle19))
    NPuzzle19.position = CGPoint(x: 600, y: 500)
    NPuzzle19.zPosition = 1

}

func Anim_Puzzle30 (Node30 : SKPuzzle) {


    let puzzle30 = SKAction.animateWithTextures(sheet_puzzle30.Puzzle30_(), timePerFrame: 0.066)
    NPuzzle30 = Node30
    NPuzzle30.runAction(SKAction.repeatActionForever(puzzle30))
    NPuzzle30.position = CGPoint(x: 700, y: 600)
    NPuzzle30.zPosition = 1

}

func Anim_Puzzle11 (Node11 : SKPuzzle) {


    let puzzle11 = SKAction.animateWithTextures(sheet_puzzle11.Puzzle11_(), timePerFrame: 0.066)
    NPuzzle11 = Node11
    NPuzzle11.runAction(SKAction.repeatActionForever(puzzle11))
    NPuzzle11.position = CGPoint(x: 800, y: 700)
    NPuzzle11.zPosition = 1

}

func Anim_Puzzle29 (Node29 : SKPuzzle) {


    let puzzle29 = SKAction.animateWithTextures(sheet_puzzle29.Puzzle29_(), timePerFrame: 0.066)
    NPuzzle29 = Node29
    NPuzzle29.runAction(SKAction.repeatActionForever(puzzle29))
    NPuzzle29.position = CGPoint(x: 900, y: 800)
    NPuzzle29.zPosition = 1

}

func Anim_Puzzle35 (Node35 : SKPuzzle) {


    let puzzle35 = SKAction.animateWithTextures(sheet_puzzle35.Puzzle35_(), timePerFrame: 0.066)
    NPuzzle35 = Node35
    NPuzzle35.runAction(SKAction.repeatActionForever(puzzle35))
    NPuzzle35.position = CGPoint(x: 1000, y: 900)
    NPuzzle35.zPosition = 1

}

}

我不确定是否可以同步这样的动画:在几个独立的部分中使用SKAction(),因为必须能够单独选择它们。< / p>

更新:我尝试按照动作组方式进行操作,但我在每个精灵上播放相同的动画,而不是为每个精灵同步动画(同步6个不同的动画:6个不同的精灵):

    let sheet13 = Puzzle13()
    let sheet19 = Puzzle19()
    let sheet30 = Puzzle30()
    let sheet11 = Puzzle11()
    let sheet29 = Puzzle29()
    let sheet35 = Puzzle35()

    let imageAnims = [sheet13.Puzzle13_0000() , sheet19.Puzzle19_0000(), sheet30.Puzzle30_0000(), sheet11.Puzzle11_0000(), sheet29.Puzzle29_0000(), sheet35.Puzzle35_0000() ]

    let puzzle13 = SKAction.animateWithTextures(sheet13.Puzzle13_(), timePerFrame: 0.066)
    let puzzle19 = SKAction.animateWithTextures(sheet19.Puzzle19_(), timePerFrame: 0.066)
    let puzzle30 = SKAction.animateWithTextures(sheet30.Puzzle30_(), timePerFrame: 0.066)
    let puzzle11 = SKAction.animateWithTextures(sheet11.Puzzle11_(), timePerFrame: 0.066)
    let puzzle29 = SKAction.animateWithTextures(sheet29.Puzzle29_(), timePerFrame: 0.066)
    let puzzle35 = SKAction.animateWithTextures(sheet35.Puzzle35_(), timePerFrame: 0.066)

    let group = SKAction.group([puzzle13,puzzle19,puzzle30,puzzle11,puzzle29,puzzle35])

    for i in 0..<imageAnims.count {
        let imageAnim = imageAnims[i]

        let spriteAnim = SKPuzzle(texture: imageAnim)

        spriteAnim.name = kanimNodeName
        spriteAnim.name2 = "\(i)"

        let offsetFraction = (CGFloat(i) + 1.0)/(CGFloat(imageAnims.count) + 1.0)

        spriteAnim.position = CGPoint(x: ((size.width)*2) * offsetFraction, y: size.height * 1.5)
        spriteAnim.zPosition = 3

        spriteAnim.runAction(SKAction.repeatActionForever(group))


        background.addChild(spriteAnim)

    }

1 个答案:

答案 0 :(得分:1)

首先,我想列出两种不同的方法来创建SKAction

使用SKAction.group开始并行操作:

let sprite = SKSpriteNode(imageNamed:"Spaceship")
let scale = SKAction.scaleTo(0.1, duration: 0.5)
let fade = SKAction.fadeOutWithDuration(0.5)
let group = SKAction.group([scale, fade])
sprite.runAction(group)

另一种有用的方法可以是完成,因此您可以知道SKAction何时完成:

extension SKNode
{
    func runAction( action: SKAction!, withKey: String!, optionalCompletion: dispatch_block_t? )
    {
        if let completion = optionalCompletion
        {
            let completionAction = SKAction.runBlock( completion )
            let compositeAction = SKAction.sequence([ action, completionAction ])
            runAction( compositeAction, withKey: withKey )
        }
        else
        {
            runAction( action, withKey: withKey )
        }
    }
}

<强>用法

node.runAction(move,withKey:"swipeMove",optionalCompletion: {
   // here the action is finished, do whatever you want
})

在那之后,关于你的项目,我见过很多node.runAction ..,你也可以采用这种策略来同步你的行为:

var myAction30 :SKAction!
var myAction31 :SKAction!

self.myAction30 = SKAction.repeatActionForever(puzzle30)
self.myAction31 = SKAction.repeatActionForever(puzzle31)
let group = SKAction.group([self.myAction30, self.myAction31])
self.runAction(group)

更新:我看过您的更新部分,当您谈到“同步”时,可能并不意味着“并行运行”。

因此,如果你想在另一个之后运行一个动作,那么还有:

self.myAction30 = SKAction.repeatActionForever(puzzle30)
self.myAction31 = SKAction.repeatActionForever(puzzle31)
let sequence = SKAction.sequence([self.myAction30, self.myAction31])
self.runAction(sequence)