HOME > ActionScript > スライドアルゴリズム > ピースを並べる

ピースを並べる

スクロールの仕様

次はピースのインスタンスを生成してフィールド上に配置します。ピースのインスタンスはFlash CS5のライブラリに作成したMCシンボルをドキュメントクラスで呼び出して生成して行きます。

インスタンスを生成して実際にピースを配置する前に、スライドの際に発生するスクロール処理の仕様について説明していきます。ピースの配置の形自体がスクロール処理の為の配置になっているので、なぜそういう配置を行うのかを把握しておく必要があるからです。

ソースファイル slide02.zip

5つのピースグループ

まず理屈の前にスクロール処理の為のオブジェクト構造を明かしておきます。
定義事項の中にある「フィールド」は、ピースを配置する為の表示コンテナなのですが、表示されないピースも沢山配置する事になります。フィールドの中で表示されるのはごく一部で、5×5で並んだピースの1グループになります。その1グループだけをマスク処理で表示されるようにし、表示されないピースのグループは、その表示されるグループの四方に1グループずつ配置します。この計5つのグループの位置関係と関連性は下の図の様になります。

フィールドの中央には表示用のピースを配置し、基本的にはこのグループが処理の基準になります。フィールドデータ(piecesFieldData:Vector.<int>)もこのグループのピースを操作されて変化した状態を反映、更新されます。
そしてそのグループの4方向に配置されたグループ4つは通常は表示されませんが、ピースの数や絵柄の並びは表示用のピースのグループと全く同じになります。表示されるピースグループと違うのは、直接操作される事がなく、このグループからフィールドデータに直接影響を与える様な事も無いという点です。
ただし、表示されるピースグループの変化が反映、更新されたフィールドデータの情報は即座にこの表示されないピースグループにも反映されます。

ここで定義事項に「表示エリア」「スクロールエリア」を追加しておきます。

用語 ピース 画面上に並べるブロックをここではピースと呼びます。
フィールド ピースを配置するステージ上の領域の事。
セル フィールドをグリッド分けして出来るマスの事をここではセルと呼びます。基本的にセルとピースは縦横の幅を同じにします。
また、このセルは描画される要素ではありません。
表示エリア 常時表示されるピースを配置するフィールド中の領域。フィールドに適用するマスクのサイズと同じ。
スクロールエリア スクロール処理の際に使用するピースを配置するフィールド中の領域。表示エリアの4方に隣接している。通常、ここに配置されたピースは表示されないけれど、スクロール処理の際は特定のピースだけが表示エリアに移り、表示されるようになる。

スクロール処理の理屈

ではスクロール処理自体の理屈を説明します。
例として、ここで言うスクロールとは右の図の様な動作の事を指しています。

上にスクロールする場合は上に消えるピースは下から出てくると言う用に、表示エリアから消えたピースは、消えた辺の対辺から出てくると言う動作がスクロールです。

まず消去法で、スクロール処理の方法として「ピースが右へ消えた時点でその消えたピースを左へ座標移動する」というような方法は使えません。これは反対側の辺のセルが必ず空白になるからです。
少なくとも消えるピースと同じインスタンスを消えるピースが表示エリアに収まっている時点から反対側に生成しておく必要があるのです。

この考え方で色々な方法を考えて試してみましたが、どの方法にも共通して「新しくインスタンスを作っては削除」という処理が出てきます。私はこの連続でメモリをガツガツ使いまくる様な方法がどうにも嫌でした。
きっちりガベージコレクションを意識すれば全然大丈夫なのですが、実際にこの処理をゲームなどに流用した場合、処理はスクロール処理だけではないのでこの手の処理は節約できるに越したことはない気がするからです。

で、気が付いたのが「あ、じゃあ生成しなきゃいいんだ」って事です。

最初に生成したピースインスタンスは削除せず、最初に生成したインスタンス以外は生成しない

ヨッシーのクッキーの様なパズルゲームや、マッチ3ゲーム(BejeweledやZOO KEEPER等)の場合、テトリスやぷよぷよなどと決定的に違うのは、「フィールドがピース(ブロック)で満ちている」という点です。そう考えると、一度生成したインスタンスを削除しないで再現する方が実は効率が良いはずです。
なので、表示エリアのグループもスクロールエリアのグループも必要なピースインスタンスは全て最初に生成してしまい、それ以後は一切生成しないし削除もしないと言う方針に決定。

スクロールエリアに配置するピースを最初は1列(行)分や2列(行)分で試したのですが、結局処理が煩雑になって増えてしまうだけだとわかり、最終的に表示エリアに配置されるピースの数、パターンと全く同じものを配置する形になりました。
こうする事で表示エリアにあるピースを端から端までスライドさせたり、マウスで高速にドラッグしたとしても、ピースが空白になるような状況は起きません。

ピースインスタンスの管理

フィールドに配置するピースの数は5×5の並びの更に5倍になります。これらは表示エリアに配置される1グループと、スクロールエリアに配置される4グループに区分して考えますがpieces配列に全てまとめて参照を保持します。

private var pieces:Vector.<MovieClip>;

