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にでアップしようかなぁ〜、
コメント