iPhoneパラボラ

開閉するパラボラのiPhoneアプリサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController, SCNSceneRendererDelegate {

    weak var sceneView : SCNView?

    var count = 0

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createParabola()

        createCamera()

    }

    func setupScene() {

        sceneView = {

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

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

            sv.scene = SCNScene()

            sv.scene?.physicsWorld.speed = 5

            sv.delegate = self

            sv.autoenablesDefaultLighting = true

            sv.allowsCameraControl = true

            self.view?.addSubview(sv)

            return sv

            }();

    }

    func createParabola() {

        

        var pt = {(i : Int) -> CGPoint in CGPoint(x:CGFloat(i), y:CGFloat(pow(Double(i), 2)) / 50.0)}

        

        let path = UIBezierPath()

        path.moveToPoint(CGPoint(x: –50, y: 50))

        [Int](-5050).each { i in path.addLineToPoint(pt(i)) }

        [Int](-5050).back { i in path.addLineToPoint(CGPoint(x:pt(i).x, y:pt(i).y + 1)) }

        

        let parabola = SCNShape(path: path, extrusionDepth: 0.5)

        [Int](0360).each { i in

            let parabolaNode = SCNNode(geometry: parabola)

            parabolaNode.name = “parabola”

            parabolaNode.physicsBody = SCNPhysicsBody.staticBody()

            parabolaNode.physicsBody?.physicsShape = SCNPhysicsShape(node: parabolaNode, options: [SCNPhysicsShapeTypeKey : SCNPhysicsShapeTypeConcavePolyhedron])

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

        }

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

        camera.camera?.zFar = 600

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

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

    }

    

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

        var doit = {(i : Int, e : AnyObject) -> Void in (e as SCNNode).runAction(SCNAction.rotateToX(0, y: CGFloat(i) * CGFloat(M_PI) / 360.0, z: 0, duration: 0.5))}

        if count != 0 {

            doit = {(i : Int, e : AnyObject) -> Void in (e as SCNNode).runAction(SCNAction.rotateToX(0, y: 0, z: 0, duration: 0.5))}

        }

        sceneView?.scene?.rootNode.childNodes

            .filter {($0 as SCNNode).name == “parabola” }.eachIdx (doit)

        

        count = (count + 1) % 2

    }

    

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

        if arc4random() % 50 == 0 {

            let ball = SCNSphere(radius: 8)

            ball.firstMaterial?.diffuse.contents = UIColor.orangeColor()

            let ballNode = SCNNode(geometry: ball)

            ballNode.position = SCNVector3(x: 0, y: 80, z: 100)

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

            

            ballNode.physicsBody = SCNPhysicsBody.dynamicBody()

            ballNode.physicsBody?.applyForce(SCNVector3(x: 0, y: –30, z: –100), impulse: true)

        }

    }

}

extension Array {

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

    func back(doit:(T) -> Void) { for (var i=self.count1; i>=0; i–) { doit(self[i]) } }

    func eachIdx(doit:(Int, T) -> Void) { for (idx, e) in enumerate(self) { doit(idx, e) } }

}