プロが教えるわが家の防犯対策術!

こんにちは。javaをはじめて3ヶ月くらいなのですが、オブジェクト指向でうまくプログラムを書くことができません。オブジェクト指向の理解のために、簡単なプログラムを作っていて疑問がわきました。

JPanel上をクリックすると、ボールが発生して動くプログラムをつくっています。クラスBallをつくり、クリック時にインスタンス化されます。そのときボールの発生位置や、初速度が乱数で決まるようにしました。

ここで、ボールとボールが接したときに跳ね返るようにしたいのですが、各Ballオブジェクトは衝突時点における全てのBallオブジェクトを持っていなければならないのでしょうか?(クリックするごとにArrayListなどにBallオブジェクトをいれて、各ボールの衝突判定のときにそのArrayListを渡す)

でもこれだと、処理が遅くなってしまいそうで、心配なのですが、他にいい案はないでしょうか?

A 回答 (4件)

No2で回答した者です。


「仮想空間」について、既にNo3回答者様のご回答が付いていますが、view と 内部ロジックの分離(独立部品化)目的です。
いまのところ、2次元平面空間でJPanelに全空間表示している状態と思うので、分離のイメージが湧かないのかもしれませんが、ボール空間の一部のみ切り取ってスクリーン(JPanel)に投影というように考えるとより具体的イメージになるかとおもいます。ボール位置情報をintで保持するかdoubleにするかは、仮想空間側で決める事項となります。
全体を表示するのか、ズームしてどこか一部を表示するのかといったロジックを、座標変換ロジックとして、仮想空間クラス側のメソッドに組み込んでやれば、JPanel側は、どの領域を表示したいかのデータを引数で渡してメソッドを呼び出し、またはsetterメソッドで環境データ設定のようなことをしてから、投影後画像作成メソッドを呼び出して、投影後画像を取り出すといったことができます。
2次元から3次元への拡張時も、呼び出し用メソッド名や引数が同じになるように作っておけば、仮想空間クラスを変更してすげ替えるだけで、JPanel側の変更はごくわずかとなります。
この仮想空間クラス拡張をも考えると、インターフェースで、表示画像取り出しメソッド名を宣言して、統一するといったことをしておくとよりよいでしょう。

しかし、いっぺんにやろうとしても、すぐには動くものにならないので、とりあえずJPanelに全部組み込んで、まずは動くものを作ってみてもよいでしょう。
いろいろな部品の動作原理が解ってきたら、上記のことをもう一度思い出してクラスを分解していくと、こういう作りをすると拡張(変更)が楽なのかといったことが解ってくると思います。ここまでくれば、デザインパターンを勉強するとより洗練されたプログラムになっていくでしょう。
私も、レイトレーシングプログラムを作ったときに、3-4回ほどクラス構成全部作り換えてようやくMVCの基本を理解できたかなと思っています。
    • good
    • 0

こんにちは。



オブジェクト指向プログラミングの目的の一つは、プログラムをオブジェクトというパーツに分け、それぞれを独立性の高い部品として設計して変更やメンテナンスを容易にすることだと私は理解しています。

今回のケースで既に前の回答者様が仰っているように、ボールクラスと当たり判定を行うクラスを分けた方が良いというアドバイスは、まさにこの目的のためです。

ボールクラス自体をいじらなくても当たり判定の処理を独立して変更することができますし、仮にボール以外のものを同じようにパネル上で動かしたい場合も、その物体のクラスのみを設計するだけで当たり判定クラスは流用できるかもしれません。

さらに補足でご質問になっている、表示系座標と仮想座標の分離についてもこの目的のためと言えます。

JPanelの座標を直接使用している場合は、他の環境に移植する場合には何らかの変更をボールクラス自体に施す必要があるかもしれません。

しかし、ボールクラスが仮想空間座標を前提に設計されていれば、JPanel以外に表示させたい場合にもボールクラスそのものを変更する必要はなくなり、部品としての独立性を保てます。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。なんとなく理解してきました。
ボール以外のものもパネル上で動かすことを前もって考える場合には、描画物クラスという抽象クラスをボールクラスが継承して、判定クラスが描画物クラスを扱うようにすれば、判定クラスを変更しなくても、新しい描画物の種類を増やしていけますね。

