いったん凍結です

大変申し訳ない感じですが、開発終了目安だった10月末である現在をもって、いったん本ツールの開発凍結宣言を出します。
私的な問題でちょっとモチベーションが続かなくなったので、いったん眠らせます。


なんのかんので年内完了くらい目安にはまたやっているとは思いますが、現時点ではいったん正式に凍結宣言ということで。
また何か進展があったら、本Blogにて開発進捗などを記していきたいと思います。

砂浜の処理

結局、拡大マップから詳細マップへの差分を求めて計算する方法はなかなか上手くいかなかったので、詳細マップ時には縮小マップのデータを基に再計算してチップを求めなおす、というやり方をとることで実装を進めています。


縮小マップの2チップ間(正確には上下左右の内上左と中央の3チップ間)を計算して出すので、どうしてもちょっとのっぺりしてしまいますね。起伏が全体的になくなります。


ただまあ、これは仕方ないかなぁと。
べき論では一番小さいマップから作って徐々に縮小するべきで、そうすると縮小時にのっぺりすることもなくなるんですが、処理速度やメモリの問題からなんでもべき論でやれるものでもないので、この辺りで妥協します。
もちろん、若干の地形変形処理を入れれば、縮小マップからの誤差を気にしない範囲で起伏を入れる事は可能なんですが、今週できるところまでという予定なので、あまりイレギュラーな処理を入れるつもりはないです。


さて、現在は川が残っているんですが、もう一つ忘れていたのは砂浜です。
砂浜は海沿いの場所にのみ出現する灰色っぽい地形なんですが、この砂浜も1チップ25kmとして25kmも奥行きのある砂浜ってのはちょっと考えにくいですよね。
2.5kmでも十分巨大といえるレベルです。


ただ世界最大のビーチはどのくらいの大きさなのかはちょっとわかりませんでした。Wikiによると鳥取砂丘で南北2.4km、東西16kmだそうです。
砂丘は砂浜なんだろうかとか、砂浜ってそういえばどうやって出来るんだっけ?とかいろいろ疑問はあるとして、左右に広がる砂浜はまああるとしても大体海沿いに1チップあれば十分なレベルでしょう。


ということで、例外処理として川以外にもう一つ砂浜も処理する必要があります。
砂浜の計算自体は簡単なのですが、拡大マップで砂浜チップ化されている場所とそれ以外の場所で差をつけるのが難しいので、基本海沿い1チップ(連結部含めて最大1チップ)を砂浜化しつつ、拡大マップで砂浜になっているところは例外的に少し大きめなのを許容するとか、そういう方針で処理したいと思います。

詳細マップの仕上げ処理についてのメモ

詳細マップのチップ仕上げ処理についてのメモです。

全体

例外となる"川"を除けば、原則としてチップ補正がかかり、元となるマップのチップを50%以上含む形で、10x10=100のチップを作っていくのがいいかなと思います。
50%は普通にランダム+50%未満ならやり直し、でいいかなという気がします。


また、周辺チップと"馴染ませる"のが結構重要なので、砂漠に面している草原だったら唐突に四角形の砂漠が出ずに、じわじわと砂漠は草原に、草原は砂漠に変化していく必要があります。
この周辺チップ馴染ませは結構苦慮しそうで、例えばこういう地形があったとします。

サバンナの左側が林っぽく、右側が砂漠っぽくなればいいんですが、どの座標が左なのかと。上側も草原っぽくする必要あるはずですし。
多分三角形で分割して、上下左右に対応したエリア分けをするべきでしょうね。

海と海岸の処理

海チップはもう全面海でいいと思います。


海岸、つまり海に面している地形に関しては、原則として海に削られます。陸に面している海が削られるのではなく、あくまで陸を削ります。
やってみないとわからないのが内海ですが、多分同一ロジックでなんとかなるでしょう。

川の処理

現在のマップが1ピクセル2.5kmということは、元のマップは1ピクセル25km。
元のマップで作られる川は原則として2ピクセルの幅を持つので、なんと川幅50kmが世界に乱立していることになります。
んなあほな。


ちなみに河口部に限定すれば、アマゾン川やラプラタ川など100kmオーバーの川も地球に存在しますが、上流も含めて50kmはありえないしあっちゃいけないかと。ちなみに、多摩川の川幅最大は、河口部で620mだそうで。大きい川だと思っててもそんなもんです。


