ボールを動かしてみよう!

注意点

テキストをちゃんと読んでから質問してください。
テキストをしっかり読まずに、図やテキストを流し読みをして分かった気になって、テキストを読めば分かることを質問してくる方が非常に多いです。

エディタ(導入必須)

繰り返しになりますが、xyzzy、Emacsなどのエディタの導入をお願いします。
特にWindows の方は xyzzy を必ず使って下さい。

エディタの導入方法はこちらです。

プログラミングが苦手で、上手くいかず質問してくる人ほど xyzzy を使っていないケースが多く、非常に困ります
自力でできず、TA・SAに質問しようという人は、必ず xyzzy を使うようにして下さい。

テニスボールを動かす

まず、今回の講義資料をダウンロードしてください。
第2回資料(Windows用)
第2回資料(Mac用)

テニスボールを動かすためには、すこしずつ表示する場所を変える必要があります。
ダウンロードした資料を解凍して、Sample01 フォルダ直下にあるGame.javaを開いて下さい。

変数

変数は、数値などの値を保持するためのものです。
例えば、X = 1; と書くと、X に 1 が保存されます。

変数の名前は自分で決めることができますが、意味のある名前 にするよう心がけましょう。
絶対に適当な名前にしてはいけません。

では、今回のサンプルプログラムを順番に見ていきましょう。
まず最初は、変数の定義です。

/********* 変数定義はこちらに *********/
// 型 変数名; の順に書いて定義する
int ball_x;
int ball_y;
	

変数の型と名前をこの場所に書くことで、その変数をプログラム中で使うことが可能になります。

続いて、定義した変数の初期化です。

/********* 初期化の手順はこちらに *********/
public void initGame()
{
    // 初期値をセット
    ball_x = 300;
    ball_y = 0;
}
	

initGame 内で初期値(変数の最初の値)をセットしています。(変数に値をセットすることを「代入する」と言います)
initGame は、ゲームを起動した時に1度だけ呼ばれる部分です。
ここでは、ball_x に300, ball_y に 0 がそれぞれ代入されています。

続いて、1/30秒毎に自動的に実行される更新処理 updateGame を見ていきます。

/********* 物体の移動等の更新処理はこちらに *********/
public void updateGame()
{
    // Y方向に3ずつ進める(Y座標は、下が正方向)
    ball_y = ball_y + 3;
}
	

ここでは、ball_y の値を、毎回 3 ずつ加算しています。

これを延々と繰り返すことになるので、ball_y は毎回 3 ずつ増えていくことになります。

最後は、1/30秒毎に実行される描画処理 drawGame です。
ここで、変数に代入された値を使っています。

/********* 画像の描画はこちらに *********/
public void drawGame()
{
    // 画面を白で塗りつぶします
    gc.clearScreen();

    // img0.png を(ball_x, ball_y)に描画します
    gc.drawImage(0, ball_x, ball_y);
}
	

drawGame は、updateGameの後に必ず実行されるので、

これを延々と繰り返すことで、テニスボールが徐々に下へと落ちていきます。

加速してみる

今度はボールの落ちる早さを徐々に早くしてみましょう。
Sample02 フォルダ直下にあるGame.javaを開いて下さい。

/********* 変数定義はこちらに *********/
// 型 変数名; の順に書いて定義する
// ボールのX座標
int ball_x;
// ボールのY座標
int ball_y;

// ボールの速度
int ball_speed;

/********* 初期化の手順はこちらに *********/
public void initGame()
{
    // 初期値をセット
    ball_x = 300;
    ball_y = 0;
    ball_speed = 0;
}
	

まず、定義にボールの速度を表す変数 ball_speed が追加されました。
もちろん、この ball_speed 変数も初期化する必要があります。

それでは、追加した変数 ball_speed を利用して、ボールの加速を表現してみましょう。

/********* 物体の移動等の更新処理はこちらに *********/
public void updateGame()
{
    // Y方向にball_speed ずつ進める
    ball_y = ball_y + ball_speed;
    // 速度を1ずつ増やす
    ball_speed = ball_speed + 1;
}
	

updateGame 内では、先ほど 3 加算していたところが、ball_speed を加算するようになっています。
ball_speed は、毎回 1 ずつ 加算されていくので、ball_y に加算される値は、0, 1, 2, 3, 4 ... と、徐々に大きくなっていきます。

さきほどはずっと同じ速度(3)で下に落ちていましたが、今度は落ちる速度が少しずつ早くなりました。
(力学でいうと、前者は等速直線運動で、後者は等加速直線運動です)

壁に跳ね返らせる

今度は、ボールを壁に跳ね返らせてみましょう。
壁に跳ね返らせるためには、if文 を使います。

if文

if ( 条件式 ) と書くことで、条件が真である(成立する)場合のみ、直後のブロックが実行されるようになります。
条件が成立することを真(true)、条件が成立しないことを偽(false)といいます。

public void updateGame()
{
    x = x + 1;
    if(x > 10)
    {
        x = 0;
    }
}
	

