2 『状態遷移』

2.1 マウスとキーハンドリングのテスト

2.1.1 マウスとキーハンドリングのテスト

リスト 2.1.1.1 MouseKeyHandlingTest.java
  1: import java.awt.Color;
  2: 
  3: import obpro.gui.BCanvas;
  4: import obpro.gui.BWindow;
  5: 
  6: /**
  7:  * マウスとキーハンドリングのテスト
  8:  * 
  9:  * @author macchan
 10:  * @date 2005/06/08 オブプロ第8回 2006/05/26修正
 11:  * @version 1.0
 12:  */
 13: public class MouseKeyHandlingTest {
 14: 
 15: 	public static void main(String[] args) {
 16: 		MouseKeyHandlingTest test = new MouseKeyHandlingTest();
 17: 		test.main();
 18: 	}
 19: 
 20: 	final Color BLACK = new Color(0, 0, 0);
 21: 	final int KEYEVENT_LABEL_X = 100;
 22: 	final int KEYEVENT_VALUE_X = 200;
 23: 	final int MOUSEEVENT_LABEL_X = 300;
 24: 	final int MOUSEEVENT_VALUE_X = 450;
 25: 
 26: 	BWindow window;
 27: 
 28: 	void main() {
 29: 		openWindow();
 30: 		doAnimation();
 31: 	}
 32: 
 33: 	// ウインドウを開く
 34: 	void openWindow() {
 35: 		window = new BWindow();
 36: 		window.setLocation(100, 100);
 37: 		window.setSize(640, 480);
 38: 		window.show();
 39: 	}
 40: 
 41: 	// アニメーションする
 42: 	void doAnimation() {
 43: 		// キャンバスを取得する
 44: 		BCanvas canvas = window.getCanvas();
 45: 
 46: 		// アニメーションする
 47: 		while (true) {
 48: 			{// 図形を描く
 49: 				canvas.clear();
 50: 				draw(canvas);
 51: 				canvas.update();
 52: 			}
 53: 
 54: 			// 眠る
 55: 			canvas.sleep(0.1);
 56: 		}
 57: 	}
 58: 
 59: 	/**
 60: 	 * 図形を描く
 61: 	 */
 62: 	void draw(BCanvas canvas) {
 63: 		// クリックされたキーの状態を表示する
 64: 		String keyCode = Integer.toString(canvas.getKeyCode());
 65: 		canvas.drawText(BLACK, "keyCode", KEYEVENT_LABEL_X, 100);
 66: 		canvas.drawText(BLACK, keyCode, KEYEVENT_VALUE_X, 100);
 67: 
 68: 		String isKeyDown = Boolean.toString(canvas.isKeyDown());
 69: 		canvas.drawText(BLACK, "isKeyDown", KEYEVENT_LABEL_X, 125);
 70: 		canvas.drawText(BLACK, isKeyDown, KEYEVENT_VALUE_X, 125);
 71: 
 72: 		// 押されているキーを表示する
 73: 		int y = 0;
 74: 		for (int i = 0; i < 256; i++) {
 75: 			if (canvas.isKeyPressing(i)) {
 76: 				canvas.drawText(BLACK, "key " + i + " is Now Pressing",
 77: 						KEYEVENT_LABEL_X, 150 + y);
 78: 				y += 25;
 79: 			}
 80: 		}
 81: 
 82: 		{// マウスイベントの状態を表示する
 83: 			// マウスの位置
 84: 			String mousePoint = canvas.getMouseX() + "," + canvas.getMouseY();
 85: 			canvas.drawText(BLACK, "mousePoint", MOUSEEVENT_LABEL_X, 100);
 86: 			canvas.drawText(BLACK, mousePoint, MOUSEEVENT_VALUE_X, 100);
 87: 
 88: 			// (いずれかのの)マウスボタンが押されているか
 89: 			String isMouseDown = Boolean.toString(canvas.isMouseDown());
 90: 			canvas.drawText(BLACK, "isMouseDown", MOUSEEVENT_LABEL_X, 125);
 91: 			canvas.drawText(BLACK, isMouseDown, MOUSEEVENT_VALUE_X, 125);
 92: 
 93: 			// 左マウスボタンが押されているか
 94: 			String isLeftMouseDown = Boolean.toString(canvas.isLeftMouseDown());
 95: 			canvas.drawText(BLACK, "isLeftMouseDown", MOUSEEVENT_LABEL_X, 150);
 96: 			canvas.drawText(BLACK, isLeftMouseDown, MOUSEEVENT_VALUE_X, 150);
 97: 
 98: 			// 右マウスボタンが押されているか
 99: 			String isRightMouseDown = Boolean.toString(canvas
100: 					.isRightMouseDown());
101: 			canvas.drawText(BLACK, "isRightMouseDown", MOUSEEVENT_LABEL_X, 175);
102: 			canvas.drawText(BLACK, isRightMouseDown, MOUSEEVENT_VALUE_X, 175);
103: 
104: 			// マウスがクリックされたか
105: 			String isClick = Boolean.toString(canvas.isClick());
106: 			canvas.drawText(BLACK, "isClick", MOUSEEVENT_LABEL_X, 200);
107: 			canvas.drawText(BLACK, isClick, MOUSEEVENT_VALUE_X, 200);
108: 
109: 			// マウスがシングルクリックがされたか
110: 			String isSingleClick = Boolean.toString(canvas.isSingleClick());
111: 			canvas.drawText(BLACK, "isSingleClick", MOUSEEVENT_LABEL_X, 225);
112: 			canvas.drawText(BLACK, isSingleClick, MOUSEEVENT_VALUE_X, 225);
113: 
114: 			// マウスがダブルクリックされたか
115: 			String isDoubleClick = Boolean.toString(canvas.isDoubleClick());
116: 			canvas.drawText(BLACK, "isDoubleClick", MOUSEEVENT_LABEL_X, 250);
117: 			canvas.drawText(BLACK, isDoubleClick, MOUSEEVENT_VALUE_X, 250);
118: 
119: 			// マウスがドラッグ中か
120: 			String isDragging = Boolean.toString(canvas.isDragging());
121: 			canvas.drawText(BLACK, "isDragging", MOUSEEVENT_LABEL_X, 275);
122: 			canvas.drawText(BLACK, isDragging, MOUSEEVENT_VALUE_X, 275);
123: 		}
124: 	}
125: }

