
影から階段がニョキニョキ出てくるiPhoneアプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
class ViewController: UIViewController, SCNPhysicsContactDelegate {
weak var sceneView : SCNView?
var start = false
var count = 2
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
create1F()
createWall()
createSteps()
createJumper()
}
func setupScene() {
let sv = SCNView(frame: view.bounds)
sv.backgroundColor = UIColor.darkGrayColor()
sv.scene = SCNScene()
sv.scene?.physicsWorld.contactDelegate = self
sv.allowsCameraControl = true
sv.autoenablesDefaultLighting = true
view.addSubview(sv)
sceneView = sv
}
func createWall() {
let wall = SCNBox(width: 10, height: 10, length: 0.1, chamferRadius: 0)
wall.firstMaterial?.diffuse.contents = UIColor.darkGrayColor()
let wallNode = SCNNode(geometry: wall)
wallNode.position = SCNVector3(x: 0, y: 5, z: –0.5)
sceneView?.scene?.rootNode.addChildNode(wallNode)
}
func create1F() {
let f = SCNBox(width: 10, height: 0.2, length: 2, chamferRadius: 0)
f.firstMaterial?.diffuse.contents = UIColor.whiteColor()
let fNode = SCNNode(geometry: f)
fNode.physicsBody = SCNPhysicsBody.staticBody()
sceneView?.scene?.rootNode.addChildNode(fNode)
}
func createSteps() {
for i in 0..<25 {
let x = ((i / 5) % 2) == 0 ? Float(i % 5) – 1 : 2 – Float(i % 5)
let y = Float(i / 5) * 2 + Float(i % 5) * 0.4
let step = SCNBox(width: 1, height: 0.1, length: 1, chamferRadius: 0)
step.firstMaterial?.diffuse.contents = UIColor.whiteColor()
let stepNode = SCNNode(geometry: step)
stepNode.name = “step \(i)”
stepNode.position = SCNVector3(x: Float(x), y: Float(y), z: 0)
stepNode.physicsBody = SCNPhysicsBody.staticBody()
sceneView?.scene?.rootNode.addChildNode(stepNode)
}
}
func createJumper() {
let jumper = SCNBox(width: 0.4, height: 0.4, length: 0.4, chamferRadius: 0.05)
jumper.firstMaterial?.diffuse.contents = UIColor(hue: 0.1, saturation: 0.3, brightness: 1, alpha: 1)
let jumperNode = SCNNode(geometry: jumper)
jumperNode.name = “jumper”
jumperNode.position = SCNVector3(x: –1, y: 1, z: 0)
jumperNode.physicsBody = SCNPhysicsBody.dynamicBody()
jumperNode.physicsBody?.friction = 0.9
sceneView?.scene?.rootNode.addChildNode(jumperNode)
}
func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) {
let step = [contact.nodeA, contact.nodeB]
.filter {
($0 as SCNNode).name == “step \(self.count – 1)”
}
if step.count > 0 {
if let nextStep = sceneView?.scene?.rootNode.childNodeWithName(“step \(self.count)”, recursively: false) {
nextStep.runAction(SCNAction.sequence([SCNAction.waitForDuration(NSTimeInterval(0.2)) , SCNAction.moveTo(SCNVector3(x: nextStep.position.x, y: nextStep.position.y, z: 0), duration: 0.2)]))
++self.count
}
}
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if !start {
start = true
self.sceneView?.scene?.rootNode.childNodes
.filter {
if let check = ($0 as! SCNNode).name?.hasPrefix(“step”) { return check }
return false
}
.each { n -> Void in
if let n = n as? SCNNode {
var delay = 0.0
if let num = n.name?.componentsSeparatedByString(” “)[1].toInt() {
if num < 2 { return }
delay = Double(num) * 0.2
}
n.runAction(SCNAction.sequence([SCNAction.waitForDuration(NSTimeInterval(delay)) , SCNAction.moveByX(0, y: 0, z: –1, duration: 0.5)]))
}
}
return;
}
// jump
if let jump = sceneView?.scene?.rootNode.childNodeWithName(“jumper”, recursively: false) {
if ((self.count – 1) / 5) % 2 == 0 {
jump.physicsBody?.applyForce(SCNVector3(x: 1.6, y: 4, z: 0), impulse: true)
} else {
jump.physicsBody?.applyForce(SCNVector3(x: –1.6, y: 4, z: 0), impulse: true)
}
}
}
}
extension Array {
func each(doit:T -> Void) { for i in self { doit(i) } }
}