iPhone10までの足し算

10までの足し算を上段5、下段5のマスをタッチして答えていくiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    

    weak var sceneView : SCNView?

    var tenBox : Array<SCNNode> = []

    var questions : Array<(Int, Int)> = []

    var a = 0, b = 10;

    var touchEnable = true

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        setupQuestion()

        createQuestion()

        createTenSquare()

        createCamera()

    }

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

        sv.scene = SCNScene()

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

        view.addSubview(sv)

        

        sceneView = sv

    }

    

    func setupQuestion() {

        for i in 19 {

            for var j=0; j+i<10; j++ {

                questions.append((Int(i), Int(j)))

            }

        }

        questions.sort {_,_ in return (arc4random() % 2) == 0 }

    }

    

    func createQuestion() {

        

        if questions.count == 0 {

            let alert = UIAlertView()

            alert.title = “Clear”

            alert.message = “Game over”

            alert.addButtonWithTitle(“OK”)

            alert.show()

        }

        

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

            old.runAction(SCNAction .rotateToX(-CGFloat(M_PI) * 0.5, y: 0, z: 0, duration: 0.5), completionHandler: { () -> Void in

                old.removeFromParentNode()

            })

        }

        

        let question = questions.removeLast()

        a = question.0

        b = question.1

        

        let q = SCNText(string: \(a) + \(b)”, extrusionDepth: 0.1)

        q.firstMaterial?.diffuse.contents = UIColor.whiteColor()

        q.alignmentMode = kCAAlignmentCenter

        q.flatness = 0.01

        let qNode = SCNNode(geometry: q)

        qNode.name = “question”

        // centering scntext

        var p = SCNVector3Zero

        var r : CGFloat = 0

        qNode.getBoundingSphereCenter(&p, radius: &r)

        qNode.pivot = SCNMatrix4MakeTranslation(p.x, 0, –20)

        

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

    }

    

    func createTenSquare() {

        

        

        let m1 = SCNMaterial()

        m1.diffuse.contents = UIColor.whiteColor()

        let m2 = SCNMaterial()

        m2.diffuse.contents = UIColor.redColor()

        

        for i in 09 {

            let x = (i % 5) * 510

            let y = -(i / 5) * 520

            let b = SCNBox(width: 4.5, height: 4.5, length: 0.2, chamferRadius: 0)

            b.materials = [m1, m2, m2]

            let bNode = SCNNode(geometry: b)

            bNode.name = “box \(i + 1)”

            bNode.position = SCNVector3(x: Float(x), y: Float(y), z: 0)

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

            

            self.tenBox.append(bNode)

        }

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

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

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

    }

    

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

        

        if !touchEnable {

            return

        }

        

        if let t = touches.first as? UITouch {

            let p = t.locationInView(self.sceneView)

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

                if hit.node.name?.componentsSeparatedByString(” “)[0] == “box” {

                    

                    touchEnable = false

                    

                    self.tenBox.each { n in n.runAction(SCNAction.rotateToX(0, y: 0, z: 0, duration: 0.1)) }

                    

                    let n = hit.node.name?.componentsSeparatedByString(” “)[1].toInt() as Int!

                    for i in 0..<n {

                        self.tenBox[i].runAction(SCNAction.sequence([SCNAction.waitForDuration(0.02 * NSTimeInterval(i) + 0.11), SCNAction.rotateToX(CGFloat(M_PI), y: 0, z: 0, duration: 0.1)]))

                    }

                    

                    // check answer

                    let ans = self.a + self.b

                    if ans == n {

                        delay(Double(n) * 0.02 + 0.2) {

                            self.createQuestion()

                            self.tenBox.each { n in n.runAction(SCNAction.rotateToX(0, y: 0, z: 0, duration: 0.1)) }

                            self.touchEnable = true

                        }

                    } else {

                        self.touchEnable = 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)

    }

}

extension Array {

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

}