2.2 状態遷移(点滅)のサンプルプログラム(1)

2.2.1 点滅のサンプルプログラム(1)

リスト 2.2.1.1 BlinkSample1.java
  1: import java.awt.Color;
  2: 
  3: import obpro.gui.BCanvas;
  4: import obpro.gui.BWindow;
  5: 
  6: /**
  7:  * 状態遷移(点滅)のサンプルプログラム その1
  8:  * 
  9:  * @author macchan
 10:  * @date 2005/06/08 オブプロ第8回
 11:  * @version 1.0
 12:  */
 13: public class BlinkSample1 {
 14: 
 15: 	public static void main(String[] args) {
 16: 		BlinkSample1 blinkSample = new BlinkSample1();
 17: 		blinkSample.main();
 18: 	}
 19: 
 20: 	final Color BLACK = new Color(0, 0, 0);
 21: 
 22: 	BWindow window;
 23: 
 24: 	void main() {
 25: 		openWindow();
 26: 		doAnimation();
 27: 	}
 28: 
 29: 	// ウインドウを開く
 30: 	void openWindow() {
 31: 		window = new BWindow();
 32: 		window.setLocation(100, 100);
 33: 		window.setSize(640, 480);
 34: 		window.show();
 35: 	}
 36: 
 37: 	BlinkRectangle1 rectangle;
 38: 
 39: 	// アニメーションする
 40: 	void doAnimation() {
 41: 		// キャンバスを取得する
 42: 		BCanvas canvas = window.getCanvas();
 43: 
 44: 		// オブジェクトを初期化する
 45: 		rectangle = new BlinkRectangle1(BLACK, 50, 50, 100, 50);
 46: 
 47: 		// アニメーションする
 48: 		while (true) {
 49: 			// 1コマの処理を行う
 50: 			rectangle.processOneStep();
 51: 
 52: 			{// 図形を描く
 53: 				canvas.clear();
 54: 				rectangle.draw(canvas);
 55: 				canvas.update();
 56: 			}
 57: 
 58: 			// 眠る
 59: 			canvas.sleep(0.1);
 60: 		}
 61: 	}
 62: 
 63: }

2.2.2 四角形を表現するクラス(点滅機能付き)(1)

リスト 2.2.2.1 BlinkRectangle1.java
  1: import java.awt.Color;
  2: 
  3: import obpro.gui.BCanvas;
  4: 
  5: /**
  6:  * 四角形を表現するクラス(点滅機能付 その1)
  7:  */
  8: public class BlinkRectangle1 {
  9: 
 10: 	// 定数
 11: 	private final int ON = 1;
 12: 	private final int OFF = 2;
 13: 
 14: 	// 状態
 15: 	private int showState = ON;
 16: 
 17: 	// 四角形の属性
 18: 	private Color color;
 19: 	private int x = 0;
 20: 	private int y = 0;
 21: 	private int width = 0;
 22: 	private int height = 0;
 23: 
 24: 	/**
 25: 	 * コンストラクタ
 26: 	 */
 27: 	public BlinkRectangle1(Color color, int x, int y, int width, int height) {
 28: 		this.color = color;
 29: 		this.x = x;
 30: 		this.y = y;
 31: 		this.width = width;
 32: 		this.height = height;
 33: 	}
 34: 
 35: 	/**
 36: 	 * 1コマの処理を行う
 37: 	 */
 38: 	public void processOneStep() {
 39: 		changeShowState();
 40: 	}
 41: 
 42: 	/**
 43: 	 * 表示状態を変える
 44: 	 */
 45: 	private void changeShowState() {
 46: 		if (showState == ON) {
 47: 			showState = OFF;
 48: 		} else if (showState == OFF) {
 49: 			showState = ON;
 50: 		}
 51: 	}
 52: 
 53: 	/**
 54: 	 * 描く
 55: 	 */
 56: 	public void draw(BCanvas canvas) {
 57: 		if (showState == ON) {
 58: 			canvas.drawLine(color, x, y, x + width, y);
 59: 			canvas.drawLine(color, x + width, y, x + width, y + height);
 60: 			canvas.drawLine(color, x + width, y + height, x, y + height);
 61: 			canvas.drawLine(color, x, y + height, x, y);
 62: 		}
 63: 
 64: 		// デバッグ出力
 65: 		canvas.drawText(color, "showState=" + showState, x + width + 100, y
 66: 				+ height);
 67: 	}
 68: 
 69: }

