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

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

こんにちはあゆめぐです^^

では早速前回の続き、今回はドラッグ終了時の判定処理を書いてみます!
前回までの記事

説明が苦手なのでわかりにくいかもですが、実装していきましょ〜。

第1段階 コンボ判定その1

ここでやること

ドラック終了時の同じ色の肉球がくっついているかの判定は左上の肉球からチェックを行います。
左上から右と下を1つずつチェックしていくことでもれなくチェックできます。
上と左は既にチェック済みになるはずなのでチェックの必要がありません

基準の右が同じ色であればさらに右をチェックするという感じでやっていきます。で3つ以上同じ色であればとりあえず色を薄くしてみます。
これだといろいろ不具合があるんですけど・・・長くなるのでとりあえずここまでを一度実装します
console.logでドラッグ終了時のコンボ数を表示しています。

console.log console.dirなどは下記の方法などでみれます。
javascriptのデバッグでよくお世話になります。

  • chrome->(右クリック)要素を調査->console
  • firefox->(右クリック)要素を調査->コンソール

コンボ数がおかしいのがわかるかと思います
第1段階

ソース説明

実際のソースはhtmlをみればわかるかと思うので説明が必要そうなところだけ

checkStampメソッド

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
       //右のチェック
      while(flg){
          //画面範囲内の場合チェック
          if(x + count < STAMP_COL){
              var nowCheckTargetStamp = getStamp(x + count,y);                 //比較対象スタンプ
              //一致の場合さらに右もチェック
              if(nowCheckBaseStamp.no === nowCheckTargetStamp.no){
                  count++;
              }else{
                  flg = false;
                  //二個以上つながっていたらコンボに追加
                  if(count >2){
                      addCombo(x,y,count,true);
                  }
                  count = 1;
              }
          }else{
              flg = false;
              if(count >2){
                  addCombo(x,y,count,true);
              }
              count = 1;
          }
      }

右の肉球のコンボ判定部分です。 whileで横がつながらなくなるまでwhileでまわしています。 whileループ終了条件は

  • 右の肉球がなくなった場合 x + count < STAMP_COL
  • 右の肉球が基準の肉球と色が違う場合

3つ以上つながっていた場合addComboメソッドを呼んでいます

1
nowStamp.comboNo = targetComboCount;

addComboメソッド内でコンボした肉球にcomboNoをつけています。 消すときにこのcomboNoが早い順に消します。

第2段階 コンボ判定その2

ここでやること

第1段階のサンプルをみてみるとわかると思いますが、二点困った点があります。

  • 十字型、H型などは別のコンボになっている
  • 4つ以上つながった場合、複数のコンボでカウントされている

なので、コンボと判定されたときに、その肉球の中に既にコンボになっているものがあればそのコンボに追加するように修正します。
ついでにコンボ表示の演出も加えてみました

これで一回目のコンボ判定は終了です
好き勝手やっているので汚いですがすみません;w;
第2段階

ソース説明

コンボ追加メソッドaddCombo内で、コンボになった肉球が既に他のコンボが確定している場合、そのコンボに追加する処理をしています。

1
2
3
4
5
6
7
8
9
10
   if(nowStamp.comboNo !== 0){
      sameComboNoList.push(nowStamp.comboNo);
      targetComboCount = nowStamp.comboNo;
      //たてのコンボでかつたてのコンボのチェックだったらチェック要らない
      if(nowStamp.comboRowFlg && !colFlg){
          checkFlg = false;
      }else if(nowStamp.comboColFlg && colFlg){
          checkFlg = false;
      }
  }

コンボが連結した場合、sameComboNoListに入れてあとですべてコンボをまとめる処理をしています。
その下の方の分岐は例えば横に4つ並んだとき、一番左と、一つ右でコンボ判定がはしるのですが、一つ右のコンボ判定のときには既に一番左のコンボ判定で判定ずみなのでcheckFlgをfalseにしてチェックを飛ばしています

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//配列のなかのコンボばんめが同時にきえるので同じコンボにまとめる
function changeSameComboStamp(){
  var sameComboNo = sameComboNoList[0];      //0番目のコンボ数にすべてあわせる
  for(var i = 1; i < sameComboNoList.length; i++){
      for(var y = 0; y < STAMP_ROW; y++){
          for(var x = 0; x < STAMP_COL; x++){
              var stamp = getStamp(x,y);
              if(stamp.comboNo == sameComboNoList[i]){

                  stamp.comboNo = sameComboNoList[0];
              }
          }
      }
  }
}