ということで川チップに関しては基本的に削ります。思い切り削らないといけないです。1ピクセルでも2.5kmの川幅で、相当な量なので、元の50kmを1ピクセルに減らすくらいの気持ちでやって、ようやく超巨大な川を実現できるレベルですし。
本来は2.5kmのチップに川は書かなくてもいいくらいですけど、地形の起伏上本当は2.5kmもないんだけどこのチップは川だよね、という見せ方は必要です。


基本的に、川チップは「川原と川が一緒」という形で考え、中心部を残しながら、海に近づくにつれて多少大きくするような処理が妥当でしょう。

森林と砂漠の処理

森林や砂漠は基本的に一面森林と砂漠にしつつ、端のチップは削ると言う形がいいかと思います。
おそろしく大きくまた変化が無い地形になりそうですが。

草原・サバンナ・林の処理

これらのは基本的に、草原やサバンナの場合は林を、林の場合は草原やサバンナを混ぜる形になります。

特殊地形

山はちょっと難しいです。
詳細マップのマップチップは高度などの情報を持っていないので、何を基準に山を作るのかと。
1チップ辺りが2.5kmなので、1チップを山にするのは妥当だと思いますが、ランダムで出現させるにしてもなんらかの基準が必要です。何も基準が無いと、砂漠になんの前触れもなく富士山が出来てしまったりすると思うので。


検討中です。例によって除外する可能性もなきにしもあらず、です。

沼は一定の森林力がある地形にランダムで出現させることになると思いますが、これまた基準が難しいですね。
元のマップで四方の高度が自チップより高い地形を探し出して、このエリアには沼が出現する、という定義付けを先にしてから、砂漠に沼地が出ないよう森林力に気をつかいつつランダム出現って感じでしょうね。

総じて

ちょっと重いですね・・。どうしようかなと。正直マップの"尤もらしさ"はなくても動くので、クォリティ後回しにした方がいい気もしてます。


来週一週間でやれる範囲、例えば海岸線と川だけとかをやって、他は四角形が連続するというレベルで満足しておくべきなのかもしれません。
まずはどの程度作れるか、やってみてから判断します。

詳細マップ最低限版のアップロード

今回のアップデートにあまり意味はないのですが、詳細マップを最低限生成できる状態にしたバージョンをアップしました。
http://tsuge.sub.jp/world/demo/


テスト用コードは前回と共通です。
KDQLKBIZDGCGAKHJBGIMJGQ6P3GCJXEH


とりあえず詳細マップ生成の画面を開いて、generate allすると生成出来ます。出来ますが、ベトナムからだと保存に異常に時間がかかってちょっとストレスです。
テスト用コードのものは生成・保存済みなので、それでふーんと眺める程度がいいかと思います。


まだ10x10のチップの中身を全然書いてないので、地形が完全に正方形です。これについては明日また対応方針を書いてみようと思います。


なぜか方向キーで現在のチップを移動することに対応したので、フィールドを歩いている気分を味わえるようになっています。
実際にこれをフィールドマップにしたらどうなるかをなんとなくイメージしたかったのでつけたのですが、やっぱりというか大変大きく感じますね。ドラクエっぽく遊ぼうと思うと120x120のワールドマップでも大きすぎるくらいです。
ためしに60x60のマップを作ってみましたが、小さ過ぎて島だけだったり、一面陸になったりと対応してないので、10倍スケールを必要に応じて2倍、3倍等に切り替えて詳細マップを作れるようにしないと、用途によっては困るかなという気もします。


一応、スクリーンショットも置いておきます。

冒頭に書いた通り今回のはあまり重要な更新ではないので、覚書程度ですが。

最低限の詳細マップ大体出来ました

詳細マップを一応作りました。
保存、読み込みもあって、「ローカルでは」快適に動作します。
ただ読み込み処理が完全非同期になるので、サーバにアップしたらどうなるかは結構見えてますね。


今回のチップはあくまでも画面表現が主体になり、属性値なんかは元々の地図からとります。
このため情報量は「どのチップであるか」のみでよくなるため、1チップ当たりの必要バイト数は1バイトです。もっともJavaScriptはchar型が無いので、すべてStringになる以上オンメモリでは実際はもうちょっと使うでしょうけど、データ的には1バイトです。


