iPhone紙から階段

紙を折って階段っぽくするiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    

    weak var sceneView : SCNView?

    var count = 0

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createPaper()

        createCamera()

    }

    

    func setupScene() {

        sceneView = {

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

            sv.scene = SCNScene()

            sv.backgroundColor = UIColor(hue: 0.4, saturation: 0.1, brightness: 1, alpha: 1)

            self.view.addSubview(sv)

            return sv

            }()

    }

    

    func createPaper() {

        [Int](09).foreach { i in

            let paper = SCNBox(width: 5, height: 5, length: 0.2 CGFloat(i) * 0.01, chamferRadius: 0)

            paper.firstMaterial?.diffuse.contents = UIColor(hue: CGFloat(i) * 0.1, saturation: 0.7, brightness: 1, alpha: 1)

            let paperNode = SCNNode(geometry: paper)

            paperNode.name = “paper \(9-i)

            paperNode.position = SCNVector3(x: 0, y: 0, z:0)

            paperNode.pivot = SCNMatrix4MakeTranslation(0, 2.5, 0)

            

            self.sceneView?.scene?.rootNode.addChildNode(paperNode)

        }

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.name = “camera”

        camera.camera = SCNCamera()

        camera.position = SCNVector3(x: 0, y: 0, z: 20)

        self.sceneView?.scene?.rootNode.addChildNode(camera)

        

        let target = SCNNode()

        self.sceneView?.scene?.rootNode.addChildNode(target)

    }

    

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

        

        let paperArr = self.sceneView?.scene?.rootNode.childNodes

            .filter { ($0 as SCNNode).name?.componentsSeparatedByString(” “)[0] == “paper” }

            .filter { ($0 as SCNNode).name?.componentsSeparatedByString(” “)[1].toInt() > self.count } as [SCNNode]

        let camera = self.sceneView?.scene?.rootNode.childNodeWithName(“camera”, recursively: false)

        

        switch(self.count) {

        case 0:

            camera?.runAction(

                SCNAction.group([

                    SCNAction.moveTo(SCNVector3(x: 0, y: 4, z: 18), duration: 0.5),

                    SCNAction.rotateByX(CGFloat(-0.1), y: 0, z: 0, duration: 0.5)

                    ]))

            paperArr.foreach {i in

                i.runAction(SCNAction.rotateByAngle(1.5 * CGFloat(M_PI), aroundAxis: SCNVector3(x: 1, y: 0, z: 0), duration: 0.5))

            }

            break

        case 1:

            camera?.runAction(SCNAction.moveTo(SCNVector3(x: 0, y: 8, z: 28), duration: 0.5))

            paperArr.foreach {i in

                i.pivot = SCNMatrix4MakeTranslation(2.5, 0, 0)

                i.transform = SCNMatrix4Translate(i.transform, 2.5, 0, –2.5)

                i.runAction(SCNAction.rotateByX(0, y: 0, z: CGFloat(M_PI), duration: 1.0))

            }

            break

            

        case 2:

            camera?.runAction(SCNAction.moveTo(SCNVector3(x: 0, y: 8, z: 32), duration: 0.5))

            paperArr.foreach {i in

                i.pivot = SCNMatrix4MakeTranslation(0, –2.5, 0)

                i.transform = SCNMatrix4Translate(i.transform, 2.5, 0, –2.5)

                i.runAction(SCNAction.rotateByX(0.5 * CGFloat(M_PI), y: 0, z: 0, duration: 0.5))

            }

            break

        case 3:

            camera?.runAction(SCNAction.moveTo(SCNVector3(x: 4, y: 11, z: 34), duration: 0.5))

            paperArr.foreach {i in

                i.pivot = SCNMatrix4MakeTranslation(0, 2.5, 0)

                i.transform = SCNMatrix4Translate(i.transform, 0, 5, 0)

                i.runAction(SCNAction.rotateByX(1.5 * CGFloat(M_PI), y: 0, z: 0, duration: 0.5))

            }

            break

        case 4:

            camera?.runAction(SCNAction.moveTo(SCNVector3(x: 5, y: 11, z: 35), duration: 0.5))

            paperArr.foreach {i in

                i.pivot = SCNMatrix4MakeTranslation(-2.5, 0, 0)

                i.transform = SCNMatrix4Translate(i.transform, 2.5, 0, –2.5)

                i.runAction(SCNAction.rotateByX(0, y: 0, z: CGFloat(M_PI), duration: 0.5))

            }

            break

        case 5:

            camera?.runAction(SCNAction.moveTo(SCNVector3(x: 7, y: 13, z: 38), duration: 0.5))

            paperArr.foreach {i in

                i.pivot = SCNMatrix4MakeTranslation(0, –2.5, 0)

                i.transform = SCNMatrix4Translate(i.transform, 2.5, 0, –2.5)

                i.runAction(SCNAction.rotateByX(0.5 * CGFloat(M_PI), y: 0, z: 0, duration: 0.5))

            }

            break

        case 6:

            camera?.runAction(

                SCNAction.group([

                    SCNAction.moveTo(SCNVector3(x: 7, y: 28, z: 32), duration: 0.5),

                    SCNAction.rotateByX(CGFloat(-0.4), y: 0, z: 0, duration: 0.5)

                    ]))

            paperArr.foreach {i in

                i.pivot = SCNMatrix4MakeTranslation(0, 2.5, 0)

                i.transform = SCNMatrix4Translate(i.transform, 0, 5, 0)

                i.runAction(SCNAction.rotateByX(1.5 * CGFloat(M_PI), y: 0, z: 0, duration: 0.5))

            }

            break

        default:

            break

        }

        

        ++self.count

    }

}

extension Array {

    func foreach(doit:(T) -> Void) {for i in self {doit(i)}}

}