iPhoneドームパズル

ドームの青くなっている部分をタッチしてバラバラにするiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SceneKit;

@interface ViewController ()

@property (nonatomic, weak) SCNView *sceneView;

@property (nonatomic) NSUInteger count;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    [self createDome];

    [self createLight];

}

– (void)setupScene {

    SCNView *sv = [[SCNView alloc] initWithFrame:self.view.bounds];

    sv.backgroundColor = [self color:0];

    sv.scene = [SCNScene scene];

    sv.allowsCameraControl = YES;

    [self.view addSubview:sv];

    

    self.sceneView = sv;

}

– (void)createDome {

    

    int rand = arc4random_uniform(40) + 5;

    

    for (int i=0; i<10; i++) {

        for (int j=0; j<5; j++) {

            

            float th = j * (M_PI / 10.0) – M_PI / 2.0;

            float ph = i * (M_PI / 5.0);

            SCNVector3 v0 = [self sphericalCoordinateTheta:th phi:ph r:3];

            

            th = j * (M_PI / 10.0) – M_PI / 2.0;

            ph = (i + 1) * (M_PI / 5.0);

            SCNVector3 v1 = [self sphericalCoordinateTheta:th phi:ph r:3];

            

            th = (j + 1) * (M_PI / 10.0) – M_PI / 2.0;

            ph = i * (M_PI / 5.0);

            SCNVector3 v2 = [self sphericalCoordinateTheta:th phi:ph r:3];

            

            th = (j + 1) * (M_PI / 10.0) – M_PI / 2.0;

            ph = (i + 1) * (M_PI / 5.0);

            SCNVector3 v3 = [self sphericalCoordinateTheta:th phi:ph r:3];

            

            SCNVector3 vx[] = {v0, v1, v2, v3};

            UInt32 indices[] = {0, 1, 2, 1, 3, 2};

            SCNGeometrySource *source = [SCNGeometrySource geometrySourceWithVertices:vx count:4];

            SCNGeometryElement *element = [SCNGeometryElement geometryElementWithData:[NSData dataWithBytes:indices length:sizeof(UInt32) * 6.0 ] primitiveType:SCNGeometryPrimitiveTypeTriangles primitiveCount:2 bytesPerIndex:sizeof(UInt32)];

            

            SCNVector3 cross = [self crossProductA:SCNVector3Make(v1.x – v0.x, v1.y – v0.y, v1.z – v0.z) b:SCNVector3Make(v2.x – v0.x, v2.y – v0.y, v2.z – v0.z)];

            SCNVector3 n[] = {cross, cross, cross, cross};

            SCNGeometrySource *normalSource = [SCNGeometrySource geometrySourceWithNormals:n count:4];

            SCNGeometry *geo = [SCNGeometry geometryWithSources:@[source, normalSource] elements:@[element]];

            

            if (rand == i + 10 * j) {

                geo.firstMaterial.diffuse.contents = [self color:2];

                geo.firstMaterial.specular.contents = [self color:2];

            } else {

                geo.firstMaterial.diffuse.contents = [self color:3];

                geo.firstMaterial.specular.contents = [self color:3];

            }

            geo.firstMaterial.doubleSided = YES;

            SCNNode *panel = [SCNNode nodeWithGeometry:geo];

            [self.sceneView.scene.rootNode addChildNode:panel];

            

            if (rand == i + 10 * j) {

                panel.name = @”blue”;

            } else {

                panel.name = @”panel”;

            }

        }

    }

}

– (void)createLight {

    SCNNode *node = [SCNNode node];

    node.light = [SCNLight light];

    node.light.color = [UIColor lightGrayColor];

    node.light.type = SCNLightTypeSpot;

    node.position = SCNVector3Make(0, 1000, 0);

    node.rotation = SCNVector4Make(1, 0, 0, –M_PI * 0.5);

    [self.sceneView.scene.rootNode addChildNode:node];

    

    

    SCNNode *node2 = [SCNNode node];

    node2.light = [SCNLight light];

    node2.light.type = SCNLightTypeAmbient;

    node2.light.color = [UIColor grayColor];

    node2.position = SCNVector3Make(0, 280, 0);

    node2.rotation = SCNVector4Make(1, 0, 0, –M_PI * 0.5);

    [self.sceneView.scene.rootNode addChildNode:node2];

}

– (SCNVector3)sphericalCoordinateTheta:(float)theta phi:(float)phi r:(float)r {

    float x = r * sin(theta) * cos(phi);

    float z = r * sin(theta) * sin(phi);

    float y = r * cos(theta);

    return SCNVector3Make(x, y, z);

}

– (SCNVector3)crossProductA:(SCNVector3)a b:(SCNVector3)b

{

    return SCNVector3Make(a.y*b.z – a.z*b.y, a.z*b.x – a.x*b.z, a.x*b.y – a.y*b.x);

}

– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    CGPoint p = [[touches anyObject] locationInView:self.sceneView];

    SCNHitTestResult *results = [self.sceneView hitTest:p options:@{SCNHitTestSortResultsKey : @YES}].firstObject;

    if (results) {

        if ([results.node.name isEqual:@”blue”]) {

            [self.sceneView.scene.rootNode.childNodes enumerateObjectsUsingBlock:^(SCNNode *node, NSUInteger idx, BOOL *stop) {

                node.physicsBody = [SCNPhysicsBody dynamicBody];

            }];

        }

    }

}

#define ColorHex(rgb) [UIColor colorWithRed:((rgb & 0xFF0000) >> 16)/255.0 green:((rgb & 0xFF00) >> 8)/255.0 blue:(rgb & 0xFF)/255.0 alpha:1.0]

– (UIColor *)color:(int)i {

    if (i > 4) {

        return nil;

    }

    int colorCode[] = {0xD9E5E8, 0x131BFF, 0x1585FF, 0xE81E00, 0xFEF4FF};

    return ColorHex(colorCode[i]);

}

@end