STEP-03
ひっくり返せる石だけ回そう
64個の石を全部回転させるとなるとちょっとつらいので、カーソルの位置に石を置くとひっくり返せる石だけ回すことにしました。そのためには、ひっくり返せるかどうかを判断しないといけません。
そこで、新たに次の2つのメソッドを用意しました。
- boolean isPosibleToPlace(int x, int y, int color)
colorの色の石を(x,y)に置くことができるかどうかを調べてくれるメソッドです。- void updateRotate(int x, int y, int color)
(x,y)にcolorの色の石を置いた場合にどの石がひっくり返せるかを調べて、 boolean rotate[][]という配列にセットしてくれるメソッドです。さあこれでうまくいくかなと思ったのですが、マウスを動かしたときの、カーソルの反応が遅いということが気になってきました。これまでは、カーソルの表示もupdate()の中で行っていました。しかし、このメソッドは、描画要求のrepaint()をコールしてすぐに実行されるという保証がありません。そのため、カーソルの移動がどうしても一呼吸遅れてしまいます。
そこで、カーソルの表示に関しては、マウスイベント処理の中で直接画面に描画してしまうことにしました。これで、カーソルの移動をスムーズに行えるようになりました。
ところが、ここでまた問題が出てきました。前述の変更によって、描画処理が複数のスレッドで行われるようになったため、お互いが干渉しあうようになってきたのです。例えば、黒い色をセットして、さあ描くぞと思った矢先に、他のスレッドに色を変えられてしまったりとか、よくあるマルチスレッドの問題ですね。
これは、synchronizedを付加して、排他制御することにより解決しました。
それから、透過GIFファイルでアニメーションすると、前のコマが残ってしまうことに気がついたので、透過GIFをやめて背景色を黒にしてしまいました。背景に別のイメージを表示させようと思うとこれではマズイですけど、おそらくそこまでやらないので問題ないでしょう。
今回は、そんなにたいした変更はないだろうと思っていたのですが、いろいろと問題が出てきたために、プログラムもかなり変わってしまいました。
う〜む、やっぱりすんなりとはいきまへんですなあ。
[STEP-02へ] [Making of Othelloへ] [STEP-04へ]
Tips
- 即応性が要求される描画処理は、update()や、paint()の中でなく、 getGraphics()して直接画面に描画したほうが良いでしょう。
- 複数のスレッドで描画処理を行う場合、synchronized宣言で排他制御にしておかないとマズイです。
NAKAGAWA Masami ( nakagawa@yo.rim.or.jp )