ボールが複数ある時にはその中の一つが上下左右の壁に当たって進行方向を変えると全部のボールが進行方向を変えてしまいます。クリックで進行方向を変える改造をする前は、各ボールは別々に跳ね返っていました。
これはクリックして進行方向が変わることを各ボールに伝えるためdx, dyをグローバル変数、つまり全部のボールに共通な変数にしてしまったことによります。
ボールの動きを見るだけならこれはこれでおもしろいかもしれませんが、ボールが多くなると動く範囲が狭くなってしまいますし、せっかく独立させた動きが一体で動くように見えてしまいます。
dxとdyを個別のスレッドの変数にもどして、クリックされたことを別の方法で知らせることを考えます。
今回はスレッドに名前がついていませんからスレッドを特定して呼びかけるわけにはいきません。スレッドの方から共通な変数にアクセスするという制約で考えます。
greenやblueのクリック数をグローバル(共通な)変数として導入します。クリックがあるとこの値を増やします。それぞれのボールでこの変数の値をローカル(共通でない)変数にコピーし、2つの値が異なっていればdx,dyを操作して変数もコピーしなおします。変数の値が同じであれば新しいクリックがなかったものとしてなにもしません。
MoveDisk6.javaをもとに変更していきます。
MoveDisk7のフィールドからdx, dyを取り除き、moveDiskクラスに移します。
MoveDisk7のフィールドに緑ボタンのクリック数、青ボタンのクリック数を記録する変数をいれます。
ローカルにも必要なのグローバル変数をgctgrn.gctbluとし、ローカルをctgrn,ctbluとします
class MoveDisk7{ int gctgrn = 0; int gctblu = 0; //int dx = 0; //int dy = 10; actionPerformed(){...} main(){...} class MyPanel{ paintComponent(){...} drawRdm(){...} nextColor(){...} } class moveDisk{ int dx = 0; int dy = 10; int ctgrn; int ctblu; run(){...} } }
MoveDiskのコンストラクタにgctgrn,gctbluのコピーを加えます。これは必須ではありません書かない場合は最初からdx,dyの処理が入るということになるだけです。
//constructor public moveDisk(MyPanel pn, BufferedImage im) { this.pnl = pn; this.image = im; //y = (int)(image.getHeight()*Math.random()); y = 100; x = (int)(image.getWidth()*Math.random()); ctgrn = gctgrn; ctblu = gctblu; }
カウントが等しくない時はdx,dyの交換をします。そのあとでローカルのカウントをグローバルに合わせます。
while ( true ){ if (gctgrn != ctgrn) { int tmp = dx; dx = dy; dy = tmp; ctgrn = gctgrn; } if (----??----) { //blueについても同様に } thg.setColor(bc); thg.fillOval(lx-d/2,ly-d/2,d,d);
actionPerformed にはいままでdx,dyの交換がありましたが、今回はカウンタgctgrn,gctbluの値を増やすだけです。
public void actionPerformed(ActionEvent e) { // .................. if (e.getSource() == gbtn) { gctgrn++; } if (e.getSource() == bbtn) { gctblu++; }
MoveDisk6.javaをもとにします
上記の様に働くようにし、動作を確認しなさい。