“레벨 문자열”을위한 최고의 솔루션?


10

레벨 시작시 무작위 레벨 맵을 생성하는 게임이 있습니다. 레벨을 저장하고로드하는 방법을 구현하고 싶습니다.

XML이 모든 변수를 저장하는 데 좋은 옵션 일 것이라고 생각했습니다. 그런 다음 XML을 구문 분석하고 동일한 수준을 생성 할 수있는 것을 쉽게 만들 수 있습니다.

그러나 XML은 아마도 내 요구에 과잉 일 것입니다. 나는 구 세가 콘솔을 사용하여 게임을 저장할 수 없었던 (웜스 게임도 그렇게 생각합니다.) 나중에 해당 줄에 구멍을 뚫 으면 정확한 레벨이로드됩니다.

"레벨 문자열"이 좋은 옵션입니까? 일종의 "base60"변환입니까? 나는 이것을 어떻게 구현할 것인가?

답변:


20

아마도 당신이 저장해야 할 모든 것은 무작위 시드이며, 일반적으로 int입니다. int를 좀 더 불투명하게 만들고 싶다면 int를 base64로 인코딩 할 수는 있지만 아마도 필요하지는 않습니다.


실제 단어에서 시드를 생성 할 수도 있고 (아마도 시드를 얻기 위해 문자를 추가하는 방법으로 구매) 더 의미있는 것을 반환 할 수 있습니다. 게임에 단어를 저장하거나 검색해야합니다.
Jonathan Fischoff

괜찮습니다. 그러나 게임을하고 있다면 동적 데이터를 저장해야합니다. 문자열은 문자 위치 / 점수 등을 저장해야합니다.이 문자열을 생성하는 가장 좋은 방법은 무엇입니까?
Adam Harte

아마도 JSON (또는 원하는 경우 XML)을 사용하여 세계 상태를 직렬화 한 다음 해당 문자열을 base64로 인코딩합니다. 그래도 유용한 점이 확실하지 않은 이유는 무엇입니까? GUI 전용 저장 /로드 시스템을 만드는 것이 어떻습니까? 나는 이것이 웹 기반이라고 가정 하고이 서버 측을 처리하고 싶지 않습니다. 아마도 shygypsy.com/farm/p.cgi 를 보시겠습니까?
coderanger

23

저장 게임에 사용하는 형식에 관계없이 버전 번호를 입력하십시오. 버전 번호를 분기하여 역 호환 가능한로드를 가지거나 너무 오래된 저장을 안전하게 인식 할 수 있습니다. 로드합니다.

당신이하지 않으면 후회합니다.


7
+1은 실제로 질문에 대답하지 않지만 매우 중요합니다.
Jonathan Fischoff

10

JSON은 좋지만 YAML이 좋습니다. :) http://www.yaml.org/http://code.google.com/p/yaml-cpp/ 는 사용하기 편리한 구현 중 하나입니다.

YAML은 다음과 같은 몇 가지 유용한 기능에 대한 지원을 추가하는 JSON의 상위 집합입니다.

  • 이진 노드. 레벨 설명을 위해 처리 할 데이터 종류를 직렬화하는 데 유용합니다. JSON을 사용하려면 구문 분석 후 / 작성하기 전에 Base64와 같은 일부 중간 형식으로 변환해야합니다. YAML에는 파서 라이브러리에 지시하는 !! 바이너리 노드 유형이 있습니다.
  • 문서 내 참조. 동일한 객체가 문서에 두 번 나타나면 JSON은 두 번 쓰고 다시 읽을 때 사본 두 개를 얻게됩니다. 많은 YAML 이미 터는이 상황을 감지 할 수 있으며로드 할 때 감지 될 수있을 때 두 번째 사본 대신 첫 번째 사본에 대한 참조를 출력합니다.
  • 사용자 정의 노드 유형. 예를 들어 !! Player, !! Enemy 등으로 목록에서 각 맵에 플래그를 지정할 수 있으므로 유형 정보를 대역 외로 유지하십시오.
  • YAML은 더 읽기 쉬운 형식을 지원합니다.
  • JSON은 YAML의 하위 집합이므로 대부분의 YAML 독자는 JSON 문서를 읽는 데 어려움이 없습니다.

1
Yaml은 매우 시원하며 일부 슈퍼 세트 기능을 피하면 어려움없이 json으로 변환 할 수 있습니다.
Jethro Larson

3

게임의 모든 데이터를 직렬화하려면 JSON을 파일 형식으로 사용하는 것이 좋습니다. XML을 사용하는 것이 더 쉬우 며 여러 언어에서 지원이 매우 좋습니다.

이 라이브러리를 C ++에 사용했으며 매우 잘 작동합니다.

http://jsoncpp.sourceforge.net/


3