2.3 状態遷移(点滅)のサンプルプログラム(2)

2.3.1 点滅のサンプルプログラム(2)

リスト 2.3.1.1 BlinkSample2.java
  1: import java.awt.Color;
  2: 
  3: import obpro.gui.BCanvas;
  4: import obpro.gui.BWindow;
  5: 
  6: /**
  7:  * 状態遷移(点滅)のサンプルプログラム その2
  8:  * 
  9:  * @author macchan
 10:  * @date 2005/06/08 オブプロ第8回
 11:  * @version 1.0
 12:  */
 13: public class BlinkSample2 {
 14: 
 15: 	public static void main(String[] args) {
 16: 		BlinkSample2 blinkSample = new BlinkSample2();
 17: 		blinkSample.main();
 18: 	}
 19: 
 20: 	final Color BLACK = new Color(0, 0, 0);
 21: 
 22: 	BWindow window;
 23: 
 24: 	void main() {
 25: 		openWindow();
 26: 		doAnimation();
 27: 	}
 28: 
 29: 	// ウインドウを開く
 30: 	void openWindow() {
 31: 		window = new BWindow();
 32: 		window.setLocation(100, 100);
 33: 		window.setSize(640, 480);
 34: 		window.show();
 35: 	}
 36: 
 37: 	BlinkRectangle2 rectangle;
 38: 
 39: 	// アニメーションする
 40: 	void doAnimation() {
 41: 		// キャンバスを取得する
 42: 		BCanvas canvas = window.getCanvas();
 43: 
 44: 		// オブジェクトを初期化する
 45: 		rectangle = new BlinkRectangle2(BLACK, 50, 50, 100, 50);
 46: 
 47: 		// アニメーションする
 48: 		while (true) {
 49: 			// 入力により,点滅状態を変更する
 50: 			if (canvas.isKeyDown()) {
 51: 				int keyCode = canvas.getKeyCode();
 52: 				if (keyCode == 65) {// a
 53: 					rectangle.changeBlinkingState();
 54: 				}
 55: 			}
 56: 
 57: 			// 1コマの処理を行う
 58: 			rectangle.processOneStep();
 59: 
 60: 			{// 図形を描く
 61: 				canvas.clear();
 62: 				rectangle.draw(canvas);
 63: 				canvas.update();
 64: 			}
 65: 
 66: 			// 眠る
 67: 			canvas.sleep(0.1);
 68: 		}
 69: 	}
 70: 
 71: }

2.3.2 四角形を表現するクラス(点滅機能付き)(2)

リスト 2.3.2.1 BlinkRectangle2.java
  1: import java.awt.Color;
  2: 
  3: import obpro.gui.BCanvas;
  4: 
  5: /**
  6:  * 四角形を表現するクラス(点滅機能付 その2)
  7:  */
  8: public class BlinkRectangle2 {
  9: 	// 定数
 10: 	private final int ON = 1;
 11: 	private final int OFF = 2;
 12: 
 13: 	private final int BLINKING = 1;
 14: 	private final int NOT_BLINKING = 2;
 15: 
 16: 	// 状態
 17: 	private int showState = ON;
 18: 	private int blinkingState = NOT_BLINKING;
 19: 
 20: 	// 四角形の属性
 21: 	private Color color;
 22: 	private int x = 0;
 23: 	private int y = 0;
 24: 	private int width = 0;
 25: 	private int height = 0;
 26: 
 27: 	/**
 28: 	 * コンストラクタ
 29: 	 */
 30: 	public BlinkRectangle2(Color color, int x, int y, int width, int height) {
 31: 		this.color = color;
 32: 		this.x = x;
 33: 		this.y = y;
 34: 		this.width = width;
 35: 		this.height = height;
 36: 	}
 37: 
 38: 	/**
 39: 	 * 1コマの処理を行う
 40: 	 */
 41: 	public void processOneStep() {
 42: 		// 表示状態を変更する
 43: 		if (blinkingState == BLINKING) {
 44: 			changeShowState();
 45: 		}
 46: 	}
 47: 
 48: 	/**
 49: 	 * 表示状態を変える
 50: 	 */
 51: 	private void changeShowState() {
 52: 		if (showState == ON) {
 53: 			showState = OFF;
 54: 		} else if (showState == OFF) {
 55: 			showState = ON;
 56: 		}
 57: 	}
 58: 
 59: 	/**
 60: 	 * 点滅状態を変える
 61: 	 */
 62: 	public void changeBlinkingState() {
 63: 		if (blinkingState == NOT_BLINKING) {
 64: 			blinkingState = BLINKING;
 65: 			showState = ON;
 66: 		} else if (blinkingState == BLINKING) {
 67: 			blinkingState = NOT_BLINKING;
 68: 			showState = ON;
 69: 		}
 70: 	}
 71: 
 72: 	/**
 73: 	 * 描く
 74: 	 */
 75: 	public void draw(BCanvas canvas) {
 76: 		if (showState == ON) {
 77: 			canvas.drawLine(color, x, y, x + width, y);
 78: 			canvas.drawLine(color, x + width, y, x + width, y + height);
 79: 			canvas.drawLine(color, x + width, y + height, x, y + height);
 80: 			canvas.drawLine(color, x, y + height, x, y);
 81: 		}
 82: 
 83: 		// デバッグ出力
 84: 		canvas.drawText(color, "showState=" + showState, x + width + 100, y
 85: 				+ height);
 86: 		canvas.drawText(color, "blinkingState=" + blinkingState, x + width
 87: 				+ 100, y + height + 50);
 88: 	}
 89: 
 90: }

