
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 1…9 {
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 0…9 {
let x = (i % 5) * 5 – 10
let y = -(i / 5) * 5 – 20
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)}}
}