जब कुछ होता है तो ध्वनि बजाने का अच्छा तरीका? यह कैसा लगता है?


10

इसलिए मैं इस बारे में सोच रहा था कि मेरी कक्षाओं को बहुत समय मिलता है। उदाहरण के लिए, Characterकक्षा की Jumpविधि में, किसी के पास एक ध्वनि प्रभाव वस्तु का संदर्भ हो सकता है और वह खेल सकता है। अपने आप से यह ठीक है लेकिन जब भौतिकी, एनीमेशन, टकराव, आदि को ध्यान में रखा जाता है, तो जंप विधि बहुत बड़ी हो जाती है और Characterकक्षा में कई अलग-अलग चीजों पर निर्भरता होती है। फिर भी, यह ठीक हो सकता है। हालांकि, क्या होगा अगर हम चरित्र को कूदने के लिए ध्वनि नहीं चाहते हैं? अब, हमें कोड की जंबल मेस में कोड की उस विशिष्ट लाइन को ढूंढना होगा Jumpऔर उसे कमेंट करना होगा या जो भी हो।

तो .. मैं सोच रहा था ..

क्या होगा अगर, इसके बजाय, किसी प्रकार की AudioSystemकक्षा थी और सभी ने इसे यादृच्छिक घटनाओं की सदस्यता दी थी जो अन्य वर्गों में रुचि रखते हैं। उदाहरण के लिए, Characterकक्षा में एक Jumpedघटना हो सकती है (स्थैतिक भी, मुझे लगता है) कि Characterविधि में वर्ग के भीतर उठाया जाता है । फिर, Characterवर्ग को छोटे ध्वनि प्रभाव के बारे में कुछ नहीं पता होगा जो चरित्र कूदता है। AudioSystemसिर्फ एक बहुत बड़ा वर्ग है कि प्रोग्रामर कुछ घटनाओं है कि स्थिर घटनाओं के उपयोग के माध्यम खेल में होती हैं साथ ध्वनि प्रभाव ऊपर हुक करने के लिए पीछे हटना सकता है किया जाएगा। फिर, अगर वह बहुत बड़ा हो गया ऐसा उपवर्गों में विभाजित किया जा सकता EffectsAudioSystem, BackgroundAudioSystem, AmbientAudioSystem, वगैरह।

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

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


5
एक ध्वनि विचार की तरह लगता है :) (अधिक गंभीर नोट पर: शिथिल युग्मित उप-प्रणालियों / कक्षाओं के बीच संचार के लिए संदेशों का उपयोग करना आम तौर पर एक अच्छा विचार डिजाइन-वार है)
bummzack

1
यह है कि यह कैसे किया जाता है, आपको अपने रेंडरिंग को एक अलग वर्ग में रखना चाहिए, यदि आप पहले से ही नहीं हैं (तो, आपको वर्ण वर्ग में कोई ड्रा) समारोह नहीं करना चाहिए।
dreta

जवाबों:


2

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

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

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

अतः अनावश्यक कक्षाओं की एक विशाल सूची होगी जो कि चरित्र और ऑडियो मैनजर के बीच एक गहरी युग्मन का परिचय देती है, सिवाय इसके कि अब यह सभी स्रोत-कोड में बिखरा हुआ है। चरित्र- और AudioManager- वर्गों में ही नहीं।

अभी भी अपने कोड को डिकूप करने के लिए एक अच्छा विचार है, लेकिन संदेश वास्तव में गहरी कपलिंग का सिर्फ एक और तरीका है। कुछ कोड को केवल युग्मित किया जाना है, उन्हें जोड़े जाने के लिए सबसे प्रत्यक्ष तरीके का उपयोग करें, ओवर-इंजीनियर न करें।


1
एक अच्छी तरह से डिजाइन की गई संदेश प्रणाली "गहरी कपलिंग का सिर्फ एक और तरीका" कैसे है? संदेश भेजना उन वस्तुओं के बिना पूर्ण न्यूनतम युग्मन है जो कभी संचार नहीं करते हैं। आपके द्वारा डिज़ाइन किया गया तरीका समस्याओं का कारण बन सकता है, लेकिन यदि सिस्टम केवल ध्वनि, स्थान लेता है, और यह उसकी सभी समस्याओं को हल करता है और आपके द्वारा सुझाई गई किसी भी चीज़ का परिचय नहीं देता है। ऑडियो सिस्टम को यह गणना नहीं करनी चाहिए कि कौन सी ध्वनि की आवश्यकता है, यह सभी सेटिंग्स को दूर करना चाहिए और अधिमानतः प्रसार मुद्दे। en.wikipedia.org/wiki/Coupling_(computer_programming)
ClassicThunder