例えば上のプログラムでは、x に1ずつ加算し、
x > 10、つまり x が10より大きくなった場合のみ、x = 0; が実行され、x が 0 になります。
x が 9 以下の場合は、x = 0; は実行されません。

条件式

以下に、条件式の例をいくつか紹介します。

// x より y が小さければ真
if(x > y)

// x より y が大きければ真
if(x < y)

// y が x 以上なら真
if(x <= y)

// y が x 以下なら真
if(x >= y)

// x と y が等しければ真
if(x == y)

// x と y が等しくなければ真
if(x != y)

// 条件式1 と 条件式2 の両方が真なら、このif文は真
if(条件式1 && 条件式2)

// 条件式1 か 条件式2 のどちらかが真なら、このif文は真
if(条件式1 || 条件式2)
	

else if

if(x > 1000)
{
    // ブロック1
}
if(x > 100)
{
    // ブロック2
}
if(x > 10)
{
    // ブロック3
}
	

上記のプログラムでは・・・

しかし、次のプログラムでは、また違った動作となります。

if(x > 1000)
{
    // ブロック1
}
else if(x > 100)
{
    // ブロック2
}
else if(x > 10)
{
    // ブロック3
}
	

else if 文は、if 文の直後にいくつか続けて書くことができます。
else if 文は、前の if 文が偽(不成立)であった場合にのみ、評価されます。

つまり、else if 文を使ったこのプログラムでは・・・

else

else 文は、一連のif 〜 else if 文の最後にのみ書くことができます。
else 文のブロックは、今までの条件が全て偽だった場合にのみ実行されます。

if(x > 100)
{
    // ブロック1
}
else
{
    // ブロック2
}
	

上記のプログラムの場合は、if ( x > 100 ) が偽だった場合、ブロック2が実行されます。

if(x > 100)
{
    // ブロック1
}
else if(x > 10)
{
    // ブロック2
}
else
{
    // ブロック3
}
	

こちらのプログラムの場合は、if ( x > 100 ) と else if ( x > 10 ) の両方が偽だった場合、ブロック3が実行されます。

if文は分かりましたか?
それでは、Sample03フォルダ直下にあるGame.javaを開いて下さい。

ボールを壁に跳ね返らせる

ここまでに学んだ if 文を使って、ボールを壁に跳ね返らせてみましょう。

まずは初期化処理です。 今回は、ボールの速度を3で初期化しています。

/********* 初期化の手順はこちらに *********/
public void initGame()
{
    // 初期値をセット
    ball_x = 300;
    ball_y = 0;
    ball_speed = 3;
}
	

続いて、1/30秒毎に呼び出される更新処理です。

/********* 物体の移動等の更新処理はこちらに *********/
public void updateGame()
{
    // Y方向に ball_speed ずつ進める
    ball_y = ball_y + ball_speed;

    // ボールが画面の下に達するか、画面の上に達した場合に真
    if(ball_y > 456 || ball_y < 0)
    {
        // ボールの速度を反転させる
        ball_speed = -ball_speed;
    }
}
	

ボールを動かした後で、画面端で跳ね返る処理を行っています。

ウインドウの座標系は、画面の左上が(0, 0)、右下が(640, 480) となるスクリーン座標系ですので、
このif 文は、ボールの y 座標が 画面の上か下 を越えた場合に真となります。


図:スクリーン座標系

if 文 のブロックの中では、ボールの速度を表す ball_spped の値の正負を反転させています。
変数名の前にマイナスをつけると、-1 を掛け算したのと同じ結果となります。
つまり -ball_y は、ball_y が 3 なら -3、ball_y が -3 なら 3 となるわけです。

このプログラムは、これを延々と繰り返すことになります。

課題1

ボールを斜めに動かし、壁に当たったら跳ね返るようにして下さい。
Kadai01フォルダの中のGame.javaを元に挑戦してみましょう。

Kadai01フォルダの中のanswer01.jar ファイルを開くと、どのようにすれば良いか見ることができます。


図:課題1の実行画面。ボールが斜めに移動し、壁にあたったら跳ね返っている

課題2

課題1を、壁に跳ね返るごとにボールの色が変わるように改良して下さい。
Kadai02フォルダの中のGame.javaを元に挑戦してみましょう。

Kadai02フォルダの中のanswer02.jar ファイルを開くと、どのようにすれば良いか見ることができます。


図:課題2の実行画面。ボールが斜めに移動し、壁に当たるたびに色が変わって跳ね返っている

課題3

課題2を、壁に跳ね返るごとにボールの速度が少しずつ速くなるように改良して下さい。
Kadai03フォルダの中のGame.javaを元に挑戦してみましょう。

Kadai03フォルダの中のanswer03.jar ファイルを開くと、どのようにすれば良いか見ることができます。


図:課題3の実行画面。ボールが斜めに移動し、壁に当たるたびに色が変わり、加速して跳ね返っている

戻る