ゲーム実装で身に付くプログラミング 4

ゲームオーバーに遷移する

ゲームオーバーに遷移する

「GameOver.java」ファイルを新規作成します。全ての色ブロックがなくなったらゲームオーバーです。ただし今回は解説を簡単にするため、ゲームオーバー画面は表示しません。

例えば、タイトル画面を参考にゲームオーバー画像とクリックでタイトル画面に遷移する処理を実装してみてください。

・サンプルコード「MainLoop.java」ファイル

(前略)
public class MainLoop extends JPanel {
(中略)

  public MainLoop(JFrame frame) {
(中略)
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int flg = 0; 
    for (int i = 0; i < colors.size(); i++) {
      Graphics2D g2d = (Graphics2D) g;
      ColorBlock c = colors.get(i);
      flg += c.update(getWidth(),getHeight());
      g2d.drawImage(c.image, c.pos[0], c.pos[1], this);
    }
    if ( flg <= 0 ) {
      timer.stop();
      frame.getContentPane().removeAll();
      frame.add(new GameOver(frame));
      frame.revalidate();
      frame.repaint();
    }
  }
}

【サンプルコードの解説】
「ColorBlock」クラスの「update」メソッドでは、色ブロックを移動した際に画面内に存在していればflgをインクリメントします。
flgが0なら色ブロックが全てなくなったとして現在のフレームの中身を全て削除し、新たに「GameOver」クラスを画面フレームに追加します。

・サンプルコード「GameOver.java」ファイル

import javax.swing.JPanel;
import javax.swing.JFrame;

public class GameOver extends JPanel {
  public GameOver(JFrame frame) {
    frame.getContentPane().removeAll();
    frame.add(new Title(frame));
    frame.revalidate();
    frame.repaint();
  }
}

【サンプルコードの解説】
ゲームオーバー画面のGameOverクラスは何もせず、すぐにTitleクラスのタイトル画面に遷移します。

背景色を表示する

やっとこのゲームの核心である背景色をセットします(図4)。背景色は赤緑青の色ブロックをクリックするとその色を強くするように計算します。

背景色の表示

・サンプルコード「MainLoop.java」ファイル

import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.Timer;
import java.util.Random;

public class MainLoop extends JPanel {
  private ArrayList<ColorBlock> colors = new ArrayList<ColorBlock>();
  private int[] rgb = {0,0,0};
  private JFrame frame;
  private Timer timer;

  public MainLoop(JFrame frame) {
    Random rand = new Random();
    this.frame = frame;
    int stage = Integer.parseInt(frame.getTitle());
    for (int i = 0; i < 3*stage; i++) colors.add(new ColorBlock(i%3));
    addMouseListener(new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        for (int i = 0; i < colors.size(); i++) {
          if ( colors.get(i).click(e) ) {
            rgb[colors.get(i).color]++;
            colors.remove(i);
            break;
          }
        }
      }
    });
    while ( rgb[0] == rgb[1] ) {
      rgb[0] = rand.nextInt(stage);
      rgb[1] = rand.nextInt(stage);
      rgb[2] = rand.nextInt(stage);
    }    
    timer = new Timer(100, e -> {
      // 毎フレームの処理 (更新・再描画)
      frame.repaint();
    });
    timer.start();
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int flg = 0; 
    for (int i = 0; i < colors.size(); i++) {
      Graphics2D g2d = (Graphics2D) g;
      ColorBlock c = colors.get(i);
      flg += c.update(getWidth(),getHeight());
      g2d.drawImage(c.image, c.pos[0], c.pos[1], this);
    }
    if ( flg <= 0 ) {
      timer.stop();
      frame.getContentPane().removeAll();
      frame.add(new GameOver(frame));
      frame.revalidate();
      frame.repaint();
    }
    if ( setBgColor() ) {
    }
  }

  private boolean setBgColor() {
    int max = (rgb[0]>rgb[1])?(rgb[0]>rgb[2]?0:2):(rgb[1]>rgb[2]?1:2);
    float i = 255/rgb[max];
    int r = (int)(i*(float)rgb[0]);
    int g = (int)(i*(float)rgb[1]);
    int b = (int)(i*(float)rgb[2]);
    this.setBackground(new Color(r,g,b));
    if ( rgb[0] == rgb[1] && rgb[1] == rgb[2] ) return true;
    return false;
  }
}

【サンプルコードの解説】
配列「rgb」プロパティの{赤,緑,青}の要素にランダムな整数値が代入されます。
クリックされたマウスカーソルの位置が色ブロックだった場合、その色のrgb配列の要素をインクリメントします。
「setBgColor」メソッドではrgb配列の中で最も大きい値の要素のインデックス(色)を取得します。その値で 255を除算した結果を変数「i」 とし、各要素にiを掛けた値を背景色に設定します。また、rgb配列の3要素がすべて同じ値の場合は、背景が白と判定してtrueを返します。

ステージクリアに遷移する

最後の仕上げです。「StageClear.java」ファイルを新規作成します。背景色が真っ白になったら「StageClear」画面に遷移しますが、何も表示せず次のステージへ進みます。

例えば、タイトル画面を参考にステージクリア画像とクリックでメインループに遷移する処理を実装してみてください。

・サンプルコード「MainLoop.java」ファイル

(前略)
public class MainLoop extends JPanel {
(中略)

  public MainLoop(JFrame frame) {
(中略)
  }

  @Override
  protected void paintComponent(Graphics g) {
(中略)
    if ( setBgColor() ) {
      timer.stop();
      frame.getContentPane().removeAll();
      frame.add(new StageClear(frame));
      frame.revalidate();
      frame.repaint();
    }
  }

  private boolean setBgColor() {
(中略)
  }
}

【サンプルコードの解説】
背景色が真っ白になったらステージクリアです。画面フレームを空にしてStageClearクラスを画面フレームに追加します。

・サンプルコード「StageClear.java」ファイル

import javax.swing.JPanel;
import javax.swing.JFrame;

public class StageClear extends JPanel {
  public StageClear(JFrame frame) {
    int title = Integer.parseInt(frame.getTitle()) + 1;
    frame.setTitle(Integer.toString(title));
    frame.getContentPane().removeAll();
    frame.add(new MainLoop(frame));
    frame.revalidate();
    frame.repaint();
  }
}

【サンプルコードの解説】
ウィンドウタイトルの"2"などがそのままステージ番号です。整数化し、インクリメントした値が次のステージの番号になります。
他はGameOver.javaのコードとほとんど同じで、違いはMainLoop画面に遷移するところだけです。

【コラム】人生ゲームを本で

本の1ページを1マスとして人生ゲームのアイデアを思いつきました。サイコロで出た目だけページを進めます。止まったところで株が高騰したりして、スマホアプリのExcelに出納帳をつけます。競ったら楽しいのではないでしょうか?会計や経理の勉強にならないかと思いましたが、公認会計士の友人に話したら「経理は地味でつまらないからゲームに不向き」と言われてしまいました…。

おわりに

今回は、ほぼ完全なオブジェクト指向言語である「Java」と、その標準ライブラリ「Swing」でGUIを設計し、画像表示には「Java2D」APIを使いました。

この記事をシェアしてください

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored