2009-04-23 22 views
1

私が以前の質問で言ったように、私はまだJavaを初めて使っています。 私はJavaでタイルベースのゲームを開発しています。動きはグリッド上にあります。私はキャラクターの動きを実装している段階にいます。SwingWorker、スレッド、またはこのアニメーションの再帰的な更新を使用する必要がありますか?

私はthis questionに貼り付けたコードを使用する予定でした。しかし、これはうまくいかず、私はSwingWorkerを使うべきだと言われました。

問題解決のために、私はこの日を考えていましたが、私は考えました。 私は少し違ったやり方で同じ効果を達成することができました。

私は、20ミリ秒ごとにオフになったタイマーを持っていたと書いてありました。

私の考えは、私は彼らの先(次の四角/タイル)寄り人1つのユニットのすべてを移動することになる、タイマーのイベントで再描画する前に、メソッド呼び出しを持っているということでした。 そのようなことができますか?ゲームの後半に100人ほどの人がいるかもしれません。 20msはすべての人を回り、1つのユニットを目的地に近づけるのに十分な時間でしょうか? 20msも短すぎますか?私はちょっと意味がないのですか?

ご意見/答え/思考は歓迎されている:)

答えて

2

OK、最初に20ミリ秒の質問に答える。あなたは20msでかなりのゲームロジックを得ることができます。しかし、私はそれがディスプレイを更新するにはあまりにも頻繁であると言います。また、OSは通常、10〜20 msのタイムスライスの順序でCPUを処理することを覚えておく必要があります。つまり、いつでも別のプロセスが、その時間だけプロセスを容易に遅延させる可能性があります。例えば、behaviour of Thread.sleep()の私の記事では、システムが適度にビジーであるため、OSが要求したスリープ時間を守ることができないというグラフからの通知を見てください。 100msのフレーム間で平均的なスリープが必要な場合は、ここで20ms程度のジッタがあまりにも悪くはありません。しかし、あなたが20msを頼んだときに20msのジッタが目立つようになるでしょう...

だから、おそらく10フレーム/秒(100ms休止)から始まり、その様子が見えます。

コードに関しては、ゲームロジックのダニタイムが同じかそれ以上になる場合は、各ティックごとにlogic-repaint-sleepを使用します。ペイントしているものを同期させる必要があることを覚えておいてください。ゲームのロジックスレッドでは、ロックを長すぎる状態にしないでください。

+0

ありがとうNeil。私は実際にあなたの記事に出くわして、かなり数回それを読んだ! Thread.sleep()の領域では非常に有益です。 あなたが100msと示唆したように試して、それがどうなるか見てみましょう。 ご協力いただきありがとうございます! :) – Relequestual

1

スイングのこのエリアには、Javaで何のおそらく最も「ブラックマジック」を持っています。それは手間がかかり、多くのアプローチがあります。

最も重要なルールは、あなたがAWTスレッドである場合を除き、画面を変更しないことですが、画面を変更するよりもはるかに多くのためAWTスレッドを使用しないでください。

すべてのスイング(ボタンリスナーのような)「コールバック」はAWTスレッド上で来ているので、あなたは通常、このことについて考える必要はありませんが、アクティブレンダリング状況のために、あなたは細心の注意を払わなければなりません。

は、一般的にこのような大規模システムでは、あなたが(すべてのデータを移動します)一度に全体の計算を行い、その後はワンステップで描画する必要があるすべてのものを再描画します。

だから、ほとんどの部分は、あなたが、あなたはトップレベルのコンポーネントで再描画関数を呼び出すと思い、継続的なスレッドに完全にあなたの塗料系外に計算します。 Repaintは、AWTスレッド上のすべてのコンポーネントにペイントイベントを配信する必要があります。そのため、問題は発生しません。

次に、各コンポーネントはその状態(すでに更新済み)を調べ、その情報を使用して自身を描画する必要があります。

これは、基本的に行われるべき方法ですが、それが遅くなることができ、それをスピードアップするためのトリックがたくさんあります。あなたは、スイングプログラミングとゲームを含む本を探したいかもしれません。

+0

あなたの答えをありがとう。どのようにそれを行うことができるかについて、私の頭の中でより多くのものを通して物事を考えさせることができました! – Relequestual

2

Billは、特にスイングは謎めいている部分(他のグラフィックス環境に比べるとあまり意味がありません)にはほとんど同意します。

いくつかの参考文献を挙げると、30fps(ほとんどのインターレースされた画面が生成するもの)は33msごとに1フレームです。 60 fpsは人間が知覚できる最高レベル(1フレーム/ 16 ms)で、ほとんどのLCDモニターは60または75 Hzでリフレッシュします。これは実際に生成できる最高速です。 20ms /フレームは50fpsのフレームレートであり、ヨーロッパの地域での電気周波数と一致し、人間の目によっては目に見えます。

私が推奨する主なことは、タイトなwhileループですべてを行うことです。これにより、あなたのゲーム速度はあなたがプレイしているシステムに大きく依存します。より速いシステムでは、たとえそれが古いもので合理的にプレイされていても(または、老朽化し​​たマシンで逆の問題を抱えていても)、プレーヤーが反応できるよりも速くフレーム噴出を得ることができます。タイマーを使用するとレートの一貫性を保つことができますが、フレームの締め切りを逃した場合に備えて防御チェックを行う必要があります。これは、タイマーが計算が終了した時点を知る必要があることを意味し、別のフレームが目盛りをつけて終了していない場合は、次のフレームをスキップします。さらに、計算の間に実際に経過する時間を記録し、それに応じてキャラクターが実際に移動した動きを調整します。

もう1つの警告:図面はAWTスレッド上で実行されなければならず、(プログラムの応答性を維持するために)計算はAWTスレッド上で更新する必要があります。計算を行うスレッドがゲームの状態を更新するようにすると、AWTスレッドは再描画の途中でこれを見て、引き裂きという効果をもたらします。したがって、AWTスレッドにポストするために状態のコピーを作成する必要があるかもしれません。これはSwingWorkerのためのもので、おそらくTimerと組み合わせて使用​​します。

驚いたことに、私が言ったことのほとんどは、あなたの他の質問に投稿したものと比べると、実際には新しいものです。

+0

もう一度ありがとうございました。これは、どのように動作するかを私の理解に最も有益であることが証明されています。私はまだStringWorkerがどのように使用されているのかちょっと混乱していることを認めていますが、少なくとも今、私はその理由を理解しています!私はNeilが言ったことと一緒に行くつもりだと思います。そして、今度は、それぞれのチックで論理 - 再描画 - 睡眠を行うことで、今のところシングルスレッドにしておきます。後でSwingWorkerをする必要がある場合は、私の質問が再び表示されます。ご協力いただきありがとうございます! :) – Relequestual

関連する問題