2.4 シューティングゲームによる実装例

2.4.1 シューティングゲーム(1)(避けゲー)

2.4.1.1 メインのクラス ShootingGame1 シューティングゲーム(1)(避けゲー)

リスト 2.4.1.1.1 ShootingGame1.java
  1: import obpro.gui.BCanvas;
  2: import obpro.gui.BWindow;
  3: 
  4: /**
  5:  * シューティングゲームサンプル(その1 避けゲー) 
  6:  * 
  7:  * @author macchan
  8:  * @date 2005/06/08 オブプロ第8回 2006/05/26修正
  9:  * @version 1.0
 10:  */
 11: public class ShootingGame1 {
 12: 
 13: 	public static void main(String[] args) {
 14: 		ShootingGame1 shootingGame = new ShootingGame1();
 15: 		shootingGame.main();
 16: 	}
 17: 
 18: 	BWindow window;
 19: 	
 20: 	PlayerAircraft player;
 21: 	EnemyAircraft enemy;
 22: 
 23: 	void main() {
 24: 		openWindow();
 25: 		doAnimation();
 26: 	}
 27: 
 28: 	//ウインドウを開く
 29: 	void openWindow() {
 30: 		window = new BWindow();
 31: 		window.setLocation(100, 100);
 32: 		window.setSize(640, 480);
 33: 		window.show();
 34: 	}
 35: 
 36: 	//アニメーションする
 37: 	void doAnimation() {
 38: 		BCanvas canvas = window.getCanvas();//キャンバスを取得する
 39: 		initializeObjects();//オブジェクトを初期化する
 40: 
 41: 		//アニメーションする
 42: 		while (true) {
 43: 			//1コマの処理を行う
 44: 			processOneStep(canvas);
 45: 
 46: 			//図形を描く
 47: 			canvas.clear();
 48: 			draw(canvas);
 49: 			canvas.update();
 50: 
 51: 			//眠る
 52: 			canvas.sleep(0.05);
 53: 		}
 54: 	}
 55: 
 56: 	//オブジェクトを初期化する
 57: 	private void initializeObjects() {
 58: 		player = new PlayerAircraft(50, 50, 100, 50);
 59: 		enemy = new EnemyAircraft(400, 50, 100, 50);
 60: 	}
 61: 
 62: 	// 1コマの処理を行う
 63: 	private void processOneStep(BCanvas canvas) {
 64: 		// (キー入力によって)自機を操作する
 65: 		if (canvas.isKeyDown()) {
 66: 			int keyCode = canvas.getKeyCode();
 67: 			if (keyCode == 37) {// 左キー
 68: 				player.move(-5, 0);
 69: 			} else if (keyCode == 38) {// 上キー
 70: 				player.move(0, -5);
 71: 			} else if (keyCode == 39) {// 右キー
 72: 				player.move(5, 0);
 73: 			} else if (keyCode == 40) {// 下キー
 74: 				player.move(0, 5);
 75: 			}
 76: 		}
 77: 
 78: 		// 各オブジェクトの1コマの処理を行う
 79: 		player.processOneStep();
 80: 		enemy.processOneStep();
 81: 
 82: 		// 当たり判定を行う
 83: 		if (player.intersects(enemy)) {
 84: 			player.explode();
 85: 		}
 86: 	}
 87: 
 88: 	// 図形を描く
 89: 	private void draw(BCanvas canvas) {
 90: 		player.draw(canvas);
 91: 		enemy.draw(canvas);
 92: 	}
 93: 
 94: }

2.4.1.2 自機を表現するクラス

