![]() |
今回はパズルのピース用のクラスを作っていくね。 |
![]() |
パズルのピース用のクラスって DraggableLayer クラスじゃないの? |
※DraggableLayer クラスについては §8.2 参照。 | |
![]() |
そーなんだけど、パズルのピースとして使うためには DraggableLayer クラスをちょっと改造しなくちゃいけないんだ。 |
![]() |
えっ、そーなの? |
![]() |
DraggableLayer クラスは onMouseDown メソッドや onMouseUp メソッドをオーバーライドしてなかったでしょ? |
![]() |
うん、確かにしてなかったけど、それって必要なの? |
![]() |
onMouseDown メソッドはドラッグが始まった時に呼び出されるよね。 |
![]() |
そだね。 |
![]() |
ピースがドラッグされ始めたら、そのピースを一番手前に表示するために onMouseDown メソッドをオーバーライドするの。 |
![]() |
え? なんで一番手前に表示するの? |
![]() |
ドラッグしてるピースより手前に他のピースがあると、ドラッグしてるピースが見づらくなっちゃうからね。 こんなふうに。 |
![]() |
ホントだ。ドラッグしてるピースが他のピースの奥に隠れて見えなくなっちゃってるね。 |
![]() |
ドラッグしてるピースを一番手前に表示すれば、 こんな感じでいつもドラッグしてるピース全体が見えるから操作しやすいでしょ? |
![]() |
確かにこれなら見やすいね。 |
![]() |
onMouseDown メソッドをオーバーライドすれば、 ドラッグが始まった時にピースを一番手前に表示させられるってワケ。 |
![]() |
なるほどねぇ。 えっと、じゃあ onMouseUp メソッドをオーバーライドするのは何でなの? |
![]() |
onMouseUp メソッドが呼び出されるのはどんな時だった? |
![]() |
マウスのボタンを離した時だよね? |
![]() |
そ。つまり、ドラッグが終わった時に呼び出されるわけね。 で、ドラッグが終わったら onMouseUp メソッドの中で、 そのピースが正しい位置に置かれてるかどうかチェックするの。 |
![]() |
それってどーいうこと? |
![]() |
例えば、下の図の(A)の方はピースが正しい位置に置かれてるけど、 (B)の方はピースの位置が正しくないよね。 |
<ピースが正しい位置に置かれている場合(A)と正しい位置に置かれていない場合(B)>
![]() |
そだね。このピースは左下に置かなきゃいけないから、(A)は合ってるけど(B)は間違ってるね。 |
![]() |
ドラッグが終わった時にピースの位置をチェックして、もし全部のピースが正しい位置に置かれてたら、 パズルが完成したってことがわかるでしょ。 |
![]() |
そっか。じゃあパズルが完成したかどうかチェックするために onMouseUp メソッドを使うんだね。 |
![]() |
ん、そういうこと。 それじゃ DraggableLayer クラスを継承して、 パズルのピース用のレイヤ PieceLayer クラスを作ってくね。 まず、コンストラクタとデストラクタ、あとメンバ変数はこんな感じ。 |
<PieceLayer クラスのコンストラクタ・デストラクタ・メンバ変数>
![]() |
わりとシンプルな感じだね。 |
![]() |
まぁそんなに追加する機能は多くないからね。 じゃまずはコンストラクタから。 |
![]() |
なんか引数が4つも増えてるね。 |
※DraggableLayer クラスのコンストラクタ・デストラクタについては §8.2 参照。 | |
![]() |
onMouseDown メソッドが呼び出された時と onMouseUp メソッドが呼び出された時にそれぞれ呼び出すメソッドへの参照と、 あとこのピースの正しい位置の座標もコンストラクタの引数に指定するようにしたから、引数が4つ増えて全部で6つになったの。 |
![]() |
えっと、第1引数の win と第2引数の par は DraggableLayer クラスのコンストラクタに指定するのとおんなじなんだよね? |
![]() |
ん、win がこのレイヤが所属するウィンドウで、 par が親レイヤだよ。 |
![]() |
第3引数の x と第4引数の y っていうのが、 このピースの正しい位置の座標なの? |
![]() |
そうだよ。 それぞれ goalLeft と goalTop っていうメンバ変数に値を保存しといて、ドラッグが終わった時に、 ピースが正しい位置に置かれてるかどうかチェックする時に参照するんだ。 |
![]() |
なるほどね。 あと、第5引数の mousedownfunc が onMouseDown メソッドが呼び出された時に呼び出すメソッドで、 第6引数の mouseupfunc が onMouseUp メソッドが呼び出された時に呼び出すメソッドだよね? |
![]() |
そ。それぞれ funcOnMouseDown と funcOnMouseUp
っていうメンバ変数に参照を保存しといて、ドラッグが始まった時と終わった時に呼び出すわけね。 次はデストラクタだけど、これは大丈夫だよね? |
![]() |
うん、スーパークラスのデストラクタを呼び出してるだけだよね。 |
![]() |
onMouseDown メソッドと
onMouseUp メソッドは、
それぞれコンストラクタで保存した funcOnMouseDown と
funcOnMouseUp を呼び出せばいいだけだから、ちょっと作ってみて。 あ、呼び出し先で使うから、引数には this を指定しといてね。 |
![]() |
わかった。 じゃあ最初は onMouseDown メソッドから作ってみるね。 |
![]() |
これでいいかな? |
![]() |
ん、OK。 |
![]() |
それじゃ次は onMouseUp メソッドを作るね。 |
![]() |
こんな感じだね。 |
![]() |
ん、こっちも OK。 それじゃ実際に PieceLayer クラスのオブジェクトを作ってみよっか。 |
![]() |
うん。 |
![]() |
first.ks はこんな感じにしとくね。 |
<PieceLayer クラスのテスト用 first.ks>
[call storage="DraggableLayer.ks"]
[call storage="PieceLayer.ks"]
[iscript]
// ピースの幅と高さを pieceWidth×pieceHeight に設定します
var pieceWidth = 64; // ピースの幅
var pieceHeight = 64; // ピースの高さ
// 正しい位置は表画面の背景レイヤの中央に設定します
var goalLeft = (kag.fore.base.width - pieceWidth) \ 2;// 正しい位置 x 座標
var goalTop = (kag.fore.base.height - pieceWidth) \ 2; // 正しい位置 y 座標
with(kag.fore.base)
{
// 表画面の背景レイヤを白色で塗りつぶします
.fillRect(0, 0, .width, .height, 0xFFFFFF);
// 正しい位置を黒い枠で囲みます
.fillRect(goalLeft, goalTop, pieceWidth, 1, 0x000000);
.fillRect(goalLeft, goalTop, 1, pieceHeight, 0x000000);
.fillRect(goalLeft + pieceWidth - 1, goalTop, 1, pieceHeight, 0x000000);
.fillRect(goalLeft, goalTop + pieceHeight - 1, pieceWidth, 1, 0x000000);
}
// 表画面の背景レイヤ上にピース用レイヤを作って kag オブジェクトに管理してもらいます
kag.add(global.pieceLayer = new PieceLayer(kag, kag.fore.base, goalLeft, goalTop, onDragStarted, onDragFinished));
// ドラッグが開始された時に実行されるメソッド
function onDragStarted(piece)
{
// レイヤを赤色で塗りつぶします
piece.fillRect(0, 0, piece.width, piece.height, 0xFFFF0000);
}
// ドラッグが終了した時に実行されるメソッド
function onDragFinished(piece)
{
with(piece)
{
// レイヤを青色で塗りつぶします
.fillRect(0, 0, .width, .height, 0xFF0000FF);
// ピースの x 座標が goalLeft±2 ピクセルの範囲にあって…
if(.left >= .goalLeft - 2 && .left <= .goalLeft + 2)
{
// さらに、ピースの y 座標が goalTop±2 ピクセルの範囲にあれば、
// ピースが正しい位置に置かれたとみなします
if(.top >= .goalTop - 2 && .top <= .goalTop + 2)
{
// ピースを正しい位置に置いて、
.setPos(.goalLeft, .goalTop);
// それ以上動かせなくします
.enabled = false;
// ピースが正しい位置に置かれたことを知らせるためにメッセージを表示します
System.inform("OK");
}
}
}
}
with(pieceLayer)
{
// ピース用レイヤの画像サイズを pieceWidth×pieceHeight ピクセルに設定します
.setImageSize(pieceWidth, pieceHeight);
// レイヤの表示サイズを画像サイズに合わせます
.setSizeToImageSize();
// レイヤを青色で塗りつぶします
.fillRect(0, 0, .width, .height, 0xFF0000FF);
// 適当な位置に置きます
.setPos(int (Math.random() * (kag.fore.base.width - .width)), int (Math.random() * (kag.fore.base.height - .height)));
// 表示状態にします
.visible = true;
}
[endscript]
![]() |
うわっ、なんかすごい長いしフクザツ… |
![]() |
う〜ん、一応基本的なことだけやろうと思ったんだけど、確かにちょっと長くなっちゃったね。 |
![]() |
かなり長いと思うんだけど… |
![]() |
まぁ、とりあえず実行してみよ。 必要なファイルはここに置いとくから。 |
![]() |
う、うん。じゃあ実行してみるね。 |
![]() |
なんか白い四角と青い四角が表示されてるけど…? |
![]() |
青い四角がピースで、白い四角が正しい位置を表してるの。 |
![]() |
えっと、じゃあピースをドラッグして、白い四角の中に入れればいいってこと? |
![]() |
そういうこと。 |
![]() |
それじゃピースをドラッグしてみるね。 |
![]() |
ん。 |
![]() |
あっ、ピースをクリックしたらピースが赤くなった! |
![]() |
ピースの上でマウスのボタンを押したらピースの色を変えるようにしてるからね。 |
![]() |
あ、そーなんだ。 |
![]() |
ちなみにボタンを離すと元の色に戻るよ。 |
![]() |
ホントだ。青色に戻ったね。 |
![]() |
んじゃ次はピースを白い四角の中までドラッグしてみて。 ちょっとくらいずれてても大丈夫だから。 |
![]() |
そうなの? |
![]() |
ん、四角の中にぴったり合わせるのは難しいから、少しずれた位置にピースを置いても、 正しい位置に置けたってみなしてるんだ。 |
![]() |
へぇ、そうなんだ。 それじゃあドラッグしてみるね。 |
![]() |
あ、「OK」って表示された! |
![]() |
これでこのピースは正しい位置に固定されたから、それ以上は動かせなくなってるはずだよ。 |
![]() |
確かにドラッグしてももう動かせないね。 |
![]() |
パズルのピースの基本的な動作は大体こんな感じだよ。 じゃ、今回はこの辺にしといて、スクリプトの方は次回見ていくことにするね。 |
![]() |
あ、スクリプトは次回にするんだ。 |
![]() |
ん、見ての通り色々説明することがあるからね。 今から見ていくとかなり長くなっちゃいそうだから。 |
![]() |
う〜ん、確かにややこしそうだもんねぇ。 |
![]() |
ってワケで、今回はここまで。 それじゃ、また次回ね! |