iPhoneつり革射的

つり革を射的するiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController, SCNPhysicsContactDelegate {

    weak var sceneView : SCNView?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createStraps()

        createCamera()

    }

    

    func setupScene() {

        sceneView = {

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

            sv.scene = SCNScene()

            sv.scene?.physicsWorld.contactDelegate = self

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

            sv.autoenablesDefaultLighting = true

            self.view.addSubview(sv)

            

            self.sceneView = sv

            return sv

        }()

    }

    

    func createStraps() {

        [Int](-22).each {

            let strap = SCNNode()

            strap.name = “strap”

            strap.position = SCNVector3(x: Float($0) * 8, y: 5, z: 0)

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

            

            let line = SCNBox(width: 1, height: 10, length: 1, chamferRadius: 0)

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

            let lineNode = SCNNode(geometry: line)

            strap.addChildNode(lineNode)

            

            let ball = SCNSphere(radius: 2)

            ball.firstMaterial?.diffuse.contents = UIColor(white: 0.95, alpha: 1)

            let ballNode = SCNNode(geometry: ball)

            ballNode.name = “strap ball”

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

            strap.addChildNode(ballNode)

            

            strap.physicsBody = SCNPhysicsBody.dynamicBody()

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

            

            let joint = SCNPhysicsBallSocketJoint(body: strap.physicsBody, anchor: SCNVector3(x: 0, y: 4.5, z: 0))

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

        }

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

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

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

    }

    

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

        let ball = SCNSphere(radius: 1)

        let hue = CGFloat(arc4random_uniform(10)) * 0.1

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

        let ballNode = SCNNode(geometry: ball)

        ballNode.name = “ball”

        ballNode.position = SCNVector3(x: 0, y: –20, z: 50)

        ballNode.physicsBody = SCNPhysicsBody.dynamicBody()

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

        

        let p = touches.anyObject()!.locationInView(self.sceneView)

        let x = (p.x CGRectGetMidX(view.bounds)) * 0.1

        ballNode.physicsBody?.applyForce(SCNVector3(x: Float(x), y: 25, z: –40), impulse: true)

    }

    

    func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) {

        if (contact.nodeA.name == “ball”) && (contact.nodeB.name == “strap”) {

            contact.nodeB.childNodeWithName(“strap ball”, recursively:false)!.geometry?.firstMaterial?.diffuse.contents = contact.nodeA.geometry?.firstMaterial?.diffuse.contents

        }

        else if (contact.nodeB.name == “ball”) && (contact.nodeA.name == “strap”) {

            contact.nodeA.childNodeWithName(“strap ball”, recursively:false)!.geometry?.firstMaterial?.diffuse.contents = contact.nodeB.geometry?.firstMaterial?.diffuse.contents

        }

    }

}

extension Array {

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

}