गेम लूप में रेंडर करने के बारे में जानें

गेम लूप लागू करने का सबसे लोकप्रिय तरीका कुछ ऐसा दिखता है:

while (playing) {
    advance state by one frame
    render the new frame
    sleep until it’s time to do the next frame
}

इसमें कुछ समस्याएं हैं. सबसे अहम बात यह है कि गेम यह तय कर सकता है कि "फ़्रेम" है. अलग-अलग डिसप्ले अलग-अलग समय पर रीफ़्रेश होंगे हैं और यह दर समय के साथ बदल सकती है. अगर फ़्रेम रेंडर होने में लगने वाला समय डिसप्ले उन्हें दिखा सकता है, लेकिन आपको कभी-कभी इसे छोड़ना होगा. अगर आप बहुत धीमा हो जाता है, तो SurfaceFlinger समय-समय पर मिलता है और पिछले फ़्रेम को फिर से दिखाएगा. इन दोनों स्थितियों में यह काम किया जा सकता है की वजह से होने वाली समस्याएं होती हैं.

आपको सिर्फ़ डिसप्ले के फ़्रेम रेट और गेम की बेहतर स्थिति के हिसाब से खेलना होगा पिछले फ़्रेम के बाद से कितना समय बीता है उसके हिसाब से. कई इस बारे में जानें:

  • Android फ़्रेम पेसिंग लाइब्रेरी का इस्तेमाल करें (इसका सुझाव दिया जाता है)
  • बफ़र सूची में पूरा टेक्स्ट भरें और "बफ़र स्वैप करें" का इस्तेमाल करें बैक-प्रेशर
  • कोरियोग्राफ़र (एपीआई 16+) का इस्तेमाल करना

Android फ़्रेम पेसिंग लाइब्रेरी

जानकारी के लिए सही फ़्रेम पेसिंग पाना देखें को ध्यान में रखें.

स्टफ़िंग की सूची

इसे लागू करना बहुत आसान है: बस बफ़र को जल्द से जल्द स्वैप करें. तय समय से पहले हो सकता है कि ऐसा करने पर जुर्माने के तौर पर, SurfaceView#lockCanvas() आपको 100 मि॰से॰ तक स्लीप मोड में ले जाएगा. अब तक का डेटा बफ़र सूची में तेज़ी से बदलाव किया जाता है और बफ़र लाइन को इतनी तेज़ी से खाली किया जाता है SurfaceFlinger सुविधा चालू कर सकती है.

इसका एक उदाहरण Android ब्रेकआउट में देखा जा सकता है. यह GLSurfaceView का इस्तेमाल करता है, जो लूप में चलता है और ऐप्लिकेशन के onDrawFrame() कॉलबैक और फिर बफ़र को स्वैप करता है. अगर बफ़र सूची भरी हुई है, तो eglSwapBuffers() कॉल बफ़र के उपलब्ध होने तक इंतज़ार करेगा. बफ़र की सुविधा तब उपलब्ध होती है, जब SurfaceFlinger ऐप्लिकेशन इन्हें रिलीज़ करता है. हालांकि, इसके बाद ऐसा होता है देखने के लिए नया लिंक प्राप्त करना. ऐसा इसलिए होता है, क्योंकि ऐसा VSYNC पर होता है, इसलिए आपका ड्रॉ लूप समय रीफ़्रेश दर के बराबर होगा. ज़्यादातर.

इस तरीके में कुछ समस्याएं हैं. सबसे पहले, ऐप्लिकेशन SurfaceFlinger गतिविधि में लगने वाला समय अलग-अलग होगा कितना काम करना है और वह सीपीयू समय से काम कर रहा है या नहीं, इस पर निर्भर करता है इस्तेमाल करते हैं. क्योंकि आपके गेम की स्थिति समय के हिसाब से आगे बढ़ती है बफ़र स्वैप होने पर, आपका ऐनिमेशन एक जैसी दर पर अपडेट नहीं होगा. टास्क कब शुरू होगा 60 एफ़पीएस (फ़्रेम प्रति सेकंड) पर चलते हैं. साथ ही, आपको समय के साथ अलग-अलग डेटा दिखता है. शायद उन गड़बड़ियों पर ध्यान न दे.

दूसरा, बफ़र स्वैप करने की प्रक्रिया का पहला कुछ काम बहुत जल्दी पूरा हो जाएगा ऐसा इसलिए हुआ है, क्योंकि बफ़र सूची में अब तक जगह नहीं बची है. फ़्रेम के बीच लगने वाले समय से शून्य के पास होता है, इसलिए गेम कुछ फ़्रेम जनरेट करेगा, जिनमें कुछ नहीं होता. ब्रेकआउट जैसे गेम में, हर बार रीफ़्रेश करने पर स्क्रीन को अपडेट किया जाता है. ऐसे गेम में, गेम के पहली बार शुरू होने (या उसे चालू करने) को छोड़कर, हमेशा भर जाता है. इसलिए, यह इफ़ेक्ट सुलभ नहीं है. ऐसा गेम जो कभी-कभी ऐनिमेशन को रोक देता है और फिर वापस आकर जितना हो सके, उतना ही तेज़ी से चलने वाले मोड में, अजीब गड़बड़ियां दिख सकती हैं.

Choreographer

कोरियोग्राफ़र से आपको अगले VSYNC पर सक्रिय होने वाला कॉलबैक सेट करने की सुविधा मिलती है. कॉन्टेंट बनाने वास्तविक VSYNC समय को तर्क के रूप में पास किया जाता है. इसलिए, भले ही आपका ऐप्लिकेशन सक्रिय न हो तुरंत ऊपर की ओर, आपको अब भी डिसप्ले रीफ़्रेश होने की सटीक तस्वीर दिखेगी अवधि शुरू हुई. वर्तमान समय के बजाय, इस मान का उपयोग करने पर यह परिणाम मिलता है आपके गेम की स्थिति अपडेट करने के लॉजिक के लिए, एक ही समय का सोर्स.

