学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

Java | 32 | ジャンプゲーム

↓↓クリックして頂けると励みになります。



31 | 乱数】 << 【ホーム】 >> 【33 | AWTメニュー

簡単なゲームを作成
簡単なゲームを作成





これまでにスレッドを生成する方法としてRunnableインターフェイスを実装する方法を紹介しましたが、今回はThreadのサブクラスを作成してスレッドを実現します。
スレッド自体の仕組みは以前と同様で、run()メソッドに記述された処理がスレッドとして実行されます。
そしてスレッドを記述したインスタンスのstart()メソッドを呼ぶことで実行されます。

public class MyThread extends Thread {

    /**コンストラクタ*/
    public MyThread() {
        //コンストラクタの処理
     }

    /**スレッド処理*/
    public void run() {
        //スレッド処理
     }

    public static void main(String[] args) {
        //スレッド生成
         MyThread test = new MyThread();
        //スレッド開始
         test.start();
    }
}



次のThreadを継承したサンプルプログラム「MyTimer.java」を作成します。


新規作成 【MyTimer.java】

/**
*Threadを継承したクラス
*/

public class MyTimer extends Thread {
	
	private int count=0;

	/**コンストラクタ*/
	public MyTimer(int sec) {

		//super(); は省略
		count = sec;
	}

	/**ループ処理のスレッド*/
	public void run() {

		while (count > 0) {

			try {
				Thread.sleep(1000);
			}
			catch (InterruptedException ex) {

				System.err.println(ex);
			}
			count--;
		}
	}

	/**残り時間の取得*/
	public int getTime() {

		return count;
	}

	/**mainメソッド*/
	public static void main(String[] args) {

		MyTimer timer = new MyTimer(10);
		timer.start();
		
		while (timer.getTime() > 0) {
			System.out.println("残り" + timer.getTime() + "秒");
		}
	}
}



早速実行してみましょう。
時間が減って0になるプログラムです。
「残り〜秒です」と表示し続けます。
10秒のタイマーです。
このプログラムは次に作成するジャンプゲームで利用します。

~/Desktop/Programming/JP $ javac MyTimer.java

~/Desktop/Programming/JP $ java MyTimer
残り10秒
残り10秒
残り10秒
残り10秒
残り10秒
残り10秒
残り10秒
残り10秒

・・・
・・・
・・・



Visual Studio Codeで以下のJavaプログラム「JumpGame.java」を作成してみましょう。


新規作成 【JumpGame.java】

/**簡単なゲーム
*時間制限があり
*右から来る障害物を[SPACE]でジャンプして回避
*[s]キーで再ゲーム
* ハイスコアの更新があります
*/

import java.awt.*;
import java.awt.event.*;

public class JumpGame extends Canvas implements KeyListener, Runnable {

	private final int MAX_IMAGE = 7;	//キャラのイメージ枚数
	private final int J_STAY = 0;	//ジャンプしていない
	private final int J_UP = 1;	//ジャンプして上昇中
	private final int J_DOWN = 2;	//ジャンプして下降中

	private Graphics offg;	//ダブルバッファリング用
	private Image offImage;
	
	private int mx, my, mw, mh, oldmy, mspace;	//キャラ用
	private int mpx, mpy;	//キャラの中心点
	private int imCount, imNum;	//キャラのイメージカウンターと番号
	private int bx, by, bw, bh, oldbx, bspace;	//障害物用
	private int sx, sy, sc;		//スコア表示用
	private int hsx, hsy, hsc;	//ハイスコア表示用
	private int tx, ty, time;	//残り時間表示用
	private int meterx, metery, meterw, meterh;	// メーター表示用

	private int meterc;	//メーター減少部分 / 秒
	private Image[] im = new Image[MAX_IMAGE];	//キャラのイメージ
	private Image box, back, meter;	//障害物と背景、メーターのイメージ

	//JumpGame2.javaでもgameFragを使用するのでこれのみpublicとする。
	public boolean gameFlag;	//ゲーム進行フラグ

	private int jFlag;	//アニメーション(ジャンプ)の状態
	private MediaTracker tracker;	//イメージ通知用
	private int key;	//キーコード取得用
	private MyTimer timer;	//残り時間設定のためのタイマー

