Bagaimana cara menyimpan dan menampilkan peta ubin secara efisien di web?

9

Tentang

Ini sebenarnya adalah dua pertanyaan dalam satu. Pertama-tama saya mencari cara untuk secara efisien menyimpan data ubin dalam jumlah besar. Aspek lain berkaitan dengan permintaan set data dan menampilkan ubin. Biarkan saya memberi Anda latar belakang terlebih dahulu.

Kami membuat game taipan multipemain berbasis browser menggunakan perpustakaan CraftyJS untuk merendernya ke Canvas. Di latar belakang GUI kami menjalankan Yii Framework pada PHP dan semuanya terhubung ke generator peta dan mesin gim Python acak.

Beginilah tampilan peta kasar pertama terlihat: http://i.imgur.com/khAXtl.png

Menyimpan data peta

Dunia game dihasilkan secara acak setiap kali game dimulai. Ukurannya adalah 100x100 ubin heksagonal untuk setiap pemain. Itu berarti bahwa untuk permainan tiga pemain, ada 90.000 ubin yang dibuat. Saat ini saya baru saja membuat array JavaScript tempat saya membuat peta.

Ini berfungsi dengan baik untuk rendering, tetapi untuk segala jenis interaksi dengan peta kita perlu menyimpan pemain mana yang memiliki ubin, struktur seperti apa yang dibangun di atasnya, berapa harga saat ini dan seterusnya. Pada awalnya, setidaknya untuk prototipe, kami ingin menggunakan MySQL, tetapi setelah beberapa pengujian, tidak secepat secepat yang saya inginkan. Mungkin penyimpanan objek seperti MongoDB akan lebih cocok untuk menyimpan data ubin daripada tabel SQL. Atau mungkin sesuatu yang lain?

Menampilkan peta

Masalah lain yang saya lihat adalah bergerak di sekitar peta. Saat ini saya sedang membuat entitas Crafty untuk setiap ubin meskipun itu tidak ada di viewport. Ini lambat, karena meskipun Crafty hanya membuat yang ada di viewport, Crafty menyimpan dan mungkin mengulangi semua ubin pada setiap acara render. Apa yang saya miliki saat ini adalah peta yang dibuat tergambar yang sangat lambat untuk memuat dan gagap ketika Anda bergerak, sekarang saya ingin membuatnya dimainkan.

Ide pertama saya adalah memuat subset ubin yang ditampilkan di viewport. Tetapi ketika seorang pemain akan memindahkan viewport ke area kosong, saya harus meminta server dan menunggu respon kembali, baru kemudian peta dapat di-render. Ini akan baik-baik saja dalam aplikasi asli, tetapi itu lamban dalam permainan web.

Cara untuk mendapatkan kinerja yang lancar dari peta bisa preloading subset ubin yang lebih besar ke dalam array javascript dan menggunakannya sebagai cache. Pemain akan memiliki beberapa layar "di-cache" dan ketika dia memindahkan viewport, saya akan memuat lebih banyak ubin ke "cache" JS.

Apakah saya menuju ke arah yang benar? Saya ingin mendapatkan lebih banyak informasi dari seseorang yang telah melakukan hal serupa. Saya baru dalam pengembangan game, tetapi telah melalui banyak sumber selama beberapa minggu terakhir.

elemen
sumber
1
Saya terkejut bahwa Anda mengidentifikasi MySQL sebagai hambatan. Apa yang Anda uji untuk sampai pada kesimpulan bahwa itu memperlambat segalanya?
bummzack
@bummzack Jika dia memiliki baris per ubin saya hampir tidak bisa melihat bagaimana semuanya tidak bisa lambat.
aaaaaaaaaaaa
1
@eBusiness Meminta beberapa ribu baris dari DB seharusnya tidak menjadi masalah. Ini harus tetap dalam kisaran beberapa milidetik. Juga bukan 90'000 baris, tetapi 30'000 baris untuk 3 pemain (100x100 per pemain).
bummzack
Maaf untuk matematika yang membingungkan, ada juga dua kali jarak antara pemain di samping zona pemain sehingga mereka memiliki jarak yang sama satu sama lain, yang membuatnya menjadi 90k. Permintaan tidak masalah. Memilih ubin 90k dan membangun peta adalah. Tapi itu bukan cara yang baik untuk melakukannya. Saya akan membuat serialisasi data peta dan menggunakan kueri ubin di db ketika diminta informasi detail.
elemen

Jawaban:

2

Gameplay
Pertama-tama saya ingin bertanya, apakah Anda benar-benar membutuhkan 10.000 ubin per pemain? Meskipun saya tidak tahu jenis permainan apa yang Anda buat, umumnya benar bahwa peta besar membuat permainan panjang. Peta terbesar di Civilization 5 adalah 10240 ubin, dan itu hanya berfungsi karena Anda tidak perlu bermain lebih dari sebagian kecil saja.

