良い世界地図生成アルゴリズムを探しています[終了]


97

私は文明のようなゲームに取り組んでおり、地球のような世界地図を生成するための優れたアルゴリズムを探しています。私はいくつかの代替案を試してみましたが、まだ本当の勝者を見つけていません。

1つのオプションは、Perlinノイズを使用して高さマップを生成し、世界の約30%が土地になるように水を追加することです。パーリンノイズ(または同様のフラクタルベースの手法)は地形に頻繁に使用され、かなり現実的ですが、結果として得られる大陸の数、サイズ、および位置を制御する方法はあまりありません。ゲームプレイの観点から持っています。

パーリンノイズ

2番目のオプションは、ランダムに配置された1タイルシード(タイルのグリッドで作業しています)から開始し、大陸の目的のサイズを決定し、各ターンで既存の大陸に水平または垂直に隣接するタイルを追加します。希望のサイズに達しました。他の大陸についても繰り返します。この手法は、Civilization 4で使用されているアルゴリズムの一部です。問題は、最初の数大陸を配置した後、他の大陸に囲まれている開始場所を選択できるため、新しい場所に適合しないことです。また、大陸を近づけすぎて、大陸よりも川のように見える傾向があります。

ランダム拡張

グリッドベースのマップ上に現実的な大陸を生成し、その数と相対的なサイズの制御を維持するための優れたアルゴリズムを知っている人はいますか?


2
なぜ90以上の賛成票がある自然な質問を閉じる必要があるのか​​わかりません。投票を再開します。
John Coleman

回答:


38

あなたはからヒントを取ることができる自然とあなたの第二のアイデアを変更します。大陸(すべてほぼ同じサイズ)を生成したら、それらをランダムに移動、回転、衝突、変形させ、互いに離れさせます。(注:これは、実装するのが最も簡単なことではない場合があります。)

編集:これを実行する別の方法を以下に示します。実装が完了した、ゲーム用の多角形マップ生成です


2
これは素晴らしいアイデアです。構造プレートを完全にエミュレートしようとすることについて私は知りませんが、各大陸が独自のランドタイルを「所有」し(単にマップアレイのジェネレータとして機能するのではなく)、基本的に独自のプレート上にあるか、または機能する限り、実装するのはそれほど難しくありません。私は今これを試さなければならないだろう:)
nathanchere 2010

@FerretallicAありがとう。私は自分でこれを試してみたいと思っています
デビッドジョンストーン

3
常に使用できる安価なトリックの1つは、数学関数で「適切な」マップを定義するものを定義し、10個のランダムなマイナー変更を作成して、それらの最良のものを使用することです。それを続けてください、そうすればあなたが望む種類のマップに向かってドリフトします。
dascandy

K-meansクラスタリングの修正を使用して、個々の土地が所有する「大陸」を判別できます。次に、ボロノイ図(クラスターを定義すると簡単になるはずです)を使用してプレート境界を決定します...ボロノイの各線分について、ランダムなモーションベクトルを決定し、地震帯と火山を決定できる必要があります。土地などの各ポイントは、プレート境界に対する位置に基づいた個々のベクトルになり、最終的にはかなり現実的なシミュレーションが行われます。
スティーブ

私はワンタイルシード法を使用しています。これに山脈などのより複雑な地形を追加する方法に関する提案はありますか?
Tyshka、

11

私はあなたがバックアップすることをお勧めします

  1. 「良い」大陸を作るものについて考えてください。
  2. 大陸のレイアウトと悪いレイアウトを区別できるアルゴリズムを記述します。
  3. アルゴリズムを調整して、優れたレイアウトがどの程度優れているかを定量化できるようにします。

それができたら、次のようなアルゴリズムを実装することができます。

  • くだらない大陸を生成し、それらを改善します。

