第6回 画像を使ったジグソーパズルを作ってみよう – jQuery入門
2009 年 5 月 7 日 投稿者: naga3jQuery入門第6回目は、画像を使った簡易ジグソーパズルゲームを作ってみます。簡易的なものなので、ピースの凹凸はありません。今回のポイントはCSSによって画像の一部分のみを指定する方法(background-position)です。まずはプレイ画面をどうぞ。
簡易ジグソーパズル
2つのピースをクリックすると入れ替わります。元の絵に戻すとクリアです。簡易ジグソーパズルのソース
使用するリソース(右クリックで保存してください)HTML
使用する画像
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("jquery", "1.3.2");</script>
<style type="text/css">
div.piece {
width: 80px;
height: 80px;
background-image: url('pict.jpg');
position: absolute;
}
</style>
<script type="text/javascript">
var sel = -1; // 現在選択されているピース番号
var pos = []; // 各ピースの現在位置
$(function() {
// シャッフルする。
for (var i = 0; i < 16; i++) pos[i] = i;
for (var i = 16; i > 0; i--) {
var j = Math.floor(Math.random() * i);
swap(i - 1, j);
}
// ピースを配置する。
for (var i = 0; i < 16; i++) {
$('body').append('<div id="piece' + i + '" class="piece"></div>');
$('#piece' + i).css({
backgroundPosition: '-' + getx(i) + 'px -' + gety(i) + 'px',
left: getx(pos[i]), top: gety(pos[i])
})
}
// ピースをクリックしたとき
$('div.piece').click(function() {
var no = this.id.substring(5);
if (sel == no) {
// 自分自身が選択されているときは選択をキャンセルする。
$(this).fadeTo(100, 1);
sel = -1;
} else if (sel == -1) {
// 何も選択されていないときは選択する。
$(this).fadeTo(100, 0.5);
sel = no;
} else {
// 他のピースが選択されているときは入れ替える。
swap(no, sel);
$('#piece' + sel).fadeTo(100, 1).animate({left: getx(pos[sel]), top: gety(pos[sel])});
$(this).animate({left: getx(pos[no]), top: gety(pos[no])}, function() {
// アニメーション終了時にクリア判定する。
var clear = true;
for (var i = 0; i < 16; i++) if (pos[i] != i) clear = false;
if (clear) alert("クリア!");
});
sel = -1;
}
});
});
// ピースの番号から座標を得る。
function getx(n) {return (n % 4) * 80;}
function gety(n) {return Math.floor(n / 4) * 80;}
// ピースの配列を入れ替える。
function swap(i, j) {
var tmp = pos[i];
pos[i] = pos[j];
pos[j] = tmp;
}
</script>
</head>
<body>
</body>
</html>
プログラムの解説
ピースのスタイルシート
div.piece {
width: 80px;
height: 80px;
background-image: url('pict.jpg');
position: absolute;
}
各ピースに割り当てられているCSSです。pict.jpgは320×320ピクセルの画像なのですが、widthとheightプロパティによって幅と高さを80ピクセルに固定し、縦横とも4分割で表示するための準備をしています。さらにpositionをabsoluteに設定することによって画面上の自由な位置にピースを表示できるようにします。グローバル変数
var sel = -1; // 現在選択されているピース番号
var pos = []; // 各ピースの現在位置
ピースには0~15の番号が付いています。画像に対するピース番号は以下の通り。| 0 | 1 | 2 | 3 |
| 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 |
ピースのシャッフル
for (var i = 0; i < 16; i++) pos[i] = i;
まず初期値として、完成形で配列posを作ります(添え字が中の値と等しい)。
for (var i = 16; i > 0; i--) {
var j = Math.floor(Math.random() * i);
swap(i - 1, j);
}
その後、配列posの中身がバラバラになるようにシャッフルしています。「Fisher-Yates」というアルゴリズムを使っていますので、詳しくはググってみてください。画面上にピースを配置する
for (var i = 0; i < 16; i++) {
$('body').append('<div id="piece' + i + '" class="piece"></div>');
$('#piece' + i).css({
backgroundPosition: '-' + getx(i) + 'px -' + gety(i) + 'px',
left: getx(pos[i]), top: gety(pos[i])
})
}
今回のポイントである、画像の一部をCSSで指定して画面上に配置している部分です。「piece + ピース番号」というidを付けたdiv要素をbodyに追加し、そのdiv要素にCSSを設定しています。background-positionは背景画像の表示開始位置を決めるプロパティなのですが、マイナスの値を設定すると開始位置を逆方向に設定する、つまり画像の途中から表示させることが可能になるのです。例えば「background-position: -80px -160px」とすると、画像の左端から80ピクセル、上端から160ピクセルの位置から画像を表示させることができます。jQueryで指定する場合はプロパティにハイフンが使えないので「backgroundPosition」と書くことに注意してください。
getxとgetyは、最下部に定義してありますが、ピース番号を指定するとその座標を返してくれる関数です。
「left: getx(pos[i]), top: gety(pos[i])」によって、シャッフルされた位置にピースを持ってきています。
ピースをクリックしたときの処理
var no = this.id.substring(5);
それぞれのピースのidは「piece + ピース番号」なので、変数noにはピース番号が入ります。
if (sel == no) {
// 自分自身が選択されているときは選択をキャンセルする。
$(this).fadeTo(100, 1);
sel = -1;
選択されているピースを再度選択したときは、選択解除しています。fadeToは透明度を変更するjQueryのメソッドで、透明度は0~1(0が完全に透明、1が完全に不透明)で指定します。今回は100msかけて透明度1になります。
} else if (sel == -1) {
// 何も選択されていないときは選択する。
$(this).fadeTo(100, 0.5);
sel = no;
何も選択されていないときはクリックされたピースを選択状態にしています。100msかけて透明度0.5(半分透けている状態)にしています。
swap(no, sel);
ピースを交換する場合は、まずpos配列でクリックされたピース番号と選択されているピース番号を入れ替えます。
$('#piece' + sel).fadeTo(100, 1).animate({left: getx(pos[sel]), top: gety(pos[sel])});
選択されているピースの透明度を元に戻し、クリックされたピースの位置へ移動するアニメーションを行なっています。
$(this).animate({left: getx(pos[no]), top: gety(pos[no])}, function() {
// アニメーション終了時にクリア判定する。
var clear = true;
for (var i = 0; i < 16; i++) if (pos[i] != i) clear = false;
if (clear) alert("クリア!");
});
クリックされたピースを選択されているピースの位置へ移動するアニメーションを行なっています。さらにアニメーションが終わったときのコールバック関数を指定し、そこでクリア条件のチェックをしています。クリア条件は、pos配列全ての要素の添え字が値と等しい時です。まとめ
・「position: absolute」によって絶対位置指定をし、「left」と「top」プロパティによって位置を指定する。・「background-position」プロパティにマイナスの値を指定することによって、画像の途中から表示を始めることができる。
・「background-position」プロパティをjQueryで指定するときは「backgroundPosition」と書く。