Basis Data
Anda sebaiknya tidak mencoba menjalankan game seperti ini dari basis data, Anda harus menyimpan data dalam memori aplikasi. Anda bisa menggunakan database untuk membuat cadangan game. Untuk cadangan yang lengkap, simpan serialisasi data game, dan kemudian Anda bisa menambahnya dengan menyimpan pesanan yang diberikan dan kemudian jalankan kembali jika cadangan perlu digunakan.

Penyimpanan JavaScript
Adapun klien, saya akan mengatakan Anda lebih baik menyimpan seluruh peta dimuat, setidaknya jika Anda tetap berpegang pada trilyun ubin memiliki semuanya di pohon objek yang bagus mungkin agak terlalu banyak, jadi Anda mungkin harus menyimpan data dalam format "semi-binary". String bekerja sangat baik untuk hal-hal semacam ini, secara bergantian, Anda dapat dengan aman menyimpan bilangan bulat tak bertanda hingga 53 bit dalam float 64 bit, banyak hal dalam array dan saya pikir Anda akan melihat jejak memori yang cukup sederhana.

Visualisasi JavaScript
Walaupun saya tidak akan mengatakan bahwa Anda tidak seharusnya menggunakan kanvas, Anda sebenarnya tidak membutuhkannya untuk hal-hal seperti ini. Atur semuanya sebagai sekelompok elemen img, dan ubah properti src untuk menampilkan bagian peta yang berbeda.

Pro tip
By the way, kadang-kadang lebih mudah untuk berbagi benih yang digunakan untuk menghasilkannya daripada berbagi seluruh peta.

aaaaaaaaaaaa
sumber
+1, tetapi sayangnya aplikasi web yang ditulis dalam PHP biasanya tidak memiliki sarana untuk menjaga status permainan.
bummzack
@bummzack, Ahh, benar, saya pikir saya entah bagaimana melewatkan kata PHP dan hanya membaca Python. Maka perubahan kerangka backend mungkin dilakukan. Node.js bisa menjadi opsi.
aaaaaaaaaaaa
Saya sedang membangun taipan transportasi yang kompetitif, pikirkan OpenTTD, peta ukuran 512x512 (262k) tidak terlalu besar untuk beberapa pemain. Saya menyadari bahwa ini ambisius, tetapi jika peta tidak terlalu besar, permainan akan berakhir terlalu cepat. Karena ini adalah permainan multipemain, saya harus menyinkronkan perubahan pada peta di antara pemain. Insting pertama saya adalah menggunakan konsep yang saya tahu dari pengembangan web dan menggunakan basis data. Tidak harus super realtime. Saya akan menggunakan visualisasi JS, karena saya ingin memiliki hal-hal dinamis di peta.
elemen
Anggap jawaban saya sebagai petunjuk, pada akhirnya Anda harus mengerjakan sendiri kinerjanya, ini masalah serius, dan Anda mungkin harus membuat beberapa kompromi.
aaaaaaaaaaaa
Saya setuju, jawaban Anda memberi saya banyak bahan untuk dipikirkan. Saya akan mencoba menemukan cara untuk menyimpan data peta bersambung dalam memori dan menyimpan database sebagai cadangan. Tapi kemudian saya harus mencari cara untuk berbagi perubahan di antara para pemain. Saya akan kembali dengan apa yang saya hasilkan setelah saya melakukan beberapa pengujian lebih lanjut.
elemen
1

MySQL tidak lambat. Kemungkinan besar Anda melakukan kueri naif atau memiliki indeks sub-optimal. Pendekatan NoSQL seperti MongoDB mungkin lebih cepat, mungkin juga tidak. Pola akses dan pilihan kueri Anda adalah yang paling penting di sini. Dimungkinkan untuk memberikan saran tentang cara meningkatkan kinerja, tetapi tidak tanpa melihat apa yang sudah Anda lakukan.

Cara untuk mendapatkan kinerja yang lancar dari peta bisa preloading subset ubin yang lebih besar ke dalam array javascript dan menggunakannya sebagai cache.

Ya tentu saja. Tidak banyak yang bisa ditambahkan di sini - klien meminta ubin dari server, jadi Anda hanya perlu memastikan bahwa yang Anda minta mencakup area yang lebih besar dari layar.

Tambahan:

kami menjalankan Yii Framework di PHP dan semuanya terhubung ke generator peta dan mesin gim Python acak.

Jika Anda kompeten dengan Python maka saya akan menyarankan Anda membuang perantara PHP. Jika Anda menjalankan game sebagai proses Python maka Anda dapat menyimpan data ubin dalam memori jauh lebih mudah dan mengurangi akses MySQL secara signifikan. Ini membantu bahwa Python adalah bahasa yang jauh lebih waras daripada PHP juga.

Kylotan
sumber