それは完全にアニーリング、遺伝的プログラミング、または何かをシミュレートしていますかどうかの改善のためには、標準の最適化のトリックのすべての種類を試すことができアドホックそれは質量の大陸の中心部反対側の端に大陸にあるwhereeverから無作為に選択されたエッジの正方形を移動するように、。しかし、鍵は、良い大陸と悪い大陸を区別できるプログラムを書くことができることです。好きなものが得られるまで、手描きの大陸とテスト大陸から始めます。


1
これは、このコンテキストではほとんど意味がありません。それは、フラクタルジェネレーターの場合、安っぽいフラクタルを生成するプログラムを作成してから、自分が持っているものが良いフラクタルかどうかを伝えるプログラムを書いてみてください。最初から「正しい」ものにする方がはるかに簡単です。そうでなければ、問題の焦点と範囲を完全に歪めます。
nathanchere 2010

1
@FerretallicAまったくそう思わない。グラフィックを使用すると、画面上に何かを取得することから始めるのが非常に役立ちます。次に、右脳がいくつかの作業を開始できます。
luser droog 2013

11

私は、Civilization 1の自動スクリーンセーバースタイルのクローンの目的に似たものを書きました。記録のために、VB.netでこれを書きましたが、質問で言語やプラットフォームについて何も触れていないので、私は続けますそれは抽象的です。

「マップ」は大陸の数、大陸のサイズの分散を指定します(たとえば、1.0はすべての大陸をほぼ同じ大陸面積に保ち、0.1までは大陸が最大の大陸の1/10の質量で存在できるようにします)、最大の大陸面積(パーセンテージとして)生成し、中央の土地バイアス。「シード」は、各大陸の地図の周りにランダムに分布し、中央バイアスに従ってマップの中心に向かって重み付けされます(たとえば、バイアスが小さいと、地球に近い分散大陸が生成され、中央バイアスが高くなると、パンゲア)。次に、成長の反復ごとに、「シード」は、最大の土地面積に到達するまで、分布アルゴリズムに従って(詳細は後で)土地タイルを割り当てます。

土地配分アルゴリズムは好きなだけ正確にすることができますが、さまざまな遺伝的アルゴリズムを適用してサイコロを振るより興味深い結果が見つかりました。Conwayの「Game of Life」は、非常に簡単に始めることができます。大陸が相互に成長することを回避するために、SOMEのグローバル対応ロジックを追加する必要がありますが、大部分は自分で処理します。よりフラクタルベースのアプローチで発見した問題(これは私の最初の傾向でした)は、結果がパターン化されすぎているか、ハック感の回避策のルールを必要とするシナリオが多すぎて、まだ十分に動的に感じられない結果が得られるというものでした。使用するアルゴリズムによっては、結果に「ぼかし」パスを適用して、豊富なシングルスクエアオーシャンタイルや市松模様の海岸線などを排除することができます。大陸が他のいくつかに囲まれてスポーンされ、成長する場所がなくなったような場合は、シードをマップ上の新しいポイントに再配置し、成長パスを続けます。はい、それは時々計画よりも多くの大陸で終わることを意味しますが、それが本当にあなたが絶対に望まないものであるなら、それを避けるのを助ける別の方法は成長アルゴリズムにバイアスをかけ、彼らが他に最も近い方向の成長を支持することです種子。最悪の場合(とにかく私の考えでは)、シードが成長して新しいマップを生成する場所がなくなったときに、シリーズに無効のフラグを立てることができます。試行回数の最大値を設定していることを確認してください。(10x10のボードに50の加重大陸をフィッティングするなど)非現実的なものが指定されても、有効なソリューションを見つけるために永遠に費やされることはありません。

Civなどの方法を保証することはできません。もちろん、気候や土地の年齢などはカバーしていませんが、シード成長アルゴリズムをいじってみると、大陸や群島などに似た非常に興味深い結果を得ることができます。同じアプローチを使用して、「有機的な」外観の川、山脈などを作成します。


11

JavaScriptで最初の画像に似たものを作成しました。それは超洗練されていませんが、動作します:

