चलायें, लेकिन जांच करें: इंजन डिजाइनर को कैसे छोटा करता है



मल्टीप्लेयर गेम डिजाइन करते समय, लगभग सबसे महत्वपूर्ण घटक संतुलन है। इस संबंध में एक गेम डिजाइनर का काम एक खुफिया विश्लेषक के काम के समान है: यदि वह अच्छी तरह से काम करता है, तो कोई भी नोटिस नहीं करता है। यह ठोकर खाने के लायक है, और खिलाड़ी बेशर्मी से त्रुटि का फायदा उठाते हैं। लेकिन सबसे दिलचस्प बात तब होती है, जब गेम डिजाइनर के अलावा प्रोग्रामर से भी गलती हो जाती है ...


इस लेख में, हम कोसैक्स 3 रणनीति के एक तत्व पर विचार करेंगे। खेल में 17 वीं और 18 वीं शताब्दी के विभिन्न प्रकार के संगीतकारों और अन्य निशानेबाजों के साथ-साथ उन प्रौद्योगिकियों का पता लगाने का अवसर शामिल है जो कस्तूरी के पुनः लोड समय को कम करते हैं। कुल मिलाकर दो सुधार हुए हैं, जिनमें से प्रत्येक गेम इंटरफ़ेस के अनुसार आग की दर में 30% लाता है।


लेकिन यहां तक ​​कि यह स्पष्ट है कि कुछ लड़ाकू इकाइयां, सुधारों पर शोध करने के बाद, न केवल 60%, बल्कि कई बार अधिक बार शूट करती हैं। जब अंतर्निहित गेम टाइमर का उपयोग करके सीधे आग की दर को मापते हैं, तो पूरी तरह से अजीब संख्याएं सामने आती हैं जिनका उल्लेख प्रतिशत के साथ कुछ नहीं करना है।


"Cossacks" के हुड के तहत


सौभाग्य से, खेल, modders के लिए एक बहुत ही दोस्ताना रूप में किया जाता है, ताकि सभी आवश्यक डेटा / scripts / फ़ोल्डर में पाठ फ़ाइलों के रूप में उपलब्ध लिपियों। वाक्य रचना द्वारा देखते हुए, स्क्रिप्ट डेल्फी में या बहुत समान भाषा में लिखी जाती हैं। आइए शॉट्स के बीच अंतराल की गणना के यांत्रिकी पर एक नज़र डालें।


नोट
  • विश्लेषण खेल "Cossacks 3" संस्करण 2.1.4 पर किया गया था।
  • नीचे दिए गए सभी स्क्रिप्ट अनुभागों में एक सरलीकृत छद्मकोश है।

  1. जब खेल शुरू होता है, तो सभी लड़ाकू इकाइयों को आरंभिक किया जाता है। प्रक्रिया प्रत्येक प्रकार के लिए जीवन शक्ति, लागत और हथियारों के मूल्यों को इंगित करती है। छोटे हथियारों के लिए, एक पैरामीटर पारित किया जाता है जो गेम फ़्रेम में शॉट्स के बीच अंतराल को इंगित करता है:


    //lib/unit.script procedure _unit_InitBase() 'musketeer' : maxhp := 70; SetObjBaseWeapon( x,x,x,x, 150, ... ); SetObjBasePrice( ... ); //lib/unit.script procedure SetObjBaseWeapon( x,x,x,x, pause, ... ) weapon.pause := _misc_FramesToTime( pause ); 

    टिप्पणियों को देखते हुए, समय की इकाई "गेम फ्रेम" पहले "Cossacks" से atavism है, जिसकी गेम प्रक्रिया को तीसरे भाग को बनाते समय कॉपी किया गया था। हालाँकि, फ्रेम तुरंत 1:32 के अनुपात के साथ खेल के सेकंड में पुन: जुड़ जाते हैं, और हम उनका सामना नहीं करते हैं:


     //lib/misc.script function _misc_FramesToTime( val ) Result := ( val * gc_frames_to_time ); //dmscript.global gc_frames_to_time := 0.03125; gc_time_to_frames := 32; 

  2. इसके अलावा, खेल की शुरुआत में, गेमिंग राष्ट्रों के डेटा को शुरू में उपलब्ध सुधार सहित शामिल किया गया है। उनमें से प्रत्येक के लिए, मूल्य चर को इंगित और संग्रहीत किया जाता है, जो इस सुधार का अध्ययन करते समय, खेल के आवश्यक मापदंडों के पुनर्गणना को प्रभावित करता है:


     //lib/country.script procedure _country_Init() _country_AddUpgrade( x,x,x,x, type_attpauseperc, -30, ... ); procedure _country_AddUpgrade( x,x,x,x, upgrade_type, value, ... ); 

    हमारे मामले में, इसका मतलब है कि प्रत्येक सुधार के बाद सैन्य इकाइयों के अंतराल को 0.7 से गुणा किया जाता है और फिर ... गोल किया जाता है!


     //lib/player.script procedure _player_ApplyUpgrade() type_attpauseperc : weapon.pause := Round( weapon.pause * (1 + value/100) ); 

    इस तथ्य को देखते हुए कि शुरू में निशानेबाजों के अंतराल 3.125 से 5.0 तक की सीमा में चल रहे हैं, पुनर्गणना के परिणाम को राउंड करने का निर्णय महत्वपूर्ण नहीं है, बल्कि अजीब लगता है।


  3. प्रत्येक फायर किए गए शॉट के बाद, अगले शॉट से पहले देरी का संकेत दिया जाता है। Iditional.attackrate संशोधक टॉवर संरचनाओं पर लागू होता है और हमारे मामले में हमेशा 1 होता है।


     //lib/unit.script procedure _unit_ApplyAttackPause() attackdelay := weapon.pause * idividual.attackrate; 


