3 『継承』

3.1 オブジェクトの動作を理解するためのサンプルプログラム

3.1.1 サンプルプログラム

3.1.1.1 サンプルプログラム(1)(インスタンス1つ)

リスト 3.1.1.1.1 Example1.java
  1: /**
  2:  * Example1.java
  3:  * オブジェクトの動作を理解するためのサンプルプログラム(その1 インスタンス一つ)
  4:  * 
  5:  * @author macchan
  6:  * @date 2005/06/15 オブプロ「継承」
  7:  * @version 1.0
  8:  */
  9: public class Example1 {
 10: 
 11: 	public static void main(String[] args) {
 12: 		Example1 example = new Example1();
 13: 		example.main();
 14: 	}
 15: 
 16: 	private ClassA a;
 17: 
 18: 	private void main() {
 19: 		//インスタンス生成&初期化
 20: 		a = new ClassA();
 21: 		a.setX(1000);
 22: 		a.setY(1000);
 23: 
 24: 		//出力
 25: 		System.out.print("a: ");
 26: 		a.display();
 27: 	}
 28: 
 29: }

3.1.1.2 サンプルプログラム(2)(複数のインスタンス)

リスト 3.1.1.2.1 Example2.java
  1: import java.util.ArrayList;
  2: 
  3: /**
  4:  * Example2.java
  5:  * オブジェクトの動作を理解するためのサンプルプログラム(その2 複数のインスタンス)
  6:  * 
  7:  * @author macchan
  8:  * @date 2005/06/15 オブプロ「継承」
  9:  * @date 2007/06/27 camei 配列をコレクション(ArrayList)で書き直す
 10:  * @version 2.0
 11:  */
 12: public class Example2 {
 13: 
 14: 	public static void main(String[] args) {
 15: 		Example2 example = new Example2();
 16: 		example.main();
 17: 	}
 18: 
 19: 	private ArrayList<ClassA> aInstances;
 20: 
 21: 	private void main() {
 22: 
 23: 		// リスト生成
 24: 		aInstances = new ArrayList<ClassA>();
 25: 
 26: 		//インスタンス生成&初期化
 27: 		initialize(aInstances);
 28: 
 29: 		//出力
 30: 		display(aInstances);
 31: 	}
 32: 
 33: 	private void initialize(ArrayList<ClassA> targets) {
 34: 		for (int i = 0; i < 3; i++) {
 35: 			ClassA a = new ClassA();
 36: 			a.setX(100 * i);
 37: 			a.setY(100 * i);
 38: 			targets.add(a);
 39: 		}
 40: 	}
 41: 
 42: 	private void display(ArrayList<ClassA> targets) {
 43: 		// ArrayList の全要素に順次アクセスするのは以下のようにも書ける
 44: 		for (int i = 0; i < targets.size(); i++) {
 45: 			ClassA a = targets.get(i);// targetsのi番目の要素を取得
 46: 			System.out.print("targets [" + i + "]: ");
 47: 			a.display();
 48: 		}
 49: 	}
 50: }

3.1.1.3 サンプルプログラム(3)(継承)

リスト 3.1.1.3.1 Example3.java
  1: /**
  2:  * Example3.java
  3:  * オブジェクトの動作を理解するためのサンプルプログラム(その3 継承)
  4:  * 
  5:  * @author macchan
  6:  * @date 2005/06/15 オブプロ「継承」
  7:  * @version 1.0
  8:  */
  9: public class Example3 {
 10: 
 11: 	public static void main(String[] args) {
 12: 		Example3 example = new Example3();
 13: 		example.main();
 14: 	}
 15: 
 16: 	private ClassA a;
 17: 	private ClassB b;
 18: 	private ClassC c;
 19: 	private ClassD d;
 20: 
 21: 	private void main() {
 22: 		//インスタンス生成
 23: 		a = new ClassA();
 24: 		b = new ClassB();
 25: 		c = new ClassC(100);
 26: 		d = new ClassD(100);
 27: 
 28: 		//値設定
 29: 		a.setX(1000);
 30: 		a.setY(1000);
 31: 		b.setX(2000);
 32: 		b.setY(2000);
 33: 		b.setW(2000);
 34: 		b.setH(2000);
 35: 		c.setX(3000);
 36: 		c.setY(3000);
 37: 		d.setX(4000);
 38: 		d.setY(4000);
 39: 		d.addZ(50);
 40: 
 41: 		//出力
 42: 		System.out.print("a: ");
 43: 		a.display();
 44: 		System.out.print("b: ");
 45: 		b.display();
 46: 		System.out.print("c: ");
 47: 		c.display();
 48: 		System.out.print("d: ");
 49: 		d.display();
 50: 	}
 51: }