http://jsfiddle.net/AyexeM/zMZ9y/

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<style type="text/css">
    #stage{
        font-family: Courier New, monospace;
    }
    span{
        display: none;
    }
    .tile{
        float:left;
        height:10px;
        width:10px;
    }
    .water{
        background-color: #55F;
    }
    .earth{
        background-color: #273;
    }
</style>
</head>

<body>


<div id="stage">

</div>

<script type="text/javascript">

var tileArray = new Array();
var probabilityModifier = 0;
var mapWidth=135;
var mapheight=65;
var tileSize=10;

var landMassAmount=2; // scale of 1 to 5
var landMassSize=3; // scale of 1 to 5


$('#stage').css('width',(mapWidth*tileSize)+'px');


for (var i = 0; i < mapWidth*mapheight; i++) {

    var probability = 0;
    var probabilityModifier = 0;

    if (i<(mapWidth*2)||i%mapWidth<2||i%mapWidth>(mapWidth-3)||i>(mapWidth*mapheight)-((mapWidth*2)+1)){

        // make the edges of the map water
        probability=0;
    }
    else {

        probability = 15 + landMassAmount;

        if (i>(mapWidth*2)+2){

            // Conform the tile upwards and to the left to its surroundings 
            var conformity =
                (tileArray[i-mapWidth-1]==(tileArray[i-(mapWidth*2)-1]))+
                (tileArray[i-mapWidth-1]==(tileArray[i-mapWidth]))+
                (tileArray[i-mapWidth-1]==(tileArray[i-1]))+
                (tileArray[i-mapWidth-1]==(tileArray[i-mapWidth-2]));

            if (conformity<2)
            {
                tileArray[i-mapWidth-1]=!tileArray[i-mapWidth-1];
            }
        }

        // get the probability of what type of tile this would be based on its surroundings 
        probabilityModifier = (tileArray[i-1]+tileArray[i-mapWidth]+tileArray[i-mapWidth+1])*(19+(landMassSize*1.4));
    }

    rndm=(Math.random()*101);
    tileArray[i]=(rndm<(probability+probabilityModifier));

}

for (var i = 0; i < tileArray.length; i++) {
    if (tileArray[i]){
        $('#stage').append('<div class="tile earth '+i+'"> </div>');
    }
    else{
        $('#stage').append('<div class="tile water '+i+'"> </div>');
    }
}

</script>

</body>
</html>

3
とてもエレガントな実装が好きです。
nathanchere 2013

みんなありがとう !!それは非常に軽いとうれしいです
Liberateur

9

ポリゴンマップ生成の記事では、ボロノイポリゴンを使用しないでマップを生成する手順を説明しています。

この男はまた、すべてのソースコードを提供します。Flash(ActionScript 3 / ECMAScript)ですが、他のオブジェクト指向言語に転置できます

など、いくつかのフラクタルenvironementソフトに実装されたアルゴリズムを使用してみてくださいTerraJを


5

ここで袖口を考えるだけです:

いくつかの開始点を選択し、それぞれにランダムに描かれた(期待される)サイズを割り当てます。必要に応じて、計画された大陸と計画された島のために個別のサイズ描画を維持できます。

土地要素をループして、まだ計画されたサイズになっていない場合は、1つの正方形を追加します。しかし、楽しい部分は、隣接する各要素が1つになる可能性を比較検討することです。考慮に入れられるかもしれないいくつかの提案:

  1. 最も近い「その他」の土地までの距離。さらに広い海洋空間を生成する方が良いです。近いほど細いチャネルになります。ビットもマージできるようにするかどうかを決定する必要があります。
  2. 種子からの距離。近いほど良い土地の塊を意味し、遠いほど良い長いビットを意味します
  3. 隣接する既存の土地の正方形の数。隣接する多くの正方形を優先して重み付けすると、滑らかな海岸が得られ、少数を優先すると、多くの入り江と半島が得られます。
  4. 近くに「リソース」の正方形が存在しますか?リソーススクエアを生成するとき、およびそれを簡単にしたい場合は、ゲームのルールによって異なります。
  5. ポールがポールに近づいたり、ポールと合流したりできますか?
  6. ??? 他に何がわからない

