iPhoneイス迷路

イスを並べて迷路にしてみるiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController, SCNSceneRendererDelegate {

    weak var sceneView : SCNView?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createChars()

        createBall()

        createCamera()

    }

    

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

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

        sv.scene = SCNScene()

        sv.autoenablesDefaultLighting = true

        sv.allowsCameraControl = true

        sv.delegate = self

        view.addSubview(sv)

        

        sceneView = sv

    }

    func createChars() {

        for i in 024 {

            let x = Float(i % 5) – 2

            let z = Float(i / 5) – 2

            createChairAtPoint(SCNVector3(x: x, y: 0, z: z))

        }

    }

    

    func createChairAtPoint(p : SCNVector3) {

        let chair = SCNNode()

        chair.name = “chair”

        chair.position = p

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

        

        let hue = arc4random() % 10

        let color = UIColor(hue: CGFloat(hue) * 0.1, saturation: 0.3, brightness: 1, alpha: 1)

        

        let seat = SCNCylinder(radius: 0.5, height: 0.1)

        seat.firstMaterial?.diffuse.contents = color

        let seatNode = SCNNode(geometry: seat)

        chair.addChildNode(seatNode)

        

        for i in 03 {

            let x = 0.45 * cos(Float(M_PI) * 0.5 * Float(i) + Float(M_PI) * 0.25)

            let z = 0.45 * sin(Float(M_PI) * 0.5 * Float(i) + Float(M_PI) * 0.25)

            let leg = SCNBox(width: 0.1, height: 0.5, length: 0.1, chamferRadius: 0)

            leg.firstMaterial?.diffuse.contents = color

            let legNode = SCNNode(geometry: leg)

            legNode.position = SCNVector3(x: x, y: –0.25, z: z)

            chair.addChildNode(legNode)

        }

        

        let back = SCNBox(width: 0.7, height: 1, length: 0.1, chamferRadius: 0)

        back.firstMaterial?.diffuse.contents = color

        let backNode = SCNNode(geometry: back)

        backNode.position = SCNVector3(x: 0, y: 0.5, z: –0.4)

        chair.addChildNode(backNode)

        

        chair.physicsBody = SCNPhysicsBody.staticBody()

        chair.physicsBody?.restitution = 1

    }

    

    func createBall() {

        let ball = SCNSphere(radius: 0.3)

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

        let ballNode = SCNNode(geometry: ball)

        ballNode.name = “ball”

        ballNode.position = SCNVector3(x: –2, y: 0.36, z: 2)

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

        

        ballNode.physicsBody = SCNPhysicsBody.dynamicBody()

        ballNode.physicsBody?.restitution = 1

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

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

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

        camera.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –0.3 * Float(M_PI))

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

    }

    

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

        if let touch = touches.first as? UITouch {

            let p = touch.locationInView(self.sceneView)

            if let hit = self.sceneView?.hitTest(p, options: [SCNHitTestSortResultsKey : true])?.first as? SCNHitTestResult {

                if hit.node.parentNode!.name == “chair” {

                    hit.node.parentNode!.runAction(SCNAction.rotateByAngle(-CGFloat(M_PI) * 0.25, aroundAxis: SCNVector3(x: 0, y: 1, z: 0), duration: 0.25))

                } else if hit.node.name == “ball” {

                    hit.node.physicsBody?.applyForce(SCNVector3(x: 0, y: 0, z: –6), impulse: true)

                }

            }

        }

    }

    

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

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

            let v = ball.physicsBody!.velocity

            if abs(v.x) > abs(v.z) {

                ball.physicsBody?.velocity = SCNVector3(x: v.x, y: 0, z: 0)

            } else {

                ball.physicsBody?.velocity = SCNVector3(x: 0, y: 0, z: v.z)

            }

        }

    }

}