1
@ClassicThunder बिंदु है व्यवहार में यह दृष्टिकोण बहुत अच्छी तरह से पैमाने पर नहीं है। यह सरल अनुप्रयोगों के लिए अच्छा काम करता है और जब तक आप सभी की जरूरत है एक सामान्य PlaySoundEvent है। लेकिन सवाल एक विशेष OnJump () - घटना को सुनने वाले AudioManager के बारे में है, इसलिए चरित्र को ऑडियो-काम से छुटकारा मिल सकता है। हालांकि यह एक साधारण PlaySoundEvent के मामले में नहीं होगा क्योंकि चरित्र को ध्वनि का चयन करना होगा और इसे AudioManager को भेजना होगा, जो ऑडियो कार्य से छुटकारा पाने के लिए OnJumpEvent को शुरू करने के मूल बिंदु को अमान्य करता है।
माईक सेमर

1
हालांकि OnJumpEvent का उपयोग करते समय, आप या तो घटना के लिए चरित्र के संदर्भ को जोड़ना या घटना में चरित्र से सभी महत्वपूर्ण डेटा की प्रतिलिपि चुन सकते हैं। बेशक आप सही हैं, उत्तरार्द्ध एक गहरी युग्मन को पेश नहीं करेगा, लेकिन यह डेटा दोहराव की समस्याओं और एक नए डेटा-पासिंग ऑब्जेक्ट से ग्रस्त होगा, जिसे अन्य सभी नई घटनाओं की तरह बनाए रखना होगा।
माईक सेमर

1
-1 कारण, जबकि मैं मानता हूं कि संदेशों का इतना विशेष (ऑनजंप) होने की संभावना एक बुरा विचार है, यह केवल एक लंबी 'नहीं यह एक बुरा विचार है' के बजाय व्यक्ति को एक PlaySound घटना बनाने के लिए उपयोगी जानकारी प्राप्त करने के लिए जो नाम लेता है एक ध्वनि प्रभाव और एक 3 डी स्थिति और / या वॉल्यूम पर यह हुआ।
जेम्स

@James इनपुट के लिए धन्यवाद, मेरे कहने का मतलब यह नहीं था कि PlaySound इवेंट का उपयोग करें, मेरा कहना था कि इवेंट्स GUI-डेटाबेस एप्लिकेशन के लिए एक अच्छा अमूर्त हैं, लेकिन एक जटिल गेम के लिए व्यावहारिक नहीं हैं।
मिक सेमर

2

मुझे नहीं लगता कि एक संदेश गुजर प्रणाली इंजीनियरिंग से अधिक है। वास्तव में यह पॉलिश चरण में काम करने के लिए नाटकीय रूप से आसान बना सकता है। आप इसे सही कर रहे हैं!

आपने जो वर्णन किया है वह वही है जो मैंने पिछले साल हमारे ग्लोबल गेम जैम गेम के लिए एक साथ फेंका था। मैं SFX को बनाने और संपादित करने के लिए ज़िम्मेदार था, और खुद को और एक अन्य संगीतकार ने इस खेल में एक तरह से लिखा था जिसे चूसना नहीं था।

एक ऑडियो परिप्रेक्ष्य से इस दृष्टिकोण के बारे में बहुत अच्छी बात यह है कि यह आपको अपनी ध्वनि के साथ कई और दिलचस्प चीजें करने की अनुमति देता है। अगर आपको लगता है कि किसी गेम में साउंड इफेक्ट महज एक साउंड फाइल, वॉल्यूम और पैनिंग है, तो आप गलत कर रहे हैं।

उदाहरण

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