इसलिए, गणना में गणितीय त्रुटि के अलावा, नीचे दिए गए स्पॉइलर के तहत जिन विवरणों को पढ़ा जा सकता है, उनमें फ्लोटिंग-पॉइंट संख्याओं का एक अनुचित राउंडिंग है। मुझे आश्चर्य है कि पहली नज़र में खेल के यांत्रिकी पर क्या मामूली प्रभाव है?


थोड़ा सा गणित

आग की दर शॉट्स के बीच अंतराल के आकार के विपरीत आनुपातिक है। और अगर यह प्रति मिनट राउंड की संख्या है जो खिलाड़ी के लिए मायने रखती है, तो खेल इंजन, एक नियम के रूप में, ठहराव की गणना करने के लिए अंतराल का उपयोग करता है। यहां पकड़ यह है कि "अंतराल को 30% तक कम करना" और "आग की दर को 30% तक बढ़ाना" पूरी तरह से अलग चीजें हैं। अंतराल t और शॉट्स n की संख्या के बीच अनुपात को एक सरल सूत्र द्वारा वर्णित किया गया है:

 fract1t2=r= fracn2n1


यदि, उदाहरण के लिए, हम 6 सेकंड (10 राउंड प्रति मिनट) का अंतराल लेते हैं और इसे 30% तक कम कर देते हैं, तो हमें प्रति मिनट 13 राउंड नहीं मिलेंगे:

