=======================================
           第5回: 得点の表示と乱数の発生
=======================================

*基本課題

1、外側に枠を作り、ボールが枠に当たる度に枠の色が変わるようにしてみよう。

2、ボールを受け損ねた時に「GAME OVER」と表示させるようにしてみよう。


*応用課題

3、バーでボールを受けた回数を右上に表示させよう。

4、上の壁に当たった時にボールが乱反射するようにしてみよう。


*難関応用課題

5、ボールが当ったら消滅する「的」を複数作ってみよう。

=======================================

基本課題ができると、、、文字が表示できるようになる!

応用課題ができると、、、ボールの動きに意外性が!

ということで、頑張りましょう。

=======================================

<課題ができたら>


・SFCで提出
  SFSの課題のページから提出してください。

  一番進んだ課題のgame.javaを添付して、
  コメント欄に内容と説明と感想(5行程度)を書いてください。

もちろん、SAのチェックも忘れずに。

=======================================

1、外側に枠を作り、ボールが枠に当たる度に枠の色が変わるようにしてみよう。

枠はgc.drawRectで書きます。


当たった回数を数える変数を用意して、
何回当たったかを数えるようにしましょう。

宣言
int point;

初期化
point=0;

跳ね返り処理の所で
point++;

これで跳ね返る度にpointの値が増えていきます。

あとは、跳ね返り回数に応じて色が変わるようにしましょう。

{
白色に;
g.fillRect();//背景塗り潰し

if(point%3==0){赤色に;}//pointを3で割った余りで色を決定
if(point%3==1){青色に;}
if(point%3==2){緑色に;}
g.drawRect();//枠を描く

ボールを描く
}

・%演算子

A%BでAをBで割った余りが返って来ます。

Aが1のとき、A%3は1
Aが3のとき、A%3は0
Aが5のとき、A%3は2

Bで割った余りなので、値は0〜(B−1)の範囲の整数です。
A%3だと、値は0または1または2になります。

・色の決定

gc.setColor(0xRRGGBB);

RR,GG,BBには、色の各要素(Red,Green,Blue)の強さを16進数で入れます。

最小は00,最大はFF,中ぐらいだと80,あたりを使います。

0xFF0000 →赤
0x00FF00 →緑
0x0000FF →青

0xFFFF00 →黄色
0xFF8080 →ピンク

などなど。
色々な値を入れて好きな色を探してみましょう。

※16進数
人間には少々扱いづらいですがコンピューターにとって非常に扱いやすいので、
プログラムでよく使用されます。

10進数は10種類の数字を使って数を表現します。
(0,1,2,3,4,5,6,7,8,9)
9に1足すと、桁が上がって10になります。

16進数は16種類の数字を使って数を表現します。
(0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F)
Fに1足すと、桁が上がって10になります。

値の前に「0x」を付けて10進数と区別します。

0x0F= 15
0x10= 16* 1+ 0 =  16
0x32= 16* 3+ 2 =  50
0x80= 16* 8+ 0 = 128
0xFF= 16*15+15 = 255

=======================================

2、ボールを受け損ねた時に「GAME OVER」と表示させるようにしてみよう。

文字の表示。

gc.drawStringというメソッドを使います。

gc.drawString(String str,int x,int y);

最初の引数が表示する文字列、
次の引数が表示するx座標、y座標、

gc.drawString("test",50,20); //(50,20)にtestと表示

前回の課題で
gameState==1の時がゲームがストップしている状態なので、
この時に文字を表示させるようにします。

drawGame(){
  画面クリア
  ボールとバーの表示

  if(gameState==1){
    ゲームオーバーと表示
  }
}


=======================================

3、バーでボールを受けた回数を右上に表示させよう。

回数を数える為に変数が必要です。

int point; point=0;

文字表示メソッドで変数をしていすると、その値が表示されます。

例:
gc.drawString("SC:"+point,50,20); //(50,20)に"SC:"の文字のあとpointの値を表示

座標は適当なので自分で調整してください。


=======================================

4、乱反射するようにしよう。

毎回同じように跳ね返るとつまらないので、
跳ね返る際に速度等を乱数(ランダム)で決めてやります。

gc.rand(min,max);
を呼ぶと最小値(min)から最大値(max)までの間の値が入ります。

a = gc.rand(0,2);

と呼ぶとaの値は0〜2になります。

a = gc.rand(0,6);

aの値は0〜6になります。

a = gc.rand(-3,3);

aの値は-3〜3になります。

また、1から5の乱数が欲しい時は、、、

a = gc.rand(1,5);

としてやればOKです。


=======================================
5、ボールが当ったら消滅する「的」を複数作ってみよう。



まずは的が表示できるようにしましょう。
背景出した時と同様に画像を作って読み込みましょう。

また、的の状態を示す変数が必要です。

int blockflag;
blockflag=1;//初期化

的がある場合は1を、無い場合は0を入れておくことにします。
このように1=オン、0=オフという状態を入れておく為の変数を
フラグと言います。

blockflagが1の時のみ的を表示させましょう。