अगर मैं इसे C ++ में लिखता, तो सभी संभव व्यवहार ध्वनियों को अमूर्त करने में थोड़ा और समय लगता। किसी सिस्टम द्वारा की गई कार्रवाई को सूचित करने वाले संदेश की आवश्यकताएं बहुत जटिल नहीं होंगी। इसके लिए केवल संदेश प्रकार, उत्पत्ति की वस्तु या वस्तु प्रभावित होना, किसी प्रकार की खेल स्थिति के संदर्भ तक पहुंच और बहुत कुछ नहीं होना चाहिए। खेल की ज़रूरतें बढ़ने पर प्रोटोकॉल बढ़ सकता है। स्वाभाविक रूप से, यदि आप कोड के कार्यान्वयन में यह सब करते हैं (जैसे हमारे घटिया जीजीजे कोड), तो आपको एक बदतर अखंड वर्ग समस्या है। लेकिन यह आसानी से एक डेटा-संचालित प्रणाली बनाकर कम किया जाता है।

वैसे भी, यहाँ हमारे गेम ऑडियो सिस्टम ने विभिन्न संदेशों पर क्या प्रतिक्रिया दी है:

  • खिलाड़ी ग्रह से टकराता है: यह एक ग्रह विस्फोट ध्वनि को ट्रिगर करेगा, जो पर्याप्त रूप से बुनियादी है। इसके तुरंत बाद यह चल रहे कॉम्बो काउंटर को क्वेरी करेगा। यदि यह पर्याप्त होता तो यह ध्वनि प्रभाव को आधा सेकंड या तो बाद में एक डायनोसोर की जीत की गर्जना के साथ चलाया जाता। इसके अलावा पृष्ठभूमि में एक यादृच्छिक ग्रह जनसंख्या मूल्य की गणना की गई थी (600 से 3000 की तरह कुछ - मुझे नहीं पता कि उस सीमा को क्यों चुना गया था, यह कुछ परित्यक्त गेमप्ले मैकेनिक था और अभी भी मेरे चारों ओर झूठ बोल रहा था ऑडियो को रोचक बनाने के लिए उपयोग करने के लिए), और इसलिए मैंने चिल्ला के दूर की ध्वनि की मात्रा को मापने के लिए इसका इस्तेमाल किया (असामयिक भाग्य से मिलने वाले ग्रह के नागरिक)।

  • त्वरण के लिए प्लेयर स्पेसबार रखता है: इसे प्राप्त करने पर थोड़ा "हूश" थ्रस्टर साउंड बजाया जाता था, लेकिन साथ ही साथ एक कम लूप वाला इंजन दहाड़ भी 1.5 सेकंड से ऊपर चला गया। कण प्रणाली ने इसका उपयोग एक उत्सर्जक IIRC में आग लगाने के लिए भी किया था

  • प्लेयर डिस्क्रिमिनेशन के लिए स्पेसबार को जाने देता है: अब जब प्लेयर ने स्पेसबार को जाने दिया था, तो ऑडियो सिस्टम को पता था कि उसे इंजन लूप को वापस रैंप पर लाना है। अगर मेरे पास अधिक समय होता तो मैं उस पर एक और ध्वनि डालना पसंद करता जो कि एक प्रकार की ध्वनि के नीचे की तरह पिचकारी थी।

  • प्लेयर खराब स्पेस के साथ टकराता है: स्पेस माइंस खराब होती है, इसलिए न केवल एक धमाके के साथ एक मेटलिक इफेक्ट साउंड होता है (जो कि सिर्फ एक साउंड में बेक किया जाता है), बल्कि एक बेतरतीब ढंग से चुनी गई डायनोसोर डिसैस साउंड भी होती है। यह अधिक "रोने" का चयन करने की संभावना है जैसे कि खिलाड़ी का स्वास्थ्य कम हो जाता है।

एक पहले से ही मजेदार खेल खेलने के लिए एक सुखद हो जाता है, जब इसका साउंडट्रैक सक्रिय और गतिशील होता है, यहां तक ​​कि जैसा कि मैंने ऊपर वर्णित किया है, केवल थोड़े सरल व्यवहारों के साथ। हाँ, सही डेटा पास होने के बारे में सुनिश्चित करने के लिए काम करने के लिए कुछ रसद हैं। लेकिन हे, बीएफडी। यह गेम कोड के बड़े दायरे में आपको लिखी गई सबसे जटिल चीज़ से दूर होगा।

