iPhone 矢印ジャンプ

クルクル回ってる矢印をとめた方向に箱がジャンプするiPhone アプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    weak var sceneView : SCNView?

    var indicatorArr : Array<SCNNode> = []

    var jump : Array<SCNVector4> = []

    var ready = true

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createPond()

        createStone()

        createCamera()

        createPlayer()

        createIndicator()

    }

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

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

        sv.scene = SCNScene()

        sv.allowsCameraControl = true

        sv.autoenablesDefaultLighting = true

        view.addSubview(sv)

                

        sceneView = sv

    }

    

    func createPond() {

        let pond = SCNCylinder(radius: 5, height: 1)

        pond.firstMaterial?.diffuse.contents = UIColor(hue: 0.55, saturation: 0.4, brightness: 1, alpha: 0.8)

        let pondNode = SCNNode(geometry: pond)

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

    }

    

    func createStone() {

        let points : Array<SCNVector3> = [

            SCNVector3(x: –2, y: 0.5, z: –4),

            SCNVector3(x:  2, y: 0.5, z: –1),

            SCNVector3(x:  0, y: 0.5, z: –2),

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

            SCNVector3(x:  0, y: 0.5, z: 2),

            SCNVector3(x: –2, y: 0.5, z: 4),

            SCNVector3(x:  2, y: 0.5, z: 4)

        ]

        

        for p in points {

            let stone = SCNCylinder(radius: 1, height: 0.2)

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

            let stoneNode = SCNNode(geometry: stone)

            stoneNode.position = p

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

            stoneNode.physicsBody = SCNPhysicsBody.staticBody()

            stoneNode.physicsBody?.restitution = 0

            stoneNode.physicsBody?.friction = 1.0

        }

    }

    

    func createPlayer() {

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

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

        let playerNode = SCNNode(geometry: player)

        playerNode.name = “player”

        playerNode.position = SCNVector3(x:  2, y: 2, z: 4)

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

        playerNode.physicsBody = SCNPhysicsBody.dynamicBody()

        playerNode.physicsBody?.angularVelocityFactor = SCNVector3Make(0, 1, 0)

        playerNode.physicsBody?.friction = 1.0

        playerNode.physicsBody?.restitution = 0

        playerNode.physicsBody?.angularDamping = 1.0

        playerNode.physicsBody?.mass = 0.3

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

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

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

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

    }

    

    func createIndicator() {

        

        for i in 03 {

            let indicator = SCNNode()

            indicator.position = SCNVector3(x: 0, y: Float(i) * 0.1, z: 7)

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

            

            let top = SCNPyramid(width: 0.5, height: 0.5, length: 0.1)

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

            let topNode = SCNNode(geometry: top)

            topNode.name = “top”

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

            topNode.position = SCNVector3(x: 0, y: 0, z: –0.8)

            indicator.addChildNode(topNode)

            

            let bar = SCNBox(width: 0.2, height: 0.05, length: 0.8, chamferRadius: 0)

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

            let barNode = SCNNode(geometry: bar)

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

            indicator.addChildNode(barNode)

            

            indicator.runAction(SCNAction.repeatActionForever(SCNAction.rotateByAngle(CGFloat(M_PI), aroundAxis: SCNVector3(x: 0, y: 1, z: 0), duration: 1.0)))

            

            indicatorArr.append(indicator)

        }

    }

    

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

        

        if let indicator = indicatorArr.last {

            jump.append(indicator.rotation)

            indicator.removeAllActions()

            indicatorArr.removeLast()

            

        } else if ready == true {

            ready = false

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

            for (i, r) in enumerate(jump) {

                let w = r.w * r.y

                let x = –sin(w)

                let z = –cos(w)

                delay(Double(i)) {

                    player?.physicsBody?.applyForce(SCNVector3(x: x, y: 1.1, z: z), impulse: true)

                }

            }

        }

    }

    

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

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

    }

}