終了した時にクリアできたことを表示して栄誉をたたえることもゲームの要素です。とりあえず Cleard と表示しましょう。
run()メソッドのwhileが終わった時がクリアです。Cleardを表示する部分はそこに書くのが適当です。
@Override public void run() { while ( tmax > clearct ){ 前回の●を四角■で消す クリアしていない障害物●を描きなおす 障害物に衝突していたらクリアを記録し四角■で消す greenボタンをクリックしていたらdx,dyを交換し正負反転する blueボタンをクリックしていたらdx,dyを交換する xにdxを加え、パネルからはみ出したら跳ね返らせる yにdyを加え、パネルからはみ出したら跳ね返らせる ●を描く 何ミリ秒か待つ } Cleardと表示する。 }
} //end of while // Cleardと表示する。 int sx = xmax/4; int sy = ymax/4; thg.drawString("Cleared",sx,sy); // ↑ sx,sy に Cleared と書く mypnl.repaint(); } //end of run()
場所は上から高さの1/4、左から幅の1/4の位置です。場所はいいのですが、文字が小さすぎます。これはBufferedImageの大きさがパネルの2倍あり、それを縮小して描いているからです。
文字の大きさを指定するにはいくつか方法があるようですが、Fontクラスを使うのが手軽です。図形の色の指定に似ています。
Font f=new Font(フォント名,スタイル,サイズ); //Font(String name, int style, int size) thg.setFont(f);
フォント名は"courier","TimesRoman"のような個別の名前も使えますが、セリフ、サンセリフなどの種類の名前も使えます。これは予めjavaが定数として設定しています。クラス名Fontをつけて使います。
Font.SERIF Font.SANS_SERIF Font.MONOSPACED Font.DIALOG
スタイルは太字とか斜体などの設定です。これも予めjavaが定数として設定しています。クラス名Fontをつけて使います。
Font.PLAIN Font.BOLD Font.ITALIC
サイズはデフォルトで12になっているようです。
とりあえず、ymax/8にしておきます。BufferedImageにあわせて決めないとBufferedImageが変わったときに小さくなったりはみ出したりしてしまいます。
ついでに色も変えました。
int sx = xmax/4;
int sy = ymax/4;
Font f=new Font(Font.SANS_SERIF,Font.PLAIN,ymax/8);
thg.setFont(f);
thg.setColor( new Color(255,153,51) );
thg.drawString("Cleared",sx,sy);
mypnl.repaint();
このとき、同時にクリックした回数や、壁に跳ね返った数を別々に、あるいはその合計数をも表示する様に工夫します。この数を少なくすることを競うゲームとします。たとえばCleardに加えて
int sx = xmax/4; int sy = ymax/4; Font f=new Font(Font.SANS_SERIF,Font.PLAIN,ymax/8); thg.setFont(f); thg.setColor( new Color(255,153,51) ); thg.drawString("Cleared",sx,sy); thg.drawString("Click "+(greenct+bluect),sx,sy+ymax/8); // ↑ sy+ymax/8 で1行下の場所を求め クリック数を書く thg.drawString("Bounce "+bouncect,sx,sy+ymax/4); // ↑ sy+ymax/4 で2行下の場所を求め 壁に当たった数 bouncect を書く mypnl.repaint();
もちろんbouncectは予め宣言をし、数えておく必要があります。
宣言と初期化はMoveDiskのフィールドか、run()メソッドの最初に置きます。
int bouncect=0;
あとは跳ね返りの処理をしているところ(複数あります)に bouncect++; と書くだけです。
正しく数えているかはゲームを何度かやってみるとわかります。
上記の様に働くようにし、動作を確認しなさい。
クリアまでの時間を競うというのもゲームのよくあるパターンです。やってみましょう
System.currentTimeMillis()は現在時をミリ秒単位で知らせてくれます。戻り値はintでなくlongです。(実際には1970年1月1日からの現在までの経過時間を返します)
ゲームの最初に
long time0 = System.currentTimeMillis();
として時刻を記録し、ゲームの終わりに、
long time1 = System.currentTimeMillis();
として時刻を再度記録します。
time1-time0
は、かかった時間をミリ秒単位で計測したものになります。つまり16000となれば16秒ということです。
普通は1000で割って秒に直します。
(time1-time0)/1000
longとintの計算なので整数に切り捨てられます。
少数点以下も表現したいときは次のようにします。
(time1-time0)/1000.0
run()のwhileの前に
long time0 = System.currentTimeMillis();
whileの{ }の後に、
long time1 = System.currentTimeMillis();
結果を整数にして良ければ次のように表示するのが簡単でしょう。long÷intはlongになりますからStringと+演算で整数として連結されます。小数も同様な方法で出せますが、その場合は桁数のコントロールをしないとはみ出します。
Font f=new Font(Font.SANS_SERIF,Font.PLAIN,ymax/8); thg.setFont(f); thg.setColor( new Color(255,153,51) ); thg.drawString("Cleared", sx,sy ); thg.drawString("Click "+(greenct+bluect), sx,sy+ymax/8 ); thg.drawString("Bounce "+bouncect, sx,sy+ymax/4 ); thg.drawString("Time "+((time1-time0)/1000),sx,sy+ymax/8*3); mypnl.repaint();
上記の様に働くようにし、動作を確認しなさい。