
銛をなげて獲物を狙うiPhoneアプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
class ViewController: UIViewController {
weak var sceneView : SCNView?
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
createBalls()
createHarpoon()
createCamera()
}
func setupScene() {
let sv = SCNView(frame: view.bounds)
sv.scene = SCNScene()
view.addSubview(sv)
sceneView = sv
}
func createBalls() {
[Int](0…10).each { i in
let ball = SCNSphere(radius: 1)
ball.firstMaterial?.diffuse.contents = UIColor(hue: 0.1 * CGFloat(i), saturation: 0.4, brightness: 1, alpha: 1)
let ballNode = SCNNode(geometry: ball)
ballNode.position = {
let x = 10 – Float(i % 5) * 5
let y = 12.5 – Float(i / 5) * 5
let z = Float(arc4random_uniform(20))
return SCNVector3(x: x, y: y, z: z)
}()
ballNode.physicsBody = SCNPhysicsBody.dynamicBody()
ballNode.physicsBody?.velocityFactor = SCNVector3(x: 1, y: 0, z: 1)
self.sceneView?.scene?.rootNode.addChildNode(ballNode)
}
}
func createHarpoon() {
let harpoon = SCNBox(width: 1, height: 1, length: 4, chamferRadius: 0)
harpoon.firstMaterial?.diffuse.contents = UIColor.darkGrayColor()
let harpoonNode = SCNNode(geometry: harpoon)
harpoonNode.name = “harpoon”
harpoonNode.position = SCNVector3(x: 0, y: 0, z: 45)
harpoonNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: 0.4)
sceneView?.scene?.rootNode.addChildNode(harpoonNode)
let pointer = SCNBox(width: 2, height: 2, length: 2, chamferRadius: 0)
pointer.firstMaterial?.diffuse.contents = UIColor(hue: 0, saturation: 0.2, brightness: 1, alpha: 0.7)
let pointerNode = SCNNode(geometry: pointer)
pointerNode.name = “pointer”
pointerNode.position = SCNVector3(x: 0, y: 10, z: 0)
sceneView?.scene?.rootNode.addChildNode(pointerNode)
harpoonNode.constraints = [SCNLookAtConstraint(target: pointerNode)]
}
func createCamera() {
let camera = SCNNode()
camera.camera = SCNCamera()
camera.camera?.zFar = 300
camera.position = SCNVector3(x: 0, y: 0, z: 55)
sceneView?.scene?.rootNode.addChildNode(camera)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
touchesMoved(touches, withEvent: event)
}
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
if let pointer = self.sceneView?.scene?.rootNode.childNodeWithName(“pointer”, recursively: false) {
let lp = touches.anyObject()!.locationInView(self.sceneView)
let p = self.sceneView!.unprojectPoint(SCNVector3(x: Float(lp.x), y: Float(lp.y), z: 0.98))
pointer.position = p
}
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
if let harpoon = sceneView?.scene?.rootNode.childNodeWithName(“harpoon”, recursively: false) {
let tmp = harpoon.presentationNode().transform
harpoon.constraints = nil
harpoon.transform = tmp
harpoon.physicsBody = SCNPhysicsBody.dynamicBody()
let v = self.sceneView!.scene!.rootNode.childNodeWithName(“pointer”, recursively: false)!.position
let dv = SCNVector3(x: v.x – harpoon.position.x, y: v.y – harpoon.position.y, z: -(harpoon.position.z – v.z))
harpoon.physicsBody?.applyForce(dv, impulse: true)
func delay(delay:Double, doit:() -> Void) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), doit)
}
delay(2.0) {
harpoon.removeFromParentNode()
self.sceneView?.scene?.rootNode.childNodeWithName(“pointer”, recursively: false)?.removeFromParentNode()
self.createHarpoon()
}
}
}
}
extension Array {
func each(doit:T -> Void) { for i in self {doit(i) }}
}