リスト 2.4.1.2.1 PlayerAircraft.java
  1: import java.awt.Color;
  2: 
  3: import obpro.cui.Random;
  4: import obpro.gui.BCanvas;
  5: 
  6: /**
  7:  * 自機を表現するクラス
  8:  */
  9: public class PlayerAircraft {
 10: 
 11: 	//定数
 12: 	private final int ALIVE = 1;
 13: 	private final int EXPLODING = 2;
 14: 	private final int DEAD = 3;
 15: 
 16: 	private final int EXPLODING_ANIMATION_COUNT = 10;
 17: 
 18: 	//状態
 19: 	private int liveState = ALIVE;
 20: 	private int explodingCount = 0;
 21: 
 22: 	//属性
 23: 	private int x = 0;
 24: 	private int y = 0;
 25: 	private int width = 0;
 26: 	private int height = 0;
 27: 
 28: 	/**
 29: 	 * コンストラクタ
 30: 	 */
 31: 	public PlayerAircraft(int x, int y, int width, int height) {
 32: 		this.x = x;
 33: 		this.y = y;
 34: 		this.width = width;
 35: 		this.height = height;
 36: 	}
 37: 	
 38: 	/**
 39: 	 * 高さを取得する
 40: 	 */
 41: 	public int getHeight() {
 42: 		return this.height;
 43: 	}
 44: 
 45: 	/**
 46: 	 * 幅を取得する
 47: 	 */
 48: 	public int getWidth() {
 49: 		return this.width;
 50: 	}
 51: 
 52: 	/**
 53: 	 * X座標を取得する
 54: 	 */
 55: 	public int getX() {
 56: 		return this.x;
 57: 	}
 58: 
 59: 	/**
 60: 	 * Y座標を取得する
 61: 	 */
 62: 	public int getY() {
 63: 		return this.y;
 64: 	}
 65: 
 66: 	/**
 67: 	 * 動かす
 68: 	 */
 69: 	public void move(int moveX, int moveY) {
 70: 		if (liveState == ALIVE) {
 71: 			x = x + moveX;
 72: 			y = y + moveY;
 73: 		}
 74: 	}
 75: 	
 76: 	/**
 77: 	 * 1コマの処理を行う	 
 78: 	 */
 79: 	public void processOneStep(){
 80: 		if (liveState == EXPLODING) {
 81: 			processExplode();
 82: 		}
 83: 	}
 84: 
 85: 	private void processExplode() {
 86: 		explodingCount++;
 87: 		if (explodingCount == EXPLODING_ANIMATION_COUNT) {
 88: 			liveState = DEAD;
 89: 		}
 90: 	}
 91: 
 92: 	public void explode() {
 93: 		if (liveState == ALIVE) {
 94: 			liveState = EXPLODING;
 95: 			explodingCount = 0;
 96: 		}
 97: 	}
 98: 
 99: 	/**
100: 	 * 敵との衝突判定をする
101: 	 */
102: 	public boolean intersects(EnemyAircraft enemy) {
103: 		int player_leftX = this.getX();
104: 		int player_rightX = this.getX() + this.getWidth();
105: 		int enemy_leftX = enemy.getX();
106: 		int enemy_rightX = enemy.getX() + enemy.getWidth();
107: 		int player_topY = this.getY();
108: 		int player_bottomY = this.getY() + this.getHeight();
109: 		int enemy_topY = enemy.getY();
110: 		int enemy_bottomY = enemy.getY() + enemy.getHeight();
111: 
112: 		return (enemy_leftX < player_rightX && enemy_rightX > player_leftX
113: 				&& enemy_topY < player_bottomY && enemy_bottomY > player_topY);
114: 	}
115: 
116: 	/**
117: 	 * 描く
118: 	 */
119: 	public void draw(BCanvas canvas) {
120: 		if (liveState == ALIVE) {
121: 			drawAircraft(canvas);
122: 		} else if (liveState == EXPLODING) {
123: 			drawAircraft(canvas);
124: 			drawExplosion(canvas);
125: 		}
126: 	}
127: 
128: 	/**
129: 	 * 飛行機を描画する
130: 	 */
131: 	private void drawAircraft(BCanvas canvas) {
132: 		//座標を決める
133: 		//コックピット
134: 		int headX = x + width * 11 / 13;
135: 		int headY = y + height * 4 / 5;
136: 
137: 		//本体
138: 		int bodyX = x + width / 13;
139: 		int bodyY = y + height * 2 / 5;
140: 		int bodyWidth = width * 10 / 13;
141: 		int bodyHeight = height * 2 / 5;
142: 
143: 		//垂直尾翼
144: 		int verticalWingX1 = x + width * 2 / 13;
145: 		int verticalWingX2 = x + width * 7 / 13;
146: 
147: 		//水平尾翼
148: 		int tailWingY = y + height * 3 / 5;
149: 		int tailWingWidth = width / 13;
150: 		int tailWingHeight = height / 5;
151: 
152: 		//本体を描く
153: 		drawFillRectangle(canvas, Color.BLUE, bodyX, bodyY, bodyWidth,
154: 				bodyHeight);
155: 		canvas.drawFillTriangle(Color.BLUE, headX, bodyY, headX, headY, x
156: 				+ width, headY);
157: 
158: 		//水平尾翼を描く
159: 		drawFillRectangle(canvas, Color.BLACK, x, tailWingY, tailWingWidth,
160: 				tailWingHeight);
161: 
162: 		//垂直尾翼を描く
163: 		canvas.drawFillTriangle(Color.GRAY, verticalWingX1, y, verticalWingX1,
164: 				bodyY, verticalWingX2, bodyY);
165: 
166: 		//主翼を描く
167: 		canvas.drawFillTriangle(Color.CYAN, verticalWingX1, tailWingY,
168: 				verticalWingX2, tailWingY, bodyX, y + height);
169: 	}
170: 
171: 	/**
172: 	 * 爆発を描画する
173: 	 */
174: 	private void drawExplosion(BCanvas canvas) {
175: 		// 火の玉の数を決める
176: 		int fireCount = explodingCount * 4;// カウント数の4倍(徐々に増える)
177: 
178: 		// 火の玉を描画する
179: 		for (int i = 0; i < fireCount; i++) {
180: 			int fireX = x + Random.getInt(width);
181: 			int fireY = y + Random.getInt(height);
182: 			drawFire(canvas, fireX, fireY);
183: 		}
184: 	}
185: 
186: 	/**
187: 	 * 火の玉を描画する
188: 	 */
189: 	private void drawFire(BCanvas canvas, int x, int y) {
190: 		canvas.drawFillArc(Color.RED, x, y, 20, 20, 0, 360);
191: 		canvas.drawFillArc(Color.MAGENTA, x + 2, y + 2, 16, 16, 0, 360);
192: 		canvas.drawFillArc(Color.WHITE, x + 1, y + 1, 14, 14, 0, 360);
193: 		canvas.drawFillArc(Color.RED, x + 8, y + 1, 3, 3, 0, 360);
194: 		canvas.drawFillArc(Color.RED, x + 2, y + 8, 3, 3, 0, 360);
195: 		canvas.drawFillArc(Color.RED, x + 10, y + 8, 2, 3, 0, 360);
196: 		canvas.drawFillArc(Color.RED, x, y + 1, 2, 2, 0, 360);
197: 		canvas.drawFillArc(Color.RED, x + 15, y + 18, 2, 2, 0, 360);
198: 	}
199: 
200: 	/**
201: 	 * 四角を描画する(塗りつぶし)
202: 	 */
203: 	private void drawFillRectangle(BCanvas canvas, Color color, int x, int y,
204: 			int width, int height) {
205: 		canvas.drawFillTriangle(color, x, y, x + width, y, x + width, y
206: 				+ height);
207: 		canvas.drawFillTriangle(color, x, y, x, y + height, x + width, y
208: 				+ height);
209: 	}
210: 
211: }

