SceneKitて凄いですよ!
作成した物体に重力、他の物体との当たり判定、影を簡単に設定する事ができます。
SceneKitで遊ぼう第2弾は、物体に重力や当たり判定を追加して遊びま〜す!
Unityがあるでしょう?なんて言わない事(笑)
では、遊んんでいきましょう!
※Xcode7で不具合が発生しましたので修正しました
遊んだシステム構成
Xcode : ver.7.0.1
Language : Objective-C
Device : iPhone5s / iOS 9.0.2
プロジェクトファイルの作成
まずはじめに、プロジェクトファイルの作成
Create New Xcode projectを選ぶ

Gameを選んで「Next」
Product Name:PlayXcodeScenekit002 ※自由に決めて問題ありません
Language:Objective-C ※世の中の流れに抵抗してみます(笑)
Game Technology:SceneKit
「Next」を押して、保存先を決めて「Create」
プロジェクトファイル完成です。
ソースコードの断捨離
ベースとなるGameViewControllerのソースコードを断捨離しましす。
viewDidLoadの赤いところを削除した
追加、修正してXcodeで遊ぶ
ベースが完成しました
追加修正していきます
背景色の変更
真っ黒な背景では、ちょっと味気ないので元気な色に変更
![]()
[UIColor blackColor]を以下の様に書き換え
![]()
Sceneクラスの作成
– (void)viewDidLoadの最終行にsceneクラスの作成と設定を追加
SCNScene *scene = [SCNScene new];の下に追加します
1.カメラの設置
2.全体を照らす光源の設置
3.影を付ける光源の設置
4.床の設置と当たり判定の設定
5.物体発生器の設置
完成した – (void)viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
// retrieve the SCNView
SCNView *scnView = (SCNView *)self.view;
// allows the user to manipulate the camera
scnView.allowsCameraControl = YES;
// show statistics such as fps and timing information
scnView.showsStatistics = YES;
// configure the view
scnView.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:1.0 alpha:1.0];
// add a tap gesture recognizer
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
NSMutableArray *gestureRecognizers = [NSMutableArray array];
[gestureRecognizers addObject:tapGesture];
[gestureRecognizers addObjectsFromArray:scnView.gestureRecognizers];
scnView.gestureRecognizers = gestureRecognizers;
// create a new scene
SCNScene *scene = [SCNScene new];
// カメラの設置
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
cameraNode.position = SCNVector3Make(0, 50, 30);
cameraNode.rotation = SCNVector4Make(1, 0, 0, - 0.9);
[scene.rootNode addChildNode:cameraNode];
// 全体を照らす光源の配置
SCNNode *ambientLightNode = [SCNNode node];
ambientLightNode.light = [SCNLight light];
ambientLightNode.light.type = SCNLightTypeAmbient;
ambientLightNode.light.color = [UIColor lightGrayColor];
[scene.rootNode addChildNode:ambientLightNode];
// 影を付ける為のスポットライトの配置
SCNNode *lightNode = [SCNNode node];
lightNode.light = [SCNLight light];
lightNode.light.type = SCNLightTypeSpot;
lightNode.light.color = [UIColor whiteColor];
lightNode.light.spotOuterAngle = 180;
lightNode.light.castsShadow = YES;
lightNode.position = SCNVector3Make(0, 50, 0);
lightNode.rotation = SCNVector4Make(1, 0, 0, -3.14 / 2.0);
lightNode.name = @"spotLight";
[scene.rootNode addChildNode:lightNode];
// 床の配置
SCNFloor *floorGround = [SCNFloor floor];
floorGround.firstMaterial.diffuse.contents = [UIColor orangeColor];
SCNNode *floorNode = [SCNNode node];
floorNode.geometry = floorGround;
floorNode.position = SCNVector3Make(0, 0, 0);
floorNode.name = @"groundFloor";
// 床への物体の当たり判定の設定
floorNode.physicsBody = [SCNPhysicsBody staticBody];
[scene.rootNode addChildNode:floorNode];
// 発生器の球体の配置
SCNSphere *generatorSphere = [SCNSphere sphereWithRadius:4];
generatorSphere.firstMaterial.diffuse.contents = [UIColor colorWithRed:.3 green:.3 blue:1 alpha:0.7];
SCNNode *generatorNode = [SCNNode node];
generatorNode.geometry = generatorSphere;
generatorNode.position = SCNVector3Make(0, 32, 0);
generatorNode.name = @"generatorSphere";
generatorNode.castsShadow = NO;
[scene.rootNode addChildNode:generatorNode];
// set the scene to the view
scnView.scene = scene;
}
実行画面
球体と地面が表示されました。
これだけでは遊べませんねから、遊び部分を追加していきます
物体の追加
球体をタップすると重さを持った物体を発生させるようにします
球体のタップ判定の修正
タップ判定methodは- (void) handleTap:(UIGestureRecognizer*)gestureRecognize
どれをタップしたかを判別するには、球体に名前をつけましたのでその名前を使用します
generatorNode.name = @”generatorSphere”;
球体をタップすると赤く光り -(voio)createAnyGeometoryの実行
createAnyGeometoryの作成
ランダムで5種類の形状、ランダムの色で物体を作成
説明を省略しすぎですかね
完成した- (void)createAnyGeometory
- (void)createAnyGeometory {
// create New Geometory
SCNGeometry *anyGeometry = nil;
// ランダムで形状の決定
NSInteger formNumber = arc4random_uniform(5);
switch (formNumber) {
case 0:
anyGeometry = [SCNPyramid pyramidWithWidth:4.5 height:4.5 length:4.5 ];
NSLog(@"SCNPyramid");
break;
case 1:
anyGeometry = [SCNCylinder cylinderWithRadius:2.0 height:3.5];
NSLog(@"SCNCylinder");
break;
case 2:
anyGeometry = [SCNSphere sphereWithRadius:2.0];
NSLog(@"SCNSphere");
break;
case 3:
anyGeometry = [SCNTorus torusWithRingRadius:2.5 pipeRadius:1.0];
NSLog(@"SCNTorus");
break;
case 4:
anyGeometry = [SCNBox boxWithWidth:4.5 height:4.5 length:4.5 chamferRadius:0.0];
NSLog(@"SCNBox");
break;
default:
anyGeometry = [SCNBox boxWithWidth:3.0 height:3.0 length:3.0 chamferRadius:1.0];
NSLog(@"SCNBoxR");
break;
}
// ランダムでRGBの色を決定
anyGeometry.firstMaterial.diffuse.contents = [UIColor colorWithRed:[self randomColorNumber]
green:[self randomColorNumber]
blue:[self randomColorNumber]
alpha:1.0];
// 形状の設定
SCNNode *anyGeometoryNode = [SCNNode nodeWithGeometry:anyGeometry];
anyGeometoryNode.position = SCNVector3Make(0.0, 30.0, 0.0);
anyGeometoryNode.name = @"anyGeometry";
// 重力の設定
anyGeometoryNode.physicsBody = [SCNPhysicsBody dynamicBody];
// シーンに追加
SCNView *scnView = (SCNView *)self.view;
[scnView.scene.rootNode addChildNode:anyGeometoryNode];
}
- (CGFloat)randomColorNumber {
double colorNumber = arc4random_uniform(100);
return colorNumber / 200.0 + 0.5;
}
実行画面
最後に隠し味
作成した重力を持った物体をタップしすると削除
– (void) handleTap:(UIGestureRecognizer*)gestureRecognizeに名前で判別して削除するコードを追加
赤い部分を追加します。
タップ!タップ!して遊ぶ!
こんなに簡単に重力、当たり判定ができるなんて・・・。
楽しい世の中になりました!
ピタゴラスイッチみたいなのを作りたくなりませんか?
ぜひ!やってみてください!
では、タップしてあそんじゃいましよう!
そして、改造して遊んでください
完成したソースコード
- (void)viewDidLoad
{
[super viewDidLoad];
// retrieve the SCNView
SCNView *scnView = (SCNView *)self.view;
// allows the user to manipulate the camera
scnView.allowsCameraControl = YES;
// show statistics such as fps and timing information
scnView.showsStatistics = YES;
// configure the view
scnView.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:1.0 alpha:1.0];
// add a tap gesture recognizer
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
NSMutableArray *gestureRecognizers = [NSMutableArray array];
[gestureRecognizers addObject:tapGesture];
[gestureRecognizers addObjectsFromArray:scnView.gestureRecognizers];
scnView.gestureRecognizers = gestureRecognizers;
// create a new scene
SCNScene *scene = [SCNScene new];
// カメラの設置
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
cameraNode.position = SCNVector3Make(0, 50, 30);
cameraNode.rotation = SCNVector4Make(1, 0, 0, - 0.9);
[scene.rootNode addChildNode:cameraNode];
// 全体を照らす光源の配置
SCNNode *ambientLightNode = [SCNNode node];
ambientLightNode.light = [SCNLight light];
ambientLightNode.light.type = SCNLightTypeAmbient;
ambientLightNode.light.color = [UIColor lightGrayColor];
[scene.rootNode addChildNode:ambientLightNode];
// 影を付ける為のスポットライトの配置
SCNNode *lightNode = [SCNNode node];
lightNode.light = [SCNLight light];
lightNode.light.type = SCNLightTypeSpot;
lightNode.light.color = [UIColor whiteColor];
lightNode.light.spotOuterAngle = 180;
lightNode.light.castsShadow = YES;
lightNode.position = SCNVector3Make(0, 50, 0);
lightNode.rotation = SCNVector4Make(1, 0, 0, -3.14 / 2.0);
lightNode.name = @"spotLight";
[scene.rootNode addChildNode:lightNode];
// 床の配置
SCNFloor *floorGround = [SCNFloor floor];
floorGround.firstMaterial.diffuse.contents = [UIColor orangeColor];
SCNNode *floorNode = [SCNNode node];
floorNode.geometry = floorGround;
floorNode.position = SCNVector3Make(0, 0, 0);
floorNode.name = @"groundFloor";
// 床への物体の当たり判定の設定
floorNode.physicsBody = [SCNPhysicsBody staticBody];
[scene.rootNode addChildNode:floorNode];
// 発生器の球体の配置
SCNSphere *generatorSphere = [SCNSphere sphereWithRadius:4];
generatorSphere.firstMaterial.diffuse.contents = [UIColor colorWithRed:.3 green:.3 blue:1 alpha:0.7];
SCNNode *generatorNode = [SCNNode node];
generatorNode.geometry = generatorSphere;
generatorNode.position = SCNVector3Make(0, 32, 0);
generatorNode.name = @"generatorSphere";
generatorNode.castsShadow = NO;
[scene.rootNode addChildNode:generatorNode];
// set the scene to the view
scnView.scene = scene;
}
- (void) handleTap:(UIGestureRecognizer*)gestureRecognize
{
// retrieve the SCNView
SCNView *scnView = (SCNView *)self.view;
// check what nodes are tapped
CGPoint p = [gestureRecognize locationInView:scnView];
NSArray *hitResults = [scnView hitTest:p options:nil];
// check that we clicked on at least one object
if([hitResults count] > 0){
// retrieved the first clicked object
SCNHitTestResult *result = [hitResults objectAtIndex:0];
// get its material
SCNMaterial *material = result.node.geometry.firstMaterial;
// 球体タップ判定
SCNNode *hitResultNode = result.node;
if ([hitResultNode.name isEqualToString:@"generatorSphere"]) {
// default color
UIColor *hitResultDefColor = material.emission.contents;
// highlight it
[SCNTransaction begin];
// [SCNTransaction setAnimationDuration:1.0];
// on completion - unhighlight
[SCNTransaction setCompletionBlock:^{
[SCNTransaction begin];
[SCNTransaction setAnimationDuration:0.5];
material.emission.contents = hitResultDefColor;
[SCNTransaction commit];
}];
material.emission.contents = [UIColor redColor];
[SCNTransaction commit];
// Create New Geometory
[self createAnyGeometory];
} else if ([hitResultNode.name isEqualToString:@"anyGeometry"]) {
NSLog(@"remove:anyGeometry");
// Color Change Geometory
material.emission.contents = [UIColor redColor];
// Remove Geometry
[hitResultNode runAction:[SCNAction sequence:@[[SCNAction fadeInWithDuration:0.2],
[SCNAction removeFromParentNode ]]
]
];
}
}
}
- (void)createAnyGeometory {
// create New Geometory
SCNGeometry *anyGeometry = nil;
// ランダムで形状の決定
NSInteger formNumber = arc4random_uniform(5);
switch (formNumber) {
case 0:
anyGeometry = [SCNPyramid pyramidWithWidth:4.5 height:4.5 length:4.5 ];
NSLog(@"SCNPyramid");
break;
case 1:
anyGeometry = [SCNCylinder cylinderWithRadius:2.0 height:3.5];
NSLog(@"SCNCylinder");
break;
case 2:
anyGeometry = [SCNSphere sphereWithRadius:2.0];
NSLog(@"SCNSphere");
break;
case 3:
anyGeometry = [SCNTorus torusWithRingRadius:2.5 pipeRadius:1.0];
NSLog(@"SCNTorus");
break;
case 4:
anyGeometry = [SCNBox boxWithWidth:4.5 height:4.5 length:4.5 chamferRadius:0.0];
NSLog(@"SCNBox");
break;
default:
anyGeometry = [SCNBox boxWithWidth:3.0 height:3.0 length:3.0 chamferRadius:1.0];
NSLog(@"SCNBoxR");
break;
}
// ランダムでRGBの色を決定
anyGeometry.firstMaterial.diffuse.contents = [UIColor colorWithRed:[self randomColorNumber]
green:[self randomColorNumber]
blue:[self randomColorNumber]
alpha:1.0];
// 形状の設定
SCNNode *anyGeometoryNode = [SCNNode nodeWithGeometry:anyGeometry];
anyGeometoryNode.position = SCNVector3Make(0.0, 30.0, 0.0);
anyGeometoryNode.name = @"anyGeometry";
// 重力の設定
anyGeometoryNode.physicsBody = [SCNPhysicsBody dynamicBody];
// シーンに追加
SCNView *scnView = (SCNView *)self.view;
[scnView.scene.rootNode addChildNode:anyGeometoryNode];
}
- (CGFloat)randomColorNumber {
double colorNumber = arc4random_uniform(100);
return colorNumber / 200.0 + 0.5;
}
そろそろ、GitHubにでアップしようかなぁ〜、



















コメント