6 \ space \ mathrm {s} \ cdot0.7 = 4.2 \ space \ mathrm {s}; \ quad \ frac {6 \ space \ mathrm {s}} {4.2 \ space \ mathrm {s} \ approx1.43 \ neq \ frac {13} {10}


वांछित मूल्य प्राप्त करने के लिए, आपको मौजूदा अंतराल को पुराने में आग की नई दर के वांछित अनुपात से विभाजित करना चाहिए:

t2= fract1r= frac6 space mathrms1.3 approx4.62 space mathrms



मापन विधि

गेम इंजन के साथ काम करने वाले मान प्राप्त करने के लिए, आप लॉगिंग फ़ंक्शन का उपयोग कर सकते हैं। ऐसा करने के लिए, आपको पहले लॉगिंग को सक्षम करना होगा:


  //cossacks.ini & editor.ini LogFileEnabled = true LogFileRoot = true 

और फिर _unit_ApplyAttackPause () प्रक्रिया के अंत में लॉग () फ़ंक्शन के लिए एक कॉल जोड़ें:


  //data/scripts/lib/unit.script procedure _unit_ApplyAttackPause(const goHnd, weapind : Integer); begin //... if (attpause<>0) then Log(TObjProp(pobjprop).sid+' '+FloatToStr(attpause)); end; 

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


कौन है कौन


प्रारंभ में, खेल स्क्रिप्ट 35 प्रकार के निशानेबाजों (मतदाताओं की गिनती नहीं जो सुधार से प्रभावित नहीं हैं) के बीच अंतर करते हैं। यदि हम उन सभी को अंतराल के आकार से जोड़ते हैं, तो हम दस श्रेणियों को अलग कर सकते हैं। मैंने उन निशानेबाजों को एकल करने के लिए आग की दर में सापेक्ष वृद्धि करके उन्हें क्रमबद्ध करने का फैसला किया, जो सुधार से सबसे अधिक लाभान्वित होते हैं। तो, विश्लेषण के परिणाम:


हमला अंतरालशॉट्स / मिनटआग की दर
श्रेणी  backslashसुधार0+1+20+1+2+1+2
मैं5.004.03.012.01520+ 25%+ 67%
द्वितीय6.885.04.08.71215+ 38%+ 72%
तृतीय5.314.03.011.31520+ 33%+ 77%
चतुर्थ5.634.03.010.71520+ 41%+ 88%
वी3.753.02.016.02030+ 25%+ 88%
छठी5.944.03.010.11520+ 48%+ 98%
सातवीं4.063.02.014.82030+ 35%+ 103%
आठवीं4.383.02.013.72030+ 46%+ 119%
नौवीं4.693.02.012.82030+ 56%+ 134%
एक्स3.132.01.019.23060+ 56%+ 213%

नीचे दिए गए आरेख में, कॉलम I - X के अनुरूप है, बाएं से दाएं। आरेख का अंतिम धराशायी स्तंभ गेम इंटरफ़ेस में घोषित वृद्धि की दर से मेल खाता है। स्तंभों का बायां समूह एक सुधार के बाद आग की दर में वृद्धि दर्शाता है, दाएं - दोनों के बाद।


श्रेणियों और इकाइयों की सूची

खेल में विभिन्न राष्ट्र हैं - 17 यूरोपीय और चार अद्वितीय (यूक्रेन, तुर्की, अल्जीरिया और स्कॉटलैंड)। यूरोपीय गुट शुरू से ही बहुत समान हैं और 17 वीं और 18 वीं शताब्दी के मस्कटियर और ड्रगोन के साथ-साथ ग्रेनेडियर्स भी हैं। लेकिन कभी-कभी कुछ राष्ट्रों के तीर टेम्पलेट से भिन्न होते हैं, या पूरी तरह से एक अद्वितीय प्रकार द्वारा प्रतिस्थापित किए जाते हैं।


श्रेणीमुकाबला इकाइयों
मैंमुस्तकीर 17 वीं शताब्दी (ऑस्ट्रिया)
स्जेकेज (हंगरी)
स्कॉटिश शूटर (इंग्लैंड)
पोलिश-लिथुआनियाई राष्ट्रमंडल (पोलैंड)
ड्रैगून 18 वीं शताब्दी (नीदरलैंड और पीडमोंट)
द्वितीयव्याध (स्विट्जरलैंड)
रॉयल मस्कटियर (फ्रांस)
तृतीयग्रेनेडियर (यूरोप को छोड़कर डेनमार्क और प्रशिया)
ड्रैगून 18 वीं शताब्दी (यूरोप को छोड़कर फ्रांस, नीदरलैंड और पीडमोंट)
लाइट घुड़सवार (विभिन्न देशों)
चतुर्थड्रैगून 17 वीं शताब्दी (यूरोप)
वीमुस्तकीर 17 वीं शताब्दी (नीदरलैंड)
छठीमुस्तकीर 17 वीं शताब्दी (स्पेन)
18 वीं शताब्दी का मुस्कितेर (बावरिया और डेनमार्क)
ग्रेनेडियर (डेनमार्क)
स्वयंसेवक (पुर्तगाल)
व्याध (फ्रांस)
सातवींसर्डियुक (यूक्रेन)
आठवीं18 वीं शताब्दी का मुस्कितेर (Saxony)
ग्रेनेडियर (प्रशिया)
नौवींमुस्तकीर 17 वीं शताब्दी (यूरोप को छोड़कर ऑस्ट्रिया, पोलैंड, नीदरलैंड और स्पेन)
मस्कटियर वाचा (स्कॉटलैंड)
धनु (रूस)
जानिसार (तुर्की)
18 वीं शताब्दी का मुसईकर (डेनमार्क, बावरिया और सैक्सोनी को छोड़कर यूरोप)
पांडुर (ऑस्ट्रिया)
ड्रैगून 18 वीं शताब्दी (फ्रांस)
एक्समुस्तकीर 17 वीं शताब्दी (पोलैंड)
हज़डुक (हंगरी)

टिप्पणी:


  • सैन्य इकाइयों के नाम खेल के रूसी इंटरफ़ेस से कॉपी किए जाते हैं।
  • 18 वीं शताब्दी के इटालिक्स में तीर इटैलिक्स में हैं।
  • घोड़े के तीर बोल्ड में हाइलाइट किए गए हैं

यह पता चला है कि 17 वीं शताब्दी के पोलिश मस्कटियर और हंगेरियन हाईजैक आग की दर में सुधार से सबसे अधिक जीतते हैं: वादा किए गए + 60% के बजाय, वे तीन बार से अधिक बार गोली मारते हैं। अंतराल के कम प्रारंभिक मूल्य के कारण, वे अंततः अन्य सभी निशानेबाजों की तुलना में दो, तीन या चार बार तेजी से शूट करते हैं।


घुड़सवार सेना के बीच, 18 वीं शताब्दी के फ्रांसीसी ड्रगोन सबसे अच्छे रूप में बसे हुए हैं: उन्हें आग की दर दोगुनी से अधिक प्राप्त होती है। परिणामस्वरूप, वे अन्य यूरोपीय देशों के अपने समकक्षों की तुलना में प्रति मिनट 50% अधिक शॉट फायर करते हैं।


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


कैसे ठीक करें?

समस्या का सबसे तेज़ और गैर-आक्रामक समाधान सुधार को लागू करने के फार्मूले को फिर से लिखना है। राउंडिंग को अस्वीकार करने के अलावा, अंतराल को 0.3 से गुणा करने के बजाय, इसे 1.3 से विभाजित करें। ऐसा करने के लिए, बस सूत्र को gc_upg_type_attpauseperc सुधार प्रक्रिया के साथ बदलें


  //lib/player.script Round(weapon.pause*(1+value/100)); 

पर


  weapon.pause/(1+(-value)/100); 

चूंकि सुधार लगातार लागू होते हैं, अंत में, घोषित + 60% के बजाय, हमें + 69% मिलता है। लेकिन यह अभी भी + 213% से बेहतर है।


अंतभाषण


इस मामले में संतुलन में गलत तरीके से पहचान करने के लिए, खेल यांत्रिकी के दो और पहलुओं का विश्लेषण किया जाना चाहिए - एक मुकाबला इकाई बनाने के लिए आवश्यक समय के साथ-साथ निशानेबाजों की क्षति और आर्थिक मूल्य। हालांकि, सामान्य ज्ञान आपको पहले अपडेट के लिए इंतजार करने के लिए कहता है ...


मुझे वीडियो से अध्ययन के लिए विचार मिला " एओईई 2 में हमले की दर क्यों अक्सर गलत होती है ", जो आयु द्वितीय की रणनीति में एक समान मुद्दे को संबोधित करती है।


UPD: त्रुटि आंशिक रूप से ठीक की गई


लेख के प्रकाशन के बाद से एक सप्ताह भी नहीं बीता है, क्योंकि अद्यतन 2.2.1 में डेवलपर्स ने गोलाई के साथ त्रुटि को ठीक किया। उसी समय, सूत्र स्वयं ही बना रहा - आग की दर प्रति उन्नयन 43% से बढ़ रही है। चूंकि गणना वृद्धिशील है, दोनों सुधारों की जांच के बाद, सभी तीर 104% तेजी से काम करते हैं।


तालिका

बढ़ते हुए क्रम में दोनों सुधारों पर शोध करने के बाद प्रति मिनट शॉट में फायर यूनिट की दर:


मुकाबला इकाइयोंशॉट्स
व्याध (स्विट्जरलैंड)
रॉयल मस्कटियर (फ्रांस)
17.8
मुस्तकीर 17 वीं शताब्दी (स्पेन)
18 वीं शताब्दी का मुस्कितेर (बावरिया और डेनमार्क)
ग्रेनेडियर (डेनमार्क)
स्वयंसेवक (पुर्तगाल)
व्याध (फ्रांस)
20.6
ड्रैगून 17 वीं शताब्दी (यूरोप)21.8
ग्रेनेडियर (यूरोप को छोड़कर डेनमार्क और प्रशिया)
ड्रैगून 18 वीं शताब्दी (यूरोप को छोड़कर फ्रांस, नीदरलैंड और पीडमोंट)
लाइट घुड़सवार (विभिन्न देशों)
23.0
मुस्तकीर 17 वीं शताब्दी (ऑस्ट्रिया)
स्जेकेज (हंगरी)
स्कॉटिश शूटर (इंग्लैंड)
पोलिश -L रैखिक राष्ट्रमंडल (पोलैंड)
ड्रैगून 18 वीं शताब्दी (नीदरलैंड और पीडमोंट)
24.5
मुस्तकीर 17 वीं शताब्दी (यूरोप को छोड़कर ऑस्ट्रिया, पोलैंड, नीदरलैंड और स्पेन)
मस्कटियर वाचा (स्कॉटलैंड)
धनु (रूस)
जानिसार (तुर्की)
18 वीं शताब्दी का मुस्कितेर (डेनमार्क, बावरिया और सैक्सोनी को छोड़कर यूरोप)
पांडुर (ऑस्ट्रिया)
ड्रैगून 18 वीं शताब्दी (फ्रांस)
26.1
18 वीं शताब्दी का मुस्कितेर (Saxony)
ग्रेनेडियर (प्रशिया)
28.0
सर्डियुक (यूक्रेन)30.1
मुस्तकीर 17 वीं शताब्दी (नीदरलैंड)32.7
मुस्तकीर 17 वीं शताब्दी (पोलैंड)
हज़डुक (हंगरी)
39.2

Source: https://habr.com/ru/post/hi414853/


All Articles