iPhone編集ごっこ

画像を並び替えて、1フレーム0.5秒の動画っぽく再生するiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SpriteKit

class ViewController: UIViewController {

    weak var scene: SKScene?

    weak var select : SKNode?

    var origin : CGPoint = CGPointZero

    

    override func viewWillAppear(animated: Bool) {

        super.viewWillAppear(animated)

        

        self.setupScene()

        self.createImageBox()

        self.createAnimationScreen()

    }

    

    func setupScene() {

        let sv = SKView(frame: self.view.bounds)

        self.view.addSubview(sv)

        let scene = SKScene(size: sv.frame.size)

        scene.backgroundColor = UIColor(hue: 0.3, saturation: 0.5, brightness: 1, alpha: 1)

        sv.presentScene(scene)

        

        self.scene = scene

    }

    func createImageBox() {

        let w = CGRectGetMaxX(self.view.bounds) / 6.0

        for i in 05 {

            let box = SKSpriteNode(color: UIColor(hue: 0.4, saturation: 0.2, brightness: 1, alpha: 1), size: CGSizeMake(w * 0.8, w * 0.8))

            box.name = “box\(i)

            box.position = CGPointMake(CGFloat(i) * w + w/2.0, w/2.0)

            self.scene?.addChild(box)

            

            for j in 05 {

                let x = w/3.5 * CGFloat(cos(Double(j) * M_PI / 3.0))

                let y = w/3.5 * CGFloat(sin(Double(j) * M_PI / 3.0))

                let dot = SKShapeNode(circleOfRadius: 8)

                dot.position = CGPointMake(x, y)

                dot.fillColor = j != i ? UIColor.clearColor() : UIColor(hue: CGFloat(i) * 0.15, saturation: 0.7, brightness: 1, alpha: 1)

                dot.lineWidth = 2

                dot.strokeColor = UIColor(hue: 0.5, saturation: 0.8, brightness: 1, alpha: 1)

                box.addChild(dot)

            }

        }

    }

    

    func createAnimationScreen() {

        let w = CGRectGetMaxY(self.view.bounds) / 2.0

        let screen = SKSpriteNode(color: UIColor.blackColor(), size: CGSizeMake(w, w))

        screen.name = “screen”

        screen.position = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMaxY(self.view.bounds) * 0.6)

        self.scene?.addChild(screen)

        

        let playbtn = SKLabelNode(text: “play”)

        playbtn.name = “play”

        playbtn.fontSize = 50

        screen.addChild(playbtn)

    }

    

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {

        let p = touches.anyObject()!.locationInNode(self.scene)

        let hit = self.scene!.nodeAtPoint(p)

        if hit.name == “play” || hit.name == “screen” {

            self.play()

        } else if (hit.name?.hasPrefix(“box”) != nil) {

            self.select = hit

            self.origin = hit.position

        }

    }

    

    override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {

        let p = touches.anyObject()!.locationInNode(self.scene)

        self.select?.position = p

    }

    

    override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {

        if let target = self.select {

            var intersect = false

            self.scene?.enumerateChildNodesWithName(“box[0-9]”, usingBlock: { (node, bool) in

                if target != node && target.intersectsNode(node) {

                    let buf = target.name

                    target.name = node.name

                    node.name = buf

                    

                    target.runAction(SKAction.moveTo(node.position, duration: 0.2))

                    node.runAction(SKAction.moveTo(self.origin, duration: 0.2))

                    intersect = true

                }

            })

            

            if !intersect {

                target.runAction(SKAction.moveTo(self.origin, duration: 0.2))

            }

            

            self.select = nil

        }

    }

    

    func play() {

        let screen = self.scene!.childNodeWithName(“screen”)

        

        var nodes = [SKNode]()

        self.scene?.enumerateChildNodesWithName(“box[0-9]”, usingBlock: { (node, bool) -> Void in

            nodes.append(node)

        })

        nodes.sort { $0.name < $1.name }

        

        

        var textures = [SKTexture]()

        for node in nodes {

            if let t = self.scene?.view?.textureFromNode(node) {

                textures.append(t)

            }

        }

        

        let screenOverlay = SKSpriteNode()

        let overlay = SKSpriteNode(texture: textures[0], size: screen!.frame.size)

        overlay.position = screen!.position

        self.scene?.addChild(overlay)

        

        let animationFramesAction = SKAction.animateWithTextures(textures, timePerFrame: 0.5, resize: true, restore: false)

        overlay.runAction(animationFramesAction, completion: {

            overlay.runAction(SKAction.fadeOutWithDuration(0.2), completion: {overlay.removeFromParent()})

        })

    }

}