3.1.2 サンプルプログラムが利用するクラスたち

3.1.2.1 クラスA

リスト 3.1.2.1.1 ClassA.java
  1: /**
  2:  * ClassA.java
  3:  * オブジェクトの動作を理解するためのサンプルプログラム(その1〜その3)
  4:  * 
  5:  * @author macchan
  6:  * @date 2005/06/02 オブプロ「継承」
  7:  * @version 1.0
  8:  */
  9: public class ClassA {
 10: 
 11: 	private int x = 100;
 12: 	private int y = 200;
 13: 
 14: 	/**
 15: 	 * xを取得する
 16: 	 */
 17: 	public int getX() {
 18: 		return x;
 19: 	}
 20: 
 21: 	/**
 22: 	 * xを設定する
 23: 	 */
 24: 	public void setX(int x) {
 25: 		this.x = x;
 26: 	}
 27: 
 28: 	/**
 29: 	 * yを取得する
 30: 	 */
 31: 	public int getY() {
 32: 		return y;
 33: 	}
 34: 
 35: 	/**
 36: 	 * yを設定する
 37: 	 */
 38: 	public void setY(int y) {
 39: 		this.y = y;
 40: 	}
 41: 
 42: 	/**
 43: 	 * 表示を行う	 
 44: 	 */
 45: 	public void display() {
 46: 		System.out.println("x=" + getX() + ", y=" + getY());
 47: 	}
 48: 
 49: }

3.1.2.2 クラスB(クラスAを継承)

リスト 3.1.2.2.1 ClassB.java
  1: /**
  2:  * ClassB.java
  3:  * オブジェクトの動作を理解するためのサンプルプログラム(その3)
  4:  * 
  5:  * @author macchan
  6:  * @date 2005/06/02 オブプロ「継承」
  7:  * @version 1.0
  8:  */
  9: public class ClassB extends ClassA {
 10: 
 11: 	private int w = 300;
 12: 	private int h = 400;
 13: 
 14: 	/**
 15: 	 * wを取得する
 16: 	 */
 17: 	public int getW() {
 18: 		return w;
 19: 	}
 20: 
 21: 	/**
 22: 	 * wを設定する
 23: 	 */
 24: 	public void setW(int w) {
 25: 		this.w = w;
 26: 	}
 27: 
 28: 	/**
 29: 	 * hを取得する
 30: 	 */
 31: 	public int getH() {
 32: 		return h;
 33: 	}
 34: 
 35: 	/**
 36: 	 * hを設定する
 37: 	 */
 38: 	public void setH(int h) {
 39: 		this.h = h;
 40: 	}
 41: 
 42: 	/**
 43: 	 * 表示を行う(オーバーライドによる再定義)	 
 44: 	 */
 45: 	public void display() {
 46: 		System.out.println("x=" + getX() + ", y=" + getY() + ", w=" + getW()
 47: 				+ ", h=" + getH());
 48: 	}
 49: 
 50: }

3.1.2.3 クラスC(クラスAを継承)

リスト 3.1.2.3.1 ClassC.java
  1: /**
  2:  * ClassC.java
  3:  * オブジェクトの動作を理解するためのサンプルプログラム(その3)
  4:  * 
  5:  * @author macchan
  6:  * @date 2005/06/02 オブプロ「継承」
  7:  * @version 1.0
  8:  */
  9: public class ClassC extends ClassA {
 10: 
 11: 	private int z;
 12: 
 13: 	public ClassC(int z) {
 14: 		this.z = z;
 15: 	}
 16: 
 17: 	/**
 18: 	 * zを取得する
 19: 	 */
 20: 	public int getZ() {
 21: 		return z;
 22: 	}
 23: 
 24: 	/**
 25: 	 * zを取得する
 26: 	 */
 27: 	public void setZ(int z) {
 28: 		this.z = z;
 29: 	}
 30: 
 31: 	/**
 32: 	 * 表示を行う(オーバーライドによる再定義)	 
 33: 	 */
 34: 	public void display() {
 35: 		System.out.println("x=" + getX() + ", y=" + getY() + ", z=" + getZ());
 36: 	}
 37: }

