웹에 타일 맵을 효율적으로 저장하고 표시하는 방법은 무엇입니까?


9

이것들은 실제로 하나의 두 가지 질문입니다. 우선 많은 양의 타일 데이터를 효율적으로 저장하는 방법을 찾고 있습니다. 다른 양상은 데이터 세트를 질의하고 타일을 디스플레이하는 것을 다룬다. 먼저 배경을 알려 드리겠습니다.

우리는 CraftyJS 라이브러리를 사용하여 브라우저 기반 멀티 플레이어 타이쿤 게임을 Canvas로 렌더링하고 있습니다. GUI의 배경에서 우리는 PHP에서 Yii Framework를 실행하고 있으며 모두 Python 랜덤 맵 생성기 및 게임 엔진에 연결됩니다.

첫 번째 대략적인 맵 렌더링 모양입니다. http://i.imgur.com/khAXtl.png

지도 데이터 저장

게임 세계는 게임이 시작될 때마다 무작위로 생성됩니다. 크기는 각 플레이어마다 100x100 육각형 타일입니다. 즉, 3 인 게임에는 90.000 개의 타일이 만들어집니다. 현재는지도를 렌더링하는 JavaScript 배열을 만듭니다.

렌더링에는 효과가 있지만 맵과의 모든 상호 작용을 위해 타일을 소유 한 플레이어, 타일 위에 어떤 종류의 구조, 현재 가격 등을 저장해야합니다. 처음에는 최소한 프로토 타입을 위해 MySQL을 사용하고 싶었지만 테스트를 마친 후에는 원하는 속도만큼 빠르지 않았습니다. 아마도 MongoDB와 같은 객체 저장소가 SQL 테이블 대신 타일 데이터를 저장하는 데 더 적합 할 것입니다. 아니면 다른 것?

지도 표시

내가 본 또 다른 문제는지도를 움직이는 것입니다. 현재 뷰포트에 있지 않더라도 각 타일에 Crafty 엔티티를 만들고 있습니다. Crafty는 뷰포트에있는 것만 렌더링하지만 각 렌더링 이벤트의 모든 타일을 저장하고 반복 할 수 있기 때문에 속도가 느립니다. 내가 현재 가지고있는 것은 그려진 속도가 느린 느린 맵으로, 움직일 때 매우 느리게 움직이며, 이제는 재생 가능하게 만들고 싶습니다.

첫 번째 아이디어는 뷰포트에있는 타일의 표시된 서브 세트를로드하는 것입니다. 그러나 플레이어가 뷰포트를 빈 공간으로 옮길 때 서버를 쿼리하고 응답을 다시 기다려야 만 맵을 렌더링 할 수 있습니다. 기본 응용 프로그램에서는 문제가 없지만 웹 게임에서는 게으르다.

맵에서 원활한 성능을 얻는 방법은 더 큰 타일의 하위 집합을 자바 스크립트 배열로 미리로드하여 캐시로 사용할 수 있습니다. 플레이어는 몇 개의 화면을 "캐시"하고 뷰포트를 이동할 때 더 많은 타일을 JS "캐시"에로드합니다.

올바른 방향으로 가고 있습니까? 비슷한 일을 한 사람에게서 더 많은 정보를 얻고 싶습니다. 저는 게임 개발에 익숙하지 않지만 지난 몇 주 동안 많은 출처를 살펴 보았습니다.


1
MySQL을 병목 현상으로 식별 한 것에 놀랐습니다. 속도가 느려지고 있다는 결론에 도달하기 위해 무엇을 테스트 했습니까?
bummzack

@bummzack 타일 당 행이 있으면 속도가 느려질 수있는 방법을 거의 볼 수 없습니다.
aaaaaaaaaaaa

1
@eBusiness DB에서 수천 행을 쿼리하는 것은 실제로 문제가되지 않습니다. 여전히 몇 밀리 초 범위 내에 있어야합니다. 또한 90,000 행이 아니라 3 명의 플레이어 (3 인당 100x100)의 경우 30,000 행이됩니다.
bummzack

혼란스러운 수학에 대해 유감스럽게도, 플레이어 영역 외에도 플레이어 사이에 두 배의 공간이있어 서로 같은 거리를 유지하므로 90k가됩니다. 쿼리는 문제가되지 않습니다. 90k 타일을 선택하고지도를 만드는 것입니다. 그러나 그것을하는 좋은 방법은 아닙니다. 자세한 정보가 요청되면 맵 데이터를 직렬화하고 db의 타일 쿼리를 사용합니다.
요소

답변:


2

게임 플레이
우선, 여러분에게 물어보고 싶은 것은 실제로 플레이어 당 10000 개의 타일이 필요합니까? 어떤 종류의 게임을 만들고 있는지 모르겠지만 일반적으로 큰지도가 긴 게임을 만드는 것은 사실입니다. Civilization 5에서 가장 큰지도는 10240 타일이며, 일부만 플레이 할 필요가 없기 때문에 일종의 작동합니다.

