iPhoneバレットタイム

バレットタイムっぽく360度のカメラでスローなiPhoneアプリのサンプルコード

import UIKit

import SceneKit

class ViewController: UIViewController, SCNSceneRendererDelegate {

    weak var sceneView : SCNView?

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createFigure()

        createBlocks()

        createCamera()

    }

    

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

        sv.backgroundColor = UIColor.darkGrayColor()

        sv.scene = SCNScene()

        sv.scene?.physicsWorld.speed = 0

        sv.autoenablesDefaultLighting = true

        sv.delegate = self

        view.addSubview(sv)

        sceneView = sv

    }

    func createFigure() {

        let figure = SCNNode()

        figure.name = “figure”

        sceneView?.scene?.rootNode.addChildNode(figure)

        let head = SCNCapsule(capRadius: 1, height: 8)

        head.firstMaterial?.diffuse.contents = UIColor.yellowColor()

        let headNode = SCNNode(geometry: head)

        headNode.transform = SCNMatrix4Scale(headNode.transform, 1, 0.25, 1)

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

        figure.addChildNode(headNode)

        

        let body = SCNBox(width: 2.5, height: 2.5, length: 1.8, chamferRadius: 0.5)

        body.firstMaterial?.diffuse.contents = UIColor.yellowColor()

        let bodyNode = SCNNode(geometry: body)

        figure.addChildNode(bodyNode)

        

        for var i=0; i<2; i++ {

            let arm = SCNBox(width: 1, height: 2.3, length: 1, chamferRadius: 0.2)

            arm.firstMaterial?.diffuse.contents = UIColor.yellowColor()

            let armNode = SCNNode(geometry: arm)

            armNode.pivot = SCNMatrix4MakeTranslation(0, 0.6, 0)

            armNode.transform = SCNMatrix4Rotate(armNode.transform, –Float(M_PI) * 0.7, 1, 0, 0)

            armNode.transform = SCNMatrix4Translate(armNode.transform, i==0 ? 1.6 : –1.6, 0.6, 0)

            figure.addChildNode(armNode)

        }

        

        for var i=0; i<2; i++ {

            let foot = SCNBox(width: 1.2, height: 2.2, length: 1.4, chamferRadius: 0.2)

            foot.firstMaterial?.diffuse.contents = UIColor.yellowColor()

            let footNode = SCNNode(geometry: foot)

            footNode.pivot = SCNMatrix4MakeTranslation(0, 0.5, 0)

            if i==0 {

                footNode.transform = SCNMatrix4Rotate(footNode.transform, –Float(M_PI) * 0.4, 1, 0, 0)

            }

            footNode.transform = SCNMatrix4Translate(footNode.transform, i==0 ? 0.6 : –0.6, –2, 0)

            figure.addChildNode(footNode)

        }

        

        figure.physicsBody = SCNPhysicsBody.dynamicBody()

    }

    

    func createBlocks() {

        [Int](010).each { i in

            let b = SCNBox(width: 1, height: 5, length: 1, chamferRadius: 0)

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

            let bNode = SCNNode(geometry: b)

            let w = Float(M_PI) / 3.0 * Float(i)

            bNode.position = SCNVector3(x: 6.0 * cos(w), y: –Float(i) * 2.0, z: 6.0 * sin(w))

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

        }

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.name = “camera”

        camera.camera = SCNCamera()

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

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

    }

    

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

        sceneView?.scene?.physicsWorld.speed = 0.4

        sceneView?.playing = true

    }

    

    func renderer(aRenderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) {

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

            camera.constraints = nil

            camera.transform = SCNMatrix4Rotate(camera.transform, Float(M_PI) * 0.005, 0, 1, 0)

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

                let constraint = SCNLookAtConstraint(target: figure)

                camera.constraints = [constraint]

            }

        }

    }

}

extension Array {

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

}