नींद का उपयोग करके एक ही थ्रेड में रेंडर / ड्राइंग कोड से तर्क / अद्यतन को अलग करना


9

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

मेरा वर्तमान छद्म कोड इस प्रकार है

loop
{
    draw();
    if (ticksElapsed() > 100)
    {
        update();
        ticks+= ticksElapsed();
    }        
}

समस्या यह है कि ड्राइंग कोड अपडेट () दर के प्रदर्शन में बाधा डालता है। और यह 100% सीपीयू की खपत करता है क्योंकि यदि नींद अंदर फेंक दी जाती है, तो यह ड्राइंग / तर्क कार्यों दोनों को फेंक देता है।

मैं भी SDL का उपयोग कर रहा हूँ और यह एक vsync विकल्प नहीं है। मैंने निश्चित और परिवर्तनीय समय-चरण के बारे में भी सुना है लेकिन मुझे यकीन नहीं है कि नींद के साथ कैसे किया जा सकता है ()


1
आपको प्रतीक्षा करने के लिए केवल 100% सीपीयू बिजली बर्बाद करने की आवश्यकता नहीं है, टिक के अंत में एक नींद (0) डाल दें यदि टिकलेसैप्स () <100। ओएस थ्रेड में तुरंत वापस आ जाएगा यदि कोई अन्य धागा नहीं है जो चलाना चाहता है। लेकिन अब 100% सीपीयू बिजली बर्बाद नहीं कर रहे हैं।
माईक सेमर

हालांकि, इस तरह के 1 थ्रेड सेटअप के लिए सबसे अच्छा समाधान vsync का उपयोग करना है, यदि आप vsync का उपयोग नहीं कर सकते हैं, तो स्लीप (0) को लूप में कॉल करें जब तक कि आप लक्ष्य फ्रेम दर तक नहीं पहुंच जाते हैं, तब अपडेट करें और ड्रा करें
Maik Semder

जवाबों:


3

आपके कोड स्निपेट में ऐसा लगता है कि आप व्यस्त-प्रतीक्षा करके अपने गेम को निश्चित-समय चरण मोड में चलाने की कोशिश कर रहे हैं यदि आपका ड्राइंग और अपडेट कम हो गया है तो 15ms (60fps)। यह संभव है और आपने सही अनुमान लगाया कि यह नींद की कॉल का उपयोग करके नहीं किया जा सकता है क्योंकि आप वास्तव में नहीं जानते हैं कि आप कितने समय तक सोने जा रहे हैं। व्यस्त-वेटिंग-लूप अच्छा समाधान है।

हालांकि उस मामले पर विचार करें जहां आपका अपडेट और ड्राइंग 15ms से अधिक है, अब आपके पास गेम ड्रॉइंग है और धीमी गति से अपडेट हो रहा है। अब आप या तो दो काम कर सकते हैं: इस स्थिति का पता लगाएं और फ़्रेम को छोड़ें (ड्राइंग को छोड़ें और तब तक अपडेट करने के लिए सीधे जाएं जब तक कि आप फिर से सिंक में न हों) हालांकि अगर कंप्यूटर को धीमा करना है तो यह कभी भी पकड़ में नहीं आएगा।

एक अन्य उपाय यह है कि आप अपने अपडेट लॉजिक को निश्चित-समय स्वतंत्र करें। इसके लिए आपको एक अलग थ्रेड की आवश्यकता नहीं है, आपको बस इस बात का सम्मान करना है कि चीजों को कितनी तेजी से आगे बढ़ना चाहिए। प्रति टिक 5pixels के बजाय, आपको 50pixels प्रति सेकंड का उपयोग करना चाहिए। इसे प्राप्त करने के लिए आपको एक उच्च परिशुद्धता टाइमर की आवश्यकता होगी, और आपके सभी अपडेट लॉजिक को टाइमर तक पहुंचने में सक्षम होना चाहिए, यह देखने के लिए कि अंतिम अपडेट के बाद कितना समय बीत चुका है।

मूल रूप से आप से जाना:

void UpdatePlayer()
 player.x += 10;

सेवा

void UpdatePlayer(float elapsedSeconds) //the total seconds elapsed since last update
 player.x += walkspeed * elapsedSeconds;

तो मेरा इंजन हमेशा 100% खपत करेगा और ऐसा कुछ भी नहीं है जो मैं वास्तव में इसके बारे में कर सकता हूं?
ओस्केंसो काशी

1
यह उतना ही चक्र का उपभोग करेगा जितना कि अनुसूचक इसे प्राप्त करने की अनुमति देता है, लेकिन यह वास्तव में एक मुद्दा नहीं है क्योंकि आप वास्तव में बहुत सारे अन्य काम नहीं कर सकते हैं जब आप एक खेल खेल रहे हैं :)।
रॉय टी।

@ ऑस्केंसो हालांकि, यह एक समस्या है यदि आप 1 से अधिक धागे का उपयोग करते हैं, तो मुख्य धागा दूसरों को जितना संभव हो उतना चलने नहीं देगा, जबकि लूप में बहुत सारी कम्प्यूटेशनल शक्ति बर्बाद कर रहे हैं, आपको वास्तव में एक नींद पर विचार करना चाहिए
Maik सेमर

@ माईक सेमर: क्या आपके पास नींद का कोई हल है (एक्स) सही नहीं है? नींद के अंतराल बीत जाने के बाद, धागा चलाने के लिए तैयार है। लेकिन एक तैयार धागे को तुरंत चलाने की गारंटी नहीं है। यह शेड्यूलर पर निर्भर है। जब आप दो थ्रेड का उपयोग कर रहे हैं, तो अन्य समाधान हैं, इसके लिए यह उत्कृष्ट लेख देखें: altdevblogaday.com/2011/07/03/threading-and-your-game-loop
Roy T.

1
@ रो नींद (0) समाधान है। यदि कोई अन्य धागा है जो चलाना चाहता है ( स्लीप WinAPI ) और अन्य थ्रेड को चलाने का मौका देता है, तो यह तुरंत वापस आ जाता है । यदि दूसरा धागा मुख्य धागे को बदले में चलाने का मौका नहीं देगा, तो आपके पास एक थ्रेडिंग समस्या है, लेकिन पहली जगह में नींद न बुलाकर बाकी सब को अवरुद्ध करना इसे और भी बदतर बना देता है और शायद ही कोई समाधान हो। कुंजी नींद (0) को कॉल करने और बीता हुआ समय का परीक्षण करने के लिए है जब तक कि आप अपने लक्ष्य तय फ्रेम दर को हिट नहीं करते हैं, इसलिए आप प्रतीक्षा करने के लिए केवल 100% सीपीयू बर्बाद नहीं करते हैं।
मिक सेमर जूल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.