2.4.1.3 敵機を表現するクラス

リスト 2.4.1.3.1 EnemyAircraft.java
  1: import java.awt.Color;
  2: 
  3: import obpro.gui.BCanvas;
  4: 
  5: /**
  6:  * 敵機を表現するクラス
  7:  */
  8: public class EnemyAircraft {
  9: 
 10: 	// 属性
 11: 	private int x = 0;
 12: 	private int y = 0;
 13: 	private int width = 0;
 14: 	private int height = 0;
 15: 
 16: 	/**
 17: 	 * コンストラクタ
 18: 	 */
 19: 	public EnemyAircraft(int x, int y, int width, int height) {
 20: 		this.x = x;
 21: 		this.y = y;
 22: 		this.width = width;
 23: 		this.height = height;
 24: 	}
 25: 
 26: 	/**
 27: 	 * 高さを取得する
 28: 	 */
 29: 	public int getHeight() {
 30: 		return this.height;
 31: 	}
 32: 
 33: 	/**
 34: 	 * 幅を取得する
 35: 	 */
 36: 	public int getWidth() {
 37: 		return this.width;
 38: 	}
 39: 
 40: 	/**
 41: 	 * X座標を取得する
 42: 	 */
 43: 	public int getX() {
 44: 		return this.x;
 45: 	}
 46: 
 47: 	/**
 48: 	 * Y座標を取得する
 49: 	 */
 50: 	public int getY() {
 51: 		return this.y;
 52: 	}
 53: 
 54: 	/**
 55: 	 * 動かす
 56: 	 */
 57: 	public void move(int moveX, int moveY) {
 58: 		x = x + moveX;
 59: 		y = y + moveY;
 60: 	}
 61: 
 62: 	/**
 63: 	 * 1コマの処理を行う
 64: 	 */
 65: 	public void processOneStep() {
 66: 		move(-5, 0);
 67: 	}
 68: 
 69: 	/**
 70: 	 * 描く
 71: 	 */
 72: 	public void draw(BCanvas canvas) {
 73: 		// 座標を決める
 74: 		// 本体
 75: 		int bodyHeight = height * 2 / 5;
 76: 		int bodyY = y + bodyHeight;
 77: 		int bodyWidth = width * 10 / 11;
 78: 
 79: 		// 垂直尾翼
 80: 		int verticalWingX = x + width * 5 / 11;
 81: 
 82: 		// 水平尾翼
 83: 		int tailWingX = x + width * 10 / 11;
 84: 		int tailWingY = y + height * 3 / 5;
 85: 		int tailWingWidth = width / 11;
 86: 		int tailWingHeight = height / 5;
 87: 
 88: 		// コックピット
 89: 		int cockpitX = x + tailWingWidth;
 90: 		int cockpitY = bodyY - tailWingWidth;
 91: 		int cockpitWidth = width * 2 / 11;
 92: 
 93: 		// 主翼
 94: 		int mainWingX1 = x + width * 3 / 11;
 95: 		int mainWingX2 = x + width * 8 / 11;
 96: 
 97: 		// 本体を描く
 98: 		drawFillRectangle(canvas, Color.BLACK, x, bodyY, bodyWidth, bodyHeight);
 99: 		canvas.drawFillArc(Color.GRAY, cockpitX, cockpitY, cockpitWidth,
100: 				cockpitWidth, 0, 180);// コックピット
101: 
102: 		// 水平尾翼を描く
103: 		drawFillRectangle(canvas, Color.BLUE, tailWingX, tailWingY,
104: 				tailWingWidth, tailWingHeight);
105: 
106: 		// 垂直尾翼を描く
107: 		canvas.drawFillTriangle(Color.RED, verticalWingX, bodyY, tailWingX, y,
108: 				tailWingX, bodyY);
109: 
110: 		// 主翼を描く
111: 		canvas.drawFillTriangle(Color.CYAN, mainWingX1, tailWingY, mainWingX2,
112: 				tailWingY, tailWingX, y + height);
113: 	}
114: 
115: 	/**
116: 	 * 四角を描画する(塗りつぶし)
117: 	 */
118: 	private void drawFillRectangle(BCanvas canvas, Color color, int x, int y,
119: 			int width, int height) {
120: 		canvas.drawFillTriangle(color, x, y, x + width, y, x + width, y
121: 				+ height);
122: 		canvas.drawFillTriangle(color, x, y, x, y + height, x + width, y
123: 				+ height);
124: 	}
125: 
126: }

