N-EMU · レトロゲームエミュレーターv1.10.1
開発の話投稿日 thorv1.5.0

正常な速度なのにカクついていた画面

ニンテンドーDSの3Dゲームは、正常な速度で動いていても画面がカクついていました。1.5.0では、フレームごとに画面に出す時刻を決め、1枚ずつ均等に表示します。

クローズドベータテスト

ニンテンドーDSの3Dゲームを遊んでいると、ゲームの速度はそのままなのに、画面がカクカクと止まることがありました。ゲームは正常な速度でフレームを作っていましたが、そのうち3分の1ほどが画面に出ていませんでした。

どこでカクつくのかを見るために、フレームレート表示を作りました。1行目はゲームが作った1秒あたりのフレーム数と実機に対する速度、2行目は画面に新しく出たフレーム数と画面の更新回数です。1行目が正常な速度なのに2行目だけが低ければ、ゲームではなく画面側の問題です。一時停止メニューの「画面」でオンとオフを切り替えられます。

DSのゲームは3Dを1秒に30回描くことが多く、重いフレームと軽いフレームが交互に来ます。すると2枚のフレームがほぼ同時に出来上がります。画面は更新のたびに一番新しいフレームを取っていたため、ほぼ同時に出来た2枚のうち前の1枚を表示できずに飛ばしていました。

今は、フレームごとに画面に出す時刻を決めます。ゲームがそのフレームを出すはずだった本来の時刻に、短い待ち時間を足した値です。フレームは4枚までためておき、画面は更新のたびに、表示時刻になったフレームのうち一番新しいものを表示します。同時に出来た2枚も、それぞれ自分の順番で1枚ずつ表示されます。

待ち時間は最初、ほとんどのフレームが出来上がる時間を基準にし、その後は直近2秒間でいちばん遅く出来上がったフレームに合わせました。しかし遅いフレームがその範囲から外れると待ち時間が短くなり、別のフレームを飛ばす問題が起きました。今はフレームが設定した待ち時間より遅れて出来上がると、待ち時間をすぐに増やし、そのまま維持します。1フレーム分短くしてもすべてのフレームを予定どおり表示できる状態が30秒続いてから、その分だけ短くします。待ち時間は最大2フレームです。表示が少し遅れても、カクつきを減らすほうを選びました。

iOSとAndroidはどちらもこの方式で表示するフレームを選びます。ゲーム機の実行周期と画面の更新周期の差が1.2%以内なら、ゲームの速度を画面の更新周期に合わせ、音の再生速度も同じ割合で調整します。iOSでは、DSの3D画面をゲームの実行とは別のスレッドで描くようにしました。DSのコアをビルドするときにリンク時最適化(LTO)を有効にする変更も加えました。

実機で確かめたのはiPhone 1台だけです。Android端末やほかのゲームでどれだけ均等に表示されるかは、まだ測っていません。

  1. 開発の話v1.3.0クローズドベータテスト

    ランアヘッドでボタンの反応を早める

    ゲームはボタンを読んでから1フレーム以上たって結果を画面に描きます。ランアヘッドはそのフレームを先に動かして反応を早め、計算が増える分バッテリーを多く使います。

  2. 開発の話v1.2.0クローズドベータテスト

    一時停止画面の繰り返し処理を減らす

    画面が止まっていても描画処理は続くことがあります。1.2.0では再描画が必要な場面を区別し、設定を保存前に試せるようにしました。

一覧に戻る対応機種と機能