日記(990)

<前 次>

ビットフィールドなんて知らなんだ

プログラミングコーナーのビット操作のところにビットフィールドのことを追記しました。
構造体やクラスの中限定で任意のビット長をもつ変数が使えるというのです。
ただ、ビットフィールドは構造体等の32ビット境界があるのでうまく変数をつめて書かないと帰って無駄が大きくなることもあり、また、配列が使えないという欠点もあったりします。

Bomber丸Worldでは、行動アルゴリズムをクラス化し、さらにGoToを実装しました。
GoToという行動タイプは今までになかったものですが、これは目的地をマップ座標で指定して、その場所へ向かうという行動を取ります。
簡単に言えば、人を追いかけるFollowの場所版ということです。
この行動は、まず目的地を最高点にし、他の場所に目的地に行くのにかかる歩数分だけ低くした点数をつけ、自分は最も点数の高くなる方向へ向かうというアルゴリズムになっています。
これ、まず全ての場所を最低点で初期化し、次に目的地を最高点にして、その場所を中心とした回り4箇所に点数をつけ、次は今点数をつけた周りに点数をつけ、更に次も同じようにして点数をつけ、自分の位置にたどり着くまでこれを繰り返します。
ただ、これを馬鹿正直に全部の場所を調べて点数をつけていたら検査する歩数の3乗のオーダーで処理回数が増え、高々32歩でたどり着く場所に1万回以上の処理が必要になったりするのでうまいこと処理を省くために調べる範囲を減らしたり調べるまでもないマスを読み飛ばしたりしています。

キャラを動かす続き

今日は押すアルゴリズムの改良と行動タイプ"Random"を実装しました。

押すアルゴリズムは、昨日作ったものだとキャラが沢山いたとき再帰呼び出しで無制限に次のキャラに動くよう促し続けると、袋小路などで「お前がどけ」「そっちこそ邪魔だ」の無限ループが発生し、フリーズすることがあったので、再帰呼び出しに制限を設け、一定回数以内の処理で動けなければその方向には移動できないということで解決しておきました。
一度これを呼び出し回数ではなく再帰の深さで判定するようにしていたのですがそうすると処理回数が4深さのオーダーで増えて、飛び出し回数で制限したときと同じ1024回で打ち切りにできるようにするには押せるキャラクターは高々5人程度になってしまい、人ごみをかき分けて進むようなネタが使えなくなってしまうことがわかったので、元の呼び出し回数式に戻しました。
再帰の深さを使ったバージョンは確実に動く人数を制限できるため、打ち切り深さを1から始めて順に深くしていけば動く人数を最小限に抑えることが可能だったはずなのですが、ちょっと袋小路の中に30人ほど人がいたら処理回数は10億回程度になりますからね、とてもじゃないが使い物になりません。
一方処理回数で打ち切る方式は適当に次々呼び出してどこかで道が開けた時点で処理終了になるのでどんなに遠回りだったとしても呼び出した経路上にいた人全員が動き出し、一人を動かすつもりが百人以上ごそっと動き出すこともしばしばです(もちろん数百人が密集していた場合だけですけどね)。
この方式だと呼び出し回数が確実に1024以下になるため、CPU負荷はそれほどかかりません。
まれに処理回数が1024に達してしまうほどの遠回りをして打ち切られることもありますが、その場合はそのフレームでは移動を諦めて、次のフレームで改めで最初から処理を開始すれば、動けるなら今度こそ高い確率で動けるでしょうし、動けなければ高々1024回の処理の後に何もしないだけです。

で、行動タイプ"Random"は、次の動きを決めるフレームでは上下左右に動くか、あるいは何もしないか、をランダムで決めます。
しかし今考えると、RPGの場合、話しかけられたら止まらなければいけません。
"Random"にしたキャラクターは結構せわしなく動くので一時的に行動タイプを"Still"などにして止めなきゃならないんですが(キャラは行動タイプを与えると勝手に動くので外部から制御するには行動タイプを変更するしかない)、そのあとはまた本来のキャラの動きに戻す必要があるので、行動タイプを変更するときは前の行動タイプを、関連する変数と共にスタックにつんでおかなければいけません。
つまり、動作とデータをひとまとめにして扱う必要があるのです。
これって…オブジェクト指向にする理由に一致するよね?
というわけで行動決定アルゴリズムはクラスにすること決定。
数が多いので少し面倒くさそうですが。