데이터베이스 데이터베이스에서
이와 같은 게임을 실행하지 말고 데이터를 응용 프로그램 메모리에 보관해야합니다. 데이터베이스를 사용하여 게임을 백업 할 수 있습니다. 완전한 백업을 위해서는 게임 데이터의 직렬화를 저장 한 다음 주어진 순서를 저장하여 증가시킨 다음 백업을 사용해야하는 경우 다시 실행할 수 있습니다.

JavaScript 저장
클라이언트에 관해서는, 적어도 멋진 객체 트리에있는 gazillion 타일을 사용하는 경우 약간의지도가 너무 클 수 있으므로 데이터 전체를로드해야합니다. "반 이진"인코딩 형식입니다. 문자열은 이런 종류의 물건에 탁월하게 작동합니다. 또는 64 비트 플로트에 최대 53 비트의 부호없는 정수를 안전하게 저장할 수 있습니다. 배열에 많은 것들을 저장하면 메모리가 거의 적당하지 않습니다.

JavaScript 시각화
필자가 반드시 캔버스를 사용해서는 안된다고 말하지는 않지만 실제로 이와 같은 작업에는 필요하지 않습니다. 모든 요소를 ​​img 요소로 설정하고 src 속성을 변경하여 맵의 다른 부분을 표시하십시오.

전문가 팁
그런데 때때로지도 전체를 공유하는 것보다 씨앗을 생성하는 데 사용되는 시드를 공유하는 것이 더 쉬운 경우가 있습니다.


+1이지만 슬프게도 PHP로 작성된 웹앱은 일반적으로 게임 상태를 메모리에 유지하는 수단이 없습니다.
bummzack

@bummzack, Ahh, 맞습니다. PHP라는 단어를 건너 뛰고 파이썬을 읽은 것 같습니다. 그러면 백엔드 프레임 워크가 변경 될 수 있습니다. Node.js는 옵션 일 수 있습니다.
aaaaaaaaaaaa

경쟁적인 교통 거물을 만들고 있습니다. OpenTTD는 512x512 (262k) 크기의지도가 몇 명의 플레이어에게는 그렇게 크지 않다고 생각합니다. 나는 그것이 야심적이라는 것을 알고 있지만,지도가 그렇게 크지 않으면 게임이 너무 빨리 끝날 것입니다. 멀티 플레이 게임이기 때문에 변경 사항을 플레이어간에 동기화해야합니다. 첫 번째 본능은 웹 개발에서 아는 개념을 사용하고 데이터베이스를 사용하는 것입니다. 슈퍼 실시간 일 필요는 없습니다. JS 시각화를 사용하려고합니다.지도에 동적 요소가 있기 때문입니다.
요소

내 대답을 조언으로 삼으십시오. 결국 성능을 직접 해결해야하며 심각한 문제이며 일부 타협해야 할 수도 있습니다.
aaaaaaaaaaaa

나는 당신의 대답이 나에게 많은 생각을 주었다는 것에 동의합니다. 직렬화 된 맵 데이터를 메모리에 유지하고 데이터베이스를 백업으로 유지하는 방법을 찾으려고 노력합니다. 그런 다음 플레이어간에 변경 사항을 공유하는 방법을 찾아야합니다. 몇 가지 추가 테스트를 수행 한 후 다시 생각해 보겠습니다.
요소

1

MySQL은 느리지 않습니다. 순진한 쿼리를 수행하거나 최적이 아닌 인덱스를 가지고있을 가능성이 큽니다. MongoDB와 같은 NoSQL 접근 방식은 더 빠를 수도 있습니다. 액세스 패턴과 쿼리 선택이 여기서 가장 중요합니다. 성능을 향상시키는 방법에 대한 조언을 줄 수는 있지만 이미하고있는 일을 보지 않고서는 안됩니다.

맵에서 원활한 성능을 얻는 방법은 더 큰 타일의 하위 집합을 자바 스크립트 배열로 미리로드하여 캐시로 사용할 수 있습니다.

물론입니다. 여기에 추가 할 것이 많지 않습니다. 클라이언트는 서버에서 타일을 요청하므로 요청한 타일이 화면보다 큰 영역을 커버하도록해야합니다.

추가:

우리는 PHP에서 Yii Framework를 실행하고 있으며 모두 파이썬 랜덤 맵 생성기 및 게임 엔진에 연결됩니다.

파이썬과 유능한 사람이라면 PHP 중개인을 버리는 것이 좋습니다. 게임을 Python 프로세스로 실행하면 타일 데이터를 훨씬 쉽게 메모리에 유지하고 MySQL 액세스를 크게 줄일 수 있습니다. 그것은 파이썬이 PHP보다 훨씬 더 깨끗한 언어라는 것을 돕는다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.