目標のゲームを作るために必要そうなものをメモ。
年内を目指していたけど、厳しそうなので年度内を目標に。
前回から少し時間が開いてしまいましたが、今回はキャラクターに話をさせてみます。
event.json
ファイルでデータを定義しています。
{
"c1" : {
"type" : "message",
"message" : {
"en" : "hello, world.",
"ja" : "よくきた、○○よ。待って追ったぞ。ここは××研究所。これから旅に出るお主に、託したいものがあって呼んだのじゃ。その宝箱の中身を持って行くがよい。世界の平和を頼んだぞ。"
}
}
}
接触時のdelegateメソッドで、playerNodeがc1
という名前のNodeに触れた時に、メッセージの内容を表示するようにしています。
- (void)didBeginContact:(SKPhysicsContact *)contact {
SKPhysicsBody *firstBody, *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
firstBody = contact.bodyA;
secondBody = contact.bodyB;
} else {
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if ((firstBody.categoryBitMask & playerCategory) != 0) {
if ((secondBody.categoryBitMask & characterCategory) != 0) {
SJCharacterNode *node = (SJCharacterNode *)secondBody.node;
NSString *name = node.name;
NSDictionary *e = [self event][name];
if ([e[@"type"] isEqualToString:@"message"]) {
_state = SJShopSceneStateMessage;
[self messageNode].message = e[@"message"][[SJUtilities lang]];
[self messageNode].hidden = NO;
}
}
}
}
メッセージの表示は、新たに追加したSJMessageNodeに担当させています。
SKLabelNodeが複数行表示に対応していないため、行数分並べて表示するという泥臭い実装になっています。 特別なことをしていない上に無駄に長いため、引用はやめておきます。
無事、キャラクターに話しかけることができるようになりました。
次は他のシーンへの遷移を実装します。
ソースコード: sj-prototype-apps/SJRolePlaying at master · tnantoka/sj-prototype-apps
Sprite Kitには物理エンジンが組み込まれており、簡単に物理シミュレーションが利用できて便利です。
ただ、デバッグ表示用の機能がないため、どこにPhysicsBodyを追加したか、見た目では知ることができません。
そんな不満を解決してくれるのが、PhysicsDebuggerです。
早速使ってみます。
CocoaPodsに対応してるので簡単です。
# ターミナルを起動してプロジェクトのフォルダまで移動
# CocoaPodsをインストールしてない人
$ gem install cocoapods
$ pod install
# Podfile
platform :ios, '7.0'
pod 'PhysicsDebugger'
# インストール
$ pod
Analyzing dependencies
Downloading dependencies
Installing PhysicsDebugger (1.0.0)
Generating Pods project
Integrating client project
[!] From now on use `SJRolePlaying.xcworkspace`.
CocoaPodsを初めて使う場合、これ以降.xcodeprojではなく、.xcworkspaceを開く必要があることに注意してください。
ヘッダをインポートして、描画対象のノードが作成される前に、init
を呼び、
drawPhysicsBodies
を呼びます。
今回は、SJMapNodeに追加してみました。
#import "YMCPhysicsDebugger.h"
#import "YMCSKNode+PhysicsDebug.h"
- (void)createNodeContents {
[YMCPhysicsDebugger init];
/* ノードの作成・追加 */
[self drawPhysicsBodies];
}
これで実行すると、以下のようにPhysicsBodyに赤枠がついて可視化されます。
手軽に使えて便利でした。
ただ、ちょっとコードに手を加える量が多いかなぁ、という印象。 まぁそれでも、毎回PhysicsBodyと同じ大きさのShapeNodeを作成して追加する、とかに比べればはるかに綺麗ですが。
あと、このライブラリに限った話ではないですが、デバッグドローのぶんNodeの数が増えて動作がもっさりになるので、常に使用しながらの開発は厳しいかもしれません。
しばらく使って様子を見てみようと思います。
今日はマップ内に他のキャラクターを表示してみます。
前回はSJCharacgterNodeの中に定数でいろいろと持たせていましたが、
characters.json
というファイルで定義するようにしました。1
{
"default" : {
"stop_time" : 0.6,
"walk_time" : 0.3,
"speed": 0.2
},
"c0" : {
"name" : "clotharmor",
"stop_row" : 0,
"stop_cols" : 2,
"walk_row" : 1,
"walk_cols" : 4,
"up_row" : 3,
"right_row" : 6,
"left_row" : 6,
"size": 64
},
"c1" : {
"name" : "scientist",
"stop_row" : 0,
"stop_cols" : 2,
"walk_row" : 0,
"walk_cols" : 2,
"up_row" : 0,
"right_row" : 0,
"left_row" : 0,
"size": 48
},
"c2" : {
"name" : "chest",
"stop_row" : 0,
"stop_cols" : 1,
"walk_row" : 0,
"walk_cols" : 1,
"up_row" : 0,
"right_row" : 0,
"left_row" : 0,
"size": 32
}
}
マップデータでどこに配置するか指定します。
-,-,-,-,-,-,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,c2,c1,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,-,-,-,-,-,-
-,-,-,-,c0,-,-,-,-,-
SJMapNode内で、cから始まるデータの場合はキャラクターを生成するようにします。
} else if ([col hasPrefix:@"c"]) {
tileSprite = [[SJCharacterNode alloc] initWithCharacterNamed:col];
tileSprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(TILE_SIZE, TILE_SIZE)];
tileSprite.physicsBody.affectedByGravity = NO;
tileSprite.physicsBody.allowsRotation = NO;
tileSprite.name = col;
}
SJCharacterNodeではjsonから設定を読み取ります。 この値を定数の代わりに使います。
- (id)initWithCharacterNamed:(NSString *)name {
NSString *path = [[NSBundle mainBundle] pathForResource:CHARACTERS_NAME ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSError *error = nil;
NSDictionary *characters = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if (error) {
NSLog(@"%@", [error localizedDescription]);
}
NSMutableDictionary *character = [characters[@"default"] mutableCopy];
[character addEntriesFromDictionary:characters[name]];
CGFloat size = [character[@"size"] floatValue];
if (self = [super initWithColor:nil size:CGSizeMake(size, size)]) {
_character = character;
[self createNodeContents];
}
return self;
}
完成です。
相変わらず全然お店ではないですが、見た目はゲームっぽくなってきました。
次は会話を実装する予定です。
ソースコード: sj-prototype-apps/SJRolePlaying at master · tnantoka/sj-prototype-apps
Objective-C的にはplistを使うのが定石だと思いますが、個人的にplistが苦手なのでここではJSONにしています。 ↩
ついにリリースされましたね。
正直なところ、そこまで魅力は感じていなかったんですが、まさかの無料ということで早速アップグレードしました。 今まで作ったサンプルが、最新版のXcodeでも問題なく動いていて一安心です。
残念ながら、このタイミングでも、日本語ドキュメント - Apple DeveloperにSprite Kit Programming Guideは追加されませんでした。 こうなると、しばらくは翻訳されなさそうです…。
NDA期間も終わったことだし、今後は機会があればMac向けの情報も扱っていきたいと思います。