60x60を10倍して600x600にするため、1枚当たりのバイト数は360,000に区切り文字として改行が入るので、実際は360,600です。
そんなにすごい値でもない気はしますが、毎回読み込むので多少遅いです。頑張ってキャッシュきかせたりしてますけど。


念のため、テストで倍率を20倍にしたり、60x60ではなく30x30にしてみたりいろいろしてみましたが、10倍の60x60が一番しっくりくるのでこのままいきます。


ただ、昨日書いた「地球の2分の1サイズ」は、5kmが1チップになりそれをよしとしようかと思ったのですが、やっぱり5kmは大きすぎるので想定サイズを地球の4分の1を想定しようと思います。
600x600のマップも試してみたんですが、やっぱり処理速度が重いので、JavaScriptで出来るのは地球の4分の1くらいが限界だろうと自分のプログラムの重さを棚に上げて勝手に妥協します。


今週はもうちょっとテストしてから、今のとりあえず詳細マップをサポートした状態でアップします。
その後は詳細マップをよりちゃんと書き込む作業もあるんですが、これはちょっとアルゴリズムを考えないといけないので検討中です。森、草原、砂漠、サバンナ辺りはいいんですが、山・沼・川・海岸線が大分厄介です。


この辺を来週やりたいんですが、結構アルゴリズムが難しいので先にブロック状の詳細マップを利用して種族分布や派生種族に入るかもしれませんが、まだ不明です。
まずは最低限の詳細マップを仕上げることに集中して、その他は後ほどですね。

派生種族について・詳細マップを作る事に決めました

結局、結論としてどうあがいても詳細マップを作らないと無理だということになりました。
長いですが、ここ最近ずっと考えていた派生種族に関する懸案をまとめるためにも、きちんと書いておこうと思います。


地球は一周4万kmと少しのようで、現在の想定マップサイズが300x300のドーナツです。
計算しやすいよう地球を3万kmと仮定すると、300x300のマップは横縦共に30,000km。
30,000 / 300 = 100なので、すると1チップ辺りの面積は10,000平方kmです。つまり今は1ピクセルが東京都5個分くらいです。


とはいえ、地球と称するにはやはりちょっと小さいので、せいぜい2分の1としましょう。地球の半分、月の2倍くらいです。
すると50km * 50kmになるので、2,500平方キロメートルまで縮みます。大体1ピクセルで東京都以上鳥取県未満です。
これ一つを丸ごと「町」というチップにしてもいいかなぁと思わないでもないんですが、本来町ってそんなビッグな単位じゃないですよねぇ。


こういう時は理想論から考えるべきという事で、いったんわき道に逸れます。

理想論

マップの階層構造について

理想的にはマップは階層構造になっていて、Googleマップの縮尺表示みたいに出来るといいです。


大体、我々日本人が馴染んでいるのはドラクエ的な拡大縮小なので、先にこのフィールド構成について考えてみます。
フィールド構成は大きく、フィールドマップ、町・ダンジョン、バトルになっていて、後ろに行くにつれてより細かくなります。
現在用意されているマップは、フィールドマップをさらに縮小したいわゆるワールドマップだけですね。


さて、1日24時間なので、1歩1時間 = 人間の時速を5kmとして、1マス5kmくらいのマップチップに落とせれば、フィールドマップは出来るんじゃないかなと思います。
ただ1歩5kmってちょっと、最小の建造物が5kmなので、5kmってつまり25平方キロメートルですから、東京の立川市丸々一個分くらいです。
こんなのに「小屋」とか「塔」とかのチップ当てはめるとえらいこっちゃとなると、30分単位として2.5kmのがいいかもです。
2.5km四方って6.25平方kmいってしまうってことなので、東京ディズニーランドが0.51平方kmで、つまりディズニーランド12個分くらいなんですよ。どんな小屋だよって感じですけど、これ以上小さくするといくらフィールドマップ歩いても一日経たないですしこんなもんじゃないすかねぇ。


