繰り返しになりますが、エディタの導入をお願いします。
エディタは、プログラムを書くためのソフトです。
テキストの、ツール・素材の紹介ページにエディタがありますので、ダウンロードして使いましょう。
こちらです。
特に、Windows の方は xyzzy を必ず使って下さい。
本格的にプログラムを書く上で、ちゃんとしたエディタを使うことは欠かせません。
絶対にメモ帳を使ってはいけません。
※勘違いしている方が多いようですが、メモ帳などのエディタはあくまで 「テキストファイルを編集するためのソフト」です。
メモ帳で保存したからといって、保存するデータが変わるわけではありません。
メモ帳で保存しても、xyzzy で保存しても、保存される .java ファイルの形式は変わりません。
しかし、メモ帳を使って作業をされると、今後困りますので、極力 xyzzy を使うようにしてください。
プログラミングが苦手で、上手くいかず質問してくる人ほど xyzzy を使っていないケースが多く、非常に困ります
自力でできず、TA・SAに質問しようという人は、必ず xyzzy を使うようにして下さい。
まず、本日の講義資料をダウンロードしてください。
第6回資料(Windows用)
第6回資料(Mac用)
前回の授業では、画面にボールを複数出すことを学びました。
それを元に、ボールの出てくる場所をバラバラにしてみましょう。
乱数とは、ランダムな数値(バラバラな数字)のことです。
要するに、サイコロと同じだと考えて下さい。
サイコロを振ると、1 〜 6 の数字のどれかを返します。
(つまり、サイコロは 1 〜 6 の乱数を生成しています。)
GameCanvas では、gc.rand(1, 6); と書くと、サイコロを一回振ったのと同じことになります。
以下のような感じで使用します。
// 受け取る変数を定義 int random_num; (中略) // gc.rand(1, 6); は 1 〜 6 のうちいずれかの値を返し、random_num はその値を保持する random_num = gc.rand(1, 6);
実際に使ってみましょう。
ダウンロードした資料を解凍して、Sample01フォルダ直下にあるgame.javaを開いて下さい。
Sample01 は、前回の講義の Sample03 を元に変更を加えたものです。見比べながら考えてみましょう。
/********* 初期化の手順はこちらに *********/ public void initGame() { for(int i=0; i<10; i=i+1) { // ボールの座標を初期化する // X座標を、0 〜 600 の範囲の乱数で初期化する ball_x[i] = gc.rand(0, 600); ball_y[i] = 0; (中略) } (以下略) }
前回の講義の Sample03 と比べて、変更した箇所は 1 ヶ所だけです。
ball_x[i] = gc.rand(0, 600); で、ボールのX座標を 0 〜 600 の範囲のいずれかの数字で初期化しています。
コンパイルして実行してみましょう。
ボールの現れる場所がバラバラになっているのが分かりますね。
スコア(点数)をつけてみましょう。
Sample02フォルダ直下にあるgame.javaを開いて下さい。
このプログラムでは、弾をラケットで打ち返す度に点数を10点追加しています。
現在の点数は、画面の左上に描画しています。
/********* 変数定義はこちらに *********/ // 型 変数名; の順に書いて定義する (中略) // 点数 int score; /********* 初期化の手順はこちらに *********/ public void initGame() { (中略) // 点数を初期化 score = 0; }
変数定義に、点数を保持する score を追加しています。
初期化部分では、score を 0 で初期化しています。
/********* 物体の移動等の更新処理はこちらに *********/ public void updateGame() { (中略) // ボールと、ラケットが当たった場合に真 if(gc.checkHitRect(racket_x, racket_y, racket_w, racket_h, ball_x, ball_y, 24, 24)) { // ボールのY方向の速度を反転させる ball_speed_y = -ball_speed_y; // 点数を10点加算する score = score + 10; } }
ボールが当たった際に、点数を10点足しています。
score = score + 10; の部分です。
/********* 画像の描画はこちらに *********/ public void drawGame() { (中略) // 点数を描画します gc.drawString("Score " + score, 0, 0); }
gc.drawString("Score " + score, 0, 0); で、画面の左上に点数を描画しています。
文字列の後に + 変数名(あるいは数字)と書くと、文字列に数字をつなげることができます。
"Score " + score で、"Score scoreの中の数字" という文字列になります。
今までゲームをプレイした中で一番良かった点数(スコア)のことを、ハイスコアといいます。
ハイスコアを画面に表示してみましょう。
Sample03フォルダ直下にあるgame.javaを開いて下さい。
Sample03 は、Sample02 を元に変更を加えたものです。見比べながら考えてみましょう。
/********* 変数定義はこちらに *********/ // 型 変数名; の順に書いて定義する (中略) // 点数 int score; // ハイスコア int high_score; /********* 初期化の手順はこちらに *********/ public void initGame() { (中略) // 点数を初期化 score = 0; // ハイスコアを初期化 high_score = 0; }
変数定義に、ハイスコアを保持する high_score を追加しています。
初期化部分では、high_score を 0 で初期化しています。
/********* 物体の移動等の更新処理はこちらに *********/ public void updateGame() { (中略) // ボールが画面の下を越えた場合 if(ball_y > 480) { // 最初の状態に戻す // ボールの座標を初期化する ball_x = 0; ball_y = 100; // ラケットの座標を初期化する racket_x = 270; racket_y = 450; // 点数を初期化する score = 0; } // ボールと、ラケットが当たった場合に真 if(gc.checkHitRect(racket_x, racket_y, racket_w, racket_h, ball_x, ball_y, 24, 24)) { // ボールのY方向の速度を反転させる ball_speed_y = -ball_speed_y; // 点数を10点加算する score = score + 10; // 点数がハイスコアを上回っていたら if(score > high_score) { // ハイスコアを更新 high_score = score; } } }
ボールが当たった際に、点数がハイスコアを上回っていたら、ハイスコアの更新をする処理を追加しています。
加えて、ボールが画面下を越えた場合に、必要な変数を初期化する処理を追加しています。
/********* 画像の描画はこちらに *********/ public void drawGame() { (中略) // 点数を描画します gc.drawString("Score " + score, 0, 0); gc.drawString("HighScore " + high_score, 200, 0); }
スコアの隣りに、ハイスコアを描画する処理を追加しています。
GameCanvas では、データをセーブデータに保存し、後で保存したデータを読み込むことが&できます。
では、実際の使い方を見てみましょう。
Sample04 フォルダ直下にあるgame.javaを開いて下さい。
Sample04 では、ゲームを終了する際にハイスコア情報を保存し、ゲームを起動した時に保存したハイスコア情報を読み込んでいます。
/********* 初期化の手順はこちらに *********/ public void initGame() { (中略) // ハイスコアを読み込む high_score = gc.load(0); } (中略) /********* 終了時の処理はこちらに *********/ public void finalGame() { // ハイスコアをセーブ gc.save(0, high_score); }
finalGame() は、右上の×ボタンを押してゲームを終了した場合に実行される処理です。
ここでは、終了した時にハイスコアを 0 番にセーブしています。
initGame() では、0 で初期化する代わりに、0 番にセーブしたデータを読み込んでいます。
セーブデータが無い場合には 0 が返されるので、セーブデータが無い場合でもちゃんと 0 で初期化することができます。
※ 難しい項目ですので、腕に自信のある方以外は読み飛ばしてもらってかまいません。
関数を使うと、複数の命令を1つにまとめることができます。
実は、今までの講義で使ってきた gc.drawImage などの gc. で始まる命令は全て関数です。
GameCanvas 側で用意されたこれらの関数は、複雑な処理をひとつにまとめ、簡単にゲームを作れるように工夫されています。
では、関数の作り方を学んでいきましょう。
関数を使いこなすことで、より良いプログラムが書けるようになります。
関数の自作に挑戦してみましょう。
Sample05 フォルダ直下にあるgame.javaを開いて下さい。
このプログラムは、画面を青く塗りつぶすだけの単純なものです。
(中略) /********* 画像の描画はこちらに *********/ public void drawGame() { // 青く塗りつぶす関数を呼ぶ clearBlue(); } /********* 終了時の処理はこちらに *********/ public void finalGame() {} // 青で画面を塗りつぶす関数を定義 void clearBlue() { // 色を青にセット gc.setColor(0, 0, 255); // 画面を塗りつぶす gc.fillRect(0, 0, 640, 480); }
一番下で、clearBlue という関数を定義しています。
この関数の中には、2 つの命令が記述されています。
定義した関数 clearBlue は、drawGame 内で呼ばれています。
clearBlue が呼ばれると、clearBlue の中身が上から順に実行されます。
(ここでは、色を青にセットし、その色で画面を塗りつぶしている)
もう一つ具体例を見てみましょう。
Sample06 フォルダ直下にあるgame.javaを開いて下さい。
Sample06 は、Sample04 を元に変更を加えたものです。
ボールが画面の下を超えた場合の初期化処理を、関数としてまとめています。
// ゲームスタート時の状態に初期化する関数を定義 void resetGameValue() { // ボールの座標を初期化する ball_x = 0; ball_y = 100; // ラケットの座標を初期化する racket_x = 270; racket_y = 450; // 点数を初期化する score = 0; }
一番下で、resetGameValue という関数を定義しています。
この関数の中に、ゲーム中に変化する変数の初期化命令をまとめています。
/********* 初期化の手順はこちらに *********/ public void initGame() { (中略) // ゲーム中に変更される変数を初期化 resetGameValue(); } /********* 物体の移動等の更新処理はこちらに *********/ public void updateGame() { (中略) // ボールが画面の下を越えた場合 if(ball_y > 480) { // ゲーム開始の状態に初期化する関数を呼び出す resetGameValue(); } (中略) }
resetGameValue 関数は、ゲーム内で変化していく値だけを初期化する関数です。
initGame 内と、updateGame 内でボールが画面の下を超えた場合に呼ばれています。
このように、いくつかの場所に同じような処理がまとまっている場合に、関数を使うと非常に便利です。
同じ内容を何度も書かずにすみますし、変更する場合も、一箇所書き換えるだけですみます。
関数を呼び出す際にカッコの中に書く数字のことを、引数と言います。
例えば、gc.setColor(0, 0, 255); は、3 つの引数を持つ関数です。
Sample05, Sample06 で作った関数は、カッコの中になにもないので、引数無しの関数です。
引数を活用した関数を定義してみましょう。
Sample07 フォルダ直下にあるgame.javaを開いて下さい。
引数に渡した数値を使って、画面を塗りつぶす関数を定義しています。
(中略) /********* 画像の描画はこちらに *********/ public void drawGame() { // 画面を塗りつぶす関数を呼ぶ // ここでは、赤で塗りつぶしている clearWindow(255, 0, 0); } /********* 終了時の処理はこちらに *********/ public void finalGame() {} // 引数に渡した数値を使って、画面を塗りつぶす関数を定義 void clearWindow(int r, int g, int b) { // 色を青にセット gc.setColor(r, g, b); // 画面を塗りつぶす gc.fillRect(0, 0, 640, 480); }
定義された clearWindow 関数には、int 型の3つの引数 r, g, b があります。
そして、drawGame では、255, 0, 0 の引数で drawGame を呼び出しています。
ここで呼び出された clearWindow の引数はそれぞれ、r は 255、g は 0、b は 0 です。
つまり、gc.setColor(r, g, b); は、gc.setColor(255, 0, 0); として実行されます。
関数は、値を返すこともできます。この返す値を、戻り値といいます。
例えば、gc.rand は、int 型の値を返す関数です。
それでは、戻り値の例を説明します。
Sample08 フォルダ直下にあるgame.javaを開いて下さい。
このプログラムでは、引数に与えた数字を 2 乗して返す関数を定義しています。
/********* 変数定義はこちらに *********/ // 型 変数名; の順に書いて定義する int value; (中略) /********* 物体の移動等の更新処理はこちらに *********/ public void updateGame() { value = square(7); } (中略) // 引数に渡した数値を使って、画面を塗りつぶす関数を定義 int square(int n) { return n * n; }
square という、int 型の引数 1 つをとり、2乗した値を返す関数を定義しています。
return 値; と書くと、その値が返されます。
return された時点で関数は終了するので、return より下に命令を書いても実行されません。注意しましょう。
square の前に書いてある int は、戻り値の型です。
ここでは、int 型の値を返すと定義しています。
なお、ここに void と書くと、値を返さない関数となります。
その場合は、return 文を書かなくてもエラーにはなりません。
updateGame 内で、square() を呼んでいます。
この関数の中では、n * n で引数を二乗して、return でその結果を返しています。
今までの課題と、今回の授業内容を組み合わせて、1人用テニスゲームを完成させてください。
自分なりに工夫して、面白いゲームを作ってみましょう。
また、余裕のある方は、関数にチャレンジしてみましょう。