すべての陸塊が計画されたサイズに達するか、何らかの理由でそれ以上成長できなくなるまで続けます。

パラメータをこれらの重み係数に合わせて調整すると、生成されるワールドの種類を調整できることに注意してください。これは、一部のCivについて私が気に入った機能です。

この方法では、ビットごとに別々に地形生成を行う必要があります。


4

ダイアモンドスクエアアルゴリズムまたはパーリンノイズを試して、高さマップのようなものを生成できます。次に、範囲値をマップに表示されるものに割り当てます。「高さ」が0から100までの場合、0-20水、20-30ビーチ、30-80草、80-100山を作成します。ノッチはミニクラフトでこれと似たようなことをしたと思いますが、私は専門家ではなく、最終的にそれを機能させた後、私はひし形の正方形の考え方にいます。


3

ここでは「動的プログラミング」スタイルのアプローチを使用できると思います。

最初に小さな問題を解決し、ソリューションをスマートに組み合わせて、より大きな問題を解決します。

A1= [elliptical rectangular random ... ]// list of continents with area A1 approx. 
A2= [elliptical rectangular random ... ]// list of continents with area A2 approx.
A3= [elliptical rectangular random ... ]// list of continents with area A3 approx.
...
An= [elliptical rectangular random ... ]// list of continents with area An approx.

// note that elliptical is approximately elliptical in shape and same for the other shapes.

Choose one/more randomly from each of the lists (An).

Now you have control over number and area of continents.

You can use genetic algorithm for positioning them 
as you see "fit" ;)

いくつかの「グラフレイアウトアルゴリズム」を見てみるのはとても良いでしょう

これらは目的に合わせて変更できます。


3

構造プレートの答えに似たマップ作成のアイデアがありました。それはこのようなものでした:

  1. グリッドの正方形をスイープして、rnd <= 0.292(地球上の乾燥した土地の実際のパーセンテージ)の場合、各正方形に「土地」の正方形を与えます。
  2. 各土地のチャンクを1つの四角形から最も近い大きな隣に向かって移行します。隣人が等距離にある場合は、より大きなチャンクに移動します。チャンクのサイズが等しい場合は、ランダムに1つを選択します。
  3. 2つの土地の正方形が接触する場合は、それらをチャンクにグループ化し、すべての正方形を今後1つの正方形として移動します。
  4. 手順2から繰り返します。すべてのチャンクが接続されたら停止します。

これは、3D空間で重力が機能する方法に似ています。かなり複雑です。あなたのニーズのためのより簡単なアルゴリズムは次のように動作します:

  1. n個のスターターランドスクエアをランダムなx、y位置に配置し、相互に許容可能な距離を置きます。これらはあなたの大陸の種です。(ピタゴラスの定理を使用して、種子が他のすべての種子との間に最小の距離を持つようにします。)
  2. その方向が海洋の正方形である場合、ランダムな方向に既存の土地の正方形から土地の正方形を生成します。
  3. 手順2を繰り返します。土地の正方形がマップの合計サイズの30%に達したら停止します。
  4. 大陸が互いに十分に近い場合は、必要に応じて陸橋を落として、パナマタイプの効果をシミュレートします。
  5. より自然に見えるように、必要に応じて小さなランダムな島をドロップします。
  6. 追加する各「島」の正方形について、同じアルゴリズムを逆に使用して、大陸から内海と湖の正方形を切り取ります。これにより、土地の割合が希望の量に維持されます。

これがどのように機能するかを教えてください。自分で試したことがありません。

PS。これはあなたが試したものに似ていると思います。それを除いて、開始する前にすべてのシードを一度に設定するので、大陸は十分に離れており、マップが十分に満たされると停止します。


2

