タイルマップを効率的に保存してWebに表示する方法


9

これらは実際には1つの2つの質問です。まず、大量のタイルデータを効率的に格納する方法を探しています。もう1つの側面は、データセットのクエリとタイルの表示を扱います。まず、背景を説明しましょう。

私たちは、CraftyJSライブラリを使用してCanvasにレンダリングするブラウザーベースのマルチプレイヤータイクーンゲームを作成しています。GUIのバックグラウンドでは、PHPでYii Frameworkを実行しており、すべてがPythonランダムマップジェネレーターとゲームエンジンに接続しています。

これが最初のラフマップレンダーの外観です。http//i.imgur.com/khAXtl.png

地図データの保存

ゲームの世界は、ゲームが開始するたびにランダムに生成されます。サイズは、各プレーヤーの100x100六角形タイルです。つまり、3人用のゲームでは、90.000のタイルが作成されます。現在は、マップをレンダリングするためのJavaScript配列を作成しています。

これはレンダリングには問題なく機能しますが、マップを操作する場合は、タイルを所有するプレーヤー、その上に構築する構造の種類、現在の価格などを保存する必要があります。最初は、少なくともプロトタイプについては、MySQLを使用したかったのですが、いくつかのテストの後、それは私が望むほど正確ではありません。たぶん、MongoDBのようなオブジェクトストアは、SQLテーブルではなくタイルデータを格納するのに適しています。それとも何か他に?

地図を表示する

私が目にするもう1つの問題は、マップ内を移動することです。現在、ビューポートにない場合でも、タイルごとにCraftyエンティティを作成しています。Craftyはビューポート内のタイルのみをレンダリングしますが、保存し、各レンダリングイベントですべてのタイルを反復処理する可能性があるため、これは低速です。私が現在持っているのは、移動が非常に遅く、動きが途切れる、描画された生成されたマップです。これを再生可能にしたいと思います。

私の最初のアイデアは、ビューポートにあるタイルの表示されたサブセットをロードすることでした。しかし、プレーヤーがビューポートを空白の領域に移動する場合、サーバーにクエリを送信して応答が返されるのを待つ必要があります。そうしないと、マップをレンダリングできません。これはネイティブアプリケーションでは問題ありませんが、Webゲームでは遅延します。

マップからスムーズなパフォーマンスを得る方法は、タイルのより大きなサブセットをJavaScript配列にプリロードし、それをキャッシュとして使用することです。プレーヤーにはいくつかの画面が「キャッシュ」されており、ビューポートを移動すると、JSの「キャッシュ」により多くのタイルがロードされます。

私は正しい方向に向かっていますか?同様のことをした人からもっと情報をもらいたいです。私はゲーム開発に不慣れですが、ここ数週間にわたって多くの情報源を経験してきました。


1
MySQLをボトルネックとして特定したことに驚いています。それが物事を遅くしているという結論に至るために何をテストしましたか?
bummzack

@bummzack彼がタイルごとに行を持っている場合、私は物事が遅くなることができなかった方法をほとんど見ることができません。
aaaaaaaaaaaa

1
@eBusiness DBから数千行をクエリしても、実際には問題になりません。これはまだ数ミリ秒の範囲にあるはずです。また、90,000行ではなく、3人のプレーヤーで30,000行になります(1プレイヤーあたり100x100)。
bummzack

わかりにくい数学で申し訳ありませんが、プレーヤーゾーンに加えて、プレーヤー間に2倍のスペースがあるため、互いに等距離になり、90kになります。クエリは問題ありません。90kタイルを選択してマップを作成するのは簡単です。しかし、それを行うには良い方法ではありません。詳細情報が要求されたときに、マップデータをシリアル化し、データベース内のタイルのクエリを使用します。
エレメント

回答:


2

ゲームプレイ
まず最初にお聞きしたいのですが、実際にはプレイヤーごとに10000タイルが必要ですか?あなたがどのようなゲームを作っているのかはわかりませんが、大きな地図で長いゲームを作ることは一般的には事実です。Civilization 5の最大のマップは10240タイルであり、その一部しかプレイする必要がないため、このようなマップだけが機能します。

