5

ボードゲームの RISK に少し似たゲーム、または Total War シリーズのキャンペーン セクションに取り組んでいます。現在、リージョン システムの実装は機能していますが、パフォーマンスが悪いため、特定のコマンドの後でゲームがハングします。私はそれをより良くすることが可能であると確信しています。

私がしたいこと

世界地図などの地図を表示し、それを地域 (国など) に分割できるようにしたいと考えています。地域をクリックして選択し、ユニットをそれらに送信し、隣接する地域を取得できるようにしたいと考えています。

私が試したこと

マップは 3 つのファイルで定義されます。

  • 次のようにフォーマットされたデータを含むテキスト ファイル。 "Region Name" "Region Color" "Game-related information" ["Adjacent Region 1", "Adjacent Region 2", ...]'
  • 各領域が黒い境界線で区切られ、独自の色を持つ画像ファイル。したがって、たとえば、2 つの領域が存在する可能性があります。一方は RGB 値 255, 0, 0 (赤) を持ち、もう一方は 255, 255, 255 (白) を持ちます。それらは黒い枠で区切られています (ただし、これはアルゴリズムが機能するために必要ではありません)。
  • 画面に描画される実際の画像である別の画像ファイル。それは「見栄えの良い」マップです。

このようなカラー マップの例: カラーマップ (すべての白い部分は、現在の実装では同じ領域に評価されます。すべてが異なる色を持っていると想像してください)。

これらのファイルをロードするときは、まずカラー イメージをロードします。次に、テキスト ファイルを読み込み、各行を調べます。必要に応じて、正しい設定でリージョンを作成します。単にデータを読み取るだけなので、ここでは実際のパフォーマンス ヒットはありません。次に、一連の Region オブジェクトが作成され、正しい色が与えられます。

この段階では、すべてが正常に機能します。領域をクリックして、カラー イメージのピクセル データを確認し、リスト内のすべての領域を調べて、その特定のピクセルの色に一致する領域を見つけることができます。

問題

ただし、ここでパフォーマンス ヒットが発生します。

問題 1: 単位

各プレイヤーはたくさんのユニットを持っています。これらのユニットをリージョンでスポーンできるようにしたいと考えています。赤い領域でユニットをスポーンしたいとしましょう。ファイル内のすべてのピクセルを調べ、赤いピクセルにヒットしたら、そこにユニットを配置します。

for(int i = 0; i < worldmap.size(); i++) {
    for(int j = 0; j < worldmap[i].size(); j++) {
         if(worldmap[i][j].color == unit_color) {
              // place it here
         }
    }
}

この疑似コードを一目見ただけで、これがうまく機能しないことがわかります。とにかく、まともなペースではありません。

問題 2: 領域の色付け

もう 1 つの問題は、「見栄えの良い」マップでプレイヤーが所有する地域に色を付けたいということです。プレイヤー 1 が青、赤、緑の 3 つの地域を所有しているとします。次に、ワールドマップを調べて、カラー画像で青、赤、緑のピクセルを見つけ、「見栄えの良い」マップでそれらのピクセルをプレイヤーの色の透明バージョンで色付けします。

ただし、これも非常に重い操作であり、数秒かかります。

聞きたいこと

これはターンベースのゲームであるため、時々ゲームが少し遅くなることはそれほど大きな問題ではありません。しかし、この醜いコードを書いているのは私の好みではありません。リージョンの各ポイントをフロートとして保存するなど、他のオプションを検討しましたが、それはメモリに大きな負荷がかかります (64 ビット x 3000x1000 解像度の画像はかなりの量です)。

このために作成されたアルゴリズムがあるかどうか、またはプロセッサを解放するためにより多くのメモリを使用する必要があるかどうか疑問に思っていました. 他のゲームとその方法を探しましたが、役に立ちませんでした。これに関するソースコードや記事をまだ見つけていません。

この質問には意図的にあまり多くのコードを入れていません。これはすでにかなり長く、コードはアプリケーションの他の部分に多くの依存関係があるためです。ただし、問題を解決するために必要な場合は、できるだけ早く投稿します。

前もって感謝します!

4

2 に答える 2

1

問題 1: X 方向と Y 方向の両方で 10 のステップ サイズでカラー マップを調べます。これにより、考慮されるピクセル数が 100 分の 1 に減少します。各国に少なくとも 10x10 ピクセルの正方形が含まれている場合に機能します。

問題 2: ここでの最善の解決策は、これをプレイヤーごとや地域ごとではなく、1 回行うことです。地域の色からプレーヤーの色へのルックアップ テーブルを作成し、地域マップのすべてのピクセルを反復処理して、対応するプレーヤーの色を検索して適用します。

領域のカラー マップを RGB 332 (合計 8​​ ビット) に減らすと役立つ場合があります。おそらく、リラの細かい色合いはそれほど多くは必要ありません。1 バイトの色だけを使用すると、ルックアップ テーブルがはるかに簡単になります。256 要素の単純な配列だけで機能します。マップが 3000x1000 ピクセルであることを考慮すると、マップ サイズも 6 MB 縮小されます。

考慮すべきもう 1 つのことは、3000x1000 ピクセルの解像度の地域マップが本当に必要かどうかです。素敵なマップはそれほど大きいかもしれませんが、地域マップは 1500x500 ピクセルの解像度でリサンプリングできます。境界線が十分に太く (2 ピクセル以上) 見えたので、領域の解像度が 1 ピクセル失われても問題ありません。それでも、リージョン マップはさらに 2.25 MB 削減されます。750 kB で、おそらく CPU キャッシュに収まります。

于 2013-07-25T06:47:49.770 に答える