また、仮想座標は、他の環境に移植する場合に、仮想座標とその環境のインターフェースだけを考えればいいようにするためのものなんですね。

つまりクラスとクラスのインターフェースを簡潔にして、クラスごとの独立性を高めるというのがオブジェクト指向の目的なんでしょうか。

お礼日時:2011/03/09 15:49

各ボール用クラスは、それぞれに固有のデータを持たせるだけで、他のことまで関知させない方が、よいでしょう。


ボール間の衝突判定は、ボール全部とボールの存在環境についての情報を握るクラスが行うようにします。
つまり、ArryListのインスタンスを保持するクラスに、各ボール間の衝突判定メソッドを組み込んで、ボールの移動方向や位置変更などを行わせます、画面の端へ行ったときの処理もここで組み込めます。
衝突判定は、各ボールから他のボールを全部リストすると2重計算になるので、既に計算した組は計算しないように組みます。2つの衝突だけ考えればいいなら、2重ループで、内部ループは、自分の番号より後方をみるだけでいいはず。3重衝突を考えると面倒になるのでとりあえず、2個組での衝突だけで考えた方がよいでしょう。

ボール全部についての情報を握るクラスは、JPanelではなく、仮想空間オブジェクトとして、別にクラスを作成すると、表示用JPanelとボール仮想空間での移動ロジックとの分離ができます。
クリックのたびに、呼び出すのは、仮想空間インスタンスが持つメソッドで、新規ボール登録メソッドと衝突判定メソッドを呼び出し、さらに表示用メソッド呼び出し。
移動での表示変更はThreadかTimer制御かな?このインスタンスを、仮想空間インスタンスと別に持つか、仮想空間インスタンス内に保持させるかどうかは、全体構成とのかねあいで決めてください。表示制御メソッド呼び出しのしやすさでは、表示用クラスの内部クラスで定義してもいいかも?
移動時の表示変更については、TimerTask().run()などから、仮想空間クラスの衝突判定メソッドを呼び出して、現在のボール情報を元に移動計算と内部データ更新を行う。その後、表示用メソッド呼び出しの手順。
概略こんな感じで、Object指向&MVC&UML的構成になると思いますけど解りますでしょうか?

この回答への補足

回答ありがとうございます。独学なので、いろいろと勉強になります。

ArrayListを保持するクラスが衝突判定するということと、衝突判定時のループのさせ方は理解できました。

>表示用JPanelとボール仮想空間での移動ロジックとの分離ができます。
という部分についてなのですが、これは、どういうことなのでしょうか?
仮想空間というのは、例えば、ボールが位置座標をintではなくdoubleで持つことができるようにするためのものですか?表示用クラスの表示メソッドで仮想空間の座標系から表示用クラスの座標系に座標変換するということでしょうか?

補足日時:2011/03/01 15:26
    • good
    • 0

n個のボールがあれば n(n-1)/2回の衝突判定は必要なので (状況によって減ることはあるが最悪これを覚悟しなきゃならない) それについてはあきらめるしかない.



でなんだけど, 「各Ballオブジェクトは衝突時点における全てのBallオブジェクトを持っていなければならないのでしょうか」がどういうことなのか, よくわかんない. そもそも「すべてのボールの情報を記憶する」クラスは存在するはずなので, そいつが衝突判定をすればいいだけではないんだろうか. カッコ内の「クリックするごとにArrayListなどにBallオブジェクトをいれて、各ボールの衝突判定のときにそのArrayListを渡す」というのも, 「誰が ArrayList などを持っているのか」「誰が誰にその ArrayList などを渡すのか」が明確じゃないので, 何とも言えない.
    • good
    • 0
この回答へのお礼

回答ありがとうございます。ボールクラスのメソッドで衝突判定しちゃってました。衝突判定するクラスをつくって、そのクラスがボール全体の情報を持ち、衝突判定するようにすればいいんですね。

お礼日時:2011/03/01 14:23

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!