もはやコメントがおかしくなってきている気もしますが、ここがコンボが複数つながった場合にコンボを一つにまとめる処理をしているメソッドです。
つながったコンボの肉球のcomboNoを同じにすることで一緒のコンボにまとめています

第3段階 ブロックを落として再度コンボ判定

ここでやること

コンボ判定が終わったらブロックを落として再度コンボ判定をするようにします
だいぶやっつけなソースになってきている気がします
zIndexまわりの指定がちょっとよくわからなかったので、コンボ表示が手前に来なかったりしますが、こまかいことは置いておこうw

第3段階

ソース説明

1
2
3
4
5
6
7
8
9
10
11
12
13
//コンボ表示終了
function showComboEnd(){
  dropStamp();                     //新しいの落とす
  
  totalCombo += comboCount - 1;

  scene.tl.delay(20).then(function(){
      comboCount = 1;

      checkStamp();                        //再起呼び出ししてもらう
  });
  
}

コンボ表示が終わった後にdropStampメソッドを呼び、その中で新しい肉球を落とす処理をしています
ブロックを落とした後は一定時間後に再度コンボ判定を行っています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//消えた分を補充する 下からずらしてく
function dropStamp(){
  for(var x = 0; x < STAMP_COL; x++){
      var maxCount = 0; //画面外の何個目か
      for(var y = STAMP_ROW - 1; y >= 0; y--){
          var stamp = getStamp(x,y);
          //空だったらずらす
          if(stamp == null){
              var flg = true;       //whileようフラグ
              var count = 1;        //何こ上までからか
              while(flg){
                  //上が画面内か判定
                  if( y - count >= 0){
                      //上もからっぽ
                      if(getStamp(x,y-count) == null){
                          count++;
                      }else{
                          //ずらす
                          flg = false;
                          stampList[x + y * STAMP_COL] = getStamp(x,y-count);
                          stampList[x + (y - count) * STAMP_COL] = null;
                          getStamp(x,y).tl.moveBy(0,count * STAMP_SIZE,10);
                      }
                  //画面外なので新しく作る
                  }else{
                      flg = false;
                      //画面外なので新しくつくる
                      maxCount++;
                      var stamp = createStamp(scene,x,y);
                      stamp.y = STAMP_SIZE * (y - count - maxCount + 1) + 200;
                      stamp.tl.moveBy(0,(count + maxCount - 1) * STAMP_SIZE,10);
                  }
              }
          }
      }
  }
}

はい、こちらが新しい肉球を落とすメソッドです。
下からつめていくのがポイントです。

下からループを回して、空っぽのマスだったら上の肉球を落としてきます。
こうすることにより、空のマスをすべて埋めることができます
もし上も空だったらさらに上を見に行きます。
上が画面外の場合は新しい肉球を画面外に追加していきます。

画面外に追加する場合はきれいに並ぶように画面外のいくつめかをmaxCountでカウントしています
修正の余地がまだまだありそうですが、基本的な部分はとりあえず完成です

今回の感想

だいぶ説明が急ぎ足になってしまいましたがパズルゲームの記事はここで一度終了!
macでfnキーを発見しました!こんなところに!というところにおりました。
windowsだと見向きもしない位置です・・・
これで日本語だって英語だって簡単に変換できます
今までwindowsのF10とかの位置のボタンをmacで押しても音量がかわるだけであきらめていました
半角カナがうてなくて苦労もしましたがもう悩まない!カナ〜〜〜

次はヘックス型のパズルゲームでもつくろうとおもっていたのですが、
cocos2d-xが3.0きたのでそちらをがんばって勉強してきます!
unityも最近さわっていないから触りたいな〜なんて思う今日このごろです

以上!