1 /*
  2  * Copyright (C) 2012-2013 たかはしのんき. All rights reserved.
  3  *
  4  * History:
  5  *  0.3 2013-06-15 JsDoc Toolkit対応。メソッド showScore の作成。
  6  *  0.2 2013-04-26 バージョンの変更。
  7  *  0.1 2013-04-07 碁盤プログラム goban06.js を元に新規作成。
  8  */
  9 
 10 /**
 11  * @fileOverview Simulator - 囲碁対局シミュレータ
 12  * @name simulator03.js
 13  * @version 0.3
 14  * @author たかはしのんき
 15  * 
 16  */
 17 
 18 // 共通に使う定数と変数
 19 var BLACK = 1;
 20 var WHITE = 2;
 21 var PX_BOWL = 134;	// 碁笥の直径 [ピクセル]
 22 var Z2_BOWL = 20;	// 碁笥の高さ / 2 [ピクセル]
 23 var PX_LID = 110;	// 碁笥の蓋の直径 [ピクセル]
 24 var Z2_LID = 8;		// 碁笥の蓋の高さ / 2 [ピクセル]
 25 var PX_STONE = 22;	// 碁石の直径 [ピクセル]
 26 var Z2_STONE = 2;	// 碁石の高さ / 2 [ピクセル]
 27 var PX_STAR = 5;	// 星の直径 [ピクセル]
 28 var PX_CHAR = 24;	// 文字の高さ [ピクセル]
 29 var Z2_BOARD = 6;	// 碁盤の高さ / 2 [ピクセル]
 30 
 31 // キャッシュにイメージを読み込んでおく
 32 var imgbb = new Image(PX_BOWL, PX_BOWL);	// 黒の碁笥 (black bowl)
 33 imgbb.src = "img/blackbowl134.png";
 34 var imgwb = new Image(PX_BOWL, PX_BOWL);	// 白の碁笥 (white bowl)
 35 imgwb.src = "img/whitebowl134.png";
 36 var imgl = new Image(PX_LID, PX_LID);		// 碁笥の蓋 (lid)
 37 imgl.src = "img/lid110.png";
 38 var imgb = new Image(PX_STONE, PX_STONE);	// 黒石 (white stone)
 39 imgb.src = "img/black22.png";
 40 var imgw = new Image(PX_STONE, PX_STONE);	// 白石 (black stone)
 41 imgw.src = "img/white22.png";
 42 var imgs = new Image(PX_STAR, PX_STAR);		// 星 (star)
 43 imgs.src = "img/star5.png";
 44 
 45 // キャッシュに効果音を読み込んでおく
 46 var ext = audioExt();
 47 var auClick = new Audio("se/button6."  + ext);
 48 var auSwitch = new Audio("se/se_sad05." + ext);
 49 var auError = new Audio("se/se_sad08." + ext);
 50 
 51 var ro = 9;							// 路数
 52 var context3;						// 碁石レイヤーのキャンバスのコンテキスト
 53 var context2;						// 影レイヤーのキャンバスのコンテキスト
 54 var passButton = new Array(2);		// [パス]ボタン
 55 var brd;							// 碁盤オブジェクト
 56 var offsetBLid = new Object();		// 黒の碁笥の蓋のオフセット
 57 var offsetWLid = new Object();		// 白の碁笥の蓋のオフセット
 58 
 59 /**
 60  * ロード時に碁盤イメージを描画します。
 61  */
 62 window.onload = function() {
 63 	// 黒石の <input id="black"> 取得
 64 	passButton[BLACK] = document.getElementById('black');
 65 	// 白石の <input id="white"> 取得
 66 	passButton[WHITE] = document.getElementById('white');
 67 
 68 	// キャンバスとコンテキスト取得
 69 	var canvas = document.querySelector('#table');
 70 	var context = canvas.getContext('2d');
 71 	var canvas3 = document.querySelector('#stones');
 72 	context3 = canvas3.getContext('2d');
 73 	var canvas2 = document.querySelector('#shadow');
 74 	context2 = canvas2.getContext('2d');
 75 	// 座標 (270, 50) にタイトルを表示
 76 	context.fillStyle = "white";
 77 	context.font = "bold 24px Arial";
 78 	var title = "Simulator 0.3";
 79 	var x = context.canvas.width / 2 - 
 80 			PX_CHAR / 1.8 * title.length / 2;
 81 	var y = PX_CHAR * 2;
 82 	context.fillText(title, x, y);
 83 	// 机の中央に 碁盤を表示
 84 	brd = new Board(ro, context);
 85 	// 碁盤の左に白の碁笥の蓋のイメージを表示
 86 	offsetWLid.x = Math.floor((brd.boardOffset.x - PX_LID) / 2);
 87 	offsetWLid.y = brd.boardOffset.y +
 88 		Math.floor((brd.boardSize.height - PX_LID) / 2);
 89 	drawObject(offsetWLid.x, offsetWLid.y, Z2_LID, imgl, context, context);
 90 	// 左上に白の碁笥のイメージを表示
 91 	var xb = offsetWLid.x - Math.floor((PX_BOWL - PX_LID) / 2);
 92 	var yb = offsetWLid.y - PX_BOWL - Z2_BOWL;
 93 	drawObject(xb, yb, Z2_BOWL, imgwb, context, context);
 94 	// 碁盤の右に黒の碁笥の蓋のイメージを表示
 95 	offsetBLid.x = offsetWLid.x + brd.boardOffset.x + brd.boardSize.width;
 96 	offsetBLid.y = offsetWLid.y;
 97 	drawObject(offsetBLid.x, offsetBLid.y, Z2_LID, imgl, context, context);
 98 	// 右下に黒の碁笥のイメージを表示
 99 	xb = offsetBLid.x - Math.floor((PX_BOWL - PX_LID) / 2);
100 	yb = offsetBLid.y + PX_LID + Z2_BOWL;
101 	drawObject(xb, yb, Z2_BOWL, imgbb, context, context);
102 	// 碁盤を表示
103 	brd.drawBoard(Z2_BOARD, context);
104 	// 黒番から
105 	passButton[WHITE].disabled = true;
106 	// クリックイベント登録
107 	canvas3.addEventListener("click", onClick, false);
108 };
109 
110 /**
111  * アゲハマの表示
112  * @param stone 石の色
113  * @param prisoner アゲハマの数
114  * @since 0.1
115  */
116 function showPrisoner(stone, prisoner) {
117 	if (stone == BLACK) {
118 		var p = document.getElementById('pb');
119 	} else {
120 		var p = document.getElementById('pw');
121 	}
122 	p.firstChild.nodeValue = prisoner;
123 }
124 
125 /**
126  * 得点の表示
127  * @param stone 石の色
128  * @param score 得点
129  * @since 0.3
130  */
131 function showScore(stone, score) {
132 	if (stone == BLACK) {
133 		var p = document.getElementById('sb');
134 	} else {
135 		var p = document.getElementById('sw');
136 	}
137 	p.firstChild.nodeValue = score;
138 }
139 
140 /**
141  * マウスイベントハンドラー
142  * 碁石を置きます。
143  * @since 0.1
144  */
145 function onClick() {
146 	var event = arguments[0];
147 	var mx = event.pageX - this.parentNode.offsetLeft;
148 	var my = event.pageY - this.parentNode.offsetTop; 
149 	var mv = brd.offsetToMove(mx, my);
150 	if (mv.onBoard) {
151 		brd.move(mv.col, mv.row, context3, context2);
152 	} else {
153 		if (brd.p.turn == BLACK) 
154 			drawObject(mx - (PX_STONE / 2), my - (PX_STONE / 2), Z2_STONE, imgb, context2, context2);
155 		else
156 			drawObject(mx - (PX_STONE / 2), my - (PX_STONE / 2), Z2_STONE, imgw, context2, context2);
157 		auError.play();
158 	}
159 }
160 
161 
162 /**
163  * [パス]ボタンの処理
164  * @since 0.1
165  */
166 function pass() {
167 	// ボタンの音を鳴らす。
168 	auSwitch.play();
169 	var col = PASS(ro);
170 	var row = PASS(ro);
171 	brd.move(col, row, context3, context2);
172 }
173 
174 /**
175  * [はじめから]ボタンの処理
176  * @since 0.1
177  */
178 function restart() {
179 	// ボタンの音を鳴らす。
180 	auSwitch.play();
181 	// 碁石と影のレイヤーをクリア
182 	context3.clearRect(0, 0, context3.canvas.width, context3.canvas.height);
183 	context2.clearRect(0, 0, context2.canvas.width, context2.canvas.height);
184 	// アゲハマのクリア
185 	showPrisoner(BLACK, 0);
186 	showPrisoner(WHITE, 0);
187 	// 得点のクリア
188 	showScore(BLACK, 0);
189 	showScore(WHITE, 0);
190 	// 黒番から
191 	brd.clear();
192 	passButton[BLACK].disabled = false;
193 	passButton[WHITE].disabled = true;
194 }
195 
196 /**
197  * ブラウザで有効なAudioの拡張子を獲得
198  * @since 0.1
199  */
200 function audioExt() {
201     var ext = "";
202     var audio = new Audio();
203  	if (audio.canPlayType("audio/ogg") == 'maybe')
204  		ext="ogg";
205     else if (audio.canPlayType("audio/mp3") == 'maybe')
206     	ext="mp3";
207     else if (audio.canPlayType("audio/wav") == 'maybe')
208     	ext="wav";
209     return ext;
210 }
211 
212 /**
213  * 円形オブジェクトを描画します。
214  * @param x 左端座標
215  * @param y 上端座標
216  * @param s 影の長さ(高さ/2)
217  * @param img オブジェクトのイメージ
218  * @param context3 描画先のコンテキストを指定します。
219  * @param context2 影用のコンテキストを指定します。
220  * @since 0.1
221  */
222 function drawObject(x, y, s, img, context3, context2) {
223 	var r = img.width / 2;
224 	context2.beginPath();
225 	context2.arc(x + r + s, y + r + s, r, 0, 2 * Math.PI);
226 	context2.fillStyle = "black";
227 	context2.globalAlpha = 0.5;
228 	context2.fill();
229 	context3.globalAlpha = 1.0;
230 	context3.drawImage(img, x, y);
231 }
232