テキストをちゃんと読んでから質問してください。
テキストをしっかり読まずに、図やテキストを流し読みをして分かった気になって、テキストを読めば分かることを質問してくる方が非常に多いです。
繰り返しになりますが、xyzzy、Emacsなどのエディタの導入をお願いします。
特にWindows の方は xyzzy を必ず使って下さい。
エディタの導入方法はこちらです。
プログラミングが苦手で、上手くいかず質問してくる人ほど xyzzy を使っていないケースが多く、非常に困ります
自力でできず、TA・SAに質問しようという人は、必ず xyzzy を使うようにして下さい。
まず、今回の講義資料をダウンロードしてください。
第3回資料(Windows用)
第3回資料(Mac用)
ダウンロードした資料を解凍して、Sample01フォルダ直下にあるGame.javaを開いて下さい。
まず最初に、ラケットの位置を表す変数、racket_x、racket_y を定義し、初期化しています。
/********* 変数定義はこちらに *********/ // 型 変数名; の順に書いて定義する // ラケットのX座標 int racket_x; // ラケットのY座標 int racket_y; /********* 初期化の手順はこちらに *********/ public void initGame() { // ラケットの座標を初期化する racket_x = 270; racket_y = 450; }
続いて、更新・描画処理です。
/********* 物体の移動等の更新処理はこちらに *********/ public void updateGame() {} /********* 画像の描画はこちらに *********/ public void drawGame() { // 画面を白で塗りつぶします gc.clearScreen(); // 色を青にセットします gc.setColor(0, 0, 255); // (racket_x, racket_y)の位置に、幅100, 高さ20 の長方形を描画します gc.fillRect(racket_x, racket_y, 100, 20); }
Sample01では、ラケットを塗りつぶした長方形として表現しています。
gc.fillRect で、塗りつぶした長方形を画面に描画することができます。
塗りつぶした長方形ではなく、辺だけを描画したい場合は、gc.drawRect を使うこともできます。
まず、gc.setColor(0, 0, 255); で、色を青にセットしています。
そして、gc.fillRect(racket_x, racket_y, 100, 20); で、塗りつぶした長方形を描画しています。
この際、塗りつぶす色は、直前でセットした青となります。
サンプルの数字を変えたり、新しい命令を追加したりして、色々と試してみましょう。
次に、ラケットを動かしてみます。
右キーが押されている場合は右へ、左キーが押されている場合には左へ移動するようにします。
そのためには、キー情報を取得しなければなりません。
isKeyPushed(キー); などの命令を使って、キー入力の状態を調べることができます。
それぞれの命令は以下の通りです。
GameCanvas内で使えるキーは、以下の通りです。
上で学んだことを活かして、ラケットを動かしてみましょう。
Sample02フォルダ直下にあるGame.javaを開いて下さい。
/********* 物体の移動等の更新処理はこちらに *********/ public void updateGame() { // 左キーが押された場合に真 if(gc.isKeyPushed(gc.KEY_LEFT)) { // ラケットを左に動かす racket_x = racket_x - 5; } // 右キーが押された場合に真 if(gc.isKeyPushed(gc.KEY_RIGHT)) { // ラケットを右に動かす racket_x = racket_x + 5; } }
更新処理以外は、Sample01と同じです。
ここでは、左キーが押されたら左に 5 動かし、右キーが押されたら右に 5 動かしています。
if(gc.isKeyPushed(gc.KEY_LEFT)) は、左キーが押された瞬間のみ真になります。
if(gc.isKeyPushed(gc.KEY_RIGHT)) は、右キーが押された瞬間のみ真になります。
ラケットにテニスボールが当たったら、テニスボールが跳ね返るようにしましょう。
Sample03 フォルダ直下にあるGame.javaを開いて下さい。
まず最初に、テニスボールとラケット用の変数を定義し、初期化しています。
/********* 変数定義はこちらに *********/ // 型 変数名; の順に書いて定義する // ボールのX座標 int ball_x; // ボールのY座標 int ball_y; // ボールのX方向の速度 int ball_speed_x; // ボールのY方向の速度 int ball_speed_y; // ラケットのX座標 int racket_x; // ラケットのY座標 int racket_y; /********* 初期化の手順はこちらに *********/ public void initGame() { // ボールの座標を初期化する ball_x = 0; ball_y = 100; // ボールの速度を初期化する ball_speed_x = 5; ball_speed_y = 5; // ラケットの座標を初期化する racket_x = 270; racket_y = 450; }
次は、updateGame 内を見てみましょう。
// 左キーが押された場合に真 if(gc.isKeyPushed(gc.KEY_LEFT)) { // ラケットを左に動かす racket_x = racket_x - 5; } // 右キーが押された場合に真 if(gc.isKeyPushed(gc.KEY_RIGHT)) { // ラケットを右に動かす racket_x = racket_x + 5; }
これは、左キーが押されたらラケットを左に、右キーが押されたらラケットを右に動かす処理です。
Sample02 で学びましたね。
// Y方向に ball_speed_y ずつ進める ball_y = ball_y + ball_speed_y; // X方向に ball_speed_x ずつ進める ball_x = ball_x + ball_speed_x; // ボールが画面の上を越えた場合 if(ball_y < 0) { // ボールのY方向の速度を反転させる ball_speed_y = -ball_speed_y; } // ボールが画面の右を越えるか、画面の左を越えた場合 if(ball_x > 616 || ball_x < 0) { // ボールのX方向の速度を反転させる ball_speed_x = -ball_speed_x; }
こちらは、ボールを動かす処理と、画面端で跳ね返らせる処理です。
忘れてしまった方は、前回の講義を見返してみましょう。
前回と異なり、画面下を越えた場合のみ跳ね返らないようにしています。
以下の部分が、今回のポイントとなる部分です。
// ボールと、ラケットが当たった場合に真 if(gc.checkHitRect(racket_x, racket_y, 100, 20, ball_x, ball_y, 24, 24)) { // ボールのY方向の速度を反転させる ball_speed_y = -ball_speed_y; }
ここでは、ラケットにボールが当たるかどうか、つまりラケットとボールが重なるかどうかをチェックしています。
そして、重なった場合にのみ跳ね返らせています。
このような、2つの物体が重なるかどうかをチェックすることを、当たり判定と呼びます。
GameCanvas では、以下の命令を使って当たり判定を行うことができます。
Sample03 の場合、ラケットを 幅100 高さ20 の四角形、ボールを 幅24 高さ24 の四角形として、2つの四角形が重なるかどうかを判定しています。
なお drawGame では、画像とラケットをそれぞれ描画しています。
/********* 画像の描画はこちらに *********/ public void drawGame() { // 画面を白で塗りつぶします gc.clearScreen(); // img0.png を(ball_x, ball_y)に描画します gc.drawImage(0, ball_x, ball_y); // 色を青にセットします gc.setColor(0, 0, 255); // (racket_x, racket_y)の位置に、幅100, 高さ20 の長方形を描画します gc.fillRect(racket_x, racket_y, 100, 20); }
当たり判定命令が、内部的にどのように判定しているのかを、ここで詳しく説明してみます。
難しいと感じた方は、無理に理解せずとも問題ありません。
以下の4つの条件を全て満たした場合、2つの四角形 A, B は重なります。
図:当たり判定の解説
当たり判定を行う2つの物体を、それぞれ A, B とします。
A の 座標は(x1, y1) 、幅と高さは w1, h1 です。
同様に、B の座標は(x2, y2)、幅と高さは w2, h2 です。
これを前述の条件に当てはめてみると、以下の式となります。
これをプログラムで表現すると、以下のようになります。
if( x1 < x2 + w2 && x1 + w1 > x2 && y1 < y2 + h2 && y1 + h1 > y2)
今回の授業で作ったプログラムを改造します。
押した瞬間だけしか移動できなかったラケットを、押しっぱなしで移動できるようにしてください。
Kadai01フォルダの中のGame.javaを元に挑戦してみましょう。
Kadai01フォルダの中のanswer01.jar ファイルを開くと、どのようにすれば良いか見ることができます。
図:課題1の実行画面。左右キーを押すとラケットがその方向へと動き、ボールに当るとボールが跳ね返る
課題1の内容を改良します。
ラケットの幅と高さを、それぞれ半分にしてください。
その際、幅と高さは、それぞれ変数が保持するようにしましょう。
Kadai02フォルダの中のGame.javaを元に挑戦してみましょう。
Kadai02フォルダの中のanswer02.jar ファイルを開くと、どのようにすれば良いか見ることができます。
図:課題2の実行画面。課題1の半分のサイズのラケットが表示されている
課題2の内容を改良します。
左右にしか移動できなかったラケットを、上下にも移動できるようにしてください。
Kadai03フォルダの中のGame.javaを元に挑戦してみましょう。
Kadai03フォルダの中のanswer03.jar ファイルを開くと、どのようにすれば良いか見ることができます。
図:課題3の実行画面。課題2のラケットが上下左右に移動できるようになっている