iPhone寿司ロール

恵方巻きの日だからすまきのiPhoneアプリサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    weak var sceneView : SCNView?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createBoard()

        createRice()

    }

    func setupScene() {

        sceneView = {

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

            sv.scene = SCNScene()

            sv.allowsCameraControl = true

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

            self.view.addSubview(sv)

            return sv

        }()

    }

    

    func createBoard() {

        let box = SCNBox(width: 100, height: 1, length: 40, chamferRadius: 0)

        box.firstMaterial?.diffuse.contents = UIColor(hue: 0.12, saturation: 0.7, brightness: 1, alpha: 1)

        let boxNode = SCNNode(geometry: box)

        boxNode.position = SCNVector3(x: 0, y: –5, z: 0)

        boxNode.physicsBody = SCNPhysicsBody.staticBody()

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

    }

    

    func createRice() {

        

        let path : UIBezierPath = {

            let p = UIBezierPath()

            let r : CGFloat = 1.7

            [Int](02).each{

                let angle = CGFloat(M_PI*2.0/3.0 * Double($0) + M_PI / 2.0)

                let pt = CGPoint(x: r * cos(angle), y: r * sin(angle))

                if ($0 == 0) {

                    p.moveToPoint(pt)

                } else {

                    p.addLineToPoint(pt)

                }

            }

            p.closePath()

            return p

        }()

        

        var tmp : SCNNode?;

        for i in 020 {

            let rice = SCNNode()

            rice.name = “rice”

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

            

            let black = SCNBox(width: 3.0, height: 0.5, length: 10, chamferRadius: 0)

            black.firstMaterial?.diffuse.contents = UIColor.blackColor()

            let blackNode = SCNNode(geometry: black)

            blackNode.position = SCNVector3(x: 0, y: –1.3, z: 0)

            rice.addChildNode(blackNode)

            

            let white = SCNShape(path: path, extrusionDepth: 10)

            white.firstMaterial?.diffuse.contents = UIColor.whiteColor()

            let whiteNode = SCNNode(geometry: white)

            rice.addChildNode(whiteNode)

            

            rice.position = SCNVector3(x: Float(i) * 330, y: 0, z: 0)

            rice.physicsBody = SCNPhysicsBody.dynamicBody()

            rice.physicsBody?.physicsShape = SCNPhysicsShape(node: rice, options: [SCNPhysicsShapeTypeKey : SCNPhysicsShapeTypeConvexHull])

            

            let gravity = SCNPhysicsField.radialGravityField()

            gravity.strength = 50

            rice.physicsField = gravity

            

            if let tmp = tmp {

                let joint = SCNPhysicsHingeJoint(bodyA: tmp.physicsBody!, axisA: SCNVector3(x: 0, y: 0, z: 1), anchorA: SCNVector3(x: 1.6, y: –1.5, z: 0), bodyB:rice.physicsBody!, axisB: SCNVector3(x: 0, y: 0, z: 1), anchorB: SCNVector3(x: –1.6, y: –1.5, z: 0))

                sceneView?.scene?.physicsWorld.addBehavior(joint)

            }

            

            tmp = rice

        }

    }

    

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

        let n : SCNNode = sceneView?.scene?.rootNode.childNodes

            .filter { ($0 as SCNNode).name == “rice” }

            .sorted { ($0.0 as SCNNode).position.x > ($0.1 as SCNNode).position.x }.first as SCNNode

        

        n.physicsBody?.applyTorque(SCNVector4(x: 0, y: 0, z: 1, w: 120), impulse: true)

        

    }

    

}

extension Array {

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

}