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

タイトル画面をクリックして遷移する

タイトル画面をクリックして遷移する

「MainLoop.java」ファイルを新規作成します。このColorゲームはクリックだけで操作します。ここではタイトル画面をクリックしたらJPanelクラスの画面が遷移します。他にもタイトル画面、メインループ画面、ゲームオーバー画面、ステージクリア画面があります。

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

import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Title extends JPanel {
  private BufferedImage image;

  public Title(JFrame frame) {
    try {
      image = ImageIO.read(new File("./images/Title.png"));
    } catch (IOException e) {
      e.printStackTrace();
    }

    addMouseListener(new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        frame.getContentPane().removeAll(); // 画面を消す
        frame.add(new MainLoop(frame)); // メインループ画面追加
        frame.revalidate(); // 更新
        frame.repaint(); // 再描画
      }
    });
  }

  @Override
  protected void paintComponent(Graphics g) {
(中略)
  }
}

【サンプルコードの解説】
「addMouseListener」メソッドでクリック時の処理を登録し、クリックされると「JFrame」から現在の画面を消し、MainLoopクラスを追加して更新・再描画します。

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

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

public class MainLoop extends JPanel {
  public MainLoop(JFrame frame) {
  }
}

【サンプルコードの解説】
「JPanel」で空のメインループ画面(メインのゲーム画面)を作成します。

色ブロックを表示する

ここで、ゲームらしく色ブロックを表示させます。「ColorBlock.java」ファイルを新規作成し、1個ずつの色ブロックを「ColorBlock」クラスで設計図を書きます。
ステージ(面)の数値はゲームウィンドウのタイトル文字をそのまま数値にしたものです。1面(ステージ)が"2"のタイトルになります。手抜きですが、解説を簡単にするためです。

色ブロックの表示

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

import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;

public class ColorBlock {
  public BufferedImage image;
  public int color;
  public int[] pos = new int[2];
  public int[] delta = new int[2];

  public ColorBlock(int color) {
    Random rand = new Random();
    this.color = color;
    try {
      image = ImageIO.read(new File("./images/"+color+".png"));
    } catch (IOException e) {
      e.printStackTrace();
    }
    for (int i = 0; i < 3*2; i++ ) {
      pos[0] = rand.nextInt(1800-50);
      pos[1] = rand.nextInt(900-50);
      delta[0] = rand.nextInt(7)-3;
      delta[1] = rand.nextInt(7)-3;
    }
  }

  public int update(int w,int h) {
    pos[0] += delta[0];
    pos[1] += delta[1];
    if (pos[0] < -100 || pos[0] > w || pos[1] < -100 || pos[1] > h) return 0;
    return 1;
  }
}

【サンプルコードの解説】
colorには色ブロックの「0(赤)」「1(緑)」「2(青)」が入ります。
色ブロックの(pos[0],pos[1])は(X,Y)座標、(delta[0],delta[1])は(増分X,増分Y)座標です。それぞれ初期値にはランダムな値を入れます。
「update」メソッドで(X,Y)座標に増分を加算して、色ブロックが画面外に出たら戻り値に0を返し、画面内なら戻り値に1を返します。

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

import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.*;
import java.util.ArrayList;
import javax.swing.Timer;

public class MainLoop extends JPanel {
  private ArrayList<ColorBlock> colors = new ArrayList<ColorBlock>();
  private JFrame frame;
  private Timer timer;

  public MainLoop(JFrame frame) {
    this.frame = frame;
    int stage = Integer.parseInt(frame.getTitle());
    for (int i = 0; i < 3*stage; i++) colors.add(new ColorBlock(i%3));
    timer = new Timer(100, e -> {
      // 毎フレームの処理 (更新・再描画)
      frame.repaint();
    });
    timer.start();
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    for (int i = 0; i < colors.size(); i++) {
      Graphics2D g2d = (Graphics2D) g;
      ColorBlock c = colors.get(i);
      c.update(getWidth(),getHeight());
      g2d.drawImage(c.image, c.pos[0], c.pos[1], this);
    }
  }
}

【サンプルコードの解説】
「ArrayList」でColorBlockクラスの配列「colors」プロパティを作成し、ステージ番号*3色だけ追加します。
Timerクラスで100ミリ秒ごと(10FPS)に再描画を設定して「start」します。
ColorBlockのインスタンスをupdateして「drawImage」メソッドで描画します。

色ブロックをクリックして消す

今度は色ブロックをクリックしたら、そのブロックだけを消します。クリックした時のマウス座標と色ブロックの位置との差の絶対値が50より小さければクリック成功です。

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

(前略)
public class ColorBlock {
(中略)

  public ColorBlock(int color) {
(中略)
  }

  public int update(int w,int h) {
(中略)
  }

  public boolean click(MouseEvent e) {
    if (Math.abs(pos[0]+50-e.getX()) < 50 && Math.abs(pos[1]+50-e.getY()) < 50) return true;
    return false;
  }
}

【サンプルコードの解説】
click メソッドでは、マウスクリックの座標が「-50 < (X, Y) < 50」の範囲内であれば当たったと判定し、trueを返します。範囲外の場合はfalseを返します。

・サンプルコード「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;

public class MainLoop extends JPanel {
(中略)

  public MainLoop(JFrame frame) {
(中略)
    addMouseListener(new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        for (int i = 0; i < colors.size(); i++) {
          if ( colors.get(i).click(e) ) {
            colors.remove(i);
            break;
          }
        }
      }
    });
  }

  @Override
  protected void paintComponent(Graphics g) {
(中略)
  }
}

【サンプルコードの解説】
メインループではイベントリスナーでマウスのクリックを検知し、色ブロックがクリックされていた場合は、そのブロックを「remove(削除)」します。

【コラム】今後足りなくなる機能

例えば、コンピュータで時間の数値は昔のままでは限度を超えてしまいます。そんな感じで今では不足する技術を見つけ出したいです。例えば「バーコードに限界がきてQRコードが生まれた」ようなことをしたいです。

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

人気記事トップ10

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

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