iPhoneチョコ丸箱

丸いチョコのボールを箱から出すiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController, SCNSceneRendererDelegate {

    weak var sceneView : SCNView?

    var turn : Bool = false

    

    override func viewDidLoad() {

        super.viewDidLoad()

        self.setupScene()

        self.createPlate()

        self.createBox()

        self.createChocoball()

        self.createCamera()

    }

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

        sv.scene = SCNScene()

        sv.backgroundColor = UIColor(hue: 0.25, saturation: 0.1, brightness: 0.75, alpha: 1)

        sv.autoenablesDefaultLighting = true

        sv.allowsCameraControl = true

        sv.delegate = self

        view.addSubview(sv)

        

        sceneView = sv

    }

    

    func createPlate() {

        let plate = SCNCylinder(radius: 10, height: 0.5)

        plate.firstMaterial?.diffuse.contents = UIColor.lightGrayColor()

        let plateNode = SCNNode(geometry: plate)

        plateNode.position = SCNVector3(x: 0, y: –8, z: 0)

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

        plateNode.physicsBody = SCNPhysicsBody.staticBody()

    }

    

    func createBox() {

        let box = SCNNode()

        box.name = “box”

        

        var shapes = [SCNPhysicsShape]()

        var transforms = [NSValue]()

        for i in 05 {

            let wall = {() -> SCNBox in

                switch i {

                case 1, 3:

                    return SCNBox(width: 5, height: 8, length: 0.01, chamferRadius: 0)

                case 4:

                    return SCNBox(width: 5, height: 0.01, length: 2, chamferRadius: 0)

                case 5:

                    return SCNBox(width: 2.5, height: 0.01, length: 2, chamferRadius: 0)

                default:

                    return SCNBox(width: 0.01, height: 8, length: 2, chamferRadius: 0)

                }

            }()

            wall.firstMaterial?.diffuse.contents = UIColor(hue: 0.1, saturation: 0.1, brightness: 1, alpha: 1)

            let wallNode = SCNNode(geometry: wall)

            

            wallNode.position = {

                switch i {

                case 0:

                    return SCNVector3(x: 2.5, y: 0, z: 0)

                case 1:

                    return SCNVector3(x: 0, y: 0, z: 1)

                case 2:

                    return SCNVector3(x: –2.5, y: 0, z: 0)

                case 3:

                    return SCNVector3(x: 0, y: 0, z: –1)

                case 4:

                    return SCNVector3(x: 0, y: –4, z: 0)

                default:

                    return SCNVector3(x: 1.25, y: 4, z: 0)

                }

            }()

            box.addChildNode(wallNode)

            shapes.append(SCNPhysicsShape(node: wallNode, options: nil))

            transforms.append(NSValue(SCNMatrix4: wallNode.transform))

        }

        

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

        box.physicsBody = SCNPhysicsBody.dynamicBody()

        box.physicsBody?.physicsShape = SCNPhysicsShape(shapes: shapes, transforms: transforms)

        

        let hinge = SCNPhysicsHingeJoint(body: box.physicsBody!, axis: SCNVector3(x: 0, y: 0, z: 1), anchor: SCNVector3(x: 0, y: 0, z: 0))

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

        

        let flap = SCNBox(width: 2.5, height: 0.01, length: 2, chamferRadius: 0)

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

        let flapNode = SCNNode(geometry: flap)

        flapNode.position = SCNVector3(x: –1.25, y: 4, z: 0)

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

        flapNode.physicsBody = SCNPhysicsBody.dynamicBody()

        

        let flapConnect = SCNPhysicsHingeJoint(bodyA: flapNode.physicsBody!, axisA: SCNVector3(x: 0, y: 0, z: 1), anchorA: SCNVector3(x: 1.25, y: 0, z: 0), bodyB: box.physicsBody!, axisB: SCNVector3(x: 0, y: 0, z: 1), anchorB: SCNVector3(x: 0, y: 4, z: 0))

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

    }

    

    func createChocoball() {

        for i in 05 {

            let ball = SCNSphere(radius: 0.8)

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

            let ballNode = SCNNode(geometry: ball)

            ballNode.position = SCNVector3(x: (i%2 == 0) ? –0.8 : 0.8, y: Float(i) * 0.6, z: 0)

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

            

            ballNode.physicsBody = SCNPhysicsBody.dynamicBody()

        }

    }

    

    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) {

        self.turn = !self.turn

    }

    

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

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

        

        if self.turn {

            box?.physicsBody?.angularVelocity = SCNVector4(x: 0, y: 0, z: 1, w: 0.4)

        }

        

        if box?.presentationNode().rotation.w > 2.3 {

            box?.physicsBody?.angularVelocity = SCNVector4Zero

        }

    }

}