ケータイFlashゲーム制作レクチャー

第16回 パズルゲームレクチャー(2)パズルを完成させる!

この記事を読むのに必要な時間:およそ 2.5 分

16番目のピースを一枚抜く

16番目のピースを抜く処理は,シーン1の3フレーム目に置いたボタンのオブジェクトアクションとして記述する(ここでは,ピースのシャッフル処理も行なっているが,それについては後で説明する)⁠

図4 16番目のピースを抜く処理の記述位置

図4 16番目のピースを抜く処理の記述位置

リスト2 16番目のピースを抜くスクリプト

on(keyPress "5"){
 /:i_17=3;        // 空きピースがある縦インデックス
 /:j_17=3;        //      〃     横インデックス
 /:v33 = 17;      // ピースに対応する変数にフレーム番号17をセット
    ・
    ・  (ピースをシャッフルする処理)
    ・
}

ピースを抜いた所は,本来は空きとなるが,実際にはピースクリップの17フレーム目に置いた黒(空き)のイメージと置き換える。

変数i_17とj_17は,現在黒(空き)のイメージが表示フレームとなっているピース位置の縦横のインデックス(0~3)を保持する。ここに16番目のピース位置(3,3)を記録し,変数v33に17をセットする。このため,ピースp33の表示フレームは17フレーム目となり,空きフレームとなる。

ピースを移動させる

シャッフル後,シーン1の4~6フレームでループを作る。このループがゲームのメインループとなる。ピースを移動するためのキー入力は,このループ内に置いたボタンのオブジェクトアクションとして記述し,リスト3のようになる(リスト3は,2キーが押下された場合のスクリプト例であるが,4キー,6キー,8キーの押下時も同様なスクリプトとなる。それぞれの詳細は,実際のflaを参照されたい)⁠

リスト3 2キー押下時にピースをスライドさせるスクリプト

on(keyPress "2"){
 if(/:i_17<3){
  old=/:i_17++;
  tellTarget("stage/p" add /:i_17 add /:j_17){
   gotoAndStop(17);
  }
  set("/:v" add old add /:j_17,
                  eval("/:v" add /:i_17 add /:j_17));
  set("/:v" add /:i_17 add /:j_17,17);
  tellTarget("stage/p" add old add /:j_17){
   gotoAndStop(eval("/:v" add ../../:old add /:j_17));
  }
  tellTarget ("stage/p" add i_17 add j_17) {
   /guide:_x = _x+30; 
   /guide:_y = _y+30;
  }
  call("checkStage");
  if(/:checkSts == 1){
   gotoAndStop("stage_ed");
  }
 }
}

2キーが押下された時,空きピースの下にあるピースを上方にスライドさせる。これは先にも記したように空きピースも実はピースクリップの17フレーム目を表示しているピースであるため,実際には上下の表示ピースの交換という形を取る。

ここで,処理の最後にcheckStageというサブルーチンcallしているが,これはスライドの結果すべてのピースが定位置に揃ったか否か(すなわち"パズルの完成")を判定するための関数である。

すべてのピースが揃ったか確認する

すべてのピースが揃ったか否かの判定は,シーン1の9フレーム目に設定したフレームアクションによって判定する。このフレームは,checkStageというラベルが設定されており,他のフレームやオブジェクトのアクションからcall命令により呼び出すことにより,サブルーチンとして機能する。

図5 checkStageサブルーチンの記述位置

図5 checkStageサブルーチンの記述位置

リスト4 checkStageサブルーチンのスクリプト

/:checkSts=1;
k=1;
for(i=0;i<4;i++){
 for(j=0;j<4;j++){
  if(eval("/:v" add i  add j ) != k++){
   if( i != /:i_17 || j != /:j_17){
    /:checkSts=0;
    i=4;
    j=4;
   }
  }
 }
}

戻り値としての変数checkStsにあらかじめ"1(=すべて一致)"をセットしておき,2重のfor文によって変数v00~v33の値を確認する。空きピースのセル以外に初期値と異なる値が発見された場合,checkStsを"0(=不一致あり)"にリセットする。サブルーチンを抜けるまで,checkStsが1のままなら,パズルは完成されているという訳だ。

ピースをシャッフルする

14,15番目のピースの入れ替わりを防止しつつシャッフルする

最後に,先送りにしておいたピースのシャッフルを説明しよう。リスト5を見ればわかる通り,ピースのシャッフルは適当な回数(ここでは200回)⁠ランダム(乱数)にピースの移動を行ない,それによってシャッフルを実現している。

こんなことをしなくても,以前カードゲーム(神経衰弱)でやったようにランダムで2つのピースを選び出し交換するという事を繰り返せば良さそうに思うかも知れない。ただ,残念ながら,今回はそう簡単な方法でシャッフルすることはできない。なぜなら,⁠14-15問題」があるからだ。前回説明したように,15パズルは,14番目と15番目のピースのみを入れ替えた場合,決して解くことができない。この問題に陥らないために,実際にピース(と対応する変数の値)をスライドさせながら,パズルをシャッフルさせているのである。

リスト5 ピースをシャッフルするスクリプト

for(k=0;k<200;k++){
  switch(random(4)){
  case 0:
   if(/:i_17>0){
    old=/:i_17--;
    set("/:v" add old add /:j_17,
                  eval("/:v" add /:i_17 add /:j_17));
    set("/:v" add /:i_17 add /:j_17,17);
   }
   break;
  case 1:
      ・
      ・  (同様に乱数値が1~3の時,残る3方向にスライド)
      ・
  }
 }
 for(i=0;i<4;i++){
  for(j=0;j<4;j++){
   tellTarget("stage/p" add i add j){
    gotoAndStop(eval("/:v" add ../../:i add ../../:j));
   }
  }
 }

16回目はここまで!Flashは,今回のようにプログラムライクな作り方も出来るのだ!次回は,この15ゲームを元にオリジナルゲームを考察するよ! ピピ!

著者プロフィール

西村直樹(にしむらなおき)

クリエイティブスタジオ Studio無限界 代表。アニメーターを経て,ゲームクリエイターとなる。ゲーム制作では,企画シナリオ,ディレクション,絵関連など幅広くこなし,ゲームクリエイターとして現在で19年となる。また,ゲームスクール,アミューズメントメディア総合学院にて,創立年から企画系講師を行い,クリエイター育成にも携わっている。現在は,マネジメントを行いつつ,コンシューマゲーム,ケータイコンテンツ,書籍執筆,その他様々なプロジェクトを進めている。

Studio無限界
URLhttp://www.mugenkai.com/


藤田和久(ふじたかずひさ)

プログラマ/テクニカルスーパーバイザー。メインフレームと呼ばれる大型コンピュータのシステム開発から,WebサイトのCGI,そしてケータイFlashに至るまで様々な環境のプログラミングに携わる。現在はStudio無限界の活動の傍ら,都内複数の専門学校において講師として,ゲーム制作,Webサイト制作,システムエンジニアリングなどの授業を担当。 また,Studio無限界とは別にFMS(個人)として,システムエンジニアリングの分野でも 活動している。

Studio無限界
URLhttp://www.mugenkai.com/

コメント

コメントの記入