私は実際にこれを試したことはありませんが、構造プレートに関するDavid Johnstoneの回答に触発されました。私は自分の古いCivプロジェクトに自分で実装してみましたが、衝突の処理に関しては別のアイデアがありました。タイルを直接生成する代わりに、各大陸はノードで構成されます。各ノードに質量を分配し、2Dメタボールアプローチを使用して一連の「ブロブ」大陸を生成します。テクトニクスと大陸移動は、ノードを移動するだけで、とんでもなく簡単に "偽造"できます。行きたい複雑さに応じて、電流のようなものを適用してノードの動きを処理し、重なり合うプレート境界に対応する山脈を生成することもできます。おそらく、ゲームプレイの側面にはそれほど多くは追加されません。

メタボールをこれまでに使用したことがない場合の良い説明:

http://www.gamedev.net/page/resources/_//feature/fprogramming/exploring-metaballs-and-isosurfaces-in-2d-r2556


2

開発中のゲーム用にこのようなものを実装しようとしているので、これが私が考えていることです。:

世界は地域に分かれています。世界の規模に応じて、地域の数が決まります。この例では、6つの地域がある中規模の世界を想定します。各グリッドゾーンは9つのグリッドゾーンに分かれています。これらのグリッドゾーンは、それぞれ9つのグリッドに分割されます。(これはキャラクターの動きではなく、単にマップの作成用です)グリッドはバイオーム用であり、グリッドゾーンは陸地の特徴(大陸vs海)のアーチ用であり、領域は全体的な気候用です。グリッドはタイルに分割されます。

ランダムに生成されたリージョンには、論理的な気候セットが割り当てられます。たとえば、グリッドゾーンはランダムに割り当てられます。海または陸。グリッドには、それらのグリッドゾーンと気候に基づく修飾子を使用してランダムにバイオームが割り当てられます。これらは、森林、砂漠、平野、氷河、沼地または火山です。これらのすべての基本が割り当てられたら、タイルセットを埋めるランダムなパーセンテージベースの関数を使用して、それらを一緒にブレンドする時が来ました。例えば; 森林バイオームがある場合、砂漠バイオームの隣に、タイルが「森林」である可能性の高いフードを減少させ、「砂漠」である可能性を増加させるアルゴリズムがあります。したがって、それらの間の約半分で、2つのバイオームを結合して、それらの間のやや滑らかな遷移をオフにする一種の混合効果がわかります。1つのグリッドゾーンから次のグリッドゾーンへの移行では、ロジックランドマスの形成を保証するために、おそらくもう少し作業が必要になります。たとえば、バイオームの中心からバイオームの端まで50のタイルがあります。つまり、接触するエッジから次のバイオームの中心まで50のタイルがあります。これにより、1つのバイオームから次のバイオームに論理的に100%変更されます。したがって、タイルが2つのバイオームの境界に近づくにつれて、パーセンテージは約60%まで狭まります。国境から遠く離れた場所でバイオームを横断する可能性が高すぎると賢明ではないと思いますが、国境をいくらかブレンドする必要があります。グリッドゾーンでは、パーセンテージの変化がはるかに顕著になります。%が約60%まで下がるのではなく、約80%まで下がるだけです。次に、二次的なチェックを実行して、海に隣接する土地バイオームの真ん中にランダムな水タイルが存在しないことを確認する必要があります。そのため、その水タイルを海の塊に接続して、水タイルを説明するチャネルを作成するか、完全に削除します。水ベースのバイオームの土地は、岩の露頭などを使用して説明する方が簡単です。

ああ、ちょっとダム、ごめんなさい。


ちょっと、そこ!私がマップを生成しようとしているように私はいくつかの研究をしていた。そして私はあなたが説明したとおりに実装しようとしていた。好奇心から、どうやってそれが判明したのですか?
VivienLeger 2017年

1

フラクタルテレインは、「機能する」(たとえば、2x2グリッド、ダイアモンドなど、ジッターがある)とわかっているレイアウトに従って配置しますが、ガウス分布の減衰ピークは、大陸の中心の端に向かって下がっています。水位を低くして、端に近づくまでほとんどが陸になるようにします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.