ボールがリングの上をぐるっと回るのをカメラで追いかけるiPhoneアプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
class ViewController: UIViewController {
weak var sceneView : SCNView?
var count = 0
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
createCircle()
createRunner()
createCamera()
}
func setupScene() {
let sv = SCNView(frame: self.view.bounds)
sv.backgroundColor = UIColor(white: 0.2, alpha: 1)
sv.scene = SCNScene()
view.addSubview(sv)
sv.autoenablesDefaultLighting = true
sceneView = sv
}
func createCircle() {
let tube = SCNTube(innerRadius: 30, outerRadius: 38, height: 0.5)
tube.firstMaterial?.diffuse.contents = UIColor(hue: 0.2, saturation: 0.6, brightness: 1, alpha: 1)
tube.firstMaterial?.specular.contents = UIColor(hue: 0.5, saturation: 0.1, brightness: 1, alpha: 1)
let tubeNode = SCNNode(geometry: tube)
tubeNode.name = “tube”
sceneView?.scene?.rootNode.addChildNode(tubeNode)
let angle = Float(M_PI) / 6.0
for i in 0..<12 {
let x = 34 * cos(angle * Float(i))
let z = 34 * sin(angle * Float(i))
let disk = SCNCylinder(radius: 3.5, height: 0.1)
disk.firstMaterial?.diffuse.contents = UIColor(hue: 0.25, saturation: 0.2, brightness: 1, alpha: 1)
let diskNode = SCNNode(geometry: disk)
diskNode.name = “disk\(i)“
diskNode.position = SCNVector3(x: x, y: 0.3, z: z)
sceneView?.scene?.rootNode.addChildNode(diskNode)
}
}
func createRunner() {
count = 0
let runner = SCNSphere(radius: 3)
runner.firstMaterial?.diffuse.contents = UIColor(hue: 0.4, saturation: 0.3, brightness: 1, alpha: 1)
let runnerNode = SCNNode(geometry: runner)
runnerNode.name = “runner”
if let position = sceneView?.scene?.rootNode.childNodeWithName(“disk\(count)“, recursively: false)?.position {
runnerNode.position = SCNVector3(x:position.x, y:3.25, z:position.z)
}
sceneView?.scene?.rootNode.addChildNode(runnerNode)
}
func createCamera() {
let camera = SCNNode()
camera.name = “camera”
camera.camera = SCNCamera()
camera.camera?.zFar = 300
camera.position = SCNVector3(x: 0, y: 40, z: 80)
camera.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –0.4)
if let runner = sceneView?.scene?.rootNode.childNodeWithName(“runner”, recursively: false) {
let con = SCNLookAtConstraint(target: runner)
con.influenceFactor = 0.4
camera.constraints = [con]
}
sceneView?.scene?.rootNode.addChildNode(camera)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
count = (count + 1) % 12
let camera = sceneView?.scene?.rootNode.childNodeWithName(“camera”, recursively: false)
let runner = sceneView?.scene?.rootNode.childNodeWithName(“runner”, recursively: false)
if let position = sceneView?.scene?.rootNode.childNodeWithName(“disk\(count)“, recursively: false)?.position {
runner?.runAction(SCNAction.moveTo(SCNVector3(x:position.x, y:3.25, z:position.z), duration: 0.4))
}
}
}