ゲームとしての体裁を整え、テニスゲームを完成させよう!

注意点

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

エディタ(導入必須)

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

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

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

タイトル画面を作る

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

今までの授業で作ってきたテニスゲームに、タイトル画面を追加してみます。
ダウンロードした資料を解凍して、Sample01フォルダ直下にあるGame.javaを開いて下さい。

今回は、変数定義にゲームの状態を表す変数gameStateが追加され、0で初期化されています。

/********* 変数定義はこちらに *********/

(中略)

// ゲームの状態
int gameState;

/********* 初期化の手順はこちらに *********/
public void initGame()
{

(中略)

    // ゲームの状態を初期化
    gameState = 0;
}
	

続いて、更新処理内で変数gameStateがどのように利用されているか見てみましょう。

/********* 物体の移動等の更新処理はこちらに *********/
public void updateGame()
{
    // タイトル画面
    if(gameState == 0)
    {
        // Enterキーが押されたらゲーム開始
        if(gc.isKeyPushed(gc.KEY_ENTER))
        {
            gameState = 1;
        }
    }
    // ゲーム画面
    else if(gameState == 1)
    {
        (中略)
    }
}
	

gameState の中身に応じて、画面が切り替わっています。
今回は、0 がタイトル画面、1 がゲーム画面です。

最初は、gameState の中身が 0 なので、if(gameState == 0) が真となり、タイトル画面の部分が実行されます。
Enterキーが押されると、gameState の中身は 1 となります。
gameState の中身が 1 の場合、else if(gameState == 1) の方が真となり、ゲーム画面の部分が実行されます。
(ゲーム画面部分の処理は、前回までにやった内容と同じです)

このように、画面に応じてゲームの状態が切り替わっていくことを、シーン遷移といいます。

 

最後は描画処理です。更新処理同様、こちらでも gameState の中身に応じた場合分けを行っています。

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

    // タイトル画面
    if(gameState == 0)
    {
        // タイトル画面の文字を描画
        gc.setColor(0, 0, 0);
        gc.drawString("テニスゲーム", 250, 150);
        gc.drawString("Push Enter" , 260, 250);
    }
    // ゲーム画面
    else if(gameState == 1)
    {
        (中略)
    }
}
	

gameState の中身が 0 の場合は、タイトル画面用の文字を描画。
gameState の中身が 1 の場合は、ゲーム画面の描画となります。
(ゲーム画面部分の描画は、前回までにやった内容と同じです)

画面の塗りつぶしは常に行う必要があるので、
gc.clearScreen(); だけは、gameState の中身に関係なく実行されます。

ポーズ画面を追加してみる

プレイ中にEnter キーを押すことで、ポーズできるようにします。
Sample02フォルダ直下にあるGame.javaを開いて下さい。

それでは、更新処理について見ていきましょう。
なお、変数定義・初期化の部分は、Sample01 と同一ですので省略しています。

public void updateGame()
{
    // タイトル画面
    if(gameState == 0)
    {
         (中略)
    }
    // ゲーム画面
    else if(gameState == 1)
    {
        // ENTERキーが押されたらポーズ
        if(gc.isKeyPushed(gc.KEY_ENTER))
        {
            gameState = 2;
        }

         (中略)

    }
    // ポーズ画面
    else if(gameState == 2)
    {
        // Enterキーが押されたらゲーム再開
        if(gc.isKeyPushed(gc.KEY_ENTER))
        {
            gameState = 1;
        }
    }
}
	

今回は、0 がタイトル画面、1 がゲーム画面、2 がポーズ画面です。

ゲーム画面内に、Enterキーが押されたらポーズ画面へと切り替わる処理が追加されています。
ここでは、if(gc.isKeyPushed(gc.KEY_ENTER)) が真となった場合に、gameState の中身を 2 に書き換えています。

else if(gameState == 2) の部分は、ポーズ画面の処理です。
Enter キーが押された場合、gameState の中身を 1 に書き換え、ゲーム画面へと切り替えています。

 

続いて描画処理です。

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

    // タイトル画面
    if(gameState == 0)
    {
        (中略)
    }
    // ゲーム画面
    else if(gameState == 1)
    {
        (中略)
    }
    // ポーズ画面
    else if(gameState == 2)
    {
        // ポーズ画面の文字を描画
        gc.setColor(0, 0, 0);
        gc.drawString("PAUSE", 280, 200);
    }
}
	

drawGame にも、ポーズ画面の描画が追加されました。
gameState の中身が 2 の場合は、ポーズ画面の描画となります。

音楽を鳴らす

ゲームプレイ中に音楽(BGM)を鳴らしてみましょう。
Sample03フォルダ直下にあるGame.javaを開いて下さい。

resフォルダの中に、bgm0.mid, bgm1.mid ファイルがあります。 GameCanvas では、.mid 形式のファイルを音楽(BGM) として利用することが出来ます。
ゲームで使いたい音楽ファイルは、bgm0.mid, bgm1.mid, bgm2.mid ... というファイル名でなければなりません。

playBGM 命令で、音楽を鳴らすことができます。
stopBGM 命令で、鳴っている音楽を停止することができます。
BGMを複数同時に鳴らすことはできませんので、注意して下さい。

では、Game.java を見てみましょう。
Sample02のプログラムを元にして、BGMの再生処理と停止処理が追加されています。
Sample02からの変更点は、updateGame だけです。

