iPhoneぱずる3D

三角と四角のプレートをパズルっぽく並べるiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    weak var scene : SCNScene?

    weak var sceneView : SCNView?

    weak var selected : SCNNode?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        self.view.backgroundColor = UIColor.lightGrayColor()

        self.setupScene()

        self.createPlate()

        self.createPiece()

        self.createCamera()

    }

    func setupScene() {

        let w = CGRectGetMaxX(self.view.bounds)

        let sv = SCNView(frame: CGRect(x: 0, y: 0, width: w, height: w))

        sv.scene = SCNScene()

        sv.backgroundColor = UIColor.orangeColor()

        self.view.addSubview(sv)

        self.scene = sv.scene

        self.sceneView = sv

    }

    

    func createPlate() {

        let plate = SCNBox(width: 50, height: 1, length: 50, chamferRadius: 0)

        plate.firstMaterial?.diffuse.contents = UIColor.brownColor()

        let plateNode = SCNNode(geometry: plate)

        plateNode.name = “plate”

        plateNode.physicsBody = SCNPhysicsBody.staticBody()

        plateNode.physicsBody?.friction = 0.9;

        self.scene?.rootNode.addChildNode(plateNode)

    }

    

    func createPiece() {

        let triangle = UIBezierPath()

        triangle.moveToPoint(CGPointMake(-3, –3))

        triangle.addLineToPoint(CGPointMake(3, –3))

        triangle.addLineToPoint(CGPointMake(-3, 3))

        

        let a = SCNShape(path: triangle, extrusionDepth: 1.0)

        a.firstMaterial?.diffuse.contents = UIColor.redColor()

        let aNode = SCNNode(geometry: a)

        aNode.name = “piece”

        aNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: Float(M_PI)/2.0)

        aNode.position = SCNVector3(x: 0, y: 3, z: –10)

        aNode.physicsBody = SCNPhysicsBody.dynamicBody()

        aNode.physicsBody?.physicsShape = SCNPhysicsShape(geometry: a, options: [SCNPhysicsShapeTypeKey:SCNPhysicsShapeTypeConcavePolyhedron])

        self.scene?.rootNode.addChildNode(aNode)

        

        let b = SCNShape(path: triangle, extrusionDepth: 1.0)

        b.firstMaterial?.diffuse.contents = UIColor.blueColor()

        let bNode = SCNNode(geometry: a)

        bNode.name = “piece”

        bNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: Float(M_PI)/2.0)

        bNode.position = SCNVector3(x: 10, y: 3, z: 10)

        bNode.transform = SCNMatrix4Rotate(bNode.transform, Float(M_PI), 0, 1, 0)

        bNode.physicsBody = SCNPhysicsBody.dynamicBody()

        bNode.physicsBody?.physicsShape = SCNPhysicsShape(geometry: a, options: [SCNPhysicsShapeTypeKey:SCNPhysicsShapeTypeConcavePolyhedron])

        self.scene?.rootNode.addChildNode(bNode)

        

        let c = SCNBox(width: 10, height: 1, length: 6, chamferRadius: 0)

        c.firstMaterial?.diffuse.contents = UIColor.greenColor()

        let cNode = SCNNode(geometry: c)

        cNode.name = “piece”

        cNode.position = SCNVector3(x: 15, y: 3, z: –8)

        cNode.physicsBody = SCNPhysicsBody.dynamicBody()

        self.scene?.rootNode.addChildNode(cNode)

    }

    

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

        let p = touches.anyObject()!.locationInView(self.sceneView)

        let hits = self.sceneView?.hitTest(p, options: [SCNHitTestSortResultsKey:true])

        if hits?.count > 0 {

            let node = hits![0].node

            if node.name == “piece” {

                self.selected = node

                self.selected?.physicsBody?.velocityFactor = SCNVector3Zero

            }

        }

    }

    

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

        // plate position

        let p = touches.anyObject()!.locationInView(self.sceneView)

        if let hits = self.sceneView?.hitTest(p, options: [SCNHitTestSortResultsKey:true]) {

            for hit in hits {

                if hit.node.name == “plate” {

                    let p = hit.worldCoordinates

                    self.selected?.position = SCNVector3(x: p.x, y: p.y + 3, z: p.z)

                }

            }

        }

    }

    

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

        

        self.selected?.physicsBody?.velocityFactor = SCNVector3(x: 1, y: 1, z: 1)

        self.selected?.physicsBody?.velocity = SCNVector3Zero

        self.selected?.physicsBody?.applyForce(SCNVector3(x: 0, y: 1, z: 0), impulse: false)

        self.selected = nil

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

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

        camera.rotation = SCNVector4Make(1, 0, 0, –0.5)

        self.scene?.rootNode.addChildNode(camera)

    }

}