【Java:的当てゲーム】お邪魔ブロックの配置

2018年8月16日

前回までで、ブロックの破壊処理や点数計算処理を実装しゲームとしては少し遊べるようになりました。

前の記事 的当てゲーム制作Top 次の記事

しかし、前回の時点では、かなりのヌルゲーとなってしまいますので、お邪魔ブロックをランダムに配置することで多少難易度を上げることにします。

お邪魔ブロック用のクラスを作成する

最初にお邪魔ブロック用のクラスを作成していきます。

このクラスには矩形当たり判定が実現できるJavaの標準クラス、Rectangleクラスの定義と、画像を表すImageクラスを定義します。

実装メソッドは下記の三種類
・drawメソッドでブロックを描画する機能。
・isHitメソッドでマウスクリックとの当たり判定する機能。
・isConflictBlockメソッドでブロック同士の当たり判定をする機能。

なぜブロック同士の当たり判定を実装する必要があるのかは後にわかると思います。

実装内容は各種クラスの機能を呼び出すだけなので非常にシンプルに終わってしまいます。

というわけで実装結果をご覧ください。

Block.java
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;

//ブロックを表すクラス
public class Block{
	private Rectangle rect;
	private Image img;
	public Block(int x, int y) {
		this.img = AppManager.getBlockImage();

		//ブロックの当たり判定用の矩形
		rect = new Rectangle(x, y, 50, 50);
	}

	//ブロックの描画
	public void draw(Graphics g) {
		g.drawImage(img, rect.x, rect.y, null);
	}

	//ブロックとの判定メソッド
	public boolean isHit(Point p) {
		return rect.contains(p);
	}

	//ブロック同士が衝突状態かどうか
	public boolean isConflictBlock(Block b) {
		return rect.intersects(b.rect);
	}
}

お邪魔ブロックの配置処理

GameMode.javaにお邪魔ブロックの配置処理を実装します。オブジェクト管理用にArrayListを新たに定義し、このリストにブロックを追加していきたいと思います。

配置はRandomクラスを使用し、画面内に30個ほどランダム配置するようにします。

配置の際、ブロック同士が重なるような配置になった場合は再配置処理を行います。ここでisConflictBlockメソッドを利用します。

一応偶然同じ場所に再配置し続けるような処理となることまで想定し配置処理は100回まで試行する処理とします。もしどこにも配置できない状態となってしまえば、無限ループとなってしまいますので、それを防ぐためですね。

最後に配置したブロックの描画処理も実装しておきます。リストをループさせ、drawメソッドを呼び出すだけです。

実装はこんな感じになりました。配置処理はコンストラクタにて定義しています。

GameMode.java
	//ブロックリスト
	ArrayList blockList = new ArrayList<>();
	
	//初期化コンストラクタ
	public GameMode() {
		Random rand = new Random();
		//ランダムで30このお邪魔ブロックを配置する
		for ( int i = 0,limit=0;i < 30 && limit < 100; limit++) {
			Block block = new Block(rand.nextInt(750), rand.nextInt(500)+50);
			if ( !blockList.stream().anyMatch(b -> b.isConflictBlock(block)) ) {
				blockList.add(block);
				i++;
			}
		}
	}
	public void draw(Graphics g) {
		//ブロックの描画
		for ( Block b : blockList ) {
			b.draw(g);
		}
	}

blockList.stream().anyMatch(b -> b.isConflictBlock(block))で既に配置したブロックと当たり判定して、当たっていたら再試行します。

drawメソッドには、ブロックを描画する処理を追加しています。追加位置は的より前に描画するために、的の描画処理よりも後に描画するようにしましょう。

実行結果

お邪魔ブロックとの当たり判定

mousePressedメソッドにブロックとの当たり判定処理を追加します。

的との当たり判定をする前に全ブロックと当たり判定を行い、ブロックに当たっていたら的との当たり判定はしないように処理させます。

実装結果はこんな感じになりました。

	public void mousePressed(MouseEvent e) {
		if ( isGameResult ) return;

		//当たり判定
		int hit = 0;
		switch ( e.getButton() ) {
			case MouseEvent.BUTTON1:
				//ブロックに当たっていたら的の当たり判定はしない
				if ( !blockList.stream().anyMatch(b -> b.isHit(e.getPoint())) ) {
					for ( int i = viewTargetList.size() - 1;i >= 0;i-- ) {
						Target t = viewTargetList.get(i);

						//ターゲットが存在していてマウス座標があっていたら破壊アニメーションを実行
						if ( t.isAlive() && t.isHit(e.getPoint()) ) {
							//マウス座標を引き渡し、得点を取得
							int point = t.getScorePoint(e.getPoint());
							combo++;
							score+=point*combo;
							breakNum++;
							maxCombo = Math.max(combo, maxCombo);

							//Targetへ破壊を通知
							t.breakProcess();
							hit++;
						}
					}
				}
				if ( hit > 0 ) {
					AppManager.breakSE();
				} else {
					combo = 0;
				}
				break;
		}
	}
実行結果

ブロックの下に的があっても的が破壊されていなければ実装は完了です。

本稿で、Block.javaの実装は完成となりますので、いつもの場所へアップロードしておきます。

また、今回のゲーム制作ではゲームの内容自体もここで完成となります。後はランキング機能を実装すれば、すべての実装が完了となります。

Java

Posted by nompor