वास्तव में, FMOD और Wwise इसी तरह काम करते हैं। उनके पास एक केंद्रीय संदेश प्रेषणकर्ता नहीं है, लेकिन आप प्रभावी रूप से अपने केंद्रीय सिस्टम में घटनाओं को पोस्ट करते हैं और वे एक ध्वनि प्रभाव खेलकर प्रतिक्रिया करते हैं जो एक संलेखन उपकरण में एक ऑडियो कार्यान्वयनकर्ता द्वारा पूर्व-डिज़ाइन किया गया था। इसे अपने गेम को एक लाइव डीजे देने की तरह सोचें। वह बैठता है और देखता है कि क्या चल रहा है, और चीजों को दिलचस्प रखने के लिए सही समय पर ध्वनि क्लिप को ट्रिगर करता है, उन्हें मिश्रण करता है ताकि वे preexisting ऑडियो वातावरण में अच्छी तरह से फिट हो सकें।

[संपादित करें] इसके अलावा, मुझे लगता है कि आपने इस C # को टैग किया है। क्या यह XNA है, और यदि आप XACT का उपयोग कर रहे हैं? यदि आप XNA का उपयोग कर रहे हैं तो आपको XACT का उपयोग करना चाहिए।


1
यह एक छोटी परियोजना के लिए काम कर सकता है, यह मजेदार भी हो सकता है। हालाँकि एक बड़ी संख्या में आप बड़ी संख्या में संदेश कक्षाओं के साथ समाप्त होते हैं, जिन्हें बनाए रखने की आवश्यकता होती है, जबकि एक साधारण फ़ंक्शन-कॉल का एक ही प्रभाव होता। यही कारण है कि घटना प्रणाली अच्छी तरह से पैमाने पर नहीं होती है, इस परियोजना को जितना बड़ा हो जाता है उसका प्रबंधन करना मुश्किल हो जाता है।
मिक सेमर

1
Btw हम अपने स्टूडियो में FMOD के साथ काम करते हैं, कोई संदेश / इवेंट-सिस्टम नहीं है, आप FMOD को इवेंट नहीं भेजते हैं, आप बस कुछ खेलने के लिए एक c-function या c ++ मेथड कहते हैं। वे बस अपनी आवाज़ को "ईवेंट" कहते हैं, जो इसे एक ईवेंट सिस्टम नहीं बनाती है, इसका सिर्फ एक शब्द है जो वे ध्वनि के बजाय उपयोग करते हैं।
मिक सेमर

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

@MaikSemder कैसे विधि कॉल अपने स्वयं के पेचीदा जाल में समाप्त नहीं होते हैं? इसके अलावा, मैंने एक इवेंट सिस्टम और Wwise और FMOD द्वारा उपयोग की जाने वाली "घटनाओं" के बीच उस अंतर पर ध्यान देने की कोशिश की। मुझे जो विचार मिल रहा है, वह यह है कि जटिल ऑडियो लॉजिक गेम ऑब्जेक्ट क्लासेस में नहीं है, और साउंड लॉजिक को अमूर्त करने से ऐसा होता है कि इंटरफ़ेस किसी ईवेंट को भेजने के लिए समान है, इससे रिच ऑडियो लॉजिक होना आसान हो जाता है। मैं वास्तव में EventManager->dispatch("Sound:PlayerJump")और बीच थोड़ा कार्यात्मक अंतर देखता हूं soundSystem->playFMODEvent("/MyGame/Player/Jump")
michael.bartnett

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

0

मैं माईक सेमर से सहमत हूं, कि एक संदेश पासिंग सिस्टम ओवर-इंजीनियरिंग (अब वैसे भी) हो सकता है।

जो मैं समझता हूं, वर्तमान में आपका वर्ग ब्योर्न "अखंड वर्ग" जैसा दिखता है, जैसा कि यहां "एक अखंड वर्ग" में देखा जा सकता है

मेरा सुझाव है कि आप उस लेख को पढ़ें, और, हालांकि एक पूर्ण घटक प्रणाली अभी के लिए ओवरकिल हो जाएगी, यदि आप "बाकी को अलग करना" पढ़ते हैं, तो इससे आपको अपने व्यवहारों को सार करने का एक अच्छा तरीका मिल सकता है और अंततः शायद और अधिक जटिल हो सकता है समाधान। यह वैसे भी शुरू करने के लिए आपको एक अच्छा आधार देगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.