हर स्क्रीन पर वही यान
एक दैनिक लीडरबोर्ड तभी निष्पक्ष है जब एक पुराने छोटे फ़ोन, एक 144 Hz टैबलेट, और एक डेस्कटॉप ब्राउज़र पर गुफा के एक ही हिस्से में उड़ना समान रूप से कठिन हो। यहां बताया गया है कि इसके लिए क्या करना पड़ा, और मैं क्या बराबर नहीं कर सका।
दैनिक गुफा वाली पोस्ट हर खिलाड़ी के लिए दुनिया को एक जैसा बनाने के बारे में थी। यह निष्पक्षता के दूसरे आधे हिस्से के बारे में है: यान को एक जैसा व्यवहार कराना। एक डिवाइस गेम के खेलने के तरीके को दो अलग-अलग तरीकों से बदल सकता है, और उन्हें दो अलग-अलग समाधानों की ज़रूरत है। एक है स्क्रीन कितनी बार रिफ्रेश होती है। दूसरा है स्क्रीन कितनी बड़ी है।
समस्या एक: फ्रेम रेट
यान की एक स्थिति और एक गति होती है। हर फ्रेम में, गुरुत्वाकर्षण या थ्रस्ट गति बदलता है, और गति स्थिति बदलती है। इसे लिखने का स्पष्ट तरीका यह है:
vy += accel * dt; // update velocity
py += vy * dt; // then move by the NEW velocity
यह हानिरहित लगता है, लेकिन सूक्ष्म रूप से गलत है। दूसरी पंक्ति ऐसा दिखावा करती है जैसे यान ने पूरा फ्रेम पहले ही अपनी फ्रेम-अंत गति से यात्रा की हो। अगर यान त्वरित हो रहा है, तो यह हर एक फ्रेम में accel × dt² के आधे से ज़्यादा हो जाता है। पेच यह है कि dt, फ्रेम की लंबाई, हर डिवाइस पर अलग होती है, इसलिए यह अधिकता भी अलग होती है, और एक यान हर रिफ्रेश रेट पर थोड़े अलग रास्ते से उड़ता था।
मैंने इसे आधे सेकंड तक दबाए रखे गए थ्रस्ट से मापा। सटीक जवाब 225 पिक्सेल है। पुराना इंटीग्रेटर 144 Hz पर 228, 60 Hz पर 232, और 30 Hz पर 240 देता था। तीन डिवाइस, एक ही इनपुट से तीन अलग दूरियां।
समाधान है ट्रैपेज़ॉइड नियम, जो फ्रेम से पहले और बाद की गति के औसत का उपयोग करता है:
const vyPrev = vy;
vy += accel * dt;
py += (vyPrev + vy) * 0.5 * dt; // average speed over the frame
स्थिर त्वरण के लिए यह सटीक है, चाहे फ्रेम की लंबाई कुछ भी हो। एक जैसी इनपुट अनुसूची को दोबारा चलाने पर अब 12 से 144 Hz तक 0.000 पिक्सेल का फैलाव मिलता है। पहले यह 4.1 पिक्सेल था। एक टेस्ट दोनों हिस्सों की पुष्टि करता है: कि नया इंटीग्रेटर सभी रिफ्रेश रेट पर सहमत है और पुराना वाकई अलग-अलग परिणाम देता था, ताकि अगर कोई इसे वापस बदले, तो लीडरबोर्ड के चुपचाप बहकने के बजाय टेस्ट फेल हो जाए।
दो ईमानदार चेतावनियां
इसने रिफ्रेश रेट के बीच स्कोर का अंतर नहीं पाटा। मुझे यह उम्मीद थी। एक सिम्युलेटेड पायलट अब भी 144 Hz पर 60 Hz की तुलना में लगभग एक-तिहाई अधिक स्कोर कर रहा था। वह अंतर भौतिकी नहीं है। यह इनपुट रिज़ॉल्यूशन है: एक अंगूठा केवल फ्रेम की सीमा पर ही दबाने से न दबाने में बदल सकता है, इसलिए एक तेज़ स्क्रीन वाकई ज़्यादा बारीक नियंत्रण देती है। कोई भी इंटीग्रेटर इसे ठीक नहीं कर सकता, और एक बॉट जो हर फ्रेम में अपना इनपुट पलटता है, वह इंसान की तुलना में इसे बढ़ा-चढ़ा देता है। भौतिकी वाला आधा हिस्सा अब सटीक है, और बाकी हार्डवेयर का एक गुण है।
यह 60 Hz पर बहुत ही मामूली कमजोरी है। आधे सेकंड की चढ़ाई अब 232 की बजाय 225 पिक्सेल तय करती है। मैंने इसे बिना भरपाई के छोड़ दिया। अगर असली डिवाइस पर परीक्षण कभी यान को सुस्त पाता है, तो लीवर थ्रस्ट कॉन्स्टेंट है, लगभग 3% ज़्यादा पुराने आधे-सेकंड के युद्धाभ्यास को बहाल कर देगा। यह कहने का अच्छा मौका है कि थ्रस्ट पहले भी खिलाड़ी की प्रतिक्रिया पर दो बार बदला जा चुका है, और वह कहानी ही वजह है कि मैं इसे छूने में सतर्क रहता हूं।
समस्या दो: स्क्रीन की ऊंचाई
प्रति सेकंड वर्ग पिक्सेल में गुरुत्वाकर्षण का मतलब 375-पॉइंट ऊंचे फ़ोन और 520-पॉइंट ऊंचे टैबलेट पर बहुत अलग-अलग होता है। अगर कॉन्स्टेंट एक जैसे होते, तो वही चढ़ाई टैबलेट पर स्क्रीन के बहुत छोटे हिस्से को पार करती, और गेम भारी महसूस होता।
इसलिए कॉन्स्टेंट को 440 पॉइंट की संदर्भ ऊंचाई के मुकाबले परिभाषित किया गया है, जो सबसे बड़े iPhone की लैंडस्केप ऊंचाई है, जहां गेम का एहसास ट्यून और परीक्षण किया गया था। किसी भी अन्य स्क्रीन पर, गुरुत्वाकर्षण, थ्रस्ट, और टर्मिनल गति सभी को H / 440 से गुणा किया जाता है। चूंकि कॉरिडोर का आधा अंतर भी ऊंचाई के साथ स्केल होता है, हर प्रक्षेपवक्र संदर्भ वाले के ज्यामितीय रूप से समान होता है: प्रति सेकंड पार किया गया कॉरिडोर का वही अंश, एक दीवार से दूसरी दीवार तक जाने का वही समय, वही महसूस होने वाली प्रतिक्रिया। एक बड़ी स्क्रीन को पिक्सेल में तीखा त्वरण मिलता है, और एक छोटी को जानबूझकर नरम त्वरण मिलता है।
यह भविष्य के सभी कोड के लिए एक नियम के साथ आता है: ऊर्ध्वाधर गति के बारे में तर्क करने वाली कोई भी चीज़ अनुपात-आधारित होनी चाहिए। टर्मिनल गति का एक अंश, ऊंचाई का एक अंश। यान की गति के मुकाबले तुलना की गई कच्ची प्रति-सेकंड-पिक्सेल कॉन्स्टेंट कभी नहीं, क्योंकि वह संख्या केवल एक डिवाइस पर सही होती है। अगर एक लिटरल अपरिहार्य है, तो उसे उसी स्केल से गुणा किया जाता है।
वेब संस्करण भी वही नियम मानता है। ब्राउज़र बिल्ड अपने कैनवास को 956 गुणा 440 पर सीमित करता है, उसी संदर्भ फ़ोन के समान आकार, इसलिए ब्राउज़र में गेम उसकी पिक्सेल और भौतिकी दोनों में सटीक प्रति है। एक पुराने वेब बिल्ड का अपना अलग एहसास गुणक था, जो केवल एक अलग सीमा के कारण होने वाली ढीलेपन से लड़ने के लिए मौजूद था, और सीमा मेल खाते ही उसे हटा दिया गया।
समस्या तीन: स्क्रीन की चौड़ाई
ऊंचाई ऊर्ध्वाधर धुरी है। चौड़ाई क्षैतिज है, और यह ज़्यादा सूक्ष्म है। बाधाएं दुनिया में तय दूरियों पर रखी जाती हैं। गुफा एक गति से स्क्रॉल होती है जिसमें स्क्रीन की चौड़ाई के लिए एक कारक शामिल होता है। इसलिए एक चौड़ी स्क्रीन पर वही बाधाएं स्क्रीन के लिहाज़ से तेज़ी से गुज़रती हैं, और हर एक पर प्रतिक्रिया देने के लिए तुम्हारे पास जो समय होता है वह चौड़ाई के अनुपात में घट जाता है।
यह एक असली खामी थी। लगभग 1,280 पॉइंट चौड़ा एक बड़ा Android टैबलेट एक छोटे फ़ोन की तुलना में साझा गुफा का सामना लगभग 1.75 गुना तेज़ी से करता था। इसलिए चौड़ाई को हर प्लेटफ़ॉर्म पर 956 पॉइंट तक सीमित किया गया है, जो लैंडस्केप में सबसे चौड़े iPhone की चौड़ाई है। इससे चौड़ा डिवाइस बाएं और दाएं काली पट्टियां पाता है। यह iPhone पर कोई असर नहीं करता और केवल बड़े Android डिवाइस और डेस्कटॉप ब्राउज़र को सीमित करता है।
इस सीमा में एक बचा हुआ हिस्सा है जिसे मैंने ठीक नहीं किया है। खिलाड़ी की टकराव त्रिज्या चौड़ाई के साथ स्केल होती है जबकि कॉरिडोर ऊंचाई के साथ स्केल होता है, इसलिए एक ज़्यादा चौकोर टैबलेट पर यान फ़ोन की तुलना में अंतर के सापेक्ष थोड़ा छोटा होता है, लगभग 20% ज़्यादा माफ़ करने वाला। इसे ठीक करने का मतलब है हिटबॉक्स बदलना, जो एक एहसास बदलाव है जिसके लिए अपना अलग प्लेटेस्ट चाहिए, और यह माफ़ करने वाली दिशा में गलत है, इसलिए यह इंतज़ार कर सकता है।
निष्पक्षता का दावा करने के बजाय उसे परखना
इनमें से कुछ भी खेलते समय दिखाई नहीं देता। तुम कुछ पिक्सेल के बहाव को महसूस नहीं कर सकते, और कोई भी एक साथ छह डिवाइसों पर एक ही गुफा नहीं खेलता। इसलिए हर दावे के पास उसे दोबारा चलाने वाला एक टेस्ट है: भौतिकी टेस्ट 12 से 144 Hz तक के फ्रेम रेट पर एक तय इनपुट को इंटीग्रेट करता है, और एक गुफा टेस्ट असली स्पॉनर को छह डिवाइस आकारों पर दोबारा चलाता है और परिणाम की बाइट-दर-बाइट तुलना करता है। मेरे अनुभव में, जो निष्पक्षता गुण तुम परखते नहीं हो, वह पहले ही चुपचाप टूट चुका होता है।
संक्षेप में, TUNL स्क्रीन के बीच तीन अलग-अलग तरीकों (फ्रेम रेट, ऊंचाई, और चौड़ाई) से निष्पक्ष है, हर एक का अलग कारण, अलग समाधान, और अलग बचा हुआ हिस्सा है। तुम अपने पास मौजूद किसी भी डिवाइस पर, आज की गुफा में खुद नतीजा देख सकते हो।