Java AWTは2Dゲームのレンダリングに適していますか?


8

[この質問の方が適していると指摘されたため、stackoverflowからこの質問を再投稿します。]

現在、2DゲームエンジンをJavaに移植しています。Stackoverflowでここで指摘されているゲームライブラリのいくつかを調べました。しかし、私が見たものはかなり単純化されており、アルファ透明度のようなものをサポートしているかどうかさえ述べていないため、ロジックをすでに記述しているC ++レンダラーを移植することにしました。

このレンダラーは、タイリングを使用して不要な再レンダリングを回避する純粋なソフトウェアレンダラーです。出力ペインより少し大きい「オフスクリーンバッファー」を作成し、このオフスクリーンバッファーをすべてのフレームの出力にブリットすることで、スクロールパフォーマンスを最適化しました。このようにして、マップ上でピクセルをスクロールしたからといって、タイルを不必要に再描画することを回避できました。

JavaのAWTを使用して実装し、オフスクリーンバッファーに大きなBufferedImageを使用しました。CPU使用率は問題ありません(C ++の約2倍です)が、連続スクロールに奇妙な問題があり、毎秒程度、レンダラーが約0.2秒間遅延します。

私のコードにはこれらの期間に発生するものはなく、オフスクリーンバッファーをメインビューに描画しないとスパイクがなくなるので、Javaが独自の内部最適化を行っていると結論付けることができます。ただし、それが何をするのかわかりません。また、スパイクを取り除くために削除する必要がある自分自身の最適化もわかりません。また、Java AWTは継続的で高FPSのスクロールを考慮して作成されたのではない可能性があり、この目的にはまったく使用できません。

これらのスパイクを取り除く方法はありますか?


4
ガベージコレクターがあなたを襲っていますか?
bummzack 2011

@bummzack:たぶん。プロファイラーでは、次のようになります。i.imgur.com / EMxkA.pngただし、特にgraphics.drawImageへの呼び出しが原因で発生する場合は、この影響をどのように減らすかわかりません
cib

回答:


4

あなたのコードを見てみないとわからないのですが、あなたの問題はガベージコレクターのようです。Javaでは、メジャーガベージコレクションとマイナーガベージコレクションが時々行われています。未成年者はCPUの一部を使い果たしますが、あまりバグを起こしません。主要なコレクションは、実行中にすべてを一時停止するため、ゲームなどのリアルタイムアプリにとって大きな問題になる可能性があります。

これを解決するには2つのオプションがあります。最初に、JVMを調整して、行われる主要なコレクションが少なくなるようにします。第二に(そして推奨されます)、ゴミを残しすぎないようにすることができます。アプリのどこに多くのオブジェクトを作成するか(私のゲームでは通常vector3クラスです)を確認し、可能な限りそれらを(特に内部ループなどで)再利用することを確認します。


2

はい。

2Dスプライトベースのゲームの場合、AWTを使用してレンダリングを処理し、効果を高めることができます。利用可能なハードウェアによっては、ハードウェアアクセラレーションも可能です。

コードや詳細なプロファイリングスニペットがなければ、問題が何であるかを言うのは困難です。私ができる最善のことは、ゲームを構築するときにJavaとAWTを操作するためのいくつかの基本的なヒントを提供することです。

ガベージコレクターの操作

JavaでのGCは、ゲームを構築する際に心に留めておかなければならないことです。これは定期的に実行され、それらへの参照がないオブジェクトを探し、メモリから削除します。この除去プロセスは遅く、発生しているヒッチの原因である可能性があります。

私の提案は、実行の存続期間中(または少なくとも、可能な限り)保持されないオブジェクト参照の作成を回避することです。理想的な目標は、GCが実行されるたびに何も実行しないようにすることです。

実際には、ゲーム全体で再利用する多くの静的変数が生じる可能性があります。これは私がそれに対処する傾向がある非常に不自然な例です:

public final class Resources {
    public static Map<int, String> strings;
    public static Map<int, Texture> textures;
    public static Map<int, GameObject> objects;
    public static Map<int, SoundEffect> sounds;
}

画面の読み込み中はMapnewキーワードを使用してインスタンスを拡大または縮小できます。しかし、プレイ中は、できる限りそれを避けたいでしょう。プレイ中に何かが破壊された場合は、オブジェクトにフラグを設定して、それが現在アクティブなものではないことを確認します。新しいオブジェクトを生成する必要がある場合Mapは、アクティブではないオブジェクトが見つかるまでを調べ、そのオブジェクトのプロパティを設定してアクティブとしてマークします。

これは、レンダリングにAWT、JavaFX、またはOpenGLを使用しているかどうかに関係なく、パフォーマンスに敏感なアプリケーションにJavaを使用する場合に覚えておきたいものです。

キャンバス

特にAWTの場合、さまざまな理由でCanvasクラスを使用してすべてをレンダリングすることを強くお勧めします。

  • レンダリングのタイミングをより細かく制御できます。つまり、独自のゲームループを記述して、補間、外挿、レート制限などを行うことができます。
  • パフォーマンスが良いようです。一連のLabelオブジェクトとImageオブジェクトをアニメーション化しようとするのではなく、許容可能なフレームレートで一度に画面上により多くのものを取得できました。
  • エディターに埋め込む方が簡単です。通常のGUIコントロールでフレームを設定し、ゲームのレンダリングロジックをCanvasに向けることで、エディターツールでゲームのレンダリングコードを再利用できるようになりました。
  • Java2D API(別名Graphics2Dクラス)に簡単にアクセスできます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.