2011-12-18 6 views
12

मैं जीसीडी का उपयोग करके समय-समय पर पृष्ठभूमि में कोड ब्लॉक कैसे चला सकता हूं? मैं कई उपप्रणालीओं के साथ एक गेम इंजन लिखने की कोशिश कर रहा हूं, जैसे प्रतिपादन, भौतिकी, खेल तर्क और इसी तरह। कुछ कार्यों को घटना-संचालित होना चाहिए, लेकिन कुछ (भौतिकी प्रणाली की तरह) को पृष्ठभूमि में आवधिक रूप से निरंतर समय के साथ कहा जाना चाहिए (उदाहरण के लिए 1/100 सेकेंड के बाद)। मैंने कोड का एक ब्लॉक बनाया है, लेकिन मैं पृष्ठभूमि में समय-समय पर इस ब्लॉक को कैसे चला सकता हूं? क्या यहां जीसीडी सही उपकरण है?मैं जीसीडी का उपयोग करके समय-समय पर पृष्ठभूमि में कोड ब्लॉक कैसे चला सकता हूं?

उत्तर

10

आप जो चाहते हैं वह एक जीसीडी प्रेषण स्रोत है। नमूना कोड के लिए, Creating a Timer Example देखें।

6

टिप्पणियों में @matt नोट्स के रूप में, आप इसके लिए टाइमर प्रेषण स्रोतों का उपयोग कर सकते हैं। वहां सही दृष्टिकोण के लिए उसका जवाब देखें।

भावी पीढ़ी के लिए, यहाँ कुछ विकल्प के साथ अपने मूल जवाब है:

  1. अपने प्रस्तुत करना कॉलबैक में (जैसे कि, CADisplayLink का उपयोग), एक GCD काम है कि इस के लिए भौतिक विज्ञान की गणना करता है बंद आग (या अगले?) फ्रेम। यदि आपको प्रति रेंडर फ्रेम में एक से अधिक अपडेट करने की आवश्यकता है, तो बस उस जॉब लूप को दो बार लें।

  2. एक भौतिकी धागा है जो स्वयं को तब तक सोता है जब तक कि इसे कुछ गणना करने की आवश्यकता न हो। यदि आपके पास इसके लिए एक अलग धागा है, तो एनएसटीमर में आपके धागे को 100 हर्ट्ज पर उठाने के लिए पर्याप्त समाधान हो सकता है। (मुख्य धागे पर, यह काम नहीं करेगा क्योंकि रनलोप पर अन्य इनपुट स्रोत इसे तेजी से फायरिंग से रोक देंगे।) यदि एनएसटीमर काम नहीं करता है, तो बस गणना करें कि अगले भौतिकी अपडेट की आवश्यकता होने तक कितना समय बचा है और अपने धागे को सोएं (उदाहरण के लिए, [NSThread sleepForTimeInterval:])

  3. एक ब्लॉक है जो dispatch_after का उपयोग करता है।

कुछ इस तरह:

dispatch_time_t next = dispatch_time(DISPATCH_TIME_NOW, 0); 
block = ^{ 
    next = dispatch_time(next, 10000000L); // increment by 10 ms 
    // do physics here 
    dispatch_after(next, queue, block); 
} 

आप (अर्थात पता लगाने अगर अपने अगले समय पूर्व का है dispatch_after यह कॉल करने से पहले आदि), फ्रेम छोड़ने के बारे में थोड़ा होशियार होने के लिए आवश्यकता हो सकती है

+0

हाय, धन्यवाद। मेरा मुख्य लक्ष्य भौतिकी उपप्रणाली को प्रतिपादन से कम करना है, इसलिए मुझे लगता है कि आपका दूसरा जवाब मेरे लिए अधिक उपयुक्त है, हालांकि मैं अभी भी सोच रहा हूं कि क्या ब्लॉक और जीसीडी के साथ कोई समाधान है या नहीं। – asdf

+0

ठीक है। मैंने एक तीसरा विकल्प जोड़ा है। –

+1

"टाइमर प्रेषण स्रोत नियमित, समय-आधारित अंतराल पर ईवेंट उत्पन्न करते हैं। आप विशिष्ट कार्यों को शुरू करने के लिए टाइमर का उपयोग कर सकते हैं जिन्हें नियमित रूप से करने की आवश्यकता होती है। उदाहरण के लिए, गेम और अन्य ग्राफिक्स-गहन अनुप्रयोग स्क्रीन या एनीमेशन अपडेट शुरू करने के लिए टाइमर का उपयोग कर सकते हैं। " यदि वह जीसीडी नियमित आवधिक कार्यों का समर्थन नहीं करता है - और वास्तव में संदर्भ में ओपी पूछ रहा है - क्या है? – matt

3

स्विफ्ट में आप GCD का उपयोग कर टाइमर बना सकते हैं:

func CreateTimerDispatchSource(interval: UInt64, leeway: UInt64, queue: dispatch_queue_t, block: dispatch_block_t) -> dispatch_source_t { 
    let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue) 
    dispatch_source_set_timer(timer, dispatch_walltime(nil, 0), interval, leeway) 
    dispatch_source_set_event_handler(timer, block) 
    return timer; 
} 

var timer = CreateTimerDispatchSource(5*NSEC_PER_SEC, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
    // do some serious stuff 
} 

प्रारंभ या टाइमर फिर से शुरू:

dispatch_resume(timer) 

टाइमर को निलंबित: उत्तर के लिए

dispatch_suspend(timer)