テキストをちゃんと読んでから質問してください。
テキストをしっかり読まずに、図やテキストを流し読みをして分かった気になって、テキストを読めば分かることを質問してくる方が非常に多いです。
繰り返しになりますが、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のラケットが上下左右に移動できるようになっている