【Java:的当てゲーム】カウントダウンの実装

2018年8月16日

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

今回はカウントダウンの実装をしていきます。


カウントダウンの実装方法はいろんな方法が思いつくと思います。私は以下の方法などを思いつきました。
・フレームカウントベースの実装
・Timerクラスを使う
・CountDownLatchクラスを使う
・スレッドスリープ1000を指定する

今回はTimerクラスを利用した実装をすることにします。

これを選択した理由ですが、カウントごとに任意の処理が実行できるメリットがあるからです。ただカウントダウンを実装したいだけならCountDownLatchが優れものですが、今回はカウントごとに別の処理もはさみたいと思っているのでTimerを選択しました。

javaのTimerクラスはいくつか種類が存在するのですが、このサイトの別記事でも紹介したjava.util.Timerクラスを使用します。

・・・swingのtimerのほうが実装が簡単そうですがまぁいいでしょう。

今回使用するTimerクラスの使い方は以下の記事をご参照ください。

タイマーの実装はこんな感じで実装してみました。

	//開始前カウント
	int prepareCountDown=3;

	//タイマー
	Timer timer = new Timer();
	TimerTask task = new TimerTask() {

		@Override
		public void run() {
			if ( prepareCountDown > 0 ) {
				prepareCountDown--;
				if ( prepareCountDown == 0 ) {
					AppManager.startSE();
				} else {
					AppManager.countSE();
				}
			} else {
				timer.cancel();
			}
		}
	};

3…2…1…STARTみたいな感じを想定しています。

AppManager.startSE()やAppManager.countSE()でカウントダウンの効果音を再生します。

さて、このタイマーの起動はコンストラクタでやってしまうことにしましょう。


	//初期化コンストラクタ
	public GameMode() {

		//タイマーの起動
		timer.scheduleAtFixedRate(task, 1000, 1000);
	}

続いて描画部分の修正です。

	public void draw(Graphics g) {
		int width = AppManager.getW();
		int height = AppManager.getH();

		//アンチエイリアスの有効化
		GraphicsUtil.setTextAntialiasing(g, true);

		//背景の描画
		g.drawImage(AppManager.getBackImage(), 0, 0, null);
		g.setColor(Color.WHITE);

		g.setFont(countDownFont);
		if ( prepareCountDown == 0 ) {
			//START
			GraphicsUtil.drawCenteringString(g, "START", width / 2, height / 2);
		} else {
			//カウントダウンの描画
			GraphicsUtil.drawCenteringString(g, ""+prepareCountDown, width / 2, height / 2);
		}

		//ステータスの描画
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, width, 50);

		g.setColor(Color.WHITE);
		g.setFont(statusFont);
		GraphicsUtil.drawCenteringString(g, "破壊数:"+breakNum, 400, 25);
		GraphicsUtil.drawCenteringString(g, "得点:"+score, 200, 25);
		GraphicsUtil.drawCenteringString(g, "コンボ:"+combo, 600, 25);
	}
実行結果

drawCenteringStringというメソッドは文字列の真ん中が指定座標となるように描画するメソッドです。

さて、これでカウントダウン機能の実装は完了ですが、もう一工夫してみましょう。

カウントダウン終了後のSTARTという文字をアニメーションさせてみます。アニメーションはフェードアウトと拡大を適用させてみます。

使用するクラスはDrawLabel、ParallelAnimation、ScaleAnimation、FadeAnimationです。

まずDrawLabelクラスはTitleModeでも使用しましたが、文字を中央描画できるクラスです。その他にアニメーションクラスの適用先としても利用できます。

次にFadeAnimationですが、これは引数のアルファ値分だけ加算処理をします。

そして、ScaleAnimationは引数の倍率分だけ加算処理をします。

最後にParallelAnimationですが、複数のアニメーションクラスを同時実行できます。JavaFXのParallelTransitionと同じ感じですね。

まぁ複数の画像で同じようなアニメーションをさせることもできますが、こういうアニメーションはプログラムから制御したほうがより滑らかなアニメーションとなりますし、画像を複数利用しない分メモリの消費も抑えられます。

それでは、修正部分のソースだけ抜粋したプログラムと実行結果をご覧ください。

	//STARTアニメーションラベル
	DrawLabel startLabel;
	ParallelAnimation startAnime;

	//windowにパネルが配置された後に呼び出される
	public void start() {
		//windowにパネルが配置された後ならGraphicsオブジェクトを取得できる
		startLabel = new DrawLabel(getGraphics(), "START", countDownFont, AppManager.getW()/2, AppManager.getH()/2);
		startAnime = new ParallelAnimation(
				new ScaleAnimation(startLabel, 0.02)
				, new FadeAnimation(startLabel, -0.03f)
		);
	}

	public void draw(Graphics g) {
		int width = AppManager.getW();
		int height = AppManager.getH();

		//アンチエイリアスの有効化
		GraphicsUtil.setTextAntialiasing(g, true);

		//背景の描画
		g.drawImage(AppManager.getBackImage(), 0, 0, null);
		g.setColor(Color.WHITE);

		g.setFont(countDownFont);
		if ( prepareCountDown == 0 ) {
			//STARTアニメーション
			startAnime.update();
			startLabel.draw(g);
		} else {
			//カウントダウンの描画
			GraphicsUtil.drawCenteringString(g, ""+prepareCountDown, width / 2, height / 2);
		}

		//ステータスの描画
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, width, 50);

		g.setColor(Color.WHITE);
		g.setFont(statusFont);
		GraphicsUtil.drawCenteringString(g, "破壊数:"+breakNum, 400, 25);
		GraphicsUtil.drawCenteringString(g, "得点:"+score, 200, 25);
		GraphicsUtil.drawCenteringString(g, "コンボ:"+combo, 600, 25);
	}
実行結果

良い感じになりました。

Java

Posted by nompor