/********* 物体の移動等の更新処理はこちらに *********/
public void updateGame()
{
    // タイトル画面
    if(gameState == 0)
    {
        // Enterキーが押されたらゲーム開始
        if(gc.isKeyPushed(gc.KEY_ENTER))
        {
            gameState = 1;

            // ゲーム開始なので、ゲーム画面の音楽を鳴らす
            gc.playBGM(0);
        }
    }
    // ゲーム画面
    else if(gameState == 1)
    {
        // ENTERキーが押されたらポーズ
        if(gc.isKeyPushed(gc.KEY_ENTER))
        {
            gameState = 2;

            // ポーズ中は曲を停止
            gc.stopBGM();
        }

        (中略)

    }
    // ポーズ画面
    else if(gameState == 2)
    {
        // Enterキーが押されたらゲーム再開
        if(gc.isKeyPushed(gc.KEY_ENTER))
        {
            gameState = 1;

            // ゲーム開始なので、再び曲を再生
            gc.playBGM(0);
        }
    }
}
	

タイトル画面からゲーム画面に変わる部分では、gc.playBGM(0); を実行して、ゲーム用の BGM を再生しています。
ゲーム画面からポーズ画面に変わる部分では、gc.stopBGM(); を実行して、BGM を停止しています。
ポーズ画面からゲーム画面に変わる部分では、gc.playBGM(0); を実行して、再びゲーム用の BGM を再生しています。

ゲームで使いたい音楽を探す

ゲームで使う音楽ファイル(.mid ファイル)を配布しているサイトをいくつか紹介します。
以下のサイトにある素材を利用する場合には、利用規約に従うよう留意しましょう。

効果音を鳴らす

ゲームプレイ中に効果音(SE)を鳴らしてみましょう。
Sample04フォルダ直下にあるGame.javaを開いて下さい。

resフォルダの中に、snd0.wav, snd1.wav ファイルがあります。
GameCanvas では、.wav 形式のファイルを効果音(SE) として利用することが出来ます。
ゲームで使いたい音楽ファイルは、snd0.wav, snd1.wav, snd2.wav ... というファイル名でなければなりません。

playSE 命令を使うと、効果音(SE)を鳴らすことができます。
stopSE 命令で、鳴っている全ての効果音(SE) を停止することができます。
BGM とは違って、同時に複数の効果音を鳴らすことが可能です。

では、Game.java を見てみましょう。
Sample02のプログラムを元にして、効果音の再生処理が追加されています。
Sample02からの変更点は、updateGame だけです。

/********* 物体の移動等の更新処理はこちらに *********/
public void updateGame()
{
    // タイトル画面
    if(gameState == 0)
    {
        (中略)
    }
    // ゲーム画面
    else if(gameState == 1)
    {
        (中略)

        // ボールと、ラケットが当たった場合に真
        if(gc.checkHitRect(racket_x, racket_y, racket_w, racket_h, ball_x, ball_y, 24, 24))
        {
            // ボールのY方向の速度を反転させる
            ball_speed_y = -ball_speed_y;

            // ラケットに当たったので、効果音を再生する
            gc.playSE(0);
        }
    }
    // ポーズ画面
    else if(gameState == 2)
    {
        (中略)
    }
}
	

ボールとラケットが当たった場合に、gc.playSE(0); を実行して、効果音を再生しています。

ゲームで使いたい効果音を探す

ゲームで使う効果音ファイル(.wav ファイル)を配布しているサイトを紹介します。
以下のサイトにある素材を利用する場合には、利用規約に従うよう留意しましょう。

課題1

今回の授業で学んだ内容を元に、テニスゲームを拡張して下さい。
以下の内容を全て満たした課題プログラムを作ってください。

Kadai01フォルダの中のGame.javaを元に挑戦してみましょう。
answer01.jar ファイルを開くと、どのようにすれば良いか見ることができます。


図:課題1の実行画面(タイトル)


図:課題1の実行画面(一時停止)


図:課題1の実行画面(ゲーム画面)


図:課題1の実行画面(ゲームオーバー)

課題2

課題1を、さらに改良してみましょう。
以下の内容を全て満たした課題プログラムを作ってください。

Kadai02フォルダの中のGame.javaを元に挑戦してみましょう。
answer02.jar ファイルを開くと、どのようにすれば良いか見ることができます。


図:課題2の実行画面(タイトル)


図:課題2の実行画面(一時停止)


図:課題2の実行画面(ゲーム画面)


図:課題2の実行画面(ゲームオーバー)


図:課題2の実行画面(クリア)

補足説明

Kadai02フォルダ内の Game.java のdrawGame 内を見ると、次のように書いてあると思います。

// 色を黒にセット
gc.setColor(0, 0, 0);
// 打ち返した回数と、画面下を超えた回数を描画
gc.drawString("Hit:" + ball_hit_num, 0, 0);
gc.drawString("Miss:" + ball_dead_num, 0, 32);
	

文字列の後に + 変数名(あるいは数字)と書くと、文字列に数字をつなげることができます。

"Hit:" + ball_hit_num と書くと、"Hit:ball_hit_num の中身の数字" の文字列が、
"Miss:" + ball_dead_num と書くと、"Miss:ball_dead_num の中身の数字" の文字列が、
それぞれ画面に表示されます。

例えば、図:課題2の実行画面(ゲーム画面) では、ball_hit_num の中身が4、ball_dead_num の中身が1だったので、
"Hit:4" "Miss:1" という文字列が表示されています。

戻る