enchant.jsでパズルゲーム その2

ayumegu(プログラマー)
よろしくお願いします。

こんにちはayumeguです。
前回は画像を並べるところまでやりましたので今回はドラッグ周りを^^

#とりあえずドラッグ ドラッグサンプル

enchant();
//--------------------画像情報-----------------------------
var STAMP_IMG = "buttons.png"; // 肉球画像
var TILE_IMG = "tile.png"; // タイル画像
//--------------------定数-----------------------------
var STAGE_WIDTH = 480; // 画面横サイズ
var STAGE_HEIGHT = 600; // 画面縦サイズ
var STAMP_SIZE = 80; // スタンプ画像サイズ
var STAMP_KIND = 6; // スタンプの種類の数
var STAMP_COL = 6; // 横に配置する数
var STAMP_ROW = 5; // 縦に配置する数
//--------------------ドラッグ情報----------------------------------
var dragOkFlg; //ドラッグしてOKかどうか
var dragStartFlg; //ドラッグ開始フラグ
var dragStartPosX; //ドラッグ開始したX
var dragStartPosY; //ドラッグ開始したY
var dragStamp; //ドラッグ中のスタンプ
var changeFlg; //ドラッグでスタンプが入れ替わったかどうか
//--------------------ステージ情報-----------------------------
var stampList; //画面のスタンプのリスト
window.onload = function(){
game = new Game(STAGE_WIDTH, STAGE_HEIGHT);
game.fps = 24;
game.preload(STAMP_IMG, TILE_IMG);
game.rootScene.backgroundColor = "black";
game.onload = function(){
scene = new GameStartScene();
game.pushScene(scene);
}
game.start();
};
//ゲーム画面
GameStartScene = enchant.Class.create(enchant.Scene, {
initialize: function () {
Scene.call(this);
// 変数初期化
dragOkFlg = false;
dragStartFlg = false;
changeFlg = false;
//背景の生成
var tile = new Sprite(STAGE_WIDTH, 400);
tile.image = game.assets[TILE_IMG];
tile.y = STAGE_HEIGHT - 400;
this.addChild(tile);
//配列作成
stampList = new Array();
for(var y = 0; y < STAMP_ROW; y++){
for(var x = 0; x < STAMP_COL; x++){
createStamp(this,x,y);
}
}
dragOkFlg = true;
}
});
//スタンプ作成
function createStamp(stage,x,y){
var stamp = new Sprite(STAMP_SIZE,STAMP_SIZE); // スタンプサイズ指定
stamp.image = game.assets[STAMP_IMG]; // スタンプ画像設定
var no = rand(0,STAMP_KIND - 1);
stamp.no = no; // 属性番号
stamp.frame = no // 画像番号
stamp.x = STAMP_SIZE * x;
stamp.y = STAMP_SIZE * y + STAGE_HEIGHT - 400;
stage.addChild(stamp);
stampList[x + y * STAMP_COL] = stamp;
stamp.addEventListener(Event.TOUCH_START, function(e) {
//ドラッグしてもOKな状態だったらドラッグ開始
if(dragOkFlg){
dragStamp = e.target;
dragStartFlg = true;
changeFlg = false;
dragStartPosX = Math.floor(e.target.x / STAMP_SIZE);
dragStartPosY = Math.floor((e.target.y - 200) / STAMP_SIZE);
e.target.opacity = 0.2;
}
});
stamp.addEventListener(Event.TOUCH_END, function(e) {
if(dragOkFlg){
dragStartFlg = false;
dragOkFlg = true;
dragStamp.opacity = 1;
if(changeFlg){
// TODO パネルが入れ替わっているので判定
console.log("パネルチェック");
}else{
dragOkFlg = true;
}
}
});
stamp.addEventListener(Event.TOUCH_MOVE,function(e){
if(dragOkFlg){
var dx = e.x;
var dy = e.y;
var nowX = Math.floor(dx / STAMP_SIZE);
var nowY = Math.floor((dy - 200)/ STAMP_SIZE);
//入れ替わってたら入れ替える
if(dragStartPosX !== nowX || dragStartPosY !== nowY){
changeFlg = true;
var moveStamp = stampList[nowX + nowY * STAMP_COL];
moveStamp.x = dragStartPosX * STAMP_SIZE;
moveStamp.y = dragStartPosY * STAMP_SIZE + 200;
dragStamp.x = nowX * STAMP_SIZE;
dragStamp.y = nowY * STAMP_SIZE + 200;
stampList[nowX + nowY * STAMP_COL] = stampList[dragStartPosX + dragStartPosY * STAMP_COL];
stampList[dragStartPosX + dragStartPosY * STAMP_COL] = moveStamp;
dragStartPosX = nowX;
dragStartPosY = nowY;
}
}
});
}
// ランダム関数
function rand(min,max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}

##説明 Event.TOUCH_START,Event.TOUCH_MOVE,Event.TOUCH_ENDイベントを記載しました。
それほど難しいことはしていませんが説明が必要そうなところだけかいつまんで
####TOUCH_STARTイベント

dragStartPosX = Math.floor(e.target.x / STAMP_SIZE);
dragStartPosY = Math.floor((e.target.y - 200) / STAMP_SIZE);

これでクリックスタート位置のタイルのマス目を計算しています。
-200は上部の隙間分です
ドラッグ中は半透明になるようにしています

####TOUCH_MOVEイベント nowX, nowYに現在のドラッグ位置のタイルのマス目を計算していれています
もし、ドラッグ開始位置と値が違えば、ドラッグしたものとしchangeFlg=trueにしています
TOUCH_END時にこのフラグがtrueの場合、パネルのコンボ判定をします
入れ替わっている場合は画像を移動させ、配列の中身も修正しています

####TOUCH_ENDイベント フラグの初期化とchangeFlgがtrueの場合に、ログを表示しています。
次回ここにパネルのコンボ判定を記載します。

##ドラッグ中のスタンプが追尾するようにする このままではドラッグしたときにちょっとみずらいのでちょっと変更してみます。
ドラッグ位置にスタンプがついてくるようにします
ドラッグサンプル修正

ソースを修正したところだけかいつまんで説明を。
実際のソースはサンプルのhtmlのソースをみてください

var cloneStamp; //ドラッグ中のスタンプのコピー

cloneStampという変数を追加しました
ドラッグの際についてくる肉球画像です

cloneStamp = new Sprite(STAMP_SIZE,STAMP_SIZE);
cloneStamp.image = game.assets[STAMP_IMG];
cloneStamp.visible = false;
this.addChild(cloneStamp)

画像設定です。ドラックしていないときは表示しないのでvisible=falseにしています

//クローンのほうを動かす
cloneStamp.frame = e.target.frame;
cloneStamp.x = e.target.x;
cloneStamp.y = e.target.y;
cloneStamp.visible = true;

こちらTOUCH_START内です。
クリックした位置の画像のフレームになるようにしています。

cloneStamp.x = dx - STAMP_SIZE / 2;
cloneStamp.y = dy - STAMP_SIZE / 2;

こちらTOUCH_MOVE内です
ドラッグの位置に画像を移動させるので画像サイズの半分を引いて、ドラッグ位置が画像の中心になるようにしています

cloneStamp.visible = false;

こちらTOUCH_END内です。
画像を非表示にしただけです

##今回の感想 ソースが長くなったらhtmlであげればいいやというところに気がついた!
次回はパズルの判定部分をやっていこうかと思います。
次はきっとソースがいっきに汚くなってしまいそうな予感
そういえばenchant.jsのzIndexって指定できるようなの用意されたのかな〜