2009-04-21 12 views
4

私はおそらくこれを間違っているので、素敵にしてください。 私はJavaゲームを開発しており、キャラクターの動きやアニメーションをテストする段階にあります。Javaの別のクラスからの再描画を呼び出しますか?

「人物」は、グリッド上で左右に上下に移動できます。 グリッドが描画されるクラスは、gamePanelクラスです。 ボタンは、gameControlPanelクラスにあります。

私は、グリッド上に人を生み出すボタンを持っています。 私は人を左右に動かすためのボタンがあります。

[上へ移動]ボタンを押すと、その人のクラスから上へ移動メソッドが呼び出されます。 ...その方法では 次のコードである(現時点では、私は。一度に一つの「人」をテストしています)

int move = 10; 
while(move!=0) 
{ 
    setTopLeftPoint(new Point((int)getTopLeftPoint().getX(), 
           (int)getTopLeftPoint().getY() - 3)); 

    try 
    { 
     Thread.sleep(300); 
    } catch (InterruptedException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    move-=1; 
} 

問題は、私が呼ぶように見えることはできませんということですPersonクラス内のgamePanelクラスの再描画メソッド。 これを回避するため、gamePanelクラスに20msごとに再描画するタイマーを作成しました。

生まれた後に上ボタンを押すと、whileループのサイクルが完了するまでボタンが押し下げられたままになり、上のグリッドの四角にその​​人の円表示が表示されます。

私はこれに関するご質問にお答えしようとします。

答えて

1

一定の間隔で再描画したい場合は、javax.swing.Timerがおそらくクラスです。 repaintという特殊なケースでは、EDT以外のスレッドから呼び出すことはできますが、現在は複数のスレッドを処理しているので難しいかもしれません。

+0

私は、複数のスレッドが私にとっては複雑すぎると信じています。私は人々がこの問題に対する一種の答えと考えるべき別の質問を持っています。私は、100msのタイマーごとにロジック - ペイント - スリープを行うことに決めました。 – Relequestual

0

ゲームを作る経験はあまりありませんが、すべてのアニメーションを制御するループを持つことは、ゲームプログラミングの基本的な側面です。ほとんどのシンプルな2Dゲームでは、ほとんどのアニメーションをレンダリングするために1つのループしかありません。

私の経験では、たくさんのものをレンダリングする良い方法は、ゲーム内のすべてのエンティティのコレクションを1か所にまとめて、Graphicsオブジェクトを各エンティティに渡すこのコレクションをループすることです。

これにより、各エンティティはグラフィックスオブジェクトに自身を描画できます。これはそれを行うための単なる方法です。

synchronized (entities) { 
    for (Entity e : entities) { 
     e.draw(g); 
     e.doAction(); 
    } 
} 
+0

はい、私は確かにこれを行いますが、上のボタンをクリックすると、whileループを使って-3を上にずらして位置を変更することになっています。絵画は変わらない。 私はちょっと間違っているかもしれないと思う。 – Relequestual

+0

私は見ると思います。それはゲームループと同じスレッドであなたの人の動きをしているようです。したがって、あなたの人は移動しますが、移動中(whileループ中)は、メインループが待っているので、メインループが再描画されません移動する人、眠る人、移動する人などです。それは良い習慣ではありませんが、あなたの人の動きをするために新しいスレッドを生成することができます。 –

+0

OK、私はこれを行うことができるかもしれません。これが良い習慣でないなら、どうすればいいでしょうか? – Relequestual

0

GUIのイベントディスパッチスレッドでボタンプレスを処理していますか?

これが当てはまる場合、GUIの再描画メソッドは、イベントディスパッチスレッドが終了するまで(つまり、ボタンが離されてループから壊れるまで)起動しません。私は最近この問題を抱えていました。私が示唆できる最良の解決策は、移動アルゴリズムを使ってクラスをスレッド可能にし、キー押下が検出されたときにスレッドを起動させることです。これにより、イベントディスパッチスレッドが終了し、GUIが再描画できるようになります。

スレッディングの詳細については、Starting a threadを参照してください。

+0

私はあなたの質問に何を意味するのか分かりません。私は私が知っている限りスレッディングを扱っていません。私はまだJavaの方が新しいです。前の答えは役に立つと思われるコメントを残しました – Relequestual

+0

私はあなたに何か非常に難解なことをしない限り、確かに尋ねましたが、答えはほぼ「はい」です。上記のSwingWorkerの代わりに独自のスレッドを作成することもできます。 –

+0

私はSwingWorkerを使用していると思うか、別のスレッドが少し複雑になってしまうかもしれません。私はこの問題に関してさらに質問をしようとしています。あなたの助けをありがとう – Relequestual

2

repaint()は直ちにGUIを再描画しません。むしろ、次の便利な機会にペイントするようにメッセージにAWTスレッドに通知します。チャンスを得ると、あなたのアプリを再描画します。ただし、イベントハンドラでこれを行う場合、AWTスレッドはすでにビジー状態であり、ハンドラを終了してAWTハンドラに制御を戻す必要があります。

AWTスレッド(イベントハンドラを含む)で長時間実行される計算は、計算が完了するまで他のイベントへの応答を停止するため、実行しないようにしてください完了しました。これは、あなたが説明したような固まったボタンとしてユーザーに表示されることがよくあります。これを回避するには、別のスレッドで計算を実行できるSwingWorkerを使用します。

最後に、注意する必要があることは(ただし必ずしも変更する必要はありません)、タイマーとスリープが目を覚ますタイミングを保証するものではありません。むしろ、時間の経過する前に目を覚まさないことを保証しますが、理論的には無期限に眠ることができます。また、すべてのマシンが1ミリ秒のタイマー分解能を持つわけではありません。特に、多くのWindowsマシンでは、タイマーの分解能は55msしかないため、20msタイマーは奇妙な結果をもたらす可能性があります。

+1

この有益な情報をありがとう。私はまだゲームの非常に基本的なテスト段階にあるので、誰が知っている。私はスイングワーカーを簡単に見ましたが、それは私には本当に混乱しています。S – Relequestual

+0

SwingWorkerは間違いなくあなたがここで必要なものです。多くのJavaのように、それは急な学習曲線を持っていますが、一度理解すれば、おそらくそのタイマーは必要ありません。 –

関連する問題