"Seviye dizesi" için en iyi çözüm?


10

Seviyenin başında rastgele seviye haritası üreten bir oyunum var. Seviyeyi kaydetmek ve yüklemek için bir yol uygulamak istiyorum.

Belki XML tüm değişkeni kaydetmek için iyi bir seçenek olacağını düşünüyordum, o zaman bu XML ayrıştırabilir ve tam olarak aynı seviyeyi oluşturmak bir şey inşa etmek benim için kolay olurdu.

Ama XML muhtemelen benim ihtiyaçlarım için abartılı. Gününüzü, oyununuzu kaydetme yeteneğine sahip olmayan eski Sega konsolu ile hatırlıyorum (Sanırım Worms oyunu da yaptı), size yazabileceğiniz bir grup karakter vereceklerdi. Eğer daha sonra bu dizeyi delerseniz, tam seviyeyi yükler.

"Seviye dizesi" iyi bir seçenek olabilir mi? Bir çeşit "base60" dönüşümü olur mu? Bunu nasıl uygularım?

Yanıtlar:


20

Muhtemelen kaydetmeniz gereken tek şey, genellikle sadece bir int olan rastgele tohumdur. Eğer biraz daha opak yapmak istiyorsanız int'i base64'e kodlayabilirsiniz, ancak bu muhtemelen gerekli değildir.


Tohumu gerçek bir kelimeden de üretebilirsiniz (belki de tohumunuzu almak için karakterleri toplayarak satın alın) ve bu şekilde daha anlamlı bir şey döndürün. Kelimeleri oyununuzda saklamanız veya geri almanız gerekir.
Jonathan Fischoff

Bu iyi, ama oyun oynanıyorsa dinamik verileri de saklamak zorunda kalacak. Dize, karakter konumlarını / puan vb kaydetmek gerekir. Peki bu dize oluşturmak için en iyi yolu nedir?
Adam Harte

Muhtemelen dünya devleti serileştirmek ve daha sonra bu dize base64-kodlamak için JSON (veya isterseniz XML) kullanabilirsiniz. Tüm bu yararlı olsa emin değilim, neden sadece daha GUI odaklı bir kaydetme / yükleme sistemi yapmak değil? Bunun web tabanlı olduğunu ve bu sunucu tarafını işlemek istemediğinizi varsayalım. Belki bir örnek için shygypsy.com/farm/p.cgi adresine bakın.
coderanger

23

Kaydetme oyunlarınız için hangi biçimi kullanırsanız kullanın, iyilik için bir sürüm numarası girin. Sürüm numarasını dallayarak geriye doğru uyumlu yüklere sahip olabilirsiniz veya çok eski olan tasarrufları güvenli bir şekilde tanıyabilirsiniz yüklemek için.

Yapmazsan pişman olursun.


7
+1 soruyu gerçekten cevaplamıyor ama çok önemli.
Jonathan Fischoff

10

JSON iyi, ama YAML daha iyi. :) http://www.yaml.org/ ve http://code.google.com/p/yaml-cpp/ daha güzel kullanımlı uygulamalardan biri için.

YAML, birkaç güzel özellik için destek ekleyen bir JSON süper setidir, özellikle:

  • İkili düğümler. Bu, düzey açıklamaları için uğraşabileceğiniz veri türlerini serileştirmek için mükemmeldir. JSON, ayrıştırmadan önce / ayrıştırmadan önce seçtiğiniz Base64 gibi bazı ara biçimlere çevirmenizi gerektirir. YAML, ayrıştırıcı kitaplığına sizin için yapmasını söyleyen bir !! ikili düğüm tipine sahiptir.
  • Belge içi referanslar. Aynı nesne belgede iki kez görünürse, JSON iki kez yazar ve tekrar okuduğunuzda iki kopya alırsınız. Birçok YAML yayıcı bu durumu algılayabilir ve ikinci bir kopya yerine, yükleme sırasında ne zaman tespit edilebileceğine ilk kopyaya bir referans gönderir.
  • Özel düğüm türleri. Listedeki her haritayı örneğin !! Oyuncu, !! Düşman vb. İle işaretleyebilir ve bu nedenle tür bilgilerinizi bant dışında tutabilirsiniz.
  • YAML daha okunabilir biçimlendirmeyi destekler.
  • JSON bir YAML alt kümesi olduğundan, çoğu YAML okuyucusu JSON belgelerini okumakta sorun yaşamaz.

1
Yaml çok güzel ve süper set özelliklerinden bazılarından kaçınırsanız, hiç zorluk çekmeden json'a dönüştürülebilir.
Jethro Larson

3

