O
To właściwie dwa pytania w jednym. Przede wszystkim szukam sposobu na wydajne przechowywanie dużych ilości danych kafelkowych. Drugi aspekt dotyczy odpytywania zestawu danych i wyświetlania kafelków. Pozwól, że najpierw dam ci trochę tła.
Tworzymy wieloosobową grę opartą na przeglądarce, używając biblioteki CraftyJS do renderowania na kanwie. W tle GUI uruchamiamy Yii Framework na PHP i wszystko to łączy się z generatorem losowych map Python i silnikiem gry.
Tak wygląda pierwsze renderowanie przybliżonej mapy: http://i.imgur.com/khAXtl.png
Przechowywanie danych mapy
Świat gry jest generowany losowo przy każdym uruchomieniu gry. Rozmiar to 100 x 100 sześciokątnych płytek dla każdego gracza. Oznacza to, że w grze trzyosobowej utworzono 90 000 płytek. Obecnie po prostu tworzę tablicę JavaScript, z której renderuję mapę.
Działa to dobrze w przypadku renderowania, ale dla każdego rodzaju interakcji z mapą musimy zapamiętać, który gracz jest właścicielem kafelka, jaka struktura jest na nim zbudowana, jaka jest jego aktualna cena i tak dalej. Początkowo, przynajmniej w przypadku prototypu, chcieliśmy używać MySQL, ale po kilku testach nie jest on tak szybki, jak bym chciał. Być może magazyn obiektów, taki jak MongoDB, lepiej nadaje się do przechowywania danych kafelków zamiast tabeli SQL. A może coś innego?
Wyświetlanie mapy
Innym problemem, który widzę, jest poruszanie się po mapie. Obecnie tworzę Podstępne byty dla każdego kafelka, nawet jeśli nie ma go w okienku ekranu. Jest to powolne, ponieważ chociaż Podstępny renderuje tylko te w okienku ekranu, przechowuje i ewentualnie iteruje wszystkie kafelki każdego zdarzenia renderowania. To, co aktualnie mam, to narysowana mapa, która bardzo wolno się ładuje i zacina się podczas poruszania, teraz chciałbym, aby można ją było odtwarzać.
Moim pierwszym pomysłem było załadowanie wyświetlanego podzbioru kafelków znajdujących się w rzutni. Ale gdy gracz przesunął obszar wyświetlania do pustego obszaru, musiałbym przesłać zapytanie do serwera i poczekać na odpowiedź, tylko wtedy mapa może zostać zrenderowana. Byłoby dobrze w natywnej aplikacji, ale jest opóźniona w grze internetowej.
Sposobem na uzyskanie płynnej wydajności z mapy może być wstępne załadowanie większego zestawu płytek do tablicy javascript i użycie go jako pamięci podręcznej. Gracz miałby kilka ekranów „buforowanych”, a kiedy poruszałby się rzutnią, ładowałbym więcej kafelków do „bufora” JS.
Czy zmierzam w dobrym kierunku? Chciałbym uzyskać więcej informacji od kogoś, kto zrobił coś podobnego. Jestem nowy w tworzeniu gier, ale przeszukiwałem wiele źródeł w ciągu ostatnich kilku tygodni.
źródło
Odpowiedzi:
Rozgrywka
Przede wszystkim chciałbym cię zapytać, czy naprawdę potrzebujesz 10000 płytek na gracza? Chociaż nie wiem, jaką grę tworzysz, ogólnie prawdą jest, że duże mapy tworzą długie gry. Największa mapa w Civilization 5 to 10240 kafelków, a to tylko działa, ponieważ nie musisz grać na więcej niż ułamku.
Baza danych
Nie powinieneś próbować uruchamiać takiej gry z bazy danych, musisz przechowywać dane w pamięci aplikacji. Możesz użyć bazy danych do wykonania kopii zapasowej gry. Aby uzyskać pełną kopię zapasową, należy zapisać serializację danych gry, a następnie można ją zwiększyć, zapisując podane zamówienia, a następnie ponownie je wykonać, jeśli kopia zapasowa musi zostać użyta.
Przechowywanie JavaScript
Jeśli chodzi o klienta, powiedziałbym, że lepiej ładuj całą mapę, przynajmniej jeśli trzymasz się kafelków gazillionów, mając to wszystko w ładnym drzewie obiektów, może to być trochę za dużo, więc prawdopodobnie powinieneś zachować dane w formacie „semi-binarnym”. Ciągi działają doskonale dla tego rodzaju rzeczy, alternatywnie, możesz bezpiecznie przechowywać niepodpisane liczby całkowite do 53 bitów w 64-bitowej liczbie zmiennoprzecinkowej, umieścić wiele z nich w tablicy i myślę, że zobaczysz dość skromny ślad pamięci.
Wizualizacja JavaScript
Chociaż nie powiem, że niekoniecznie powinieneś używać płótna, tak naprawdę nie potrzebujesz go do takich rzeczy. Skonfiguruj to jako grupę elementów img i zmień właściwość src, aby wyświetlać różne części mapy.
Wskazówka Pro
Nawiasem mówiąc, czasem łatwiej jest udostępnić ziarno użyte do jego wygenerowania niż udostępnić całą mapę.
źródło
MySQL nie jest wolny. Najprawdopodobniej wykonujesz zapytania naiwne lub masz nieoptymalne wskaźniki. Podejścia NoSQL, takie jak MongoDB, mogą być szybsze, a może nie. Najważniejszy jest tutaj wzór dostępu i wybór zapytania. Można udzielić porady, jak poprawić wydajność, ale nie bez obejrzenia tego, co już robisz.
Tak oczywiście. Nie ma tu wiele do dodania - klient prosi o kafelki z serwera, więc musisz tylko upewnić się, że te, o które prosisz, obejmują obszar większy niż ekran.
Uzupełnienie:
Jeśli znasz się na Pythonie, radzę porzucić pośrednika PHP. Jeśli uruchomisz grę jako proces w języku Python, możesz znacznie łatwiej przechowywać dane kafelków w pamięci i znacznie ograniczyć dostęp do MySQL. Pomaga to, że Python jest również znacznie zdrowszym językiem niż PHP.
źródło