iPhoneシマリング

リング状に色違いの玉を等間隔に並べるiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    weak var sceneView : SCNView?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createRing()

        createCamera()

    }

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

        sv.scene = SCNScene()

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

        sv.allowsCameraControl = true

        view.addSubview(sv)

        

        sceneView = sv

    }

    

    func createRing() {

        let ring = SCNTube(innerRadius: 5, outerRadius: 5.2, height: 0.2)

        ring.firstMaterial?.diffuse.contents = UIColor(white: 0.9, alpha: 1)

        let ringNode = SCNNode(geometry: ring)

        ringNode.pivot = SCNMatrix4MakeRotation(Float(M_PI) * 0.5, 1, 0, 0)

        ringNode.name = “ring”

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

        

        let cnt = 10

        let dw = M_PI / Double(cnt)

        for i in 0..<cnt {

            let s = SCNSphere(radius: 0.5)

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

            let sNode = SCNNode(geometry: s)

            sNode.name = \(i)”

            sNode.pivot = SCNMatrix4MakeTranslation(0, 0, –5.1)

            ringNode.addChildNode(sNode)

            

        }

    }

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

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

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

    }

    

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

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

            ring.name = “”

            let dw = M_PI / 5.0

            for s in ring.childNodes {

                let w = Float(s.name.toInt()!) * Float(dw)

                s.runAction(SCNAction.rotateToX(0, y: CGFloat(w) , z: 0, duration: 3.0), completionHandler: { () -> Void in

                    ring.runAction(SCNAction.repeatActionForever(SCNAction.rotateByX(0, y: 1, z: 0, duration: 2.0)))

                })

            }

        }

    }

}

extension Array {

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

}