アルゴリズム解説
囲み判定と塗りつぶし処理のアルゴリズムについて。
魔力マップ(配列)を用意します。
この上で魔力ラインの囲み判定と塗りつぶし処理を行います。
_0 | _1 | _2 | _3 | _4 | _5 | _6 | _7 | _8 | _9 | |
---|---|---|---|---|---|---|---|---|---|---|
0x | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 |
1x | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
2x | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
3x | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
4x | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
5x | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
6x | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
7x | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
8x | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
9x | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |
説明は10×10のマップを前提にします。上記の数字はアドレスです(以後省略)。
魔力ラインの制御のために、オブジェクト管理テーブルに以下の情報を持たせています。
Index# | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |
アドレス | 82 | 83 | 73 | 63 | 53 | 43 | 33 | 34 | 24 | 25 | 26 | 36 | 46 | 56 | 55 | |||||
方向 | → | → | ↑ | ↑ | ↑ | ↑ | ↑ | → | ↑ | → | → | ↓ | ↓ | ↓ | ← |
このテーブルのIndex#=99のところはプレーヤーの状態値です。
アドレスはプレーヤーの移動履歴。方向は、プレーヤーがそのアドレスに到達した時点での向きを示しています。
プレーヤーが一歩進むごとに、前側へ1つ分memcopyすることで、各情報を継承しています。
では、オブジェクト管理テーブルの情報をもとにマップ上に魔力ラインを置いてみます。
マスの値としてIndex#を格納すると、プレーヤーの位置「←」を99として、ひとつ前の場所は98、その前の場所は97というように、降順で置かれていきます。
_0 | _1 | _2 | _3 | _4 | _5 | _6 | _7 | _8 | _9 | |
---|---|---|---|---|---|---|---|---|---|---|
0x | ||||||||||
1x | ||||||||||
2x | 93 | 94 | 95 | |||||||
3x | 91 | 92 | 96 | |||||||
4x | 90 | 97 | ||||||||
5x | 89 | ← | 98 | |||||||
6x | 88 | |||||||||
7x | 87 | |||||||||
8x | 85 | 86 | ||||||||
9x |
(空欄の値は0とします)
上記の状態からプレーヤーが2歩前進、マップでは左側へ2マス移動すると、オブジェクト管理テーブルの中身は以下のようになります。
Index# | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |
アドレス | 73 | 63 | 53 | 43 | 33 | 34 | 24 | 25 | 26 | 36 | 46 | 56 | 55 | 54 | 53 | |||||
方向 | ↑ | ↑ | ↑ | ↑ | ↑ | → | ↑ | → | → | ↓ | ↓ | ↓ | ← | ← | ← |
魔力マップは、プレーヤーが移動するたびに最新情報で更新されますので、以下のようになります。
_0 | _1 | _2 | _3 | _4 | _5 | _6 | _7 | _8 | _9 | |
---|---|---|---|---|---|---|---|---|---|---|
0x | ||||||||||
1x | ||||||||||
2x | 91 | 92 | 93 | |||||||
3x | 89 | 90 | 94 | |||||||
4x | 88 | 95 | ||||||||
5x | 87 | 98 | 97 | 96 | ||||||
6x | 86 | |||||||||
7x | 85 | |||||||||
8x | ||||||||||
9x |
プレーヤーが移動する場所(アドレス53)に値が入っているので魔力ラインが閉じている(上記の場合87-98)と判断できます。
Kacotte!の浄化能力発動は「囲って」ループ状に閉じたことを条件としますので、有効なマーク値は95以下ということになります。
(97にあたった場合は、魔力ラインの長さを0に戻しています)
さて、囲み判定が出たので、塗りつぶすエリア(囲みの内側)が魔力ラインのどちら側になるかを判別します。
オブジェクト管理テーブルの「方向」の情報を拾って、右折は+1、左折は−1として、どちらにどのくらい方向転換したかを求めます。
起点は閉じた場所なので、Index#87から計算します。
Index# | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |
アドレス | 73 | 63 | 53 | 43 | 33 | 34 | 24 | 25 | 26 | 36 | 46 | 56 | 55 | 54 | 53 | |||||
方向 | ↑ | ↑ | ↑ | ↑ | ↑ | → | ↑ | → | → | ↓ | ↓ | ↓ | ← | ← | ← | |||||
転回値 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 2 | 2 | 2 | 3 | 3 | 3 |
最終的にプラスになりましたので、このループは右回りで閉じたことがわかります。(マイナスであれば左回りです。)
右回りのループなので、各魔力ラインの方向に対して右がループの内側とわかります。
※ちなみに、「矢印の方向=転回値」ではないので、仮に上記の状態から右折(上向き)すると、転回値は0ではなく4になります。
では塗りつぶしを行います。(このタイミングで、マップの魔力ラインもIndex#87から引き直します。)
魔力ラインに沿ってマップにIndex#を格納しつつ、1マス内側のアドレスを塗りつぶし候補として求めていきます。
Index# | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |
アドレス | 53 | 43 | 33 | 34 | 24 | 25 | 26 | 36 | 46 | 56 | 55 | 54 | 53 |
候補 | 54 | 44 | 34 | 44 | 25 | 35 | 36 | 35 | 45 | 55 | 45 | 44 | 43 |
この候補データを元に、更にマップの空のマスを埋めながら、新しい塗りつぶし候補を探します。
アドレス54は空ではない(既に魔力ライン98がある)ので読み捨てます。
アドレス44は空なので、ここを埋めます(便宜上★とします)。
そしてアドレス44の上下左右を候補として登録します。
残りの候補 | 34 | 44 | 25 | 35 | 36 | 35 | 45 | 55 | 45 | 44 | 43 | 43 | 34 | 45 | 54 |
次のアドレス34は90、その次のアドレス44は先ほどの★になっていますので、読み捨て。
これを繰り返していき、候補がなくなったところで塗りつぶし終了です。
魔力マップはこのようになっています。
_0 | _1 | _2 | _3 | _4 | _5 | _6 | _7 | _8 | _9 | |
---|---|---|---|---|---|---|---|---|---|---|
0x | ||||||||||
1x | ||||||||||
2x | 91 | 92 | 93 | |||||||
3x | 89 | 90 | ★ | 94 | ||||||
4x | 88 | ★ | ★ | 95 | ||||||
5x | 87 | 98 | 97 | 96 | ||||||
6x | ||||||||||
7x | ||||||||||
8x | ||||||||||
9x |
この魔力マップを元にフィールド描画する際、空でないマスに浄化のエフェクトを適用します。