ダウンロードページのギャラリーに開発中の画像を公開し始めました。

キャラを動かす

今日はキャラが動かせるようになりました。
方向を与えてやれば、その方向が移動であるか、その方向に誰かいないかを判定して、移動可能であればその方向に移動します。
そして、動こうとした方向に誰かいた場合、そのキャラに動くよう促して、動いてくれた場合はもうその場所にキャラはいないので自分も移動します。
それから、行動アルゴリズムのうち、User、つまりユーザーの操作に反応して動くタイプを作るため、キー入力クラスも作りました。
現在は画像表示を作っているので今のところ仮のものですが。
今日の画像は、白いのを操作して、他の二人を押していっているところです。

1141656285.png

マップの話の続きの続き

で、マップ表示ができるようになって調子に乗ってキャラも表示できるようにしちゃいました。
キャラ部分がまた作りこみが甘いうちからテスト実行なんかしちゃってエラー続出。
自分で考えた仕様を自分で把握しきれていないというのが最悪でした。
思い出したおかげでなんとか形になったものの、次のステップに進む前に一度キャラ部分の再点検が必要そうです。

1141569988.png

マップの話の続き

さて、ようやくマップ表示できそうなところまでこぎつけました。
今日作ったのは、マップチップ管理の読み込み部分。
とりあえず読み込んでいないものは随時読み込んで、終了時にまとめてメモリ解放しています。
この先マップチップ管理には必要なくなった画像を随時解放していく部分を作るのですが最後に一気に解放する処理があるので今のところ優先順位を落としています。
そしてマップの地形データの読み込み。
マップチップ番号とチップを置く高さが入っています。
しかしまだこれでもマップは表示できる段階ではありません。
早くマップぐらい表示したいんですが。

Bomber丸Worldのマップの話

今日はマップ表示でもやったろかと思ってたんですがマップデータを用意する前に考えなくちゃいけないことがいろいろあったため作れませんでした。
まずマップチップが用意されてない。
まだテスト段階なので素材はテスト用マップチップでいいのですがそれを使えるようにするためのデータの形式が決まっていなかったのです。
で、それを考えていると今度は内部的に3Dで処理している座標の扱いがまだ決まっていないためにマップの高さ情報が決められないということに気付いたので今度は座標系をきっちり決めることになったんですよ。
で、まあ、決めた結果はいつものようにダウンロードページの開発室においてあります。

モンキーウォーク

ミディビ更新しました。
できること自体はそんなに変わっていません。

Bomber丸Worldのキャラの動きについて考えてます。
動きタイプをFollowにすると基本的に特定の人物についていくんですが、実は人によって歩調が違ってましてね、つまり、相手の動きが速いと取り残されることがあるということです。
それから更に踏み込んで考えたのが、バルーンモンキー。
バルーンモンキーって知ってますか?マザー2の。
ジェフの後についてくるキャラクターなんですが、ほっとくとしばらくその辺をうろうろしていて、ある程度距離を置くと思い出したように駆けつけてくるんです。
そのようにしてつかず離れず追いかけてくるのがバルーンモンキー。
これが結構面白そうなのでやってみたいのです。
アルゴリズムは案外簡単です。
ある距離以上に離れるまではRandomで歩かせておいて、離れたらFollowモードに内部的に切り替えるのです。
あと、前に言ったかどうか知りませんが、相手を押すというシステムも作っています。
押すリスクも加えて追いかけるプログラムを書くのは少し難しそうな気がしますがそう難しくもなさそうなのでまあできそうな気がします。(どっちだ

<前 次>