iPhone銛

銛をなげて獲物を狙うiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    

    weak var sceneView : SCNView?

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createBalls()

        createHarpoon()

        createCamera()

    }

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

        sv.scene = SCNScene()

        view.addSubview(sv)

        

        sceneView = sv

    }

    

    func createBalls() {

        [Int](010).each { i in

            let ball = SCNSphere(radius: 1)

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

            let ballNode = SCNNode(geometry: ball)

            ballNode.position = {

                let x = 10Float(i % 5) * 5

                let y = 12.5Float(i / 5) * 5

                let z = Float(arc4random_uniform(20))

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

            }()

            ballNode.physicsBody = SCNPhysicsBody.dynamicBody()

            ballNode.physicsBody?.velocityFactor = SCNVector3(x: 1, y: 0, z: 1)

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

        }

    }

    

    func createHarpoon() {

        let harpoon = SCNBox(width: 1, height: 1, length: 4, chamferRadius: 0)

        harpoon.firstMaterial?.diffuse.contents = UIColor.darkGrayColor()

        let harpoonNode = SCNNode(geometry: harpoon)

        harpoonNode.name = “harpoon”

        harpoonNode.position = SCNVector3(x: 0, y: 0, z: 45)

        harpoonNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: 0.4)

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

        

        let pointer = SCNBox(width: 2, height: 2, length: 2, chamferRadius: 0)

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

        let pointerNode = SCNNode(geometry: pointer)

        pointerNode.name = “pointer”

        pointerNode.position = SCNVector3(x: 0, y: 10, z: 0)

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

        

        harpoonNode.constraints = [SCNLookAtConstraint(target: pointerNode)]

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

        camera.camera?.zFar = 300

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

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

    }

    

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

        touchesMoved(touches, withEvent: event)

    }

    

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

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

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

            let p = self.sceneView!.unprojectPoint(SCNVector3(x: Float(lp.x), y: Float(lp.y), z: 0.98))

            pointer.position = p

        }

    }

    

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

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

            

            let tmp = harpoon.presentationNode().transform

            harpoon.constraints = nil

            harpoon.transform = tmp

            

            harpoon.physicsBody = SCNPhysicsBody.dynamicBody()

            let v = self.sceneView!.scene!.rootNode.childNodeWithName(“pointer”, recursively: false)!.position

            let dv = SCNVector3(x: v.x – harpoon.position.x, y: v.y – harpoon.position.y, z: -(harpoon.position.z – v.z))

            harpoon.physicsBody?.applyForce(dv, impulse: true)

            

            func delay(delay:Double, doit:() -> Void) {

                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), doit)

            }

            

            delay(2.0) {

                harpoon.removeFromParentNode()

                self.sceneView?.scene?.rootNode.childNodeWithName(“pointer”, recursively: false)?.removeFromParentNode()

                self.createHarpoon()

            }

        }

    }

}

extension Array {

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

}