
ボウルのなかにボールをどんどんいれていくiPhoneアプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
class ViewController: UIViewController {
weak var scene : SCNScene?
weak var sceneView : SCNView?
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(hue: 0.75, saturation: 0.3, brightness: 1, alpha: 1)
self.setupScene()
self.createBowl()
self.createCamera()
self.createLight()
self.createTargetSight()
}
func setupScene() {
let w = CGRectGetMaxX(self.view.bounds)
let sv = SCNView(frame: CGRect(x: 0, y: 0, width: w, height: w))
sv.backgroundColor = UIColor(hue: 0.85, saturation: 0.3, brightness: 1, alpha: 1)
sv.scene = SCNScene()
self.view.addSubview(sv)
self.scene = sv.scene
self.sceneView = sv
}
func createBowl() {
let bowl = SCNNode()
bowl.runAction(SCNAction.rotateByAngle(–1.6, aroundAxis: SCNVector3(x: 0, y: 1, z: 0), duration: 20.0))
self.scene?.rootNode.addChildNode(bowl)
let dAngle : Float = Float(M_PI) / 20.0
for t in 0..<10 {
for p in 0..<40 {
let box = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)
box.firstMaterial?.diffuse.contents = UIColor(hue: 0.6, saturation: 0.3, brightness: 1, alpha: 1)
let boxNode = SCNNode(geometry: box)
boxNode.position = self.sphericalCoordinate(Float(t) * dAngle + Float(M_PI/2.0), phi: Float(p) * dAngle, r: 10)
bowl.addChildNode(boxNode)
boxNode.physicsBody = SCNPhysicsBody.staticBody()
}
}
}
func createCamera() {
let camera = SCNNode()
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 0, y: 5, z: 30)
self.scene?.rootNode.addChildNode(camera)
}
func createLight() {
let light = SCNLight()
light.type = SCNLightTypeSpot
let lightNode = SCNNode()
lightNode.light = light
lightNode.position = SCNVector3(x: 0, y: 10, z: 80)
self.scene?.rootNode.addChildNode(lightNode)
}
func createTargetSight() {
let r = CGRectGetMaxX(self.view.bounds) * 0.3
let path = UIBezierPath()
for i in 0..<4 {
let start = CGFloat(i) * CGFloat(M_PI/2.0) – CGFloat(M_PI) / 6.0
let end = start + CGFloat(M_PI/3.0)
path.appendPath(UIBezierPath(arcCenter: CGPointZero, radius:r, startAngle:start, endAngle:end , clockwise: true))
}
let target = CAShapeLayer()
target.position = CGPoint(x: CGRectGetMidX(self.view.bounds), y: CGRectGetMaxY(self.view.bounds) * 3.0/4.0)
target.fillColor = UIColor.yellowColor().CGColor
target.path = path.CGPath
self.view.layer.addSublayer(target)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let p0 = touches.anyObject()!.locationInView(self.view)
let p = CGPoint(x: p0.x, y: p0.y – CGRectGetMidY(self.view.bounds))
let mark = UIView(frame: CGRectMake(0, 0, 6, 6))
mark.backgroundColor = UIColor.clearColor()
mark.layer.borderWidth = 2
mark.layer.borderColor = UIColor.blackColor().CGColor
mark.center = p0
self.view.addSubview(mark)
let o = self.sceneView!.projectPoint(SCNVector3Zero)
let p3 = self.sceneView!.unprojectPoint(SCNVector3(x: Float(p.x), y: Float(p.y), z: o.z))
let ball = SCNSphere(radius: 3)
let hue = CGFloat(arc4random() % 10) * 0.1
ball.firstMaterial?.diffuse.contents = UIColor(hue: hue, saturation: 0.3, brightness: 1, alpha: 1)
let ballNode = SCNNode(geometry: ball)
ballNode.position = SCNVector3(x: p3.x, y: 15, z: -p3.y/2.0)
self.scene?.rootNode.addChildNode(ballNode)
ballNode.physicsBody = SCNPhysicsBody.dynamicBody()
}
func sphericalCoordinate(theta:Float, phi:Float, r:Float) -> SCNVector3 {
let x = r * sin(theta) * cos(phi)
let z = r * sin(theta) * sin(phi)
let y = r * cos(theta)
return SCNVector3(x: x, y: y, z: z)
}
}