크기에 제한을받지 않고 기본적으로 지원되는 경우 (예 : .NET 및 Flash) XML을 선택하는 것이 좋지만 슬림 한 형식을 원하는 경우 고유 한 형식을 만들고 파서를 매우 쉽게 만들 수 있습니다. 나는 보통 1 문자를 사용합니다. 각 객체를 분리하려면 쉼표를 사용하십시오. 문자열을 디코딩하려면 쉼표로 분할하십시오. 이제 각 객체에는 서로 다른 속성이 필요하므로 이러한 속성을 세미콜론과 같은 다른 문자로 구분하고 다른 문자를 사용하여 속성 이름과 속성 이름을 구분하십시오. 콜론. 따라서 string.split을 사용하여 정규식없이 쉽게 디코딩 할 수 있습니다. 예를 들면 다음과 같습니다.

id:1;x:5;y:45.2;angle:45,id:28;x:56;y:89;angle:12;health:78

속성 이름을 1 자 이하로 유지하면 더 많은 공간을 절약 할 수 있습니다 (예 : 건강을 위해 h). 예 :

i:1;x:5;y:45.2;a:45,i:28;x:56;y:89;a:12;h:78

JSON 대안과 비교하십시오.

{"o":[{"i":1, "x":5, "y":45.2, "a":45}, {"i":28, "x":56, "y":89, "a":12, "h":78}]}

또한 숫자의 크기를 줄이려면 인쇄 가능한 전체 UTF16 문자 세트를 사용하여 숫자를 인코딩 할 수 있습니다. 이 스레드 는 하나의 화면 문자에 얼마나 많은 데이터를 넣을 수 있는지에 대한 질문을 스택 오버플로에 대해 묻게 했습니다 . 점자, 간지 및 체스 조각이 마음에 들지 않으면 정수에 대한 값이 40,000 개가 넘는 것 같습니다. ♔♕♖♗♘♙♚♛♜♝♞♟

크기를 더 줄이려면 읽기 / 쓰기 순서를 사용하여 어떤 값이 어느 값인지 결정하면 처음 두 문자는 id를 나타내고 다음 두 문자는 x 위치, 다음 두 문자는 y 위치, 각도, 건강 상태를 나타냅니다. 등 :

F5DGP@%&002DFTK#OP1F

다른 예제와 동일한 정보를 모두 저장할 수 있습니다.

타일 ​​그리드는 각 문자가 다른 유형의 타일을 나타내는 문자열로 저장 될 수 있습니다. 예 :

i789pog5h3kl

내가 용암을 의미하는 곳, 9는 잔디 등을 의미하는 곳


이것은 내가 요구하는 것의 선을 따라 더 있습니다. 내 질문에 XML을 언급했지만 여전히 사람들이 제안합니다!
Adam Harte

1
그 주위에 {}을 추가하면 기본적으로 JSON이 있습니다 ;-)
coderanger

따옴표도 추가해야합니다. 아마도 두 배의 문자 일지 모르지만 객체가 중첩 될 것입니다.
Iain

1

.Net으로 코딩하는 경우 XML을 사용하는 것이 매우 쉽습니다. 레벨 클래스를 몇 줄만으로 XML로 / 직렬화 / 직렬화 할 수 있으며 잘 관리 된 클래스에서 모두 클래스화할 수 있습니다.

지도는 모든 데이터가로드 된지도 유형의 변수입니다.

Dim TheMap As New Map

Map 클래스가 이미 구축되어 있다고 가정하면 맵이 XML로 저장됩니다.

Dim Serializer As New System.Xml.Serialization.XmlSerializer(GetType(TheMap))
Dim Strm As New FileStream("c:\Map.xml", FileMode.Create, FileAccess.Write, FileShare.None)
Serializer.Serialize(Strm, TheMap)
Strm.Close()

그러면 코드에서 다시 사용되도록 해당 XML을 맵 클래스로 다시로드합니다.

Dim Reader As New StreamReader("map.xml")
Dim Serializer As New System.Xml.Serialization.XmlSerializer(GetType(TheMap))

TheMap = Serializer.Deserialize(Reader)
Reader.Close()

이제 XML 파일이 클래스에로드되어 쉽게 사용할 수 있습니다.

"레벨 문자열"문제와 관련하여 이전에 언급 한 내용이 훌륭하게 작동하면 시드 번호를 "레벨 문자열"로 사용할 수 있습니다.

그렇지 않으면 원하는 많은 다른 맵을 미리 생성하여 모두 "Level String"으로 저장 한 다음이를 사용하여 적절한 맵을 가져올 수 있습니다.


XML이 싫더라도 +1-언어가 기본 직렬화 형식을 제공하는 경우, 특히 다른 도구가 이론적으로 구문 분석 할 수있는 형식 인 경우 (XML / JSON / YAML과 같은) 가장 먼저 고려하는 것이 가장 좋습니다.