if(blockflag==1)gc.drawImage(IMG_BLOCK,50,50);//ブロック描画

次に、ボールが的に当った時に的を消す処理を入れます。

座標(50,50)に縦12横12の的を書いたとすると、

if(x> 50-12 && x < 50+12 && y > 50-12 && y< 50+12 && blockflag==1){

  /* ボールが的に接触していて、かつ的が存在している */

  blockflag=0;

  /* 的を消した時にスコアを加えたいならここで加える */
}

という処理をすれば、ボールが当った時に箱が消えます。

この当り判定はビットマップとビットマップの接触を見ているので、
実際に当っていなくてもブロックが消えてしまします。
(ボールのbitmapの場合、bitmapの4隅は表示していない)

気になる人は正しい当り判定なり対処法なりを
考えてみましょう。

的を動かしたい場合はボールと同様に座標を変数で持たせて、
座標を変化させる処理を加えます。
「2発当てると壊れる」的を作ってみるのも良いでしょう。
色々工夫してみてください。

※変数booleanについて

javaやc++にはboolean型の変数という、
yes(true)とno(false)、二つの状態のみを表現する変数があります。
状態が二つしかない場合はbooleanを使うと綺麗でわかりやすいです。

boolean blockflag; //boolean型の変数blockflagを宣言

blockflag=true; //初期化

if(ボールと的が接触&&blockflag)blockflag=false;

if(blockflag) 的を描画;

※条件(blockflag)は(blockflag==true)と同じ意味です。

ただ、「2発当てると壊れる」的等を作りたくなった場合は
状態が2種類以上になりますので、(初期状態、1発当てた状態、壊れた状態)
int型を使った方が作りやすいと思います。

=====
<的を複数作る>

・的の作り方のまとめ

まあ端的に言えば、的の有無を示す為の変数を用意して、
的がある時のみ表示してあげるようにします。
で、ボールが的に重なった時に、的の有無を示す変数の値を
「有」→「無」に変更してあげれば、
ボールが当たると消える的を作ることができます。

この部分を複数個つくれば複数の的ができます。

プログラムをひたすらコピー&ペーストする方法もありますが、
ここでは配列を使う方法について書いておきます。

配列変数というのは値を入れる箱(=変数)いくつも並んでいるものです。
普通の変数との違いは、変数の名前の後に[]が付いていて、
[]の中の数値で何番目の箱か指定します。

int blockflag[] = new int[3];

こうすると、blockflag[0],blockflag[1],blockflag[2]の
3個の変数が使えるようになります。

blockflag[0]=1; //1個目の箱の状態を「有」に
blockflag[1]=1; //2個目の箱の状態を「有」に
blockflag[2]=1; //3個目の箱の状態を「有」に

今までは箱のx,y座標は同じ場所でしたが、
3個とも同じ場所だと1個しか見えないので、
それぞれの箱がどこにあるか、場所を保存するために変数が必要です。

int blockx[] = new int[3];
int blocky[] = new int[3];

blockx[0]= 10; blocky[0]=10; //1個目の箱の座標を(10,10)に
blockx[1]= 10; blocky[1]=70; //2個目の箱の座標を(10,70)に
blockx[2]= 50; blocky[2]=50; //3個目の箱の座標を(50,50)に

さらに表示部分も3個つくります。
ここで、繰り返しの文forを使います。

forの一番簡単な使い方は

for(int i=0;i<繰り返す回数;i++){
  繰り返す内容
}

こうすると、iの値が0から1ずつ増えていきつつ、
繰り返す内容を繰り返す回数だけ実行します。

繰り返す内容の所に

if(blockflag[i]==1){
  gc.drawImage(blockImg,blockx[i],blocky[i]);
}

と書いてあげれば、繰り替えしの1回目はiの値が0なので
blockflag[i]はblockflag[0]を指すことになり、
blockflag[0]の内容にしたがってボールを描画します。
繰り替えしの2回目はblockflag[1]の内容にしたがってボールを描画、
繰り替えしの3回目はblockflag[2]の内容にしたがってボールを描画、
となり、ボールを3個それぞれの場所に描くことができます。

あとは、ボールと壁のあたり判定の部分も3回分記述してやれば
この課題については完成です。

=======================================

余談


再来週の授業は、月曜に慶早戦が行われた場合、休講になります。
土日で決着がつかないと、月曜試合が行われる可能性がありますが、
もし月曜が雨だと試合は行われません。

ですから、休講になる条件は、

if( 土日で決着がつかない && 月曜が晴れ )

と書けます。

また、土日で決着がつかないのは、
土日の試合で1勝1敗だったか、土日どちらかが雨で流れた時です。
この条件は

if( 土日の試合で1勝1敗 || 土日どちらかが雨で流れた )

と書けます。

&&や||を混在させる時は、条件を()でくくります。
ということで、

if( ( 土日の試合で1勝1敗 || 土日どちらかが雨で流れた ) && 月曜が晴れ ){
  来週は休講;
}

です。

=======================================