3.1.2.4 クラスD(クラスAを継承)

リスト 3.1.2.4.1 ClassD.java
  1: /**
  2:  * ClassD.java
  3:  * オブジェクトの動作を理解するためのサンプルプログラム(その3)
  4:  * 
  5:  * @author macchan
  6:  * @date 2005/06/02 オブプロ「継承」
  7:  * @version 1.0
  8:  */
  9: public class ClassD extends ClassC {
 10: 
 11: 	/**
 12: 	 * コンストラクタは継承しないので,必ず再定義する必要がある
 13: 	 */
 14: 	public ClassD(int z) {
 15: 		super(z);
 16: 	}
 17: 
 18: 	/**
 19: 	 * zを増やす
 20: 	 */
 21: 	public void addZ(int addZ) {
 22: 		int z = getZ();//スーパークラスのメソッドを呼ぶ
 23: 		setZ(z + addZ);//スーパークラスのメソッドを呼ぶ
 24: 	}
 25: 
 26: }

3.2 シューティングゲーム

3.2.1 シューティングゲーム(3)(シューティングゲーム(2)と同じ)

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

3.2.2 シューティングゲームのキャラクターを表現するクラス

リスト 3.2.2.1 ShootingCharacter.java
  1: /**
  2:  * シューティングゲームのキャラクターを表現するクラス
  3:  */
  4: public class ShootingCharacter {
  5: 
  6: 	// 属性
  7: 	private int x = 0;
  8: 	private int y = 0;
  9: 	private int width = 0;
 10: 	private int height = 0;
 11: 
 12: 	/**
 13: 	 * コンストラクタ
 14: 	 */
 15: 	public ShootingCharacter(int x, int y, int width, int height) {
 16: 		this.x = x;
 17: 		this.y = y;
 18: 		this.width = width;
 19: 		this.height = height;
 20: 	}
 21: 
 22: 	/**
 23: 	 * 高さを取得する
 24: 	 */
 25: 	public int getHeight() {
 26: 		return this.height;
 27: 	}
 28: 
 29: 	/**
 30: 	 * 幅を取得する
 31: 	 */
 32: 	public int getWidth() {
 33: 		return this.width;
 34: 	}
 35: 
 36: 	/**
 37: 	 * X座標を取得する
 38: 	 */
 39: 	public int getX() {
 40: 		return this.x;
 41: 	}
 42: 
 43: 	/**
 44: 	 * Y座標を取得する
 45: 	 */
 46: 	public int getY() {
 47: 		return this.y;
 48: 	}
 49: 
 50: 	/**
 51: 	 * 位置を再設定する
 52: 	 */
 53: 	public void setLocation(int newX, int newY) {
 54: 		x = newX;
 55: 		y = newY;
 56: 	}
 57: 
 58: 	/**
 59: 	 * 動かす
 60: 	 */
 61: 	public void move(int moveX, int moveY) {
 62: 		x = x + moveX;
 63: 		y = y + moveY;
 64: 	}
 65: }

3.2.3 自機を表現するクラス