これが町やダンジョンになるとさらに細かくなって、大体ソードワールドなんかでは1ラウンドを10秒と計算しているようなので、1ラウンドごとで区切るなら5km / 60 / 6 = 14m単位になります。
10秒だと細かすぎる場合、1分当たりとして5km / 60 = 83mでもいいかもですが。60歩で1時間、1440歩で一日が経ちます。10秒だと1日経つのに8640歩。


バトルの場合はさらに細かくなって、せめて2m単位くらいまで落とすべきではないですかね。
まあ、バトルのフィールドがいるかどうかなどは別問題として。


これを段階的に縮尺表示出来るくらいのディテールでデータを持つのが理想ですね。

世界創造ツールでの話

世界創造ツールではタウンマップとダンジョンマップは作らないですし、当然戦闘シーンも無いので、フィールドマップだけですね。
フィールドマップを1時間単位とするか30分単位とするか微妙なところですが、世界創造ツールが必要なのは1時間単位くらいでしょうね。


最小単位が立川市丸ごと、ディズニーランド49個分っていうのも正直どうかと思うんですが、立川市全域程度ならぎりぎり「町」を1チップで表現しても許容出来る範囲でしょう。
どうしても許容できない場合は世界サイズを地球の2分の1ではなく、4分の1で考えるのもいいですし、600x600で自動生成してもいいです。とりあえず、今回のケースでは立川市全域が1ピクセルというのは「あり」とします。


現在の1ピクセルが50kmで、目標が5kmなので、ざっと10分の1にすればいいことになります。
つまり今の300x300を、3,000x3,000のマップで表現できればいいということです。

現実論

現実的に3,000x3,000のマップをメモリに読み込んだら死にます。9,000,000ピクセルですからね。
300x300の100倍の重さです。スロットが3つ増えたとか5つ増えたとかそういうレベルで四苦八苦していたので、処理速度的には普通に分割するべきでしょうね。


例によって適当にマップを作りました。



これのマップ左上16x16を10倍に拡大してグリッド入れるとこんな感じです。


実際海チップは別にして、草原チップにはもう少しごみごみしたものが入るとは思います。多少木があったりとかですね。16x16でも10倍なので160x160になります。


現在表示しているマップが300x300であるため、このサイズのまま切り出すなら本来30x30を切り出すべきですが、これだと小さ過ぎてキリが無いので60x60に切っちゃっていいと思います。表示は600x600で多分なんとかなるでしょう。


60で切ると、25分割です。
なので、25個分のちょっと詳細なマップを作れば、念願の拡大表示が出来る計算になります。
この1ピクセルをさらに32x32サイズにすればRPGでよく使われるマップになるわけです。


RPGツクールとかでゲーム作ってみたことある人ならわかると思いますが、フィールドマップのサイズで3,000x3,000は相当です。一般的なオフラインゲームであれば、60x60部分だけで世界地図にしてもゲームとして余裕で成立するレベルです。
ドラクエ3ジパングとかものっそい小さいですからね。一日歩けば日本列島制覇余裕ですし。あれをリアルにやるとこうなります。オンラインゲームなんかは多分このくらいのサイズです。

詳細マップの作成と種族分布への利用

現在の10倍の精度でちょっと詳細なマップを作ったとして、次に種族分布への利用方法なんですが・・。
最悪、今までの種族生成 + 種族分布は全部捨てることになる可能性があります。
パターン2つ考えています。

パターンA: 食物連鎖の頂点を種族分布で決定

パターン1では種族分布は別途種族分布で動かします。
種族分布で大体の分布を決めてから詳細マップを作って、その詳細マップに種族分布の結果を「大体」反映した種族のデフォルト配置を作ります。


大体というのは、種族分布で決めるのはあくまでも食物連鎖の頂点のみであり、その地点の頂点に立ったからといって、その地域の全域が一種族で埋まるわけではないという形です。
今の1ピクセルが100ピクセルになるので、頂点に立った種族は内25%程度かなと。
その後、詳細マップでの分布処理において最大50%まで増えることはあるものの、それ以上には増えないという形にしたいと思います*1


ただ、派生種族同士の戦いは結局のところその地の食物連鎖の頂点を決めるという戦いであり、派生種族同士の戦争で種族分布も変わってくるので、種族分布の意味が無いのではという根本的な問題があります。

パターンB: すべて詳細マップで作り直し

