java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

クリックゲームを作成してみた

投稿日:

最終更新日:2018年01月24日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

GUIプログラミングでゲームを作る場合、得点を計算することがあると思います。今回は単純なクリックゲームを作ることにしました。

概要

ゲームの概要は以下の通りです。

  • クリック対象の四角をランダムな位置に黒で表示する。
  • 上記の四角は一定時間経つと位置が変わる。
  • マウスポインタの位置を中心に四角を緑で表示する。
  • 上記2つの四角に重なった時、以下の処理をする。
    • クリック対象の四角を赤くする。
    • クリックされた場合、点数を加算する

四角の大きさは適当ですが、クリック対象の方が大きいサイズとします。

クリック対象の四角

クリック対象の四角をランダムに表示させることを最初にやりました。四角はRectangleクラスを使います。位置をランダムに表示させるには、setLocation()メソッドで位置を変更することにしました。一定時間で位置を変えるために、TimerクラスとTimerTaskを使ました。

上記の動きのみの場合、以下のようなプログラムになりました。

ソース

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JFrame;

public class MyJFrame extends JFrame {

	private final static int LENGTH_OF_WINDOW = 300;

	private final static int LENGTH_OF_TARGET = 50;

	private Rectangle target = new Rectangle(-LENGTH_OF_TARGET, -LENGTH_OF_TARGET,
			LENGTH_OF_TARGET, LENGTH_OF_TARGET);

	public static void main(String[] args) {
		new MyJFrame();
	}

	public MyJFrame() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setSize(LENGTH_OF_WINDOW, LENGTH_OF_WINDOW);

		setVisible(true);

		Timer timer = new java.util.Timer();
		timer.schedule(new MyTimeTask(), 1000l, 2000l);
	}

	public void paint(Graphics g) {
	    g.drawImage(getScreen(), 0, 0, this);
	}

	private Image getScreen() {
		Image screen = createImage(LENGTH_OF_WINDOW, LENGTH_OF_WINDOW);
	    Graphics2D g = (Graphics2D)screen.getGraphics();

	    // ターゲット描画
		g.setColor(Color.black);
		g.draw(target);

		return screen;
	}

	private class MyTimeTask extends TimerTask {

		@Override
		public void run() {
			int x = (int)(Math.random() * LENGTH_OF_WINDOW);
			int y = (int)(Math.random() * LENGTH_OF_WINDOW);
			target.setLocation(x, y);
			repaint();
		}

	}

}

メンバ変数targetはクリック対象の四角です。初期位置では画面表示されないようにしました。位置を設定は、TimerTaskを継承したMyTimeTaskのrun()メソッドで行っています。Mathクラスのrandom()メソッドは「0.0以上で1.0より小さい、正の符号の付いたdouble値」を返却します。なので、フレームの辺の長さを掛けてint型にキャストすることで、画面全体を動くようにしています。

プレーヤーの四角

プレーヤーの四角もRectangleクラスのメンバ変数にしました。マウスポインタ中心に位置するという仕様にしたので、位置設定は少しだけ工夫が必要です。

以下はプレーヤーの四角を表示するだけのプログラムです。

ソース

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;

public class MyJFrame extends JFrame {

	private final static int LENGTH_OF_WINDOW = 300;

	private final static int LENGTH_OF_PLAYER = 10;

	private Rectangle player = new Rectangle(-LENGTH_OF_PLAYER, -LENGTH_OF_PLAYER,
			LENGTH_OF_PLAYER, LENGTH_OF_PLAYER);

	public static void main(String[] args) {
		new MyJFrame();
	}

	public MyJFrame() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setSize(LENGTH_OF_WINDOW, LENGTH_OF_WINDOW);

		// リスナー
		MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
		addMouseMotionListener(myMouseAdapter);