参照を配列に保持する際の順序ですが、隣接リストテーブルを作成した考え方と同じ方法で参照します。
ただし番号は表示エリアが0番と考えて、上に隣接したスクロールエリアを1番、そこから時計回りに右を2、下を3、左を4という順番になります。こう考える事で配列のインデックスと、各エリアのピースが位置するセルの番号を効率よく整理して対応させる事が出来ます。

配列のインデックスを各グループのピースの参照は次の配列のインデックス位置に保持されています。

例えば表示エリアのピースで11番のピースをマウスでプレスした場合、その位置に対応しているスクロールエリア内のピース番号の算出方法は以下のようになります。

表示エリア インデックス [11]
スクロールエリア 上 5×5×1 + 11
スクロールエリア 右 5×5×2 + 11
スクロールエリア 下 5×5×3 + 11
スクロールエリア 左 5×5×4 + 11

これを定数を用いると以下のように表されます。

スクロールエリア 上 NUM_CELLS×(TOP + 1) + 11
スクロールエリア 右 NUM_CELLS×(RIGHT + 1) + 11
スクロールエリア 下 NUM_CELLS×(BOTTOM + 1) + 11
スクロールエリア 左 NUM_CELLS×(LEFT + 1) + 11

TOP、RIGHT、BOTTOM、LEFTは隣接リストテーブルを作成した際に用意した定数を流用しています。隣接リストテーブルの方向コードは上が0番から始まっているので、エリアの方向に使用する時には+1して使用します。

他に一つのエリア上に存在するセルの横の数、縦の数と総数を表す定数を追加します。

private const NUM_CELL_X:uint = 5;
private const NUM_CELL_Y:uint = 5;
private const NUM_CELLS:uint  = NUM_CELL_X * NUM_CELL_Y;

ピースをスライドさせる際はプレスされたピースが存在する列(もしくは行)に所属するピースを上記の算出方法を用いて、また別の一まとまりのグループとして抽出して扱います。

ピースの配置

スクロール処理の為の理屈を説明したところで実際にピースのインスタンスを生成して配置します。
この処理を実行するのはpiecesInit()メソッド(Main.asファイル 147行目)です。処理の内容そのものについては、別段特殊な事はしていませんのでソースを追って確認して下さい。
ここで重要な点は各エリアで最初のピースを配置する位置です。つまり各エリアの一番左上に配置するのピースの座標についてですが、下の図の様な配置になります。
それぞれのエリアの配置開始座標は下の図のようになります。

各エリアにピースを配置するときの座標の算出は、各エリアの一つ目(左上)のピースをどこに配置するかを計算した上で、続くピースの座標を計算しています。
piecesInit()メソッドの中ではforループの中で、基準点の座標を切り替えながら(Main.asファイル 188行目)ピースを配置していっています。

ピースを配置した後はあらかじめpieceFieldDataに用意(fieldDataInit()(Main.asファイル 128行目))しておいたピース絵柄のパターンコードに従って、ピースの絵柄を変更して行くだけです。
そのピース絵柄の変更はpiecesUpdate()メソッド(Main.asファイル 199行目)で一括して行っています。

また、表示エリアの左上を表示コンテナ(field:Sprite)の基準点(0, 0)に合わせていますが、これはその方がfield自体を一つのオブジェクトとしてステージに配置する際に色々と扱いやすくなるからそうしています。

動作確認

今回はfield表示コンテナ状態がわかるように、fieldをステージ中央に配置して、マスクの表示非表示を切り替えられるボタンを設置しています。右下のボタンを押すと表示が切り替わります。

Flashファイルをご覧いただくためには、
アドビシステム株式会社のフラッシュプレーヤー(Flash Player)が必要です。
インストールされていない方は下のボタンから、最新版が無償で入手できます。

Adobe Flash Playerのダウンロード

ソースファイルについて

ダウンロードリンクにあるzipファイルの中にはドキュメントクラスとなるMain.asファイルの他に、CS5とCS4形式で保存したflaファイルが一つずつ入っています。これらのflaファイルはCS4とCS5のバージョン以外では開けません。中のフォルダ構成がそのままならflaファイルをFlash CS5もしくはCS4で開いてパブリッシュすれば動作するはずですが、フォルダやファイルを個別に移動した場合はそれに合わせて適宜flaファイルの設定を変更して下さい。

  • PiecesSlide.fla (CS5用)
  • PiecesSlide_forCS4.fla (CS4用)
  • src/Main.as
  • bin/

基本的にはCS5用のファイルを使用する事が前提で進めますが、FlashCS4を使用している方はCS4用の方を使用して下さい。
ただしCS4用のflaファイルについてはFlash CS5でCS4用に保存したものですので動作確認はしておりません。開けなかったり使用できない場合があるかもしれませんが、その際はどうぞご容赦願います。
またファイルの設定などはWindows環境での作業を想定していますので、Flash CS5を使用していてもそのままの設定では使えない場合があります。適宜設定を変更するなどしてご使用願います。
flaファイルの設定などがわからない場合は公式リファレンスを参考にして下さい。申し訳ありませんがご質問等にはお答えできません。

TOP