	/**コンストラクタ*/
	public JumpGame() {

		setSize(500, 250);
		setBackground(Color.black);
		addKeyListener(this);

		Toolkit tk = Toolkit.getDefaultToolkit();
		tracker = new MediaTracker(this);		//メディアトラッカーにイメージを登録

		box = tk.getImage("box.gif");
		tracker.addImage(box, 1);
		
		for (int i=0; i<MAX_IMAGE; i++) {

			im[i] = tk.getImage("char" + i + ".gif");
			tracker.addImage(im[i], 0);
		}

		//背景イメージを生成と登録
		back = tk.getImage("back.gif");
		tracker.addImage(back, 2);

		//背景イメージを生成と登録
		meter = tk.getImage("meter.gif");
		tracker.addImage(meter, 2);

		//全イメージを読み込むまで待つ
		try {
			tracker.waitForAll();
		}
		catch (InterruptedException ex) {
			System.err.println(ex);
		}

		//キャラ、障害物、メーターのイメージの大きさを取得
		mw = im[0].getWidth(this);
		mh = im[0].getHeight(this);
		bw = box.getWidth(this);
		bh = box.getHeight(this);

		meterw = meter.getWidth(this);
		meterh = meter.getHeight(this);

		//キャラの中心点を計算
		mpx = mw/2;
		mpy = mh/2;

		//ハイスコアの初期設定はここでのみ行う
		hsc = 0;
		hsx = 200;
		hsy = 10;		//ハイスコアの表示座標
	}

	/**ゲーム開始処理*/
	public void gameStart() {

		gameInit();			//変数の初期化
		timer = new MyTimer(30);	//タイマーの設定(30秒)
		new Thread(this).start();	//ゲーム開始
		timer.start();			//秒タイマー開始
	}

	/**ゲームに使用する変数の初期化*/
	public void gameInit() {

		//キャラのx,y座標、ジャンプの間隔
		mx = 100;
		my = 200;
		mspace = 5;

		//障害物のx,y座標、移動間隔
		bx = 450;
		by = 200;
		bspace = 5;

		jFlag = J_STAY;		//ジャンプしていない=0(上昇=1、下降=2)
		gameFlag = true;		//ゲームオーバーならfalse

		sx = 10;			//スコアの表示座標
		sy = 10;
		sc = 0;			//スコアは0点から

		tx = 400;			//残り時間の表示座標
		ty = 10;
		time = 30;		//表示用に残り時間を初期化

		meterx = 400;		//残り時間メーターの表示座標
		metery = 20;
		meterc = meterw/30;	//メータ減少部分 / 秒

		imCount = 0;		//キャライメージの増減カウンター
		imNum = 0;		//キャライメージ1枚目からスタート
	}

	/**メインの処理(スレッド処理)*/
	public void run() {

		while (gameFlag == true) {			//gameFlagがfalesになるまで繰り返し

			try {
				Thread.sleep(20);		//20ミリ秒スリープ
			}
			catch ( InterruptedException ex) {
				System.err.println(ex);
			}
			repaint();
		}
	}

