iPhone ツイスト紙

くるっとねじってリボンっぽくしたものを上から降らせるiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    weak var sceneView : SCNView?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        setupScene()

        createGround()

        createBuildings()

        createCamera()

    }

    func setupScene() {

        let sv = SCNView(frame: self.view.bounds)

        sv.backgroundColor = UIColor(hue: 0.6, saturation: 0.1, brightness: 0.9, alpha: 1)

        sv.scene = SCNScene()

        view.addSubview(sv)

        

        sceneView = sv

    }

    func createGround() {

        let box = SCNBox(width: 40, height: 1, length: 40, chamferRadius: 0)

        box.firstMaterial?.diffuse.contents = UIColor(hue: 0.6, saturation: 0.5, brightness: 0.4, alpha: 1)

        let ground = SCNNode(geometry: box)

        ground.physicsBody = SCNPhysicsBody.staticBody()

        sceneView?.scene?.rootNode.addChildNode(ground)

    }

    

    func createBuildings() {

        

        for i in 0..<20 {

            let w = arc4random_uniform(2) + 3

            let h = arc4random_uniform(8) + 1

            let saturation = CGFloat(arc4random_uniform(5)) * 0.1 + 0.2

            let box = SCNBox(width: CGFloat(w), height: CGFloat(h), length: 2, chamferRadius: 0)

            box.firstMaterial?.diffuse.contents = UIColor(hue: 0.6, saturation: saturation, brightness: 0.7, alpha: 1)

            

            let x = 4.0 * Float(i % 10) – 18.0

            let z = 10.0 * Float(i / 10) – 10.0 + Float(arc4random_uniform(10))

            let building = SCNNode(geometry: box)

            building.position = SCNVector3(x: x, y: 5, z: z)

            building.physicsBody = SCNPhysicsBody.dynamicBody()

            sceneView?.scene?.rootNode.addChildNode(building)

        }

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

        camera.position = SCNVector3(x: 0, y: 10, z: 50)

        sceneView?.scene?.rootNode.addChildNode(camera)

    }

    

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {

        createTwistPaper()

    }

    

    func createTwistPaper() {

        let paper = SCNNode()

        let x = Float(arc4random_uniform(30)) – 15

        let z = Float(arc4random_uniform(30)) – 15

        paper.position = SCNVector3(x: x, y: 30, z: z)

        sceneView?.scene?.rootNode.addChildNode(paper)

        

        var materials = [SCNMaterial]()

        for i in 0..<4 {

            materials.append(SCNMaterial())

            materials[i].diffuse.contents = UIColor(hue: 0, saturation: 0.2 + CGFloat(i) * 0.1, brightness: 1, alpha: 1)

        }

        

        let partA = SCNPyramid(width: 2, height: 3, length: 0.1)

        partA.materials = materials

        let partANode = SCNNode(geometry: partA)

        partANode.pivot = SCNMatrix4MakeTranslation(0, 2.5, 0)

        partANode.transform = SCNMatrix4Rotate(partANode.transform, Float(M_PI) * 0.5, 0, 0, 1)

        partANode.transform = SCNMatrix4Rotate(partANode.transform, Float(M_PI) * 1.3, 1, 0, 0)

        paper.addChildNode(partANode)

        

        let partB = partA.copy() as SCNPyramid

        let partBNode = SCNNode(geometry: partB)

        partBNode.pivot = SCNMatrix4MakeTranslation(0, 2.5, 0)

        partBNode.transform = SCNMatrix4Rotate(partBNode.transform, Float(M_PI) * –0.5, 0, 0, 1)

        partBNode.transform = SCNMatrix4Rotate(partBNode.transform, Float(M_PI) * 0.3, 1, 0, 0)

        paper.addChildNode(partBNode)

        paper.physicsBody = SCNPhysicsBody.dynamicBody()

        paper.physicsBody?.damping = 0.6

        paper.physicsBody?.applyTorque(SCNVector4Make(0, 1, 0, 3.14), impulse: true)

    }

}