2.4.1.4 弾を表現するクラス

リスト 2.4.1.4.1 Bullet.java
  1: import java.awt.Color;
  2: 
  3: import obpro.gui.BCanvas;
  4: 
  5: /**
  6:  * 弾を表現するクラス
  7:  */
  8: public class Bullet {
  9: 
 10: 	// 定数
 11: 	private final int ALIVE = 1;
 12: 	private final int DEAD = 2;
 13: 
 14: 	// 状態
 15: 	private int liveState = DEAD;
 16: 
 17: 	// 属性
 18: 	private Color color = new Color(0, 0, 255);
 19: 	private int x = 0;
 20: 	private int y = 0;
 21: 	private int width = 0;
 22: 	private int height = 0;
 23: 
 24: 	/**
 25: 	 * コンストラクタ
 26: 	 */
 27: 	public Bullet(int x, int y, int width, int height) {
 28: 		this.x = x;
 29: 		this.y = y;
 30: 		this.width = width;
 31: 		this.height = height;
 32: 	}
 33: 
 34: 	/**
 35: 	 * X座標を取得する
 36: 	 */
 37: 	public int getX() {
 38: 		return x;
 39: 	}
 40: 
 41: 	/**
 42: 	 * Y座標を取得する
 43: 	 */
 44: 	public int getY() {
 45: 		return y;
 46: 	}
 47: 
 48: 	/**
 49: 	 * 動かす
 50: 	 */
 51: 	public void move(int moveX, int moveY) {
 52: 		if (liveState == ALIVE) {
 53: 			x = x + moveX;
 54: 			y = y + moveY;
 55: 		}
 56: 	}
 57: 
 58: 	/**
 59: 	 * 1ステップの処理をする
 60: 	 */
 61: 	public void processOneStep(BCanvas canvas) {
 62: 		if (isLive()) {
 63: 			move(15, 0);// 動かす
 64: 
 65: 			// 画面外に出た場合の処理
 66: 			if (getX() > canvas.getCanvasWidth()) {
 67: 				destroy();
 68: 			}
 69: 		}
 70: 	}
 71: 
 72: 	/**
 73: 	 * 弾を発射する(有効化する)
 74: 	 */
 75: 	public void fire(PlayerAircraft player) {
 76: 		if (liveState == DEAD) {
 77: 			this.x = player.getX() + player.getWidth() / 2 - width / 2;
 78: 			this.y = player.getY() + player.getHeight() / 2 - height / 2;
 79: 			liveState = ALIVE;
 80: 		}
 81: 	}
 82: 
 83: 	/**
 84: 	 * 弾を消滅させる(無効化する)
 85: 	 */
 86: 	public void destroy() {
 87: 		if (liveState == ALIVE) {
 88: 			liveState = DEAD;
 89: 		}
 90: 	}
 91: 
 92: 	/**
 93: 	 * 弾が有効かどうか調べる
 94: 	 */
 95: 	public boolean isLive() {
 96: 		return liveState == ALIVE;
 97: 	}
 98: 
 99: 	/**
100: 	 * 描く
101: 	 */
102: 	public void draw(BCanvas canvas) {
103: 		if (liveState == ALIVE) {
104: 			canvas.drawFillTriangle(color, x, y, x + width, y, x, y + height);
105: 			canvas.drawFillTriangle(color, x, y + height, x + width,
106: 					y + height, x + width, y);
107: 		}
108: 	}
109: 
110: }

2.4.2 シューティングゲーム(2)(弾出し&スムーズな自機操作)

