खेल राज्य बचत / लोड हो रहा है?


12

गेम स्टेट (प्रोफाइल) को बचाने के लिए सबसे अधिक उपयोग की जाने वाली विधि या एल्गोरिथ्म क्या है, डेटाबेस टेक्स्ट फाइलें कैसे एन्क्रिप्शन जाती हैं और संबंधित चीजें।

मैंने देखा है सीज़र IV ने mySQL का उपयोग किया है।

कोई सुझाव।

जवाबों:


20

मुझे पूरा यकीन है कि यह सबसे अधिक बार एक मालिकाना (बाइनरी) प्रारूप में किया जाता है, बस जो भी गेम स्टेट स्ट्रक्चर से आप एक फाइल में उपयोग करते हैं, या उस फाइल को स्ट्रक्चर के एक इंस्टेंस में वापस पढ़ते हैं। C ++ में उदाहरण के लिए आप किसी ऑब्जेक्ट को बाइट्स के एक सरणी की तरह व्यवहार कर सकते हैं और बस फ़ाइल में इसे फिर से लिखना (या फ़ाइल से फ़्रेड) (और) अपने ऑब्जेक्ट फॉर्म में वापस डाल सकते हैं।

यदि आप जावा या किसी अन्य भाषा का उपयोग कर रहे हैं, तो आप कार्य को वास्तव में आसान बनाने के लिए क्रमांकन का उपयोग करने का विकल्प चुन सकते हैं । जावा स्पष्टीकरण इस उत्तर के निचले भाग में है; अन्य भाषाएं (C ++ की तुलना में उच्चतर) के पास निश्चित रूप से अपने स्वयं के क्रमांकन पुस्तकालय या अंतर्निहित कार्य हैं, जिन्हें आपको उपयोग करने का विकल्प चुनना चाहिए। कोई फर्क नहीं पड़ता कि कैसे क्रमिक दिनचर्या नियमित हो सकती है, आजकल हार्ड ड्राइव स्थान सस्ता है, खासकर जब खेल राज्य बहुत बड़ा नहीं होना चाहिए, और यह आपको लिखने और अपनी खुद की क्रमबद्ध दिनचर्या को बनाए रखने से रोकता है ।

आपको MySQL का उपयोग बिल्कुल नहीं करना चाहिए (बस इस समीक्षा का पहला वाक्य पढ़ें )। यदि आपको वास्तव में किसी कारण के लिए रिलेशनल डेटाबेस की आवश्यकता है , तो SQLite का उपयोग करें ; यह एक हल्का डेटाबेस सिस्टम है और एकल डेटाबेस फाइल में मौजूद है। लेकिन ज्यादातर खेलों के लिए, रिलेशनल डेटाबेस जाने का तरीका नहीं है, और जो कंपनियां उनका उपयोग करने की कोशिश करती हैं, वे आमतौर पर एक सच्चे रिलेशनल डेटाबेस के बजाय एक कुंजी-मूल्य लुकअप तालिका के रूप में उपयोग करते हैं।

स्थानीय डिस्क फ़ाइलों के एन्क्रिप्शन का कोई भी प्रकार केवल मोटापा है ; कोई भी हैकर आपके कार्यक्रम को ठीक करने के तुरंत बाद डेटा को सूँघ लेगा। मैं व्यक्तिगत रूप से उस तरह की चीज के खिलाफ हूं, ESPECIALLY एक खिलाड़ी के खेल के साथ। मेरा विचार है कि यदि वे चाहें तो खेल के मालिकों (ग्राहकों, मन को आप को भुगतान करना) को खेल में हैक करने की अनुमति दी जानी चाहिए। कुछ मामलों में यह समुदाय की अधिक समझ पैदा कर सकता है, और आपके गेम के लिए "मॉड्स" विकसित किया जा सकता है जो आपके लिए अधिक ग्राहक चलाते हैं। सबसे हालिया उदाहरण जो दिमाग में आता है वह Minecraft मॉड में पोर्टल है जिसे हाल ही में जारी किया गया था। यह पूरे इंटरनेट पर गेमर समाचार साइटों में प्रकाशित हुआ है, और आप इसे Minecraft की बिक्री को बढ़ा सकते हैं।