Oyundaki tüm verileri serileştirmek istiyorsanız, dosya biçiminiz olarak JSON'u öneriyorum, bu yüzden XML'i kullanmak daha kolay ve destek birçok dilde çok iyi.

Bu kitaplığı C ++ için kullandım ve çok iyi çalışıyor.

http://jsoncpp.sourceforge.net/


3

XML, boyutla sınırlı değilseniz ve yerel olarak destekleniyorsa (örn. .NET ve Flash'ta) iyi bir seçimdir, ancak ince bir biçim istiyorsanız, kendi biçiminizi ve ayrıştırıcıyı kolayca oluşturabilirsiniz. Normalde 1 karakter kullanıyorum. her nesneyi ayırmak için virgül kullanın. Dizginin kodunu çözmek için virgül üzerinde bir bölünme yapın. Şimdi her nesnenin farklı özelliklere ihtiyacı vardır, bu yüzden bunları farklı bir karakterle, örneğin yarı kolonla ayırın ve özellik adlarını özellik değerlerinden ayırmak için başka bir karakter kullanın, örn. Kolon. Bu nedenle, sadece string.split kullanılarak regex olmadan kolayca kod çözülebilir. İşte bir örnek:

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

özellik adlarını 1 karaktere kadar koruyarak daha fazla yerden tasarruf edebilirsiniz, örneğin sağlık için h. Örneğin.

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

JSON alternatifiyle karşılaştırın:

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

Ayrıca, sayılarınızın boyutunu küçültmek istiyorsanız, yazdırılabilir UTF16 karakterlerinin tamamını kullanarak bunları kodlayabilirsiniz. Bu iş parçacığı , bir ekran karakterine ne kadar veri toplayabileceğiniz konusunda Stack Overflow hakkında bir soru sormam için bana ilham verdi . Eğer brail, Kanji ve satranç taşlarına sahip olmak sakıncası yoksa cevap tamsayı için 40.000'in üzerinde bir değer gibi görünüyor: ♔♕♖♗♘♙♚♛♔♕♖♗♘♙♚

Daha fazla boyut küçültmek için, hangi değerin hangisi olduğunu belirlemek için okuma / yazma sırasını kullanabilirsiniz, bu nedenle ilk iki karakter kimliği temsil eder, sonraki iki x konumu, sonraki iki y, sonra açı, sonra sağlık Yani:

F5DGP@%&002DFTK#OP1F

diğer örneklerle aynı bilgileri saklayabilir.

Döşeme ızgaraları, her karakter farklı türde bir döşemeyi temsil eden yalnızca bir dize olarak saklanabilir, örneğin:

i789pog5h3kl

lav, 9 çim vb.


Bu daha çok sorduğum şeyler boyunca. Sorumda XML'den bahsediyorum, ama yine de insanlar bunu öneriyor!
Adam Harte

1
Bunun etrafına {} ekleyin ve temelde JSON ;-)
coderanger

Bir sürü alıntı işareti eklemeniz gerekir. Muhtemelen karakter sayısını iki katına çıkarır, ancak nesnelerin iç içe geçmesini sağlarsınız.
Iain

1

Net kodlama yapıyorsanız, XML'i sadece birkaç satırla XML'e / dışına serileştirebilir / serileştirebilir ve daha sonra hepsi güzel yönetilen bir sınıfta XML ile gitmek çok kolaydır.

Harita, tüm verilerinizi yüklediğiniz Map türünde bir değişken olacaktır.

Dim TheMap As New Map

Önceden oluşturulmuş bir Map sınıfınız varsa, haritanızı XML'e kaydeder:

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()

Bu, daha sonra kodda kullanılmak üzere bu XML'yi harita sınıfınıza geri yükler.

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

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

Artık XML dosyanızdaki kolay kullanım için sınıfınıza yüklenir.

"Level String" sorununuza gelince, daha önce belirtilenler harika olurdu, Seed numarasını "Level String" olarak kullanabilirsiniz.

Aksi takdirde, istediğiniz birçok farklı haritayı önceden oluşturabilir ve hepsinin bir "Seviye Dizesi" ile kaydedilmesini sağlayabilir ve ardından bunu uygun haritayı çekmek için kullanabilirsiniz.


XML'den nefret etmeme rağmen +1 - Dil varsayılan bir serileştirme biçimi sağlıyorsa, özellikle diğer araçların teorik olarak ayrıştırabileceği (XML / JSON / YAML gibi) bir biçim olduğunu düşünmek en iyisidir.

0

