LV1

駆け出し三十路プログラマー奮闘記。iPhone/Macを中心に絶賛修行中。

順番に実行したい処理をマルチスレッドで直感的に書く

ここのところ、ネットワークの非同期通信を使うためにマルチスレッドプログラミングと格闘していました。

そんな中、ふと「これって、RPGのバトルみたいに、○○の攻撃!→××の攻撃!みたいに順番に処理したいゲームプログラミングで使えるんじゃない!?」と思いサンプルを書いてみました。

マルチスレッドにはiOS4で導入されたGCDを使っています。

- (void)mainLoop:(NSTimer*)timer //NSTimerから定期的に呼ばれる
{
	if (!_hasStarted) {
		//以下のブロックをスレッドで処理
		dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
			[self msg:@"spkrlnのこうげき"];
			[self wait:3.0];
			[self msg:@"いっかくうなぎに30のダメージ!!"];
			[self wait:3.0];
		});
		_hasStarted = YES;
	}
	//描画はメインスレッドから毎フレーム呼ばれる
	[self draw];
}

- (void)msg:(NSString*)message
{
	for (int i = 1; i <= [message length]; ++i) {
		NSString* substr = [message substringToIndex:i];
		//UIの更新はメインスレッドで!
		dispatch_async(dispatch_get_main_queue(), ^{
			[_textView setText:substr];
		});
		//メソッドから抜けることなくスリープで済ませられちゃう!
		[NSThread sleepForTimeInterval:0.05];
	}
}

- (void)wait:(NSTimeInterval)seconds
{
	//ここもスリープでおk!
	[NSThread sleepForTimeInterval:seconds];
}

特に、

[self msg:@"spkrlnのこうげき"];
[self wait:3.0];
[self msg:@"いっかくうなぎに30のダメージ!!"];
[self wait:3.0];

の部分など、普通なら文字送りやウェイトのせいで、1回のメソッド呼び出しで処理が完了することはないので、いったん状態を変数に保存してメソッドを抜けて、次のフレームで条件分岐して処理を引き継いで…と、なかなかきれいに書けないのですが、今回はとても直感的に書けました。
Luaのコルーチンのような感じ。これはいいかも。