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

第8回カードゲームレクチャー(2) スクリプトを仕込む!!

魔法の呪文!? FlashLite1.xのActionScriptの底力を知ろう!

予告通り、今回からバリバリとスクリプトを仕込んで行くよ!え? 「FlashLite1.xのScriptじゃ大した事できないでしょ?」って? 誰だい、そんなこと言ってるのは!そんな人こそ、このレクチャーを読むのだピピ~ィ!!

擬似配列を使ったデータ上のシャッフル

複数のオブジェクトやデータを一様に扱いたい場合、たいていのプログラム言語では、配列というデータ構造を利用する。Flashでもバージョン5のActionScriptからこの"配列"が使えるようになった。しかし、Flash4のスクリプト仕様を踏襲するFlashLite1.xのスクリプトには、この配列がない。その代わりとして用いられている方法が、擬似配列である。

今回作成する"神経衰弱ゲーム"の場合、場に並ぶ8枚のカード(とそのパラメタを管理するための変数)を、この擬似配列で作成する。

(1)擬似配列の作り方

いきなり⁠擬似配列⁠などと仰々しい名前を出して脅かしてしまったかも知れないが、実の所は普通のオブジェクトであり、普通の変数だ。ただ、そのインスタンス名(もしくは変数名)を末尾のみ連番とした統一の名前で命名すれば良いのだ。

