所謂スタッフロール。
設定ファイルで表示する内容を指定します。
(Xcodeのインデントがなんか変で見づらい…)
{
    "type" : "roll",
    "roll" : [
              {
              "text" : "Prototype Quest",
              "size" : 24.0
              },
              {
              "text" : "Staff",
              "size" : 20.0
              },
              {
              "text" : "tnantoka",
              "size" : 20.0
              },
              {
              "text" : "Special Thanks",
              "size" : 24.0
              },
              {
              "text" : "Browser Quest",
              "size" : 20.0
              },
              {
              "text" : "mosamosa font",
              "size" : 20.0
              },
              {
              "text" : "Fin",
              "size" : 28.0
              }
              ],
    "speed" : 4.0,
    "next" : "title"
}これを下から上へスクロールさせながら表示して、 終わったらnextで指定されているタイトル画面に遷移させます。
- (void)createSceneContents {
    _labelNodes = @[].mutableCopy;
    
    for (NSDictionary *label in self.sceneData[@"roll"]) {
        SKLabelNode *labelNode = [SKLabelNode labelNodeWithFontNamed:FONT_NORMAL];
        labelNode.text = label[@"text"];
        labelNode.fontSize = [label[@"size"] floatValue];
        [_labelNodes addObject:labelNode];
    }
    
    [self performSelector:@selector(showNextLabelNode) withObject:nil afterDelay:DELAY];
    
}
- (void)showNextLabelNode {
    
    SKLabelNode *labelNode = _labelNodes.firstObject;
    labelNode.position = CGPointMake(CGRectGetMidX(self.frame), 0);
    [self addChild:labelNode];
    CGFloat y;
    CGFloat duration;
    if (_labelNodes.count > 1) {
        y = CGRectGetHeight(self.frame) + CGRectGetHeight(labelNode.frame);
        duration = [self.sceneData[@"speed"] floatValue];
    } else {
        y = CGRectGetMidY(self.frame) + CGRectGetMidY(labelNode.frame);
        duration = [self.sceneData[@"speed"] floatValue] / 2.0f;
    }
    SKAction *moveX = [SKAction moveByX:0 y:y duration:duration];
    SKAction *run = [SKAction runBlock:^{
        if (_labelNodes.count > 1) {
            [_currentLabelNode removeFromParent];
            [_labelNodes removeObjectAtIndex:0];
            [self showNextLabelNode];
        } else {
            self.nextScene = self.sceneData[@"next"];
            [self performSelector:@selector(loadNextScene) withObject:nil afterDelay:DELAY];
            return;
        }
    }];
    SKAction *sequence = [SKAction sequence:@[moveX, run]];
    [labelNode runAction:sequence];
    _currentLabelNode = labelNode;
}ラベルの移動はSKActionで実施。
移動と次のラベルを表示するアクションをそれぞれ用意して、sequenceにまとめてラベルに適用しています。
できました。
だいぶ必要そうな画面はそろってきました。
そろそろ戦闘などのメイン部分に手を出したいと思います。
ソースコード: sj-prototype-apps/SJRolePlaying at master · tnantoka/sj-prototype-apps
iOS Advent Calendar 2013 - Qiita [キータ]に出来心で投稿してみました。
iOS - Sprite Kitでブロック崩し - Qiita [キータ]
こんな感じのブロック崩しを作るhello, worldものです。
![]()
お時間のある方は目を通してくみてください。
「この記事を読めば、とりあえずSprite Kitをはじめられる」みたいな記事にしたくて、 このサイトのチュートリアルに書いたことをコンパクトにまとめようと思ったんですが、 結局かなり長文になってしまいました。 なかなか難しいですね…。
あと、英訳もしようと思ったんですが全然間に合いませんでした。 気が向いたらまた手を加えます。
ただ、
の画像はわりと自信作です。 Sprite Kitの登場人物が、なんとなく把握いただけるのではないでしょうか。
さて、次からはまたRPGの製作に戻ります。 (年内リリースが絶望的になってきましたが…)
章とサブタイトルを表示して次のシーンへ進むだけの単純なもの。
設定ファイルでは表示内容とnextを指定。
{
    "type" : "chapter",
    "title" : {
        "en" : "CHAPTER 1",
        "ja" : "第一章"
    },
    "subtitle" : {
        "en" : "THE MANIPULATOR & THE SUBSERVIENT",
        "ja" : "利用する者されるもの者"
    },
    "next" : "story_opening"
}これを画面に表示して、一定時間まった後次のシーンを読み込む。
- (void)createSceneContents {
    
    SKLabelNode *titleLabel1 = [SKLabelNode labelNodeWithFontNamed:FONT_NORMAL];
    titleLabel1.text = self.sceneData[@"title"][[SJUtilities lang]];
    titleLabel1.fontSize = 28.0f;
    titleLabel1.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + MARGIN);
    titleLabel1.verticalAlignmentMode =SKLabelVerticalAlignmentModeBottom;
    [self addChild:titleLabel1];
    
    SKLabelNode *titleLabel2 = [SKLabelNode labelNodeWithFontNamed:titleLabel1.fontName];
    titleLabel2.text = self.sceneData[@"subtitle"][[SJUtilities lang]];;
    titleLabel2.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - MARGIN);
    titleLabel2.fontSize = 20.0f;
    titleLabel2.verticalAlignmentMode =SKLabelVerticalAlignmentModeTop;
    [self addChild:titleLabel2];
    
    self.nextScene = self.sceneData[@"next"];
    [self performSelector:@selector(loadNextScene) withObject:nil afterDelay:DELAY];
}できました。
以上。
ソースコード: sj-prototype-apps/SJRolePlaying at master · tnantoka/sj-prototype-apps
画面上のキャラクターを別のキャラクターに入れ替えます。
なくても何とかなりそうですが、宝箱を開ける演出とかしたいので一応用意しておきます。
まずは設定。
「これじゃ!」とメッセージを表示した後、replaceイベントでc2というキャラクターをc3に入れ替え。
その後またメッセージを表示。
という内容です。
{
    "type" : "story",
    "map" : "map_shop",
    "events" : {
        "c1" : {
            "type" : "message",
            "message" : {
                "en" : "Here you are!",
                "ja" : "これじゃ!"
            },
            "next" : "c1a"
        },
        "c1a" : {
            "type" : "replace",
            "from" : "c2",
            "to" : "c3",
            "next" : "c1b"
        },
        "c1b" : {
            "type" : "message",
            "message" : {
                "en" : "Take good care of it.",
                "ja" : "お主の分身じゃ。大切にするんじゃぞ。"
            },
            "next" : "story_replace"
        }
    }
}キャラクターの入れ替えは、SJMapNodeにメソッドを追加して対応。
- (void)replaceCharacterNodeFrom:(NSString *)fromName to:(NSString *)toName {
    
    SKNode *fromNode = [self childNodeWithName:fromName];
    SKNode *toNode = [self newCharacterNode:toName];
    
    toNode.position = fromNode.position;
    
    [fromNode removeFromParent];
    [self addChild:toNode];
}それをSJStorySceneから呼び出します。
- (void)processEvent:(NSString *)name {
    
    /* 省略 */
    } else if ([event[@"type"] isEqualToString:@"replace"]) {
        [[self mapNode] replaceCharacterNodeFrom:event[@"from"] to:event[@"to"]];
        [self processEvent:event[@"next"]];
    }
}完成。
いい感じです。
ソースコード: sj-prototype-apps/SJRolePlaying at master · tnantoka/sj-prototype-apps