iPhoneシャッフル筒

4つの筒にボールを入れてシャッフルするiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SceneKit;

@interface NSMutableArray(KnuthShuffle)

– (NSMutableArray *)shuffled;

@end

@implementation NSMutableArray(KnuthShuffle)

– (NSMutableArray *)shuffled {

    for (NSUInteger i = self.count1; i>0; i–) {

        NSUInteger j = arc4random_uniform((uint32_t)i+1);

        [self exchangeObjectAtIndex:i withObjectAtIndex:j];

    }

    return self;

}

@end

@interface ViewController ()

@property (nonatomic, weak) SCNView *sceneView;

@property (nonatomic) int state;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    [self createTable];

    [self createPot];

    [self createCamera];

}

– (void)setupScene {

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

    sv.scene = [SCNScene scene];

    sv.backgroundColor = [self color:4];

    sv.autoenablesDefaultLighting = YES;

    [self.view addSubview:sv];

    

    self.sceneView = sv;

}

– (void)createTable {

    SCNBox *box = [SCNBox boxWithWidth:30 height:3 length:30 chamferRadius:1];

    box.firstMaterial.diffuse.contents = [self color:0];

    SCNNode *boxNode = [SCNNode nodeWithGeometry:box];

    boxNode.physicsBody = [SCNPhysicsBody staticBody];

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

}

– (void)createPot {

    float r = 10;

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

        float x = r * cos(i * M_PI * 0.5);

        float z = r * sin(i * M_PI * 0.5);

        SCNTube *pot = [SCNTube tubeWithInnerRadius:1.8 outerRadius:2 height:4];

        pot.firstMaterial.diffuse.contents = [self color:1];

        SCNNode *potNode = [SCNNode nodeWithGeometry:pot];

        potNode.name = @”pot”;

        potNode.position = SCNVector3Make(x, 3.5, z);

        potNode.physicsBody = [SCNPhysicsBody dynamicBody];

        potNode.physicsBody.physicsShape = [SCNPhysicsShape shapeWithNode:potNode options:@{SCNPhysicsShapeTypeKey : SCNPhysicsShapeTypeConcavePolyhedron}];

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

    }

}

– (void)createCamera {

    SCNNode *camera = [SCNNode node];

    camera.camera = [SCNCamera camera];

    camera.position = SCNVector3Make(0, 30, 70);

    camera.rotation = SCNVector4Make(1, 0, 0, –0.3);

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

}

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

{

    NSArray *pots = [[self.sceneView.scene.rootNode childNodes] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@”name == %@”, @”pot”]];

    

    if (self.state == 0) {

        int red = arc4random_uniform(3);

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

            SCNNode *pot = pots[i];

            SCNSphere *ball = [SCNSphere sphereWithRadius:1];

            ball.firstMaterial.diffuse.contents = (red != i) ? [self color:2] : [self color:3];

            SCNNode *ballNode = [SCNNode nodeWithGeometry:ball];

            ballNode.name = @”ball”;

            ballNode.position = SCNVector3Make(0, 10, 0);

            ballNode.physicsBody = [SCNPhysicsBody dynamicBody];

            ballNode.physicsBody.restitution = 0;

            [pot addChildNode:ballNode];

        }

        ++self.state;

    }

    

    else if (self.state < 4) {

        SCNVector3 p[4];

        for (int i=0; i<4; i++)

            p[i] = ((SCNNode *)pots[i]).position;

        NSMutableArray *n = [[@[@0, @1, @2, @3] mutableCopy] shuffled];

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

            ((SCNNode *)[pots[i] childNodeWithName:@”ball” recursively:NO]).physicsBody = nil;

            [pots[i] runAction:[SCNAction moveTo:p[[n[i] intValue]] duration:0.4]];

        }

        ++self.state;

    }

    

    else {

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

            SCNNode *ball = ((SCNNode *)[pots[i] childNodeWithName:@”ball” recursively:NO]);

            ball.physicsBody = [SCNPhysicsBody dynamicBody];

            [ball.physicsBody applyForce:SCNVector3Make(0, 13, 0) impulse:YES];

        }

        self.state = 1;

    }

}

#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[] = {0xF4C430, 0xFAEBD7, 0xFFFAF0, 0xC71C00, 0x3C3C3C};

    return ColorHex(colorCode[i]);

}

@end