		setVisible(true);
	}

	public void paint(Graphics g) {
	    g.drawImage(getScreen(), 0, 0, this);
	}

	private Image getScreen() {
		Image screen = createImage(LENGTH_OF_WINDOW, LENGTH_OF_WINDOW);
	    Graphics2D g = (Graphics2D)screen.getGraphics();

		// 自機描画
		g.setColor(Color.green);
		g.draw(player);

		return screen;
	}

	private class MyMouseAdapter extends MouseAdapter {
		@Override
		public void mouseMoved(MouseEvent e) {
		    // 長方形の位置変更
		    player.setLocation(e.getX() - LENGTH_OF_PLAYER / 2, e.getY() - LENGTH_OF_PLAYER / 2);
			// 描画する
			repaint();
		}
	}

}

Rectangleクラスのメンバ変数を定義してインスタンスを格納し、それをプレーヤーの四角として使いまわすということにしました。

MouseAdapterクラスを継承したMyMouseAdapterクラスのmouseMoved()メソッドで四角の位置を設定しています。RectangleクラスのsetLocation()メソッドで位置をマウスポインタ中心にしています。定数に辺の長さを定義しておき、その半分をマウスポインタの座標からずらして、位置を設定するということをしています。これでマウスポインタが四角の中心になります。

クリックで点数加算

上記2つをもとにして、重なっているときにクリックされたら点数を加算するというプログラムを作りました。

ソース

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JFrame;

public class MyJFrame extends JFrame {

	private final static int LENGTH_OF_WINDOW = 300;

	private final static int LENGTH_OF_TARGET = 50;

	private final static int LENGTH_OF_PLAYER = 10;

	private Rectangle target = new Rectangle(-LENGTH_OF_TARGET, -LENGTH_OF_TARGET,
			LENGTH_OF_TARGET, LENGTH_OF_TARGET);
	private Rectangle player = new Rectangle(-LENGTH_OF_PLAYER, -LENGTH_OF_PLAYER,
			LENGTH_OF_PLAYER, LENGTH_OF_PLAYER);

	private int score = 0;

	public static void main(String[] args) {
		new MyJFrame();
	}

	public MyJFrame() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setSize(LENGTH_OF_WINDOW, LENGTH_OF_WINDOW);

		// リスナー
		MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
		addMouseListener(myMouseAdapter);
		addMouseMotionListener(myMouseAdapter);

		setVisible(true);

		Timer timer = new java.util.Timer();
		timer.schedule(new MyTimeTask(), 1000l, 2000l);
	}

	public void paint(Graphics g) {
	    g.drawImage(getScreen(), 0, 0, this);
	}

	private Image getScreen() {
		Image screen = createImage(LENGTH_OF_WINDOW, LENGTH_OF_WINDOW);
	    Graphics2D g = (Graphics2D)screen.getGraphics();

	    // ターゲット描画
	    if (target.intersects(player)) {
			g.setColor(Color.red);
	    } else {
			g.setColor(Color.black);
	    }
		g.draw(target);

		// 自機描画
		g.setColor(Color.green);
		g.draw(player);

		// 点数表示
		g.setColor(Color.black);
		g.drawString("点数:" + score, 50, 50);

		return screen;
	}

	private class MyTimeTask extends TimerTask {

		@Override
		public void run() {
			int x = (int)(Math.random() * LENGTH_OF_WINDOW);
			int y = (int)(Math.random() * LENGTH_OF_WINDOW);
			target.setLocation(x, y);
			repaint();
		}

	}

	private class MyMouseAdapter extends MouseAdapter {
		@Override
		public void mouseClicked(MouseEvent e) {
		    // スコア
		    if (player.intersects(target)) {
		    	score ++;
		    }
			// 描画する
			repaint();
		}

		@Override
		public void mouseMoved(MouseEvent e) {
		    // 長方形の位置変更
		    player.setLocation(e.getX() - LENGTH_OF_PLAYER / 2, e.getY() - LENGTH_OF_PLAYER / 2);
			// 描画する
			repaint();
		}
	}

}

重なりの判定はintersects()メソッドを使っています。このメソッドを使うだけで当たり判定が出来るのは便利です。