
クルクル回ってる矢印をとめた方向に箱がジャンプするiPhone アプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
class ViewController: UIViewController {
weak var sceneView : SCNView?
var indicatorArr : Array<SCNNode> = []
var jump : Array<SCNVector4> = []
var ready = true
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
createPond()
createStone()
createCamera()
createPlayer()
createIndicator()
}
func setupScene() {
let sv = SCNView(frame: view.bounds)
sv.backgroundColor = UIColor(hue: 0.25, saturation: 0.1, brightness: 1, alpha: 1)
sv.scene = SCNScene()
sv.allowsCameraControl = true
sv.autoenablesDefaultLighting = true
view.addSubview(sv)
sceneView = sv
}
func createPond() {
let pond = SCNCylinder(radius: 5, height: 1)
pond.firstMaterial?.diffuse.contents = UIColor(hue: 0.55, saturation: 0.4, brightness: 1, alpha: 0.8)
let pondNode = SCNNode(geometry: pond)
sceneView?.scene?.rootNode.addChildNode(pondNode)
}
func createStone() {
let points : Array<SCNVector3> = [
SCNVector3(x: –2, y: 0.5, z: –4),
SCNVector3(x: 2, y: 0.5, z: –1),
SCNVector3(x: 0, y: 0.5, z: –2),
SCNVector3(x: –1, y: 0.5, z: 0),
SCNVector3(x: 0, y: 0.5, z: 2),
SCNVector3(x: –2, y: 0.5, z: 4),
SCNVector3(x: 2, y: 0.5, z: 4)
]
for p in points {
let stone = SCNCylinder(radius: 1, height: 0.2)
stone.firstMaterial?.diffuse.contents = UIColor.lightGrayColor()
let stoneNode = SCNNode(geometry: stone)
stoneNode.position = p
sceneView?.scene?.rootNode.addChildNode(stoneNode)
stoneNode.physicsBody = SCNPhysicsBody.staticBody()
stoneNode.physicsBody?.restitution = 0
stoneNode.physicsBody?.friction = 1.0
}
}
func createPlayer() {
let player = SCNBox(width: 0.5, height: 0.5, length: 0.5, chamferRadius: 0.1)
player.firstMaterial?.diffuse.contents = UIColor.yellowColor()
let playerNode = SCNNode(geometry: player)
playerNode.name = “player”
playerNode.position = SCNVector3(x: 2, y: 2, z: 4)
sceneView?.scene?.rootNode.addChildNode(playerNode)
playerNode.physicsBody = SCNPhysicsBody.dynamicBody()
playerNode.physicsBody?.angularVelocityFactor = SCNVector3Make(0, 1, 0)
playerNode.physicsBody?.friction = 1.0
playerNode.physicsBody?.restitution = 0
playerNode.physicsBody?.angularDamping = 1.0
playerNode.physicsBody?.mass = 0.3
}
func createCamera() {
let camera = SCNNode()
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 0, y: 3, z: 11)
camera.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –0.3)
sceneView?.scene?.rootNode.addChildNode(camera)
}
func createIndicator() {
for i in 0…3 {
let indicator = SCNNode()
indicator.position = SCNVector3(x: 0, y: Float(i) * 0.1, z: 7)
sceneView?.scene?.rootNode.addChildNode(indicator)
let top = SCNPyramid(width: 0.5, height: 0.5, length: 0.1)
top.firstMaterial?.diffuse.contents = UIColor(hue: CGFloat(i) * 0.1, saturation: 0.4, brightness: 1, alpha: 1)
let topNode = SCNNode(geometry: top)
topNode.name = “top”
topNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –Float(M_PI) * 0.5)
topNode.position = SCNVector3(x: 0, y: 0, z: –0.8)
indicator.addChildNode(topNode)
let bar = SCNBox(width: 0.2, height: 0.05, length: 0.8, chamferRadius: 0)
bar.firstMaterial?.diffuse.contents = UIColor(hue: CGFloat(i) * 0.1, saturation: 0.4, brightness: 1, alpha: 1)
let barNode = SCNNode(geometry: bar)
barNode.position = SCNVector3(x: 0, y: 0, z: –0.5)
indicator.addChildNode(barNode)
indicator.runAction(SCNAction.repeatActionForever(SCNAction.rotateByAngle(CGFloat(M_PI), aroundAxis: SCNVector3(x: 0, y: 1, z: 0), duration: 1.0)))
indicatorArr.append(indicator)
}
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if let indicator = indicatorArr.last {
jump.append(indicator.rotation)
indicator.removeAllActions()
indicatorArr.removeLast()
} else if ready == true {
ready = false
let player = sceneView?.scene?.rootNode.childNodeWithName(“player”, recursively: false)
for (i, r) in enumerate(jump) {
let w = r.w * r.y
let x = –sin(w)
let z = –cos(w)
delay(Double(i)) {
player?.physicsBody?.applyForce(SCNVector3(x: x, y: 1.1, z: z), impulse: 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)
}
}