リスト 3.2.3.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 extends ShootingCharacter {
 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_SIZE = 10;
 17: 
 18: 	//状態
 19: 	private int liveState = ALIVE;
 20: 	private int explodingCount = 0;
 21: 
 22: 	/**
 23: 	 * コンストラクタ
 24: 	 */
 25: 	public PlayerAircraft(int x, int y, int width, int height) {
 26: 		super(x, y, width, height);
 27: 	}
 28: 
 29: 	/**
 30: 	 * 動かす(オーバーライドによる再定義)
 31: 	 */
 32: 	public void move(int moveX, int moveY) {
 33: 		if (liveState == ALIVE) {
 34: 			super.move(moveX, moveY);
 35: 		}
 36: 	}
 37: 
 38: 	/**
 39: 	 * 1ステップの処理をする
 40: 	 */
 41: 	public void processOneStep() {
 42: 		processExplore();
 43: 	}
 44: 
 45: 	/**
 46: 	 * 爆発の処理をする
 47: 	 */
 48: 	private void processExplore() {
 49: 		if (liveState == EXPLODING) {
 50: 			explodingCount++;
 51: 			if (explodingCount == EXPLODING_ANIMATION_SIZE) {
 52: 				liveState = DEAD;
 53: 			}
 54: 		}
 55: 	}
 56: 
 57: 	/**
 58: 	 * 爆発する(爆発状態に遷移する)
 59: 	 */
 60: 	public void explode() {
 61: 		if (liveState == ALIVE) {
 62: 			liveState = EXPLODING;
 63: 			explodingCount = 0;
 64: 		}
 65: 	}
 66: 
 67: 	/**
 68: 	 * 敵との衝突判定をする
 69: 	 */
 70: 	public boolean intersects(EnemyAircraft enemy) {
 71: 		int player_leftX = this.getX();
 72: 		int player_rightX = this.getX() + this.getWidth();
 73: 		int enemy_leftX = enemy.getX();
 74: 		int enemy_rightX = enemy.getX() + enemy.getWidth();
 75: 		int player_topY = this.getY();
 76: 		int player_bottomY = this.getY() + this.getHeight();
 77: 		int enemy_topY = enemy.getY();
 78: 		int enemy_bottomY = enemy.getY() + enemy.getHeight();
 79: 
 80: 		return (enemy_leftX < player_rightX && enemy_rightX > player_leftX
 81: 				&& enemy_topY < player_bottomY && enemy_bottomY > player_topY);
 82: 	}
 83: 
 84: 	/**
 85: 	 * 描く
 86: 	 */
 87: 	public void draw(BCanvas canvas) {
 88: 		if (liveState == ALIVE) {
 89: 			drawAircraft(canvas);
 90: 		} else if (liveState == EXPLODING) {
 91: 			drawAircraft(canvas);
 92: 			drawExplosion(canvas);
 93: 		}
 94: 	}
 95: 
 96: 	/**
 97: 	 * 飛行機を描画する
 98: 	 */
 99: 	private void drawAircraft(BCanvas canvas) {
100: 		//座標を決める
101: 		//コックピット
102: 		int headX = getX() + getWidth() * 11 / 13;
103: 		int headY = getY() + getHeight() * 4 / 5;
104: 
105: 		//本体
106: 		int bodyX = getX() + getWidth() / 13;
107: 		int bodyY = getY() + getHeight() * 2 / 5;
108: 		int bodyWidth = getWidth() * 10 / 13;
109: 		int bodyHeight = getHeight() * 2 / 5;
110: 
111: 		//垂直尾翼
112: 		int verticalWingX1 = getX() + getWidth() * 2 / 13;
113: 		int verticalWingX2 = getX() + getWidth() * 7 / 13;
114: 
115: 		//水平尾翼
116: 		int tailWingY = getY() + getHeight() * 3 / 5;
117: 		int tailWingWidth = getWidth() / 13;
118: 		int tailWingHeight = getHeight() / 5;
119: 
120: 		//本体を描く
121: 		drawFillRectangle(canvas, Color.BLUE, bodyX, bodyY, bodyWidth,
122: 				bodyHeight);
123: 		canvas.drawFillTriangle(Color.BLUE, headX, bodyY, headX, headY, getX()
124: 				+ getWidth(), headY);
125: 
126: 		//水平尾翼を描く
127: 		drawFillRectangle(canvas, Color.BLACK, getX(), tailWingY,
128: 				tailWingWidth, tailWingHeight);
129: 
130: 		//垂直尾翼を描く
131: 		canvas.drawFillTriangle(Color.GRAY, verticalWingX1, getY(),
132: 				verticalWingX1, bodyY, verticalWingX2, bodyY);
133: 
134: 		//主翼を描く
135: 		canvas.drawFillTriangle(Color.CYAN, verticalWingX1, tailWingY,
136: 				verticalWingX2, tailWingY, bodyX, getY() + getHeight());
137: 	}
138: 
139: 	/**
140: 	 * 爆発を描画する
141: 	 */
142: 	private void drawExplosion(BCanvas canvas) {
143: 		// 火の玉の数を決める
144: 		int fireCount = explodingCount * 4;// カウント数の4倍(徐々に増える)
145: 
146: 		// 火の玉を描画する
147: 		for (int i = 0; i < fireCount; i++) {
148: 			int fireX = getX() + Random.getInt(getWidth());
149: 			int fireY = getY() + Random.getInt(getHeight());
150: 			drawFire(canvas, fireX, fireY);
151: 		}
152: 	}
153: 
154: 	/**
155: 	 * 火の玉を描画する
156: 	 */
157: 	private void drawFire(BCanvas canvas, int x, int y) {
158: 		canvas.drawFillArc(Color.RED, x, y, 20, 20, 0, 360);
159: 		canvas.drawFillArc(Color.MAGENTA, x + 2, y + 2, 16, 16, 0, 360);
160: 		canvas.drawFillArc(Color.WHITE, x + 1, y + 1, 14, 14, 0, 360);
161: 		canvas.drawFillArc(Color.RED, x + 8, y + 1, 3, 3, 0, 360);
162: 		canvas.drawFillArc(Color.RED, x + 2, y + 8, 3, 3, 0, 360);
163: 		canvas.drawFillArc(Color.RED, x + 10, y + 8, 2, 3, 0, 360);
164: 		canvas.drawFillArc(Color.RED, x, y + 1, 2, 2, 0, 360);
165: 		canvas.drawFillArc(Color.RED, x + 15, y + 18, 2, 2, 0, 360);
166: 	}
167: 
168: 	/**
169: 	 * 四角を描画する(塗りつぶし)
170: 	 */
171: 	private void drawFillRectangle(BCanvas canvas, Color color, int x, int y,
172: 			int width, int height) {
173: 		canvas.drawFillTriangle(color, x, y, x + width, y, x + width, y
174: 				+ height);
175: 		canvas.drawFillTriangle(color, x, y, x, y + height, x + width, y
176: 				+ height);
177: 	}
178: 
179: }

3.2.4 敵機を表現するクラス

リスト 3.2.4.1 EnemyAircraft.java
  1: import java.awt.Color;
  2: 
  3: import obpro.gui.BCanvas;
  4: 
  5: /**
  6:  * 敵機を表現するクラス
  7:  */
  8: public class EnemyAircraft extends ShootingCharacter {
  9: 
 10: 	/**
 11: 	 * コンストラクタ
 12: 	 */
 13: 	public EnemyAircraft(int x, int y, int width, int height) {
 14: 		super(x, y, width, height);
 15: 	}
 16: 
 17: 	/**
 18: 	 * 1ステップの処理をする
 19: 	 */
 20: 	public void processOneStep() {
 21: 		move(-5, 0);
 22: 	}
 23: 
 24: 	/**
 25: 	 * 描く
 26: 	 */
 27: 	public void draw(BCanvas canvas) {
 28: 		// 座標を決める
 29: 		// 本体
 30: 		int bodyHeight = getHeight() * 2 / 5;
 31: 		int bodyY = getY() + bodyHeight;
 32: 		int bodyWidth = getWidth() * 10 / 11;
 33: 
 34: 		// 垂直尾翼
 35: 		int verticalWingX = getX() + getWidth() * 5 / 11;
 36: 
 37: 		// 水平尾翼
 38: 		int tailWingX = getX() + getWidth() * 10 / 11;
 39: 		int tailWingY = getY() + getHeight() * 3 / 5;
 40: 		int tailWingWidth = getWidth() / 11;
 41: 		int tailWingHeight = getHeight() / 5;
 42: 
 43: 		// コックピット
 44: 		int cockpitX = getX() + tailWingWidth;
 45: 		int cockpitY = bodyY - tailWingWidth;
 46: 		int cockpitWidth = getWidth() * 2 / 11;
 47: 
 48: 		// 主翼
 49: 		int mainWingX1 = getX() + getWidth() * 3 / 11;
 50: 		int mainWingX2 = getX() + getWidth() * 8 / 11;
 51: 
 52: 		// 本体を描く
 53: 		drawFillRectangle(canvas, Color.BLACK, getX(), bodyY, bodyWidth,
 54: 				bodyHeight);
 55: 		canvas.drawFillArc(Color.GRAY, cockpitX, cockpitY, cockpitWidth,
 56: 				cockpitWidth, 0, 180);// コックピット
 57: 
 58: 		// 水平尾翼を描く
 59: 		drawFillRectangle(canvas, Color.BLUE, tailWingX, tailWingY,
 60: 				tailWingWidth, tailWingHeight);
 61: 
 62: 		// 垂直尾翼を描く
 63: 		canvas.drawFillTriangle(Color.RED, verticalWingX, bodyY, tailWingX,
 64: 				getY(), tailWingX, bodyY);
 65: 
 66: 		// 主翼を描く
 67: 		canvas.drawFillTriangle(Color.CYAN, mainWingX1, tailWingY, mainWingX2,
 68: 				tailWingY, tailWingX, getY() + getHeight());
 69: 	}
 70: 
 71: 	/**
 72: 	 * 四角を描画する(塗りつぶし)
 73: 	 */
 74: 	private void drawFillRectangle(BCanvas canvas, Color color, int x, int y,
 75: 			int width, int height) {
 76: 		canvas.drawFillTriangle(color, x, y, x + width, y, x + width, y
 77: 				+ height);
 78: 		canvas.drawFillTriangle(color, x, y, x, y + height, x + width, y
 79: 				+ height);
 80: 	}
 81: 
 82: }

3.2.5 弾を表現するクラス

リスト 3.2.5.1 Bullet.java
  1: import java.awt.Color;
  2: 
  3: import obpro.gui.BCanvas;
  4: 
  5: /**
  6:  * 弾を表現するクラス
  7:  */
  8: public class Bullet extends ShootingCharacter {
  9: 
 10: 	//定数
 11: 	private final int LIVE = 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: 
 20: 	/**
 21: 	 * コンストラクタ
 22: 	 */
 23: 	public Bullet(int x, int y, int width, int height) {
 24: 		super(x, y, width, height);
 25: 	}
 26: 
 27: 	/**
 28: 	 * 1ステップの処理をする
 29: 	 */
 30: 	public void processOneStep(BCanvas canvas) {
 31: 		if (liveState == LIVE) {
 32: 			//動かす
 33: 			move(15, 0);
 34: 
 35: 			//画面外に出た場合の処理
 36: 			if (getX() > canvas.getCanvasWidth()) {
 37: 				destroy();
 38: 			}
 39: 		}
 40: 	}
 41: 
 42: 	/**
 43: 	 * 弾を発射する(有効化する)
 44: 	 */
 45: 	public void fire(PlayerAircraft player) {
 46: 		if (liveState == DEAD) {
 47: 			int x = player.getX() + player.getWidth() / 2 - getWidth() / 2;
 48: 			int y = player.getY() + player.getHeight() / 2 - getHeight() / 2;
 49: 			setLocation(x, y);
 50: 			liveState = LIVE;
 51: 		}
 52: 	}
 53: 
 54: 	/**
 55: 	 * 弾を消滅させる(無効化する)
 56: 	 */
 57: 	public void destroy() {
 58: 		if (liveState == LIVE) {
 59: 			liveState = DEAD;
 60: 		}
 61: 	}
 62: 
 63: 	/**
 64: 	 * 弾が有効かどうか調べる
 65: 	 */
 66: 	public boolean isAlive() {
 67: 		return liveState == LIVE;
 68: 	}
 69: 
 70: 	/**
 71: 	 * 描く
 72: 	 */
 73: 	public void draw(BCanvas canvas) {
 74: 		if (isAlive()) {
 75: 			canvas.drawFillTriangle(color, getX(), getY(), getX() + getWidth(),
 76: 					getY(), getX(), getY() + getHeight());
 77: 			canvas.drawFillTriangle(color, getX(), getY() + getHeight(), getX()
 78: 					+ getWidth(), getY() + getHeight(), getX() + getWidth(),
 79: 					getY());
 80: 		}
 81: 	}
 82: 
 83: }