
4つの筒にボールを入れてシャッフルするiPhoneアプリのサンプルコードを描いてみます。
#import “ViewController.h”
@import SceneKit;
@interface NSMutableArray(KnuthShuffle)
– (NSMutableArray *)shuffled;
@end
@implementation NSMutableArray(KnuthShuffle)
– (NSMutableArray *)shuffled {
for (NSUInteger i = self.count–1; 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