structTüm oyun durumunu merkezi bir yerde saklamak için basit veya benzer bir cihaz (dilinize bağlı olarak) kullanırdım. Ayarlayıcıların / alıcıların korunmasını istiyorsanız, yapıyı a class.

Eğer bunu hissediyorsanız, bit alanlarını kullanın veya bitsel operatörleri kullanarak kendiniz biraz manipülasyon yapın.

Bazı dillerde, yapı dolgusu ve paketleme kurallarının biraz karmaşık olabileceğini unutmayın - ancak bir veya iki baytınız varsa davanız için çok önemli olmayabilir.

Ayrıca , yapıyı yakından paketlemek için #pragma(örneğin #pragma pack(1)) veya __attribute__a'yı kullanarak dolguyu ortadan kaldırabilirsiniz. Bu, derleyicinize ve hedef mimarinize bağlı olarak çalışabilir veya çalışmayabilir.

Bit alanlarının ve paket uygulamalarının veya niteliklerinin kullanımının taşınabilirliği azaltabileceğini unutmayın. Donanım mimarileri arasında, yapı alanı endianitesi (bayt sırası) da değişebilir. Dolayısıyla, taşınabilirliği deniyorsanız, bundan kaçınmak isteyebilirsiniz.

(Örneğin Pac-Man için, bu yapı saf olarak bir harita kimliği veya harita tohumu, bir Pac-Man x ve y pozisyonu, dört hayalet x ve y pozisyonu ve 32-64 peletin varlığı veya yokluğu için büyük bir bit alanı içerebilir, maksimum ne olursa olsun.)

Yapınızı aldıktan sonra, bir xxencode işlevi gibi bir şeye iletin :

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

Bu işlevi yazmak biraz hataya açıktır; örneğin bir kerede 6 bit elde etmek için baytları kaydırmanız ve birleştirmeniz ve ardından uygun bir karaktere çevirmeniz gerekir. Şahsen ben bunu "eğlence" için yapıyordu sürece başkasının kodunu avlamak için çalışacağız (ve muhtemelen bunun için bir test paketi istiyorum).

Eski okulun gücünü asla structdoğru yerlerde hafife almayın . Burada GBA ve DS oyunları için bir ton kullandık.


Ham yapı serileştirmesi yeni kod değil, taşınabilir ve son derece kırılgan. Çok sınırlı kaynaklara sahip bir platform için veri pişirme işleminin son adımı olmadığı sürece, çok erken optimizasyon. 6 bit ila 8'i tercih etmenizin bir nedeni var mı? Biçim zaten insan tarafından okunamayacak, gerçek bir yapı düzeninin hızından ve hata ayıklama özelliklerinden de yararlanabilirsiniz.

@Joe: Taşınabilir olmadığını ve bazı potansiyel endişelerden bahsetmiştim. Soru özellikle eski Sega oyunları ve bahsi geçen base60 dönüşümü gibi insan tarafından okunabilen bir "seviye dizesi" istedi; xxencode gibi bir yapıdan bir yapı geçirmek bunu yapar. Bu mutlaka bir erken optimizasyon değildir: bit paketli olmayan basit bir yapı, veri kaydetmenin saklanması için güzel bir "merkezi" yoldur ve verilerle etkileşen kodun çoğunu basitleştirebilir . Bkz. Örneğin Noel Llopis'in üye olmayan arkadaş olmayan yapılar ve "tersyüz" programlaması hakkındaki son makaleleri. Bu sadece KISS.
leander

1
Bu şekilde tamamen katılıyorum. Evet, sürümler veya sistemler arasında taşınabilir değildir, ancak yine de kaydetme oyunları, geliştirme sırasında yeniden kullanılması veya platformlar arasında kopyalanması gereken kaynaklar değildir. Hata ayıklama, yerinde okuma / yazma ile ilgili bir sorun değildir, bir kez uygular ve sonsuza dek çalışır. Genişletilebilirlik gerçekten bir sorunsa - ilk ybayt / kelime olarak bir sürüm numarası ekleyin ve bunu açabilirsiniz (ancak bu bir veri güvenlik açığı oluşturur). Bu, xml'nin sürüm oluşturma sorunlarını çözeceği gibi değil - sadece bir değer ayarlamaktan daha fazla katılım eğilimi. Evet, pragmatikim.
Kaj

0

XML, keyfi yapılandırılmış belgeler (öğeler ağacın farklı düzeylerinde görünebilir) veya yabancı biçim yerleştirme (svg'yi bir xhtml sayfasına koymak gibi) için iyidir. Bu gereksinimlere sahip değilseniz, bu gerçekten verimsiz bir biçimdir ve csv veya json gibi daha basit bir şey tercih edilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.