Play Xcode : SceneKitで遊ぼう!+重力

skydiving-603646_1280

SceneKitて凄いですよ!
作成した物体に重力、他の物体との当たり判定、影を簡単に設定する事ができます。

SceneKitで遊ぼう第2弾は、物体に重力や当たり判定を追加して遊びま〜す!

Unityがあるでしょう?なんて言わない事(笑)

では、遊んんでいきましょう!

※Xcode7で不具合が発生しましたので修正しました

遊んだシステム構成

Xcode : ver.7.0.1
Language : Objective-C
Device : iPhone5s / iOS 9.0.2

プロジェクトファイルの作成

まずはじめに、プロジェクトファイルの作成

20150507_001

Create New Xcode projectを選ぶ
20150507_002

Gameを選んで「Next」

20150531_001

Product Name:PlayXcodeScenekit002 ※自由に決めて問題ありません

Language:Objective-C ※世の中の流れに抵抗してみます(笑)

Game Technology:SceneKit

「Next」を押して、保存先を決めて「Create」

20150531_002

プロジェクトファイル完成です。

ソースコードの断捨離

ベースとなるGameViewControllerのソースコードを断捨離しましす。

20150531_003

viewDidLoadの赤いところを削除した

20150531_004
すっきりしました。

追加、修正してXcodeで遊ぶ

ベースが完成しました
追加修正していきます

背景色の変更

真っ黒な背景では、ちょっと味気ないので元気な色に変更

20150531_005

[UIColor blackColor]を以下の様に書き換え

20150531_006

Sceneクラスの作成

– (void)viewDidLoadの最終行にsceneクラスの作成と設定を追加

20150531_008

SCNScene *scene = [SCNScene new];の下に追加します

1.カメラの設置

20150531_009

2.全体を照らす光源の設置

20150531_010

3.影を付ける光源の設置

20150531_011

4.床の設置と当たり判定の設定

20150531_012

5.物体発生器の設置

20150531_013

完成した – (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;
}

実行画面

20150531_014

球体と地面が表示されました。

これだけでは遊べませんねから、遊び部分を追加していきます

物体の追加

球体をタップすると重さを持った物体を発生させるようにします

球体のタップ判定の修正

タップ判定methodは- (void) handleTap:(UIGestureRecognizer*)gestureRecognize

どれをタップしたかを判別するには、球体に名前をつけましたのでその名前を使用します

generatorNode.name                             = @”generatorSphere”;

20150531_015

球体をタップすると赤く光り -(voio)createAnyGeometoryの実行

createAnyGeometoryの作成

ランダムで5種類の形状、ランダムの色で物体を作成

20150531_016

説明を省略しすぎですかね

完成した- (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;
}

実行画面

20150531_017

最後に隠し味

作成した重力を持った物体をタップしすると削除

20150531_018

– (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にでアップしようかなぁ〜、

スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存

フォローする

スポンサーリンク