例えば、phase3の「カードを選ぶ、めくる(プレイ部分⁠⁠」においては、"場"に8枚分のカードクリップのインスタンスが並ぶことになるが、これらのインスタンス名をCard0~Card7とするだけで、擬似配列は利用可能なのだ。

Fla画面1 ゲームクリップ上に配置したオブジェクト
Fla画面1 ゲームクリップ上に配置したオブジェクト

ご覧いただけば分かるように各カードクリップは、ゲームクリップ上に直接配置しているわけではなく、プレイクリップを介している。プレイクリップのインスタンス名は、"CardPlay"である。

(2)各カードのマークやナンバーを保持する変数

前回の復習になるがカードクリップは、1フレーム目に裏模様のイメージを、2フレーム目以降に52枚分のカードパターンを、すべて持っている。フレームアクションとして、1フレーム目にstopが記述されているため、初期状態では裏向きのまま停止しているのだ。したがってカードがめくられた場合には、2フレーム目以降のどこかのフレームにgotoAndStopでジャンプすれば、そのフレームに設定したマークやナンバーを表示することができる。ここでカードは、何度もめくられたり戻されたりする点に注意が必要である。めくられる度にカードのマークやナンバーが変わってしまったのでは、ゲームにならない。そこでカードごとに、ジャンプすべきフレーム番号を保持する変数が必要になる。この変数は8枚のカードそれぞれに対応しているため、カードのインスタンス名と同様に擬似配列とした方が扱いやすい。そこで、各カードのマークやナンバーを保持する変数として、CardVal0~CardVal7を設定することにする。

(3)シャッフルさせるスクリプト

ゲームクリップの1フレーム目にカードをシャッフルさせるスクリプトを記述する。もっともカードそのものをシャッフルさせる必要はない。CardVal0~CardVal7に設定するフレーム番号をシャッフルさせるだけで良いのだ。

Fla画面2 カードをシャッフルさせるスクリプトの記述場所
Fla画面2 カードをシャッフルさせるスクリプトの記述場所

ここに記述するスクリプトは次のようなものだ。

List1 カードをシャッフルさせるスクリプト
//0~12の数列を作る・・・・・・①
for(i=0;i<13;i++){
    set("Number" add i, i);
}
//適当に交換して、乱数列を作る(頭4つを利用)・・・・・・②
for(i=0;i<13;i++){
    idx1 = Random( 13);
    idx2 = Random( 13);
    temp = Eval("Number" add idx1);
    set("Number" add idx1,Eval("Number" add  idx2));
    set("Number" add idx2,temp);
}
//場に並ぶカードの決定・・・・・・③
for(i=0;i<4;i++){
    j=i+4;
    switch(Random( 6)){
       case 0:                  //スーツ(ダイヤ×クローバ)
          set("CardVal" add i,Eval("Number" add i)+2);
          set("CardVal" add j,Eval("Number" add i)+15);
          break;
       case 1:                  //スーツ(ダイヤ×ハート)
          set("CardVal" add i,Eval("Number" add i)+2);
          set("CardVal" add j,Eval("Number" add i)+28);
          break;
       case 2:                  //スーツ(ダイヤ×スペード)
          set("CardVal" add i,Eval("Number" add i)+2);
          set("CardVal" add j,Eval("Number" add i)+41);
          break;
      case 3:                  //スーツ(クローバ×ハート)
          set("CardVal" add i,Eval("Number" add i)+15);
          set("CardVal" add j,Eval("Number" add i)+28);
          break;
       case 4:                  //スーツ(クローバ×スペード)
          set("CardVal" add i,Eval("Number" add i)+15);
          set("CardVal" add j,Eval("Number" add i)+41);
          break;
       case 5:                  //スーツ(ハート×スペード)
          set("CardVal" add i,Eval("Number" add i)+28);
          set("CardVal" add j,Eval("Number" add i)+41);
          break;
    }
    //カードロック状態を未ロックにする・・・・・・④
    set("CardLook" add i, 0);
    set("CardLook" add j, 0);
}
//場に並ぶカードを切る・・・・・・⑤
for(i=0;i<20;i++){
    idx1 = Random( 8);
    idx2 = Random( 8);
    temp = Eval("CardVal" add idx1);
    set("CardVal" add idx1,Eval("CardVal" add  idx2));
    set("CardVal" add idx2,temp);
}
//各種フラグの初期化・・・・・・⑥
selectCard1 = -1;   //1枚目にめくったカードのインデックス
selectCard2 = -1;   //2枚目にめくったカードのインデックス
sameCount = 0;      //揃った回数
missCount = 0;      //ミスした回数
targetIndex = 0;    //選択候補カードのインデックス

List1をご覧いただけばわかるように、このフレームで行っている処理は大きく6つのブロックに分けることができるリスト内①~⑥⁠。ここで④と⑥は、カードのシャッフルには直接関係ない処理なので後回しとし、残る4つのブロックを順に解説することにしよう。

① 0~12の数列を作る

先に、場に置かれるカードのナンバーを(マークに関係なく)決めてしまう。そのためにまず0~12の13個の数値を保存するための擬似配列を作成する。ここでは、for文による繰り返しの中で変数iの値が0から12へとカウントアップしていくので、"Number" add iは、"Number0"~"Number12"という文字列になる。関数setはこれを変数名として、そこに変数iの値0~12を代入する。この結果、変数Number0の値は0、Number1の値は1というように変数NumberX(Xは連番)は、そのXと同じ値を保持することになる。

② 適当に交換して、乱数列を作る

関数Randomを利用して適当に選んだ2つのNumberXの保持する値を交換する。これを数回繰り返すことにより、Number0~Number12の中の値はシャッフルされ、NumberXを連番で順次参照した時にその値は乱数列となる。この内、頭から4つが場に並ぶカードのナンバーとなる。

③ 場に並ぶカードの決定

ナンバーが決まったら次はマークの番だ。場には必ず同じナンバー異なるマークの4組計8枚のカードが置かれることになるので、Number0~Number4の値を元にそれぞれ2つずつの異なるマークを割り当てて、変数CardVal0~CardVal7に代入する。この時CardValXに代入する値は、カードクリップのフレーム番号であり、各カードは、

  • ダイヤのA~K・・・2~14フレーム目
  • クローバのA~K・・・15~27フレーム目
  • ハートのA~K・・・28~40フレーム目
  • スペードのA~K・・・41~53フレーム目

と並んでいるので、各マークのAの位置のフレーム番号にNumberXの値を足してあげれば良いということになる。

⑤場に並ぶカードを切る

③のままでは、Card0とCard4、Card1とCard5というように上下のカードが必ず対になってしまう。そこでCardVal0~CarVal7の値を②と同様に関数Randomを利用して適当に交換する。これで、やっとカードのシャッフルが完成する。

(4)ゲームを進める上で必要となる変数とその初期値

List1では、カードのシャッフル以外にも、このゲームの制御に必要な変数の初期値設定を行なっている(リスト中の④と⑥の部分⁠⁠。ここで、これらの変数の用途を説明しておこう。

CardLook0~7
そのカードがめくれるか否かの状態を示すフラグ。値が"0"の時はめくる事が可能。既にめくれている場合やペアが成立した場合に、このフラグを"1"としカードをめくる選択対象からはずす。
selectCard1、2
めくられたカードのインデックス(0~7の連番のこと)を保存する。初期値である"-1"か否かをチェックすることで、1枚目および2枚目がめくられたか否かの判定が可能となる。
sameCount
2枚のカードのナンバーが揃った回数を保存するカウンター。従って、この値が4になればゲームクリアということになる。カウンターなので初期値は当然"0"である。
missCount
2枚のカードのナンバーが揃わなかった回数を保存するカウンター。sameCountの逆で、この値が4になるとゲームオーバーとなる。これも初期値は"0"を設定。
targetIndex
選択候補枠(現在めくる対象となっているカードを示すハイライト)の付いているカードのインデックスを保存する。

めくるカードを選択させる

どのカードをめくるかプレイヤーに選択させよう。まず、今めくることの出来るカードを示すために選択候補枠を作る。この枠を4キーもしくは6キーの押下に応じて左右に移動させて、プレイヤーにカードを選ばせるのだ。

(1)選択候補枠クリップ(1枚目用)

Fla画面3を見ての通り、カードよりやや大きめの角を丸めた四角をタイムライン上に二色(白とライトブルー)並べ、これを循環させることによって点滅しているように見せかける。ただし、カードがめくられた後(2枚目の選択時)は、2枚目の選択の邪魔にならないように、点滅を停止する。

Fla画面3 1枚目用選択候補枠クリップ
Fla画面3 1枚目用選択候補枠クリップ

4フレーム目に記述するスクリプトは至って簡単!

List2 1枚目用選択候補枠クリップ4フレーム目のスクリプト
//カードが開いているときは点滅しない
if(../../:selectCard1 > -1){
 gotoAndPlay(1);
}

変数selectCard1が-1より大きい場合、1枚目のカードがめくられているという事なので、ライトブルーの四角を表示するフレームに入る前に1フレーム目に戻す。白1色のみの循環のため、点滅は停止したように見える。

(2)選択候補クリップ(1枚目用)

(1)と紛らわしい名前で申し訳ないが、今度はどこに選択候補枠を描くか、それを決めるためのクリップである。Fla画面4、タイムライン上8フレーム目までを全てキーフレームとし、各フレームにそれぞれCard0~Card7に合わせて表示位置を調整した選択候補枠クリップを配置する。このムービークリップは、1フレーム目でstopを掛けているので、4キーもしくは6キーの押下にあわせて、表示するフレームを移動させれば良いことになる。なお、9フレーム目以降空白フレームが続いているが、これはNULLというラベルを読みやすくするための処置であり、実際には空白フレームは9フレームのみ1つ設けてあれば構わない。

Fla画面4 1枚目用選択候補クリップ
Fla画面4 1枚目用選択候補クリップ

(3)2枚目用は若干修正

2枚目のカードをめくる際に必要となる選択候補枠クリップと選択候補クリップは、⁠1⁠⁠、⁠2)で説明したものとは若干作りが異なるため同じムービークリップを兼用とはいかず、また別に作成する必要がある(もっとも、ライブラリウインドウ内でシンボルをコピーしてしまえば、若干の修正で済む話ではあるが⁠⁠。

Fla画面5 2枚目用選択候補枠クリップ
Fla画面5 2枚目用選択候補枠クリップ

4フレーム目のスクリプトも修正!

List3 2枚目用選択候補枠クリップ4フレーム目のスクリプト
//カードが開いているときは点滅しない
if(../../:selectCard2 > -1){
 gotoAndPlay(1);
}

チェックする変数が、selectCard1ではなくselectCard2となる。

Fla画面6 2枚目用選択候補クリップ
Fla画面6 2枚目用選択候補クリップ

2枚目用選択候補枠は、1枚目選択時は非表示とするため、1フレーム目に空白フレームを置き、stopを掛けておく。


そして、いよいよこの選択候補枠移動の仕掛けボタンアクションの仕込みになるのだけれど、長くなるので次回に譲ろう。

8回目はここまで!擬似配列など、参考になったかな? この調子で、次回もバリバリとスクリプトを書くぞー!!楽しみに待つのだ! ピピ!

おすすめ記事

記事・ニュース一覧