अगर किसी कारण से आप वास्तव में खेल के विकास के लिए जावा का उपयोग करने के लिए पर्याप्त रूप से पागल हैं, तो मैं यहां जावा में क्रमबद्धता का एक त्वरित विवरण प्रस्तुत करता हूं:

अपने सभी गेम स्टेट डेटा को एक कक्षा में रखें Serializable, लागू करके कक्षा को क्रमबद्ध बनाएं , transientयदि आप विशेष त्वरित संस्करण को वर्ग में मिलाते हैं तो कीवर्ड का उपयोग करें (क्षणिक वस्तुएं अनुक्रमित नहीं हैं), और बस ObjectOutputStreamफ़ाइल से लिखने और फ़ाइल ObjectInputStreamसे पढ़ने के लिए उपयोग करें । बस।


2
Hehe, The Witcher ने अपने डेटा को एन्क्रिप्ट नहीं किया। हेक्स एडिटर में सेव गेम फ़ाइल को खोलना बहुत आसान है, इसके साथ थोड़ा गड़बड़ करें और सभी नग्न चिक कार्ड प्राप्त करें ... हे भगवान, मुझे बहुत खेद है!
एंथनी

मैंने खेलों को बचाने के लिए .NET बाइनरी क्रमांकन का उपयोग किया है, और सी # शायद जावा से थोड़ा अधिक उचित मंच है, जिस पर गेम विकसित करना है। मुझे यह पसंद है कि कैसे यह स्वचालित रूप से एक पूरे ऑब्जेक्ट ग्राफ को स्वचालित रूप से बचाता है। यह इतना अधिक कठिन हुआ करता था। बेशक अब बनावट की तरह अनावश्यक टुकड़ों को बाहर करने की चुनौती है, लेकिन इसे पूरा करना कोई बड़ी बात नहीं है।
BlueMonkMN

मैं इस बात से असहमत नहीं हूं कि C # गेम विकसित करने के लिए जावा से थोड़ा अधिक लोकप्रिय है। अधिक उचित का तात्पर्य कुछ व्यक्तिपरकता से है, और एक्सएनए और जावा दोनों के डेवलपर के रूप में, मैं जावा को पसंद करता हूं। सी # में क्रमांकन पर निर्देशों को सूचीबद्ध करने के लिए स्वतंत्र महसूस करें यदि आप चाहें, तो मैंने कभी ऐसा नहीं किया है, लेकिन मैं इसे अपने उत्तर में संपादित कर सकता हूं। जावा के क्रमांकन पूरे ऑब्जेक्ट ग्राफ को बचाता है और चर पर 'क्षणिक' कीवर्ड बनावट जैसे अनावश्यक टुकड़ों को बाहर करता है; किसी भी गैर-क्षणिक सदस्यों को सीरियल करने योग्य होना चाहिए या आप उसके चारों ओर प्राप्त करने के लिए एक कस्टम राइटऑबजेक्ट विधि लिख सकते हैं।
Ricket

अजगर का अचार आपके लिए एक संपूर्ण ऑब्जेक्ट ग्राफ भी बचाएगा और उपयोग में आसान है। जब यह वशीभूत होने का
drhayes 19

अंतर्निहित बाइनरी फॉर्मैटर का उपयोग करते समय, सी # / में नेट को कुछ क्षेत्रों से अलग करना। नेट उन्हें [NonSerialized] विशेषता के साथ एड करने के समान सरल है। हालांकि, अनदेखी करना आसान है, यह है कि कंपाइलर-जनरेटेड इवेंट्स (यानी कस्टम ऐड / रिमूव ऑपरेटर्स के बिना कोई भी इवेंट) अपने ग्राहकों को स्टोर करने के लिए एक बैकिंग फ़ील्ड बनाते हैं। इस प्रकार, गलती से (और अनजाने में) एक क्रमबद्ध ऑब्जेक्ट ग्राफ में घटना संचालकों को शामिल करना आसान है। इसके आस-पास जाने के लिए, आपको घटना की घोषणा में गैर-पंजीकृत विशेषता जोड़ने की आवश्यकता है, लेकिन आपको "फ़ील्ड:" क्वालीफ़ायर जोड़ने की आवश्यकता है:[field: NonSerialized]
माइक स्ट्रोबेल

