空き缶っぽいのにボールを投げるiPhoneアプリのサンプルコードを描いてみます。
#import “ViewController.h”
@import SceneKit;
@interface ViewController () <SCNSceneRendererDelegate>
@property (nonatomic, weak) SCNView *sceneView;
@property (nonatomic, weak) SCNNode *selected;
@property (nonatomic, strong) NSValue *movePoint;
@end
@implementation ViewController
– (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
[self setupScene];
[self createCan];
[self createBall];
}
– (void)setupScene {
float w = CGRectGetMaxX(self.view.bounds);
SCNView *sv = [[SCNView alloc] initWithFrame:CGRectMake(0, 100, w, w)];
sv.backgroundColor = [self color:0];
sv.scene = [SCNScene scene];
sv.delegate = self;
[self.view addSubview:sv];
self.sceneView = sv;
}
– (void)createCan {
SCNBox *ground = [SCNBox boxWithWidth:40 height:1 length:40 chamferRadius:0];
ground.firstMaterial.diffuse.contents = [self color:1];
SCNNode *groundNode = [SCNNode nodeWithGeometry:ground];
groundNode.physicsBody = [SCNPhysicsBody staticBody];
[self.sceneView.scene.rootNode addChildNode:groundNode];
SCNBox *rack = [SCNBox boxWithWidth:40 height:1 length:5 chamferRadius:0];
rack.firstMaterial.diffuse.contents = [self color:1];
SCNNode *rackNode = [SCNNode nodeWithGeometry:rack];
rackNode.position = SCNVector3Make(0, 10, –15);
rackNode.physicsBody = [SCNPhysicsBody staticBody];
[self.sceneView.scene.rootNode addChildNode:rackNode];
for (int i=0; i<2; i++) {
SCNCylinder *can = [SCNCylinder cylinderWithRadius:2 height:6];
can.firstMaterial.diffuse.contents = [self color:i + 2];
SCNNode *canNode = [SCNNode nodeWithGeometry:can];
canNode.position = SCNVector3Make(-10 + 20 * i, 13.1, –15);
canNode.physicsBody = [SCNPhysicsBody dynamicBody];
[self.sceneView.scene.rootNode addChildNode:canNode];
}
}
– (void)createBall {
SCNSphere *ball = [SCNSphere sphereWithRadius:2];
CALayer *tex = [CALayer layer];
tex.frame = CGRectMake(0, 0, 100, 100);
tex.backgroundColor = [self color:4].CGColor;
CALayer *texSub = [CALayer layer];
texSub.frame = CGRectMake(0, 50, 100, 50);
texSub.backgroundColor = [self color:3].CGColor;
[tex addSublayer:texSub];
ball.firstMaterial.diffuse.contents = tex;//[self color:4];
SCNNode *ballNode = [SCNNode nodeWithGeometry:ball];
ballNode.name = @”ball”;
ballNode.position = SCNVector3Make(0, 2, 19);
ballNode.physicsBody = [SCNPhysicsBody dynamicBody];
ballNode.physicsBody.allowsResting = NO;
ballNode.physicsBody.friction = 0.8;
[self.sceneView.scene.rootNode addChildNode:ballNode];
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint p = [[touches anyObject] locationInView:self.sceneView];
SCNNode *hit = [[self.sceneView hitTest:p options:@{SCNHitTestSortResultsKey:@YES}].firstObject node];
if ([hit.name isEqual:@”ball”]) {
self.selected = hit;
}
}
– (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint p = [[touches anyObject] locationInView:self.sceneView];
if (!self.selected) return;
if (p.y > 180) {
SCNVector3 v = [self.sceneView unprojectPoint:SCNVector3Make(p.x, p.y, 0.1)];
self.movePoint = [NSValue valueWithSCNVector3:SCNVector3Make(v.x * 10.0,self.selected.position.y, self.selected.position.z)];
} else {
[self.selected.physicsBody applyForce:SCNVector3Make(0, 30, –60) impulse:YES];
self.selected = nil;
}
}
– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
self.selected.physicsBody.angularVelocity = SCNVector4Zero;
self.selected = nil;
self.movePoint = nil;
}
– (void)renderer:(id<SCNSceneRenderer>)aRenderer updateAtTime:(NSTimeInterval)time
{
SCNNode *ball = [self.sceneView.scene.rootNode childNodeWithName:@”ball” recursively:NO];
if (self.movePoint) {
float d = ball.presentationNode.position.x – [self.movePoint SCNVector3Value].x;
if (d > 1) {
[ball.physicsBody applyTorque:SCNVector4Make(0, 0, 1, 20) impulse:NO];
} else if (d < –1) {
[ball.physicsBody applyTorque:SCNVector4Make(0, 0, 1, –20) impulse:NO];
} else {
ball.physicsBody.angularVelocity = SCNVector4Zero;
}
}
if (ball.presentationNode.position.z < 0) {
ball.name = @””;
[self createBall];
}
}
#define ColorHex(rgb) [UIColor colorWithRed:((rgb & 0xFF0000) >> 16)/255.0 green:((rgb & 0xFF00) >> 8)/255.0 blue:(rgb & 0xFF)/255.0 alpha:1]
– (UIColor *)color:(int)i {
switch (i) {
case 0: return ColorHex(0xE3BBBC);
case 1: return ColorHex(0x27415B);
case 2: return ColorHex(0x7CBCB2);
case 3: return ColorHex(0xE3E3E3);
case 4: return ColorHex(0xD26F6C);
}
return nil;
}
@end