根本的な問題を重視して考えたのがこっちで、結局最初から詳細マップでやればいいじゃんという話が出てきます。
この時のフローはこんな感じです。

  • 最初にデフォルト種族(犬や人間など)を特にいじらず、いきなり詳細マップ
  • 詳細マップを作った後、詳細マップにランダムでデフォルトの全種族が適当な場所に配置される
  • 種族は今の種族分布と同じように領土争いを詳細マップの単位で繰り広げる
  • 種族は一定期間繁殖をすると突然変異で派生種族に分離する
  • 派生種族は多くの場合すぐに死ぬ(環境適応が出来ないか、元の種族に迫害される)が、時々共存するものやより優れたものが出来て生き残る
  • 文明を持つ種族は、一定期間が経過すると町を作ることがある


今までのアウトプットを使えない根本的な理由は、種族は後から作る、というものがあります。本来はそうなんですよね。
こっちがベストな気はしているのですが、作り直し工数と残り時間がちょっと少ないのでかなり悩んでます。


でも結局、こういうことをやっても根本的な問題は残るんですよね。
文明が発展するのは種族が現れたタイミングではなく、もっと後なので、同一の種族でも言語は全然違うものになりえるわけです。


世界創造ツールの定義では、中国人も日本人も同じなんですよ。モンゴロイドアングロサクソンのように根本的に違うわけではないです。しかし現実ではモンゴロイドの言語は非常に多彩です。これは種族より文明や文化が後だからです。


ベース種族は人で、そこからネグロイドが派生して、コーカソイドが出てきて、コーカソイドからアングロサクソンモンゴロイドが出てきて・・という程度では根本的に現実世界をトレースしきれません。言語も「モンゴロイド語」とひとくくりになります。


でも種族より文明や文化を後にするなんてそれこそ何年かかるのだという話になるので、現実的な落としどころを探していて、現実的な落としどころということであれば作り直しをするべきではないのではとも思っています。

今後について

長々と書いてきましたが、要は1ピクセルが東京都より大きいという現在の構造に無理があるので、腹を括って詳細マップを作ろうと決めたというのが今回の趣旨です。


まずは詳細マップを作ります。最初は草原チップの詳細マップは草原や木があるなどという形ではなく、一面草原という形にするとは思いますが。


詳細マップについては、最低限の形までは今週中で仕上げるつもりです。

*1:町などの場合は例外がありえますが

陸や海などの命名機能付き版のアップ

陸や海など、特定の箇所に名前をつける機能を追加したバージョンをアップしました。
http://tsuge.sub.jp/world/demo/


なおデータ構造の変更に伴いこれまでのデータが使えなくなってます。すいません・・。
一応、今回のテストコードも置いておきます。
KDQLKBIZDGCGAKHJBGIMJGQ6P3GCJXEH
※種族関連はアップデートが無いため、種族の生成はしていません。


画面右下の追加情報欄から諸々確認できます。
このマップの最大の特異点はモハロフ・オリレフ海溝とフィックス海溝があるリズ・カスポフ洋で、この洋のおかげで深海が多いです。
他、陸地では、ミハルロゾフという広大な砂漠があるナザロゾフ大陸が、種族分布での特異点になりそうな感じですね。




一からテストする場合、ログイン後、「地図自動生成のテスト」からgenerate allボタンをクリックし、画面右下の「追加情報」から森や砂漠などを選択することで、各地域の命名された様子を見ることが出来ます。
一応保存や読み込みにも対応しています。


また、少しアルゴリズムの見直しをした関係で、若干地図生成速度が上がっています。
ただ命名でネットワーク速度にもよりますが結構時間を食うので、トータルでは遅くなってますけども・・。


なお、名前自動生成システムのアップデートがあった関係で、少しロシア人の男性っぽい名前が多くなり、ブラジル系統が入った時以上に違和感が出ていますが、名前についてはその内ちゃんとするだろうと大目で見ていただければ。




今後についてですが、命名のその他欄をぼちぼち増やしつつ、派生種族に戻ります。
その他欄は特に難しい作業ではないのですが判定ロジックが多いので、気が向いたときにちょっとずつ増やします。
派生種族の方は・・相変わらず頭痛い問題です。
まずは詳細マップを作るかどうかから考えていきたいと思います。