	/**再描写が必要な場合の処理*/
	public void update(Graphics g) {

		oldmy = my;
		oldbx = bx;

		//キャラクタ、障害物の消去(全画面消去)
		offg.setColor(Color.white);
		offg.fillRect(0, 0, getSize().width, getSize().height);

		//口を空けるアニメか、閉じるアニメかを設定
		if (imNum >= (MAX_IMAGE-1)) {
	
			imCount = -1;
		}
		else if (imNum <= 0) {

			imCount = 1;
		}
		imNum+=imCount;

		//スペースキーが押されたときの処理
		if (jFlag == J_UP) {

			my -= mspace;

			if (my <= 100) {		//この位置まで来たらフラグ変更

				jFlag = J_DOWN;
			}
		}

		else if (jFlag == J_DOWN) {	//下降中

			my += mspace;

			if ( my >= 200 ) {	//この位置まで来たらフラグ変更

				jFlag = J_STAY;
			}
		}

		//障害物を左へ移動
		bx -= bspace;

		if (bx < 0) {

			bx = 450;
			sc++;
		}

		//残り時間の取得
		time = timer.getTime();

		//キャラと障害物が重なった場合(キャラの中心点で判定か、
		//残り時間が無くなったときはゲームオーバー
		if ( (mx+mpx >= bx && mx+mpx < bx+bw && my+mpy >= by && my+mpy < by+bh) || time == 0) {

			gameFlag = false;

			//ハイスコアの更新チェック
			if (sc > hsc) {

				hsc = sc;
			}
		}

		//オフスクリーン・バッファへの描き込み。実際にはまだ見えない
		offg.drawImage(back, 0, 0, this);		//背景

		//残り時間メーター
		//第2~5引数(表示範囲)、第6~9引数(元イメージの範囲)
		offg.drawImage(meter, meterx, metery, meterx+meterc*time, metery+meterh, 0, 0, meterc*time, meterh, this);

		offg.drawImage(im[imNum], mx, my, this);
		offg.drawImage(box, bx, by, this);

		//スコアの表示
		offg.setColor(Color.red);
		offg.drawString("Score:" + sc, sx, sy);

		//ハイスコアの表示
		offg.setColor(Color.yellow);
		offg.drawString("Hi-Score:" + hsc, hsx, hsy);

		//残りタイムの表示
		offg.setColor(Color.blue);
		offg.drawString("Time:" + time, tx, ty);

		if (gameFlag == false) {

			offg.setColor(Color.red);
			offg.drawString("Game Over!!", 100, 100);
			offg.drawString("Start [S] Key", 100, 150);
		}

		//オフスクリーン・バッファに描かれたものを画面に表示
		g.drawImage(offImage, 0, 0, this);
	}

	/**キャンバスで描画の必要があるときに呼ばれるメソッド*/
	public void paint(Graphics g) {

		//オフスクリーン・バッファの領域がない場合は作成
		if (offg == null) {

			offImage = createImage(getSize().width, getSize().height);
			offg = offImage.getGraphics();
		}

		//offImageを描画
		g.drawImage(offImage, 0, 0, this);
	}

	/**キーが押されたときの処理*/
	public void keyPressed(KeyEvent evt) {
		
		key = evt.getKeyCode();

		//ゲームオーバー時に[S]キーでゲーム開始
		if (gameFlag == false && key == evt.VK_S) {

			gameStart();	//ゲーム開始
		}

		//スペースキーが押されて、
		//なおかつジャンプしてないときのみ処理を行う
		if (key == evt.VK_SPACE && jFlag == J_STAY) {

			jFlag = J_UP;
		}
	}

	/**その他のキー処理*/
	public void keyReleased(KeyEvent evt) { }
	public void keyTyped(KeyEvent evt) { }


	/**main()*/
	public static void main(String[] args) {

		JumpGame sample = new JumpGame();

		//クローズボタンで終了するように自作したクラス
		MyFrame frame = new MyFrame("JumpGame");
		frame.add(sample);
		frame.pack();
		frame.setVisible(true);

		sample.gameStart();
	}
}



なおこのプログラムを実行するには以下のイメージファイル(box.gif、back.gif、meter.gif)、画像ファイル(char0.gif〜char6.gif)が必要になります。
プログラムを保存するフォルダに保存してください。


[back.gif]
[box.gif]
[meter.gif]
[char0.gif]
[char1.gif]
[char2.gif]
[char3.gif]
[char4.gif]
[char5.gif]
[char6.gif]


ではコンパイルして実行します。
前のセッションで作成した「MyFrame.java」を利用していますのでクローズボタンを使って終了できます。
このセッションで作成した「MyTimer.java」を利用しています。


時間制限があります。
右から来る障害物を[SPACE]でジャンプして回避します。
[s]キーで再ゲーム開始です。
ただし、ゲームが始まったら一度、マウスで画面のどこかをクリックしなければキーボードの入力を受け付けてくれません。
ハイスコアの更新があります。

~/Desktop/Programming/JP $ javac JumpGame.java 
~/Desktop/Programming/JP $ java JumpGame     


ジャンプゲーム
ジャンプゲーム




31 | 乱数】 << 【ホーム】 >> 【33 | AWTメニュー





↓↓クリックして頂けると励みになります。

YAE C5 CLINIC(札幌美容クリニック)

関連記事(外部サイト)