リスト 2.4.2.1 ShootingGame2.java
  1: import java.util.ArrayList;
  2: 
  3: import obpro.gui.BCanvas;
  4: import obpro.gui.BWindow;
  5: 
  6: /**
  7:  * シューティングゲームサンプル (その2 弾出し & スムースな自機操作)
  8:  * 
  9:  * @author macchan
 10:  * @date 2005/06/08 オブプロ第8回
 11:  * @date 2007/06/21 コレクション(ArrayList)を使うように修正
 12:  * @version 1.1
 13:  */
 14: public class ShootingGame2 {
 15: 
 16: 	public static void main(String[] args) {
 17: 		ShootingGame2 shootingGame = new ShootingGame2();
 18: 		shootingGame.main();
 19: 	}
 20: 
 21: 	BWindow window;
 22: 
 23: 	PlayerAircraft player;
 24: 	EnemyAircraft enemy;
 25: 	// ArrayListバージョン
 26: 	ArrayList<Bullet> bullets = new ArrayList<Bullet>();
 27: 	// 配列バージョン
 28: 	// Bullet[] bullets = new Bullet[3];
 29: 
 30: 	void main() {
 31: 		openWindow();
 32: 		doAnimation();
 33: 	}
 34: 
 35: 	// ウインドウを開く
 36: 	void openWindow() {
 37: 		window = new BWindow();
 38: 		window.setLocation(100, 100);
 39: 		window.setSize(640, 480);
 40: 		window.show();
 41: 	}
 42: 
 43: 	// アニメーションする
 44: 	void doAnimation() {
 45: 		BCanvas canvas = window.getCanvas();// キャンバスを取得する
 46: 		initializeObjects();// オブジェクトを初期化する
 47: 
 48: 		// アニメーションする
 49: 		while (true) {
 50: 			// 1コマの処理を行う
 51: 			processOneStep(canvas);
 52: 
 53: 			// 図形を描く
 54: 			canvas.clear();
 55: 			draw(canvas);
 56: 			canvas.update();
 57: 
 58: 			// 眠る
 59: 			canvas.sleep(0.05);
 60: 		}
 61: 	}
 62: 
 63: 	// オブジェクトを初期化する
 64: 	private void initializeObjects() {
 65: 		player = new PlayerAircraft(50, 50, 100, 50);
 66: 		enemy = new EnemyAircraft(400, 50, 100, 50);
 67: 		// ArrayListバージョン
 68: 		for (int i = 0; i < 3; i++) {
 69: 			bullets.add(new Bullet(-1, -1, 20, 10));
 70: 		}
 71: 		// 配列バージョン
 72: 		// for (int i = 0; i < bullets.length; i++) {
 73: 		// bullets[i] = new Bullet(-1, -1, 20, 10);
 74: 		// }
 75: 	}
 76: 
 77: 	// 1コマの処理を行う
 78: 	private void processOneStep(BCanvas canvas) {
 79: 		// (キー入力によって)自機を操作する
 80: 		if (canvas.isKeyPressing(37)) {// 左キー
 81: 			player.move(-5, 0);
 82: 		}
 83: 		if (canvas.isKeyPressing(38)) {// 上キー
 84: 			player.move(0, -5);
 85: 		}
 86: 		if (canvas.isKeyPressing(39)) {// 右キー
 87: 			player.move(5, 0);
 88: 		}
 89: 		if (canvas.isKeyPressing(40)) {// 下キー
 90: 			player.move(0, 5);
 91: 		}
 92: 
 93: 		// キー入力によって弾を出す
 94: 		if (canvas.isKeyDown()) {
 95: 			int keyCode = canvas.getKeyCode();
 96: 			if (keyCode == 70) {// fキー
 97: 				// (有効でない弾を探して)弾を発射する
 98: 				// ArrayListバージョン
 99: 				for (Bullet bullet : bullets) {
100: 					if (bullet.isLive() == false) {
101: 						bullet.fire(player);
102: 						break;
103: 					}
104: 				}
105: 				// 配列バージョン
106: 				// for (int i = 0; i < bullets.length; i++) {
107: 				// if (bullets[i].isLive() == false) {
108: 				// bullets[i].fire(player);
109: 				// break;
110: 				// }
111: 				// }
112: 			}
113: 		}
114: 
115: 		// 各オブジェクトの1コマの処理を行う
116: 		player.processOneStep();
117: 		enemy.processOneStep();
118: 		// ArrayListバージョン
119: 		for (Bullet bullet : bullets) {
120: 			bullet.processOneStep(canvas);
121: 		}
122: 		// 配列バージョン
123: 		// for (int i = 0; i < bullets.length; i++) {
124: 		// bullets[i].processOneStep(canvas);
125: 		// }
126: 
127: 		// 当たり判定を行う
128: 		if (player.intersects(enemy)) {
129: 			player.explode();
130: 		}
131: 	}
132: 
133: 	// 図形を描く
134: 	private void draw(BCanvas canvas) {
135: 		player.draw(canvas);
136: 		enemy.draw(canvas);
137: 		// ArrayListバージョン
138: 		for (Bullet bullet : bullets) {
139: 			bullet.draw(canvas);
140: 		}
141: 		// 配列バージョン
142: 		// for (int i = 0; i < bullets.length; i++) {
143: 		// bullets[i].draw(canvas);
144: 		// }
145: 	}
146: }