Goban 0.2
マウスをクリックすると碁石を自由に置けるようにしました。一度置くと取り除くことはできません。配置はまだきれいに揃えていません。
実行結果
ソース
"expand source" を押すと展開されます。元に戻すには、このページを再ロードしてください。
goban02.html
省略します。
goban02.js
定義とメインです。ロードの際に実行されます。イメージは前もってロードするように変更しました。
/**
* Goban - 碁盤イメージの描画
* @version 0.2
* @author たかはしのんき
*
*/
// キャッシュにイメージを読み込んでおく
var imgbb = new Image(134, 134); // 黒の碁笥 (black bowl)
imgbb.src = "img/blackbowl134.png";
var imgwb = new Image(134, 134); // 白の碁笥 (white bowl)
imgwb.src = "img/whitebowl134.png";
var imgl = new Image(110, 110); // 碁笥の蓋 (lid)
imgl.src = "img/lid110.png";
var imgb = new Image(22, 22); // 黒石 (white stone)
imgb.src = "img/black22.png";
var imgw = new Image(22, 22); // 白石 (black stone)
imgw.src = "img/white22.png";
// キャッシュに効果音を読み込んでおく
var ext = audioExt();
var auClick = new Audio("se/button6." + ext);
var auSwitch = new Audio("se/se_sad05." + ext);
var auError = new Audio("se/se_sad08." + ext);
// 共通に使う定数と変数
var BLACK = 1;
var WHITE = 2;
var turn;
var context;
/**
* ロード時に碁盤イメージを描画します。
*/
window.onload = function() {
// キャンバスとコンテキスト取得
var canvas = document.querySelector('#table');
context = canvas.getContext('2d');
// 座標 (270, 50) にタイトルを表示
context.fillStyle = "white";
context.font = "bold 24px Arial";
context.fillText("Goban 0.2", 270, 50);
// 座標 (50, 110) に白の碁笥のイメージを表示
drawObject(50, 110, 20, imgwb, context);
// 座標 (120, 300) に白の碁笥の蓋のイメージを表示
drawObject(120, 300, 8, imgl, context);
// 座標 (400, 300) に黒の碁笥のイメージを表示
drawObject(400, 300, 20, imgbb, context);
// 座標 (410, 110) に黒の碁笥の蓋のイメージを表示
drawObject(410, 110, 8, imgl, context);
// 座標 (435, 135) に黒石のイメージを表示
drawObject(435, 135, 2, imgb, context);
// 座標 (450, 150) に白石のイメージを表示
drawObject(450, 150, 2, imgw, context);
// 座標 (210, 110) に6路盤の碁盤を表示
drawBoard(210, 110, 6, 9, context);
// 黒番から
turn = BLACK;
// クリックイベント登録
canvas.addEventListener("click", onClick, false);
};
マウスイベントハンドラーを追加しました。
/**
* マウスイベントハンドラー
* とりあえず碁石を置きます。
* @since 0.2
*/
function onClick() {
var mx = event.offsetX;
var my = event.offsetY;
if (turn == BLACK)
drawObject(mx - 11, my - 11, 2, imgb, context);
else
drawObject(mx - 11, my - 11, 2, imgw, context);
auClick.play();
turn = 3 - turn;
}
効果音のために有効な拡張子を調べる処理を追加しました。
/**
* ブラウザで有効なAudioの拡張子を獲得
* @since 0.2
*/
function audioExt() {
var ext = "";
var audio = new Audio();
if (audio.canPlayType("audio/ogg") == 'maybe')
ext="ogg";
else if (audio.canPlayType("audio/mp3") == 'maybe')
ext="mp3";
else if (audio.canPlayType("audio/wav") == 'maybe')
ext="wav";
return ext;
}
円形オブジェクトを描画します。変更はありません。
/**
* 円形オブジェクトを描画します。
* @param x 左端座標
* @param y 上端座標
* @param s 影の長さ(高さ/2)
* @param img オブジェクトのイメージ
* @param context 描画先のコンテキストを指定します。
* @since 0.1
*/
function drawObject(x, y, s, img, context) {
var r = img.width / 2;
context.beginPath();
context.arc(x + r + s, y + r + s, r, 0, 2 * Math.PI);
context.fillStyle = "black";
context.globalAlpha = 0.5;
context.fill();
context.globalAlpha = 1.0;
context.drawImage(img, x, y);
}
碁盤を描画します。星の描画はまだ入れていません。格子がぼやけないよう、stroke() から fill() に変更しました。
/**
* 碁盤を描画します。
* @param x 左端座標
* @param y 上端座標
* @param ro 路数
* @param s 影の長さ(高さ/2)
* @param context 描画先のコンテキストを指定します。
* @since 0.1
*/
function drawBoard(x, y, ro, s, context) {
var dx = 22;
var dy = 24;
var width = dx * (ro + 1);
var height = dy * (ro + 1);
var gwidth = dx * (ro - 1) + 2;
var gheight = dy * (ro - 1) + 2;
var gx = x + Math.floor((width - gwidth) / 2);
var gy = y + Math.floor((height - gheight) / 2);
// 碁盤の影
context.beginPath();
context.moveTo(x, y);
context.lineTo(x + width, y);
context.lineTo(x + width + s, y + s);
context.lineTo(x + width + s, y + height + s);
context.lineTo(x + s, y + height + s);
context.lineTo(x, y + height);
context.closePath();
context.fillStyle = "black";
context.globalAlpha = 0.5;
context.fill();
// 碁盤
context.beginPath();
context.rect(x, y, width, height);
context.fillStyle = "burlywood";
context.globalAlpha = 1.0;
context.fill();
// 木目
drawWoodGrain(x, y, width, height, context);
// 格子
context.fillStyle = "black";
var x1, y1, lwidth;
// (横の格子線)
x1 = gx;
for (var row = 1; row <= ro; row++) {
if (row == 1)
y1 = gy + (row - 1) * dy;
else
y1 = gy + 1 + (row - 1) * dy;
if (row == 1 || row == ro)
lwidth = 2;
else
lwidth = 1;
context.beginPath();
context.rect(x1, y1, gwidth, lwidth);
context.fill();
}
// 縦の格子線
y1 = gy;
for (var col = 1; col <= ro; col++) {
if (col == 1)
x1 = gx + (col - 1) * dx;
else
x1 = gx + 1 + (col - 1) * dx;
if (col == 1 || col == ro)
lwidth = 2;
else
lwidth = 1;
context.beginPath();
context.rect(x1, y1, lwidth, gheight);
context.fill();
}
}
木目を描画します。クリッピングの範囲を縦横に1ドットずつ広げました。
/**
* 木目を描画します。
* @param x 左端座標
* @param y 上端座標
* @param width 描画する幅
* @param height 描画する高さ
* @param context 描画先のコンテキストを指定します。
* @since 0.1
*/
function drawWoodGrain(x, y, width, height, context) {
context.strokeStyle = "rgb(192, 153, 86)"; // 木目の色
var xb0 = x;
var xb1 = x + width;
var yb0 = y;
var yb1 = y + height;
var xo, yo, xw, yw;
var xc = xb0 + (xb1 - xb0) * 5 / 7; // 木目の中心
var yc = yb0 + (yb1 - yb0) * 5 / 4;
for (var rw = 5; rw <= 460; rw += 5) {
xo = xc + rw;
yo = yc;
for (var theta = 0; theta <= 2 * Math.PI;
theta += 2 * Math.PI / 19) {
xw = xc + Math.floor(rw * Math.cos(theta));
yw = yc + 13 * Math.floor(rw * Math.sin(theta));
var xw0 = xo, xw1 = xw, yw0 = yo, yw1 = yw;
if (yw1<yb0 && yb0<yw0) { //上辺でクリッピング
xw1 = xw0+(xw1-xw0)*(yb0-yw0)/(yw1-yw0);
yw1 = yb0;
} else if (yw0<yb0 && yb0<yw1) { //上辺でクリッピング
xw0 = xw1+(xw0-xw1)*(yb0-yw1)/(yw0-yw1);
yw0 = yb0;
}
if (yw1<yb1 && yb1<yw0) { //下辺でクリッピング
xw0 = xw1+(xw0-xw1)*(yb1-yw1)/(yw0-yw1);
yw0 = yb1;
} else if (yw0<yb1 && yb1<yw1) { //下辺でクリッピング
xw1 = xw0+(xw1-xw0)*(yb1-yw0)/(yw1-yw0);
yw1 = yb1;
}
if (xw1<xb0 && xb0<xw0) { //左辺でクリッピング
xw1 = xb0;
yw1 = yw0+(yw1-yw0)*(xb0-xw0)/(xw1-xw0);
} else if (xw0<xb0 && xb0<xw1) { //左辺でクリッピング
xw0 = xb0;
yw0 = yw1+(yw0-yw1)*(xb0-xw1)/(xw0-xw1);
}
if (xw1<xb1 && xb1<xw0) { //右辺でクリッピング
xw0 = xb1;
yw0 = yw1+(yw0-yw1)*(xb1-xw1)/(xw0-xw1);
} else if (xw0<xb1 && xb1<xw1) { //右辺でクリッピング
xw1 = xb1;
yw1 = yw0+(yw1-yw0)*(xb1-xw0)/(xw1-xw0);
}
if (xb0<=xw0 && xw0<=xb1 && xb0<=xw1 && xw1<=xb1 &&
yb0<=yw0 && yw0<=yb1 && yb0<=yw1 && yw1<=yb1) {
context.beginPath();
context.moveTo(xw0, yw0);
context.lineTo(xw1, yw1);
context.stroke();
}
xo = xw;
yo = yw;
}
}
}