
つり革を射的するiPhoneアプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
class ViewController: UIViewController, SCNPhysicsContactDelegate {
weak var sceneView : SCNView?
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
createStraps()
createCamera()
}
func setupScene() {
sceneView = {
let sv = SCNView(frame: self.view.bounds)
sv.scene = SCNScene()
sv.scene?.physicsWorld.contactDelegate = self
sv.backgroundColor = UIColor(hue: 0.3, saturation: 0.1, brightness: 1, alpha: 1)
sv.autoenablesDefaultLighting = true
self.view.addSubview(sv)
self.sceneView = sv
return sv
}()
}
func createStraps() {
[Int](-2…2).each {
let strap = SCNNode()
strap.name = “strap”
strap.position = SCNVector3(x: Float($0) * 8, y: 5, z: 0)
self.sceneView?.scene?.rootNode.addChildNode(strap)
let line = SCNBox(width: 1, height: 10, length: 1, chamferRadius: 0)
line.firstMaterial?.diffuse.contents = UIColor(hue: 0.13, saturation: 0.3, brightness: 1, alpha: 1)
let lineNode = SCNNode(geometry: line)
strap.addChildNode(lineNode)
let ball = SCNSphere(radius: 2)
ball.firstMaterial?.diffuse.contents = UIColor(white: 0.95, alpha: 1)
let ballNode = SCNNode(geometry: ball)
ballNode.name = “strap ball”
ballNode.position = SCNVector3(x: 0, y: –4, z: 0)
strap.addChildNode(ballNode)
strap.physicsBody = SCNPhysicsBody.dynamicBody()
strap.physicsBody?.physicsShape = SCNPhysicsShape(node: strap, options: [SCNPhysicsShapeTypeKey : SCNPhysicsShapeTypeConvexHull])
let joint = SCNPhysicsBallSocketJoint(body: strap.physicsBody, anchor: SCNVector3(x: 0, y: 4.5, z: 0))
self.sceneView?.scene?.physicsWorld.addBehavior(joint)
}
}
func createCamera() {
let camera = SCNNode()
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 0, y: 0, z: 60)
self.sceneView?.scene?.rootNode.addChildNode(camera)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let ball = SCNSphere(radius: 1)
let hue = CGFloat(arc4random_uniform(10)) * 0.1
ball.firstMaterial?.diffuse.contents = UIColor(hue: hue, saturation: 0.2, brightness: 1, alpha: 1)
let ballNode = SCNNode(geometry: ball)
ballNode.name = “ball”
ballNode.position = SCNVector3(x: 0, y: –20, z: 50)
ballNode.physicsBody = SCNPhysicsBody.dynamicBody()
self.sceneView?.scene?.rootNode.addChildNode(ballNode)
let p = touches.anyObject()!.locationInView(self.sceneView)
let x = (p.x – CGRectGetMidX(view.bounds)) * 0.1
ballNode.physicsBody?.applyForce(SCNVector3(x: Float(x), y: 25, z: –40), impulse: true)
}
func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) {
if (contact.nodeA.name == “ball”) && (contact.nodeB.name == “strap”) {
contact.nodeB.childNodeWithName(“strap ball”, recursively:false)!.geometry?.firstMaterial?.diffuse.contents = contact.nodeA.geometry?.firstMaterial?.diffuse.contents
}
else if (contact.nodeB.name == “ball”) && (contact.nodeA.name == “strap”) {
contact.nodeA.childNodeWithName(“strap ball”, recursively:false)!.geometry?.firstMaterial?.diffuse.contents = contact.nodeB.geometry?.firstMaterial?.diffuse.contents
}
}
}
extension Array {
func each(doit:(T) -> Void) { for i in self { doit(i) } }
}