iPhone周回する

ボールがリングの上をぐるっと回るのをカメラで追いかけるiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    weak var sceneView : SCNView?

    var count = 0

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createCircle()

        createRunner()

        createCamera()

    }

    

    func setupScene() {

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

        sv.backgroundColor = UIColor(white: 0.2, alpha: 1)

        sv.scene = SCNScene()

        view.addSubview(sv)

        

        sv.autoenablesDefaultLighting = true

        sceneView = sv

    }

    

    func createCircle() {

        let tube = SCNTube(innerRadius: 30, outerRadius: 38, height: 0.5)

        tube.firstMaterial?.diffuse.contents = UIColor(hue: 0.2, saturation: 0.6, brightness: 1, alpha: 1)

        tube.firstMaterial?.specular.contents = UIColor(hue: 0.5, saturation: 0.1, brightness: 1, alpha: 1)

        let tubeNode = SCNNode(geometry: tube)

        tubeNode.name = “tube”

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

        

        let angle = Float(M_PI) / 6.0

        for i in 0..<12 {

            

            let x = 34 * cos(angle * Float(i))

            let z = 34 * sin(angle * Float(i))

            let disk = SCNCylinder(radius: 3.5, height: 0.1)

            disk.firstMaterial?.diffuse.contents = UIColor(hue: 0.25, saturation: 0.2, brightness: 1, alpha: 1)

            let diskNode = SCNNode(geometry: disk)

            diskNode.name = “disk\(i)

            diskNode.position = SCNVector3(x: x, y: 0.3, z: z)

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

        }

    }

    func createRunner() {

        count = 0

        

        let runner = SCNSphere(radius: 3)

        runner.firstMaterial?.diffuse.contents = UIColor(hue: 0.4, saturation: 0.3, brightness: 1, alpha: 1)

        let runnerNode = SCNNode(geometry: runner)

        runnerNode.name = “runner”

        if let position = sceneView?.scene?.rootNode.childNodeWithName(“disk\(count), recursively: false)?.position {

            runnerNode.position = SCNVector3(x:position.x, y:3.25, z:position.z)

        }

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

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.name = “camera”

        camera.camera = SCNCamera()

        camera.camera?.zFar = 300

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

        camera.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –0.4)

        

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

            let con = SCNLookAtConstraint(target: runner)

            con.influenceFactor = 0.4

            camera.constraints = [con]

        }

        

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

    }

    

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

        count = (count + 1) % 12

        

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

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

        

        if let position = sceneView?.scene?.rootNode.childNodeWithName(“disk\(count), recursively: false)?.position {

            runner?.runAction(SCNAction.moveTo(SCNVector3(x:position.x, y:3.25, z:position.z), duration: 0.4))

        }

    }

}