提供:Japanese Scratch-Wiki
ここでは、マップチップ(マップタイル、map tile、などと表記される場合もある。)を用いた画面スクロールをプロジェクトに実装する方法を説明する。
他のプログラミング言語とは違い、Scratchではクローンを使用することができる。
クローンを使用することにより、マップチップスクロールを簡単に実装することができる。
マップチップスクロールに必要な知識
グローバル変数とローカル変数
マップチップスクロールをクローンで実現するためには、変数とクローンの関係を知る必要がある。
ここでは"スプライト-1"と言うスプライトから2つのクローン"スプライト-1-A"と"スプライト-1-B"を作ったと想定して話を進める。
クローンされたとき、各クローンが下記スクリプトを実行したとする。
なお、このスクリプトが実行されるとき、各変数の値は0になるものとする。
クローンされたとき::hat//各クローンが変数を書き換える [グローバル変数 v]を(1)ずつ変える::variables [ローカル変数 v]を(1)ずつ変える::variables
上記スクリプトが実行されると、グローバル変数の値は2になるが、ローカル変数の値は0のまま変わらない。
これは、グローバル変数はすべてのスプライト、クローン、ステージで共有されるのに対し、ローカル変数は1つのスプライトとそのクローンごとにすべて別の変数として扱われるからである。この仕組みを利用してクローンに識別マーカーを付けることによって2つの値(スクロールさせるための仮想x,y座標)から、それぞれのクローンを指定の場所に置く足掛かりにすることができる。
画面の座標とスクロールの座標
マップチップを使ったスクロールを実現するためには、画面の座標とスクロールの座標は別のものとして使う必要がある。 なぜかというと、画面の座標はx座標は-240~240まで、y座標は-180~180までしか無いからである。それ以上の座標を扱うために、グローバル変数で「仮想x座標」と「仮想y座標」を指定する必要がある。仮想x,y座標は画面の外の座標を表すことができ、(例えばx:512,y:256など)その軸を中心にマップチップの配置を決めることで画面スクロールを制御することができる。
リストからデータを取り出す
マップチップスクロールで必要な「マップデータ」はリストに格納する必要がある。マップデータは特定の法則に従ってある地点でのマップチップの仮想座標のコスチュームの番号を記録することで作る事ができる。具体的な方法を下記に示す。
リスト:マップデータ 1[00000000000000000000] 2[00010101010101010100] 3[00010202020202020100] 4[00010202020202020100] 5[00010101010101010100] 6[00000000000000000000]
上記のようなリストがマップデータの例である。この例の場合、リストの各要素(リストの長さ)がy座標を表し、各要素の文字列(数字列)がx座標を表す。このリストの場合だと、1データを2桁の文字列(00,01,02)で表している。このデータから特定の2桁を取り出す式が以下のスクリプトである。
(([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(1))番目の文字::operators)と(([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(2))番目の文字::operators)
x識別子・y識別子はローカル変数を使ったマーカーである。後ほど詳しく説明するので今はあまり気にしなくてもよい。
((((x識別子)-(1))*(2))+(1))
の、"-1*2+1"の左から3つ目の"2"の部分はデータ1つの長さである。なのでもし、データを三桁にしたい場合は
(((([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(3))+(1))番目の文字::operators)と(([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(3))+(2))番目の文字::operators))と(([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(3))+(3))番目の文字::operators))
のようにすることで3桁のデータを取り出すことができる。
クローンと初期描画
クローンを使ったマップチップベースのスクロールでは、一番最初のクローンの工程が非常に重要である。クローンはその性質上クローンする段階で識別子をつけなければそれ以上の操作ができなくなる。識別子付きのクローン生成の例は以下のスクリプトである。
定義 クローン 横軸(横軸の個数::custom-arg)縦軸(縦軸の個数::custom-arg) [y識別子 v]を(0)にする::variables (縦軸の個数::custom-arg)回繰り返す{[x識別子 v]を(0)にする::variables [y識別子 v]を(1)ずつ変える::variables (横軸の個数::custom-arg)回繰り返す{ [x識別子 v]を(1)ずつ変える::variables (自分自身 v)のクローンを作る }::control }::control
このスクリプトで、各マップチップのマス目ごとの座標を変数でマーキングしながらクローンする。
そして以下のスクリプトでマップチップをステージ上に配置する。
クローンされたとき::hat ずっと{ x座標を((((横軸の個数)/(2))*(マップチップのサイズ))-((x識別子)*(マップチップのサイズ)))、y座標を((((縦軸の個数)/(2))*(マップチップのサイズ))-((y識別子)*(マップチップのサイズ)))にする }::control
このスクリプトでクローンされたマップチップをステージに並べることができる。このスクリプトを実行しただけだと、マップチップが若干左下に寄るが、スクロールさせる場合は問題ない。
次に、マップデータに格納された2桁のデータを取り出してコスチュームに反映するスクリプトを示す。
コスチュームを((([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(1))番目の文字::operators)と(([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(2))番目の文字::operators))にする::looks
上記のスクリプトと組み合わせて
定義 クローン 横軸(横軸の個数::custom-arg)縦軸(縦軸の個数::custom-arg) [y識別子 v]を(0)にする::variables (縦軸の個数::custom-arg)回繰り返す{[x識別子 v]を(0)にする::variables [y識別子 v]を(1)ずつ変える::variables (横軸の個数::custom-arg)回繰り返す{ [x識別子 v]を(1)ずつ変える::variables (自分自身 v)のクローンを作る }::control }::control @greenFlag が押されたとき::events hat クローン 横軸(横軸の個数)縦軸(縦軸の個数)::custom クローンされたとき::hat コスチュームを((([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(1))番目の文字::operators)と(([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(2))番目の文字::operators))にする::looks ずっと{ x座標を((((横軸の個数)/(2))*(マップチップのサイズ))-((x識別子)*(マップチップのサイズ)))、y座標を((((縦軸の個数)/(2))*(マップチップのサイズ))-((y識別子)*(マップチップのサイズ)))にする }::control
のようにすることで、クローンを生成・初期描画までの処理を行うことができる。
スクロールの実装
マップチップのスクロールは(もしステージ全体にマップチップを配置する場合)行または列ごとに列のx座標が239以上または-239以下になるか行のy座標が179以上または-179以下になると反対の座標(例えばある列のx座標が239以上になった場合x座標を-238に移動させる)に移動させることによって、あたかもマップチップが無限に続いているように見せかける処理を行うことが基本となる。そして、その反対側に移動させたクローンのコスチュームをマップデータのデータに従い変更することでスクロールを表現している。 まずはクローンを端から端に移動させるだけのスクリプトを示す。
クローンされたとき::hat コスチュームを((([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(1))番目の文字::operators)と(([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(2))番目の文字::operators))にする::looks ずっと{ x座標を((仮想x座標)+((((横軸の個数)/(2))*(マップチップのサイズ))-((x識別子)*(マップチップのサイズ))))、y座標を((仮想y座標)+((((縦軸の個数)/(2))*(マップチップのサイズ))-((y識別子)*(マップチップのサイズ))))にする もし<(x座標::motion)>(239)>なら{ [x識別子 v]を((0)-(横軸の個数))ずつ変える }::control もし<(x座標::motion)<(-239)>なら{ [x識別子 v]を(横軸の個数)ずつ変える }::control もし<(y座標::motion)<(-179)>なら{ [y識別子 v]を(縦軸の個数)ずつ変える }::control もし<(y座標::motion)>(179)>なら{ [y識別子 v]を((0)-(縦軸の個数))ずつ変える }::control }::control
このように識別子をマス目の幅分ずらすことによってx座標とy座標を指定するブロックで勝手に逆側にシフトされる。 また、x座標とy座標を指定するブロックにグローバル変数の"仮想x座標"と"仮想y座標"を加算していることに注意してほしい。 このスクリプトに先ほどのコスチューム指定スクリプトを入れることでスクロールを実装することができる。
定義 コスチューム指定::custom コスチュームを((([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(1))番目の文字::operators)と(([マップデータ v]の(y識別子)番目::list)の((((x識別子)-(1))*(2))+(2))番目の文字::operators))にする::looks クローンされたとき::hat コスチューム指定::custom ずっと{ x座標を((仮想x座標)+((((横軸の個数)/(2))*(マップチップのサイズ))-((x識別子)*(マップチップのサイズ))))、y座標を((仮想y座標)+((((縦軸の個数)/(2))*(マップチップのサイズ))-((y識別子)*(マップチップのサイズ))))にする もし<(x座標::motion)>(239)>なら{ [x識別子 v]を((0)-(横軸の個数))ずつ変える コスチューム指定::custom }::control もし<(x座標::motion)<(-239)>なら{ [x識別子 v]を(横軸の個数)ずつ変える コスチューム指定::custom }::control もし<(y座標::motion)<(-179)>なら{ [y識別子 v]を(縦軸の個数)ずつ変える コスチューム指定::custom }::control もし<(y座標::motion)>(179)>なら{ [y識別子 v]を((0)-(縦軸の個数))ずつ変える コスチューム指定::custom }::control }::control