データベース
このようなゲームをデータベースから実行しないでください。データをアプリケーションメモリに保持する必要があります。データベースを使用してゲームをバックアップできます。完全なバックアップを行うには、ゲームデータのシリアル化を保存します。次に、指定された注文を保存してそれを増やし、バックアップを使用する必要がある場合はそれらを再実行できます。

JavaScriptストレージ
クライアントについては、少なくともマップ全体をロードしたままにしておくとよいでしょう。少なくとも、素晴らしいオブジェクトツリーにすべてが配置されているガジリオンタイルに固執する場合は、少なすぎる場合があるため、おそらくデータを保持する必要があります。 「セミバイナリ」エンコード形式。文字列はこの種のものに最適であり、代わりに、最大53ビットの符号なし整数を64ビットフロートに安全に格納でき、それらの多くを配列に格納すると、かなり控えめなメモリフットプリントが表示されると思います。

JavaScriptの視覚化
キャンバスを必ずしも使用するべきではないとは言いませんが、実際にはこのようなものには必要ありません。すべてをimg要素の束として設定し、srcプロパティを変更して、マップのさまざまな部分を表示します。

プロのヒント
ちなみに、マップ全体を共有するよりも、生成に使用したシードを共有する方が簡単な場合があります。


+1ですが、悲しいことに、PHPで記述されたWebアプリは通常、ゲームの状態をメモリに保持する手段がありません。
bummzack

@bummzack、ああ、そうです、私はどういうわけか私はPHPという単語をスキップしてPythonを読んだだけだと思います。次に、バックエンドフレームワークの変更が必要になる場合があります。Node.jsはオプションになる可能性があります。
aaaaaaaaaaaa

私は競争力のある輸送の大物を構築しています。OpenTTDを考えてください。512x512(262k)のサイズのマップは、2人のプレイヤーにとってそれほど大きくありません。意欲的だと思いますが、地図がそれほど大きくなければ、ゲームはすぐに終わります。マルチプレイヤーゲームなので、マップ間の変更をプレイヤー間で同期する必要があります。私の最初の本能は、Web開発で知っている概念を使用してデータベースを使用することでした。超リアルタイムである必要はありません。地図上に動的なものを配置したいので、JSビジュアライゼーションを使用します。
要素、

私の回答をいくつかの指針と考えてください。結局、パフォーマンスを自分で解決する必要があります。それは深刻な問題であり、妥協する必要があるかもしれません。
aaaaaaaaaaaa

私は同意します、あなたの答えは私に多くの思考の糧を与えました。シリアル化されたマップデータをメモリに保持し、データベースをバックアップとして保持する方法を探します。しかし、私はプレーヤー間で変更を共有する方法を理解する必要があります。さらにいくつかのテストを行った後、思いついたことに戻ります。
要素

1

MySQLは遅くありません。おそらく、単純なクエリを実行しているか、最適ではないインデックスを使用しています。MongoDBのようなNoSQLアプローチの方が高速かもしれませんし、そうでないかもしれません。ここで本当に重要なのは、アクセスパターンとクエリの選択です。パフォーマンスを改善する方法についてアドバイスをすることは可能ですが、すでに何をしているのかを見ることなしにはできません。

マップからスムーズなパフォーマンスを得る方法は、タイルのより大きなサブセットをJavaScript配列にプリロードし、それをキャッシュとして使用することです。

はい、もちろん。ここで追加するものはそれほど多くありません。クライアントがサーバーからタイルを要求するので、要求するタイルが画面よりも広い領域をカバーしていることを確認する必要があります。

補遺:

PHPでYii Frameworkを実行しており、すべてがPythonのランダムマップジェネレーターとゲームエンジンに接続しています。

あなたがPythonに熟練しているなら、私はあなたがPHPミドルマンを捨てることをお勧めします。ゲームをPythonプロセスとして実行すると、タイルデータをメモリに保持しやすくなり、MySQLアクセスを大幅に削減できます。また、PythonがPHPよりもはるかに健全な言語であることも役立ちます。

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