3

यदि आप अपना कोड लिख रहे हैं, तो C ++ में कहें, आप बाइनरी फ़ाइलों का उपयोग कर सकते हैं द्विआधारी फाइलें आपको ओफ़्फ़्यूशन के माध्यम से एन्क्रिप्शन का एक रूप देती हैं। लेकिन जैसा कि सभी इंटर्नेट्स में प्रलेखित है, यह सुरक्षा का बहुत कमजोर रूप है।

या, यदि आप मानव पठनीय समाधान चाहते हैं तो आप रैपिडएक्सएमएल जैसी किसी चीज़ का उपयोग कर सकते हैं।

यदि आप किसी प्रकार की रूपरेखा का उपयोग कर रहे हैं, तो इसे फ़ाइल समर्थन कार्यों में देखें। HTH


0

अधिकांश गेम जो मैंने देखे हैं, वे बाइनरी फाइलों को पढ़ने / लिखने के लिए सिर्फ हाथ से लिखे गए कोड का उपयोग करते हैं। अक्सर डिस्क प्रारूप पर किसी ऑब्जेक्ट की मेमोरी लेआउट की एक सटीक प्रतिकृति होगी ताकि लोड हो रहा है:

  1. स्मृति में फ़ाइल पढ़ें।
  2. ऑब्जेक्ट प्रकार के लिए बफर को कास्ट पॉइंटर।

यह तेज़ है, लेकिन यह मंच-विशिष्ट, और अनम्य बनाए रखने के लिए एक घर का काम है।

हाल ही में, मैंने देखा है कि कुछ गेम SQLite का उपयोग करते हैं। जिन लोगों से मैंने बात की है, वे इसे पसंद करते हैं।


0

कुछ अन्य उत्तरों में सीरियललाइज़ेशन का उल्लेख किया गया है, और मैं मानता हूं कि यह एक उचित समाधान है। एक तरह से यह विफल रहता है, हालांकि संस्करण में है।

कहते हैं कि आप अपना गेम जारी करते हैं और लोग इसे खेलते हैं और कुछ गेम बचाते हैं। फिर बाद के पैच में आप एक बग को ठीक करना चाहते हैं या कुछ विशेषताएं जोड़ सकते हैं। यदि आप एक सरल बाइनरी क्रमांकन पद्धति का उपयोग करते हैं और आप अपनी कक्षाओं में एक सदस्य जोड़ते हैं तो आपके क्रमांकन पुराने सहेजे गए गेम के साथ संगत नहीं हो सकते हैं जब ग्राहक आपके पैच को स्थापित करते हैं।

आप जो भी दृष्टिकोण का उपयोग करते हैं, खेल को पहली बार जारी करने से पहले सुनिश्चित करें कि आप इस मुद्दे पर सोचते हैं! पैच अप्लाई करने के बाद शुरू होने पर ग्राहकों को खुशी नहीं होगी।

इससे बचने का एक तरीका यह है कि प्रत्येक बेसिक डेटा टाइप में सेव (वर्जन) और लोड (वर्जन) तरीके हों, जो यह जानने के लिए पर्याप्त स्मार्ट हों कि गेम के प्रत्येक वर्जन के लिए कौन सा डेटा सेव और लोड करना है। इस तरह से आप अपने सहेजे गए गेम की बैकवर्ड संगतता का समर्थन कर सकते हैं और यदि उपयोगकर्ता चल रहे हैं तो गेम के नए संस्करण से किसी गेम को सहेजने का प्रयास करने पर शालीनतापूर्वक असफल हो जाते हैं।


1
एक त्वरित नोट के रूप में: खेल के प्रत्येक संस्करण के लिए "सेव" और "लोड" फंक्शंस को लागू करना जल्दी से एक रखरखाव दुःस्वप्न में बदल जाता है। मैंने पाया है कि एक बेहतर समाधान एक संस्करण संख्या को एम्बेड करना है, खेल के वर्तमान संस्करण के लिए "सहेजें / लोड करें" फ़ंक्शन लिखें, और सबसे हाल के गैर-वर्तमान संस्करण से वर्तमान संस्करण में "रूपांतरण" फ़ंक्शन लिखें। फिर बस अपने सभी रूपांतरण कार्यों को अपने आसपास रखें। एक दस-संस्करण-पुराने गेम को लोड करने की कोशिश करने से श्रृंखला में दस रूपांतरण फ़ंक्शन चलेंगे, फिर देशी "वर्तमान गेम संस्करण लोड करें" फ़ंक्शन।
ZorbaTHut