दुर्भाग्य से, हर VSYNC के बाद आपको कॉलबैक मिलता है, यह काम नहीं करता इस बात की गारंटी दें कि कॉलबैक सही समय पर होगा या उस पर तेज़ी से कार्रवाई कर सके. आपके ऐप्लिकेशन को पता लगाना होगा कि ऐसी स्थितियों में फ़्रेम को मैन्युअल तरीके से हटाया जाता है.

"Record GL ऐप्लिकेशन" ग्राफ़िक का इस्तेमाल, कुछ पर (जैसे नेक्सस 4 और Nexus 5) डिवाइसों के लिए इंस्टॉल किया है, तो गतिविधि बस बैठकर देखें. जीएल रेंडरिंग सामान्य है, लेकिन कभी-कभी एलिमेंट फिर से बनाए जाते हैं और मेज़र/लेआउट पास में बहुत ज़्यादा समय लग सकता है, डिवाइस कम पावर वाले मोड में चला गया है. (systrace के मुताबिक, Android 4.4 पर घड़ियों के स्लो होने के बाद, 6 मि॰से॰ के बजाय 28 मि॰से॰ लगते हैं. खींचकर छोड़ने पर जब आपको लगता है कि आप गतिविधि से इंटरैक्ट कर रहे हैं. इसलिए क्लॉक की स्पीड उच्च रहती है और आप कभी भी फ़्रेम नहीं छोड़ पाएंगे.)

इसका एक आसान तरीका यह था कि कोरियोग्राफ़र कॉलबैक में फ़्रेम ड्रॉप किया जाए, अगर मौजूदा समय VSYNC समय के बाद N मिलीसेकंड से अधिक है. आम तौर पर, N की वैल्यू यह पहले से देखे गए VSYNC इंटरवल के आधार पर तय किया जाता है. उदाहरण के लिए, अगर रीफ़्रेश करने का समय 16.7 मि॰से॰ (60 एफ़पीएस) है. और ज़्यादा वीडियो चलाने पर एक फ़्रेम ड्रॉप हो सकता है 15 मि॰से॰ से ज़्यादा देरी हो.

अगर आपने "Record GL ऐप्लिकेशन" देखा है चलाए जाने पर, आपको ड्रॉप-फ़्रेम काउंटर और फ़्रेम गिरने पर बॉर्डर में लाल रंग का फ़्लैश भी दिखता है. जब तक आपकी आंखें बहुत अच्छी हैं, हालांकि, आपको ऐनिमेशन का स्टटर नहीं दिखेगा. 60 एफ़पीएस (फ़्रेम प्रति सेकंड) पर, ऐप किसी भी व्यक्ति का ध्यान दिए बिना कभी-कभी फ़्रेम को छोड़ सकता है, एनिमेशन स्थिर दर से लगातार आगे बढ़ रहा है. आपको कितना फ़ायदा हो सकता है यह कुछ हद तक इस बात पर निर्भर करता है कि आप क्या बना रहे हैं, दिखाया गया है और ऐप्लिकेशन को इस्तेमाल करने वाला व्यक्ति जैंक का पता लगाने में कितना अच्छा है.

थ्रेड मैनेज करना

आम तौर पर, अगर SurfaceView, GLSurfaceView या TextureView में आपको इसे किसी डेडिकेटेड थ्रेड में रेंडर करना है. कभी कुछ न करें "बहुत ज़्यादा वज़न उठाना" या ऐसी किसी भी चीज़ का इस्तेमाल करने में यूज़र इंटरफ़ेस (यूआई) थ्रेड. इसके बजाय, गेम के लिए दो थ्रेड बनाएं: गेम थ्रेड और रेंडर थ्रेड. अपने गेम की परफ़ॉर्मेंस को बेहतर बनाना लेख पढ़ें हमारा वीडियो देखें.

ब्रेकआउट और "Record GL ऐप्लिकेशन" खास तौर पर रेंडरर थ्रेड का इस्तेमाल करता है और वे उस थ्रेड पर एनिमेशन स्थिति अपडेट करें. यह तरीका तब तक एक सही रहेगा, जब तक कि गेम की स्थिति को तुरंत अपडेट किया जा सकता है.

वहीं, कुछ गेम में गेम लॉजिक और रेंडरिंग को पूरी तरह से अलग कर दिया जाता है. अगर आपके पास एक आसान गेम, जिसमें हर 100 मि॰से॰ में ब्लॉक को हिलाने के अलावा कुछ और नहीं किया जा सकता. खास थ्रेड के लिए बनाया गया जिसने अभी-अभी ऐसा किया:

run() {
    Thread.sleep(100);
    synchronized (mLock) {
        moveBlock();
    }
}

(हो सकता है कि आप ड्रिफ़्ट होने से रोकने के लिए किसी तय घड़ी के समय को सोने का समय तय करना चाहें -- Sleep() पूरी तरह से संगत नहीं है और MoveBlock() को शून्य समय -- लेकिन आपको यह समझ आ गया होगा.)

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

किसी भी जटिलता वाले सीन के लिए, आपको आने वाले इवेंट की सूची बनानी है इन्हें जागने के समय और सोने के समय के हिसाब से क्रम में लगाया गया है. हालांकि, यह जानकारी पहले जैसी ही है सुझाव.