0

struct언어에 따라 간단 하거나 유사한 장치를 사용하여 모든 게임 상태를 중앙에 저장합니다. setter / getter를 보호하려면 구조체를 a에 래핑 할 수 있습니다 class.

당신이 그것을 느끼면 비트 필드를 사용 하거나 비트 연산자를 사용하여 직접 비트 조작을하십시오.

일부 언어에서는 구조체 패딩과 패킹에 대한 규칙 이 약간 복잡 할 수 있지만, 1 ~ 2 바이트의 패딩이있는 경우에는 그다지 중요하지 않을 수 있습니다.

패딩을 제거 하여 #pragma(와 같은 #pragma pack(1)) 또는 을 사용 __attribute__하여 구조체를 밀착 시킬 수도 있습니다 . 컴파일러와 대상 아키텍처에 따라 작동하거나 작동하지 않을 수 있습니다.

비트 필드 및 팩 pragma 또는 속성을 사용하면 이식성이 떨어질 수 있습니다. 하드웨어 아키텍처에서 구조체 필드 엔디안 (바이트 순서)도 변경 될 수 있습니다. 따라서 이식성을 시도하는 경우 이것을 피할 수 있습니다.

(예를 들어 Pac-Man의 경우이 구조체에는 맵 ID 또는 맵 시드, Pac-Man x 및 y 위치, 4 개의 유령 x 및 y 위치, 32-64 개의 펠릿 유무에 대한 큰 비트 필드가 포함되어있을 수 있습니다. 최대 값에 관계없이)

구조체가 있으면 xxencode 함수 와 같은 것으로 전달하십시오 .

encode_save( char * outStringBuf, size_t outStringBufSize,
             const SaveStruct * inSaveData, size_t inSaveDataSize )

이 함수를 작성하는 것은 약간 오류가 발생하기 쉽습니다. 예를 들어 한 번에 6 비트를 얻기 위해 필요한만큼 바이트를 이동 및 결합한 다음 적절한 문자로 변환해야합니다. "재미"를 위해 이것을하지 않는 한 개인적으로 다른 사람의 코드를 찾으려고 노력할 것입니다 (그리고 아마도 테스트 스위트를 원할 것입니다).

struct올바른 장소에서 구식 학교의 힘을 과소 평가하지 마십시오 . 우리는 여기에서 GBA 및 DS 게임에 톤을 사용했습니다.


원시 구조 직렬화는 이식이 불가능하고 매우 취약한 wrt 새 코드입니다. 리소스가 매우 제한된 플랫폼의 데이터를 굽는 마지막 단계가 아니라면 매우 조기에 최적화됩니다. 6 비트에서 8 비트를 선호하는 이유가 있습니까? 형식은 어쨌든 사람이 읽을 수는 없으며 실제 구조 레이아웃의 속도와 디버깅 가능성을 활용할 수도 있습니다.

@Joe : 이식성이없고 잠재적 인 문제가 있다고 언급했습니다. 이 질문은 구 세가 게임과 같이 사람이 읽을 수있는 "레벨 문자열"을 구체적으로 요구했으며 base60 변환을 언급했습니다. xxencode와 같은 것을 통해 구조체를 전달하면이 작업을 수행합니다. 비트 맵이 아닌 간단한 구조체는 데이터 저장을 저장하는 훌륭한 "중앙"방법이며 데이터와 상호 작용 하는 많은 코드를 단순화 할 수 있습니다 . 비회원 비 친구 구조 및 "내부"프로그래밍에 관한 Noel Llopis의 최근 기사를 참조하십시오. 이것은 단지 KISS입니다.
leander

1
나는이 방법에 전적으로 동의한다. 그렇습니다. 버전이나 시스템간에 이식 가능하지는 않지만 다시 게임 저장은 개발 중에 재사용하거나 플랫폼간에 복사해야하는 리소스가 아닙니다. 디버깅 가능성은 적절한 읽기 / 쓰기 문제가 아니며 한 번 구현하면 영원히 작동합니다. 확장 성이 실제로 문제가되는 경우 첫 번째 ybyte / word로 버전 번호를 추가하면 데이터 취약점이 생길 수 있지만이를 전환 할 수 있습니다. XML이 버전 관리 문제를 해결하는 것은 아닙니다. 단순히 값을 설정하는 것보다 더 복잡합니다. 예, 실용적입니다.
Kaj

0

XML은 임의로 구조화 된 문서 (요소가 다른 레벨의 트리에 나타날 수 있음) 또는 외부 형식 임베딩 (예 : xhtml 페이지에 svg 삽입)에 좋습니다. 이러한 요구 사항이 없으면 실제로 비효율적 인 형식이며 csv 또는 json과 같은 더 간단한 것이 좋습니다.

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