लंबे समय तक बनाए रखने के लिए बहुत आसान है - "हर पिछले गेम फ़ाइल को लोड करना" की एक श्रृंखला को ध्यान में रखते हुए कार्य जल्दी से एक बहुपद-समय ऑपरेशन में बदल जाता है।
ZorbaTHut

जिन खेलों में मैंने काम किया है, वे उस जटिल नहीं हैं - लोड की कई प्रतियाँ रखने / सहेजने के तरीकों के बजाय एक एकल विधि संस्करण संख्या का उपयोग करके यह निर्धारित करती है कि कौन से बाइट को पढ़ना और लिखना है। इसे और भी आसान बना दिया जाता है यदि आप केवल संरचनाएँ नहीं लिखते हैं, लेकिन आदिम डेटा प्रकार के स्तर (जैसे ReadByte / ReadFload / etc) पर परिचालन के रूप में लोडिंग और बचत को लागू करते हैं। फिर यदि आप एक नया सदस्य जोड़ते हैं तो आप कुछ ऐसा कर सकते हैं जैसे (संस्करण> 10) {someNewByte = ReadByte (); } इसे इस तरह से लागू करने से विभिन्न एंडियन प्लेटफॉर्म को सपोर्ट करना आसान हो जाता है।
केविन42

वर्जनिंग सपोर्ट में सुधार से बचने का एक और तरीका यह है कि अपनी वस्तुओं के क्रमांकन / डीरियलाइजेशन के तरीकों को एक स्ट्रीम से सीधे व्यक्तिगत मान लिखने / पढ़ने से बचें। इसके बजाय, ऑब्जेक्ट कुंजी / मान जोड़े का उपयोग करके अपने स्वामित्व डेटा को एक संपत्ति बैग में लिख सकते हैं, और फिर बैग को धारा में लिख सकते हैं। डीसेरिएलाइज़ेशन के दौरान, वस्तुओं को नाम से बैग से मान पढ़ा जा सकता है। लेकिन विशिष्ट संस्करण संख्या की जांच करने के बजाय, जैसे कि केवि 42 ने सुझाव दिया, आपके पास बस यह हो सकता है कि लापता मूल्यों को कैसे प्रबंधित किया जाए (अर्थात जब आवश्यक मूल्य बैग में नहीं हो तो मानक डिफ़ॉल्ट मान का उपयोग करें)।
माइक स्ट्रोबेल

0

यदि आप उसी प्रारूप का उपयोग कर सकते हैं जिसका उपयोग आप अपने स्तरों को स्टोर करने के लिए करते हैं, तो यह एक बोनस है।

उदाहरण के लिए, Peggle जैसे गेम में प्रारंभिक बोर्ड लेआउट, गेंदों की संख्या, वर्तमान स्कोर (प्रारंभिक बोर्ड के लिए 0) आदि हो सकते हैं, फिर एक सहेजा गया खेल बिल्कुल उसी प्रारूप का उपयोग कर सकता है।

यदि आप एक ही प्रारूप का उपयोग करते हैं तो सेव गेम और लेवल लोड आपके काम को आसान बनाने वाले कोड को साझा कर सकते हैं!

वास्तव में बड़ी मैप फ़ाइलों वाली गेम के लिए, सेव गेम को मैप फाइल को संदर्भ में शामिल किया जा सकता है। प्रारंभिक स्तर की फाइलें वही काम कर सकती हैं, यहां तक ​​कि, जो उस नक्शे पर वापस आना आसान बनाती है, भले ही किसी कारण से कहानी में चरित्र उसी स्थान पर वापस आ गया हो, सिवाय कुछ एनपीसी के मृत हैं और सभी मृत शरीर पड़े हुए हैं ऊपर।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.