ゲーム盤の定義ができたので、Applet上にゲーム盤を表示してみましょう。
Applet上に絵を描く場合には、少なくともpaint()
というメソッドを
オーバーライドする必要があります。
paint()
は、Appletが最初にロードされたとき、
Appletのあるページに戻ったとき、
他のウィンドウに隠れていたAppletの一部が再び見えるようになったとき
などに呼び出されるメソッドです。
//----------------------------------------------------------------------------- // public void paint(Graphics g) // 現在のゲームの状態を描画する。 //----------------------------------------------------------------------------- public void paint(Graphics g) { }
paint()
には、Graphics
クラスのインスタンスが
引き数として渡されます。
Graphics
クラスは「描画対象」を表現したクラスです。
すべての描画操作はGraphics
クラスに定義されています。
Graphics
クラスは抽象クラスであり、Graphics
クラス自体のインスタンスは存在しません。 Webブラウザなどの実行環境が、ハードウェア/OSに依存した描画方法を記述したGraphics
クラスのサブクラスを独自に定義していて、 そのクラスのインスタンスをpaint()
の引き数に渡してきます。
Graphics
クラスを使って絵を描くときには、
まずsetColor()
メソッドで色を指定する必要があります。
setColor()
メソッドの引き数は
Color
クラスのインスタンスです。
ここではColor
クラスのクラス変数で定義されている色を元に
色の定義を行います。
//----------------------------------------------------------------------------- // クラス変数定義 //----------------------------------------------------------------------------- // 使用する色のインデックス public final static int BG_COLOR = 0; // 背景色 public final static int NUTRAL_COLOR = 1; // 中立の玉の色 public final static int FIRST_COLOR = 2; // 先手の玉の色 public final static int SECOND_COLOR = 3; // 後手の玉の色 // 使用する色の定義 public final static Color color[] = { Color.lightGray, Color.green.darker(), Color.blue, Color.red };
darker()
は色を少し暗くするメソッドです。
UpperHandGame
クラスでは、玉の位置を0〜54の番号で表現していました。
描画するときには位置の番号を2次元の座標に変換する必要があります。
描画するたびに計算するのは効率が悪そうなので、
あらかじめ計算しておいてクラス変数に記録しておくことにしました。
//----------------------------------------------------------------------------- // クラス変数定義 //----------------------------------------------------------------------------- // 玉の大きさ private final static int size = 20; // 玉の描画エリア private static Rectangle area[]; //----------------------------------------------------------------------------- // クラス変数の初期化 //----------------------------------------------------------------------------- static { // 玉の描画エリアを初期化する。 // 位置pと、その(x,y,z)座標の対応をとり、sizeから位置pの描画エリアを // 計算している。 area = new Rectangle[55]; int p = 0; for (int z = 4; z >= 0; z--) { for (int y = 0; y <= z; y++) { for (int x = 0; x <= z; x++) { area[p] = new Rectangle( (4 - z) * size / 2 + size * x, (4 - z) * size / 2 + size * y, size, size); p++; } } } }
static { ... }
の部分はstaticイニシャライザといって、
クラスがロードされた直後に実行される名前のないクラスメソッドです。
クラス変数の初期化に処理が必要な場合にstaticイニシャライザを使います。
paint()
を実装する
準備が整ったので、paint()
を実装しましょう。
盤だけを描画する内部メソッドpaintBoard()
、
指定された位置の玉を描画する内部メソッドpaintBall()
を使っています。
//----------------------------------------------------------------------------- // public void paint(Graphics g) // 現在のゲームの状態を描画する。 //----------------------------------------------------------------------------- public void paint(Graphics g) { System.err.println("UpperHand.paint() called."); paintBoard(g); // 盤を描画する。 // 玉を描画する。 for (int p = 0; p < area.length; p++) { paintBall(g, p); } } //----------------------------------------------------------------------------- // private void paintBoard(Graphics g) // ゲーム盤のみを描画する。 //----------------------------------------------------------------------------- private void paintBoard(Graphics g) { // 描画色を「背景色」とする。 g.setColor(color[BG_COLOR]); // 5×5の盤面に浮き上がった四角形を書く。 for (int y = 0; y < 5; y++) { for (int x = 0; x < 5; x++) { g.fill3DRect(x * size, y * size, size, size, true); } } } //----------------------------------------------------------------------------- // private void paintBall(Graphics g, int p) // pで指定された位置の玉を描画する。 //----------------------------------------------------------------------------- private void paintBall(Graphics g, int p) { Color c; // 玉の色を決定する。 switch (game.boardStatus(p)) { case UpperHandGame.FIRST: c = color[FIRST_COLOR]; break; case UpperHandGame.SECOND: c = color[SECOND_COLOR]; break; case UpperHandGame.NUTRAL: c = color[NUTRAL_COLOR]; break; default: return; } // 描画エリアより少し小さめに円を描く。 g.setColor(c); g.fillOval(area[p].x + 1, area[p].y + 1, area[p].width - 2, area[p].height - 2); }
Javaソースコード (Ver. 1.1a3)