एक्सबॉक्स कंट्रोलर को एब्सट्रैक्ट करने का सही तरीका


12

मुझे एक XBox360 कंट्रोलर मिला है जिसे मैं एक एप्लिकेशन के लिए इनपुट के रूप में उपयोग करना चाहता हूं।

क्या मैं बाहर काम नहीं कर सकता एक इंटरफ़ेस के माध्यम से इसे उजागर करने का सबसे अच्छा अभ्यास तरीका है।

पर्दे के पीछे, नियंत्रक (एस) को संभालने वाला वर्ग पोलिंग बटन की स्थिति पर निर्भर करता है।

मैंने शुरू में कुछ लिंक की कोशिश की:

Event ButtonPressed() as ButtonEnum

कहाँ ButtonEnumथा ButtonRed, ButtonStartआदि ...

यह थोड़ा सीमित है कि यह केवल बटन प्रेस का समर्थन करता है, न कि होल्ड / पैटर्न (दो बार प्रेस, आदि)

अगला विचार यह था कि बटन स्टेट को ऐप जैसे ही एक्सपेक्ट किया जाए

Property RedPressed as Boolean
Property StartPressed as Boolean
Property Thumb1XAxis as Double

यह बहुत लचीला है, लेकिन वास्तव में यह ऐप में बहुत अधिक काम करता है और ऐप को पोल करने की आवश्यकता होती है - यदि संभव हो तो मैं ईवेंट संचालित करना पसंद करूंगा।

मैंने कई घटनाओं को जोड़ना माना जैसे:

Event ButtonPressed(Button as ButtonEnum)
Event ButtonPressedTwice(Button as ButtonEnum)
Event ButtonHeldStart(Button as ButtonEnum)
Event ButtonHeldEnd(Button as ButtonEnum)

लेकिन यह थोड़ा भद्दा लगता है और "बिंद बटन" स्क्रीन पर एक वास्तविक दर्द था।

क्या कोई कृपया मुझे नियंत्रकों से इनपुट को संभालने के लिए "सही" तरीके से इंगित कर सकता है।

NB: मैं जो इंटरफ़ेस लागू करता है वर्ग के अंदर SlimDX का उपयोग कर रहा हूं। यह मुझे बहुत आसानी से राज्य पढ़ने की अनुमति देता है। कोई भी विकल्प जो मेरी समस्या का समाधान करेगा, उसकी भी सराहना की जाएगी

जवाबों:


21

कोई भी सही मानचित्रण नहीं है जो आपको एक मंच विशिष्ट अमूर्तता प्रदान करता है, क्योंकि जाहिर है कि 360 नियंत्रक के लिए समझ में आने वाले अधिकांश पहचानकर्ता एक प्लेस्टेशन नियंत्रक (सर्कल के बजाय ए, बी, बी के बजाय) के लिए गलत हैं। और निश्चित रूप से एक Wii नियंत्रक पूरी तरह से एक और बात है।

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

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

ऊपरी परत खेल की परत है। यह आवेग लेता है, और परवाह नहीं करता है कि वे कैसे उत्पन्न हुए थे। शायद वे एक नियंत्रक से आए थे, या एक नियंत्रक की रिकॉर्डिंग, या शायद वे एक एआई से आए थे। इस स्तर पर, आप परवाह नहीं करते हैं। आप जो परवाह करते हैं, वह यह है कि एक नया जंप आवेग है, या कि त्वरक आवेग जारी है, या कि डाइव आवेग का मूल्य 0.35 है इस टिक।

इस तरह की प्रणाली के साथ, आप प्रत्येक नियंत्रक के लिए एक बार नीचे की परत लिखते हैं। ऊपरी परत प्लेटफ़ॉर्म स्वतंत्र है। मध्य परत के लिए कोड को केवल एक बार लिखा जाना चाहिए, लेकिन प्रत्येक प्लेटफॉर्म / कंट्रोलर के लिए डेटा (रीमैपिंग) की आवश्यकता होती है।


यह बहुत साफ और सुरुचिपूर्ण दृष्टिकोण की तरह लगता है। धन्यवाद!
बेसिक

1
बहुत अच्छा। मेरी तुलना में बहुत बेहतर: पी
जोर्डन मायलोनास 22

3
बहुत अच्छा अमूर्तता। लेकिन लागू करते समय सावधान रहें: हर उपयोगकर्ता कार्रवाई के लिए नई आवेग वस्तु का निर्माण और विनाश न करें। पूलिंग का प्रयोग करें। कचरा उठाने वाला आपको धन्यवाद देगा।
grega g

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

@grega आप दोनों को धन्यवाद - मैंने ऐसा नहीं सोचा था।
बेसिक

1

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

निचले स्तर को "मतदान आधारित" स्तर माना जा सकता है, और एक बटन की वर्तमान स्थिति को उजागर करता है। ऐसा ही एक अंतरफलक बस 2 कार्य हो सकता है, GetAnalogState(InputIdentifier)और GetDigitalState(InputIdentifier)जहां InputIdentifierका प्रतिनिधित्व कौन सा बटन, ट्रिगर एक enumerated मूल्य है या आप के खिलाफ कर रहे हैं जाँच चिपके रहते हैं। (एक बटन के लिए GetAnalogState चल रहा है 1.0 या 0.0 लौटेगा, और एक एनालॉग स्टिक के लिए GetDigitalState चलाने से पूर्व निर्धारित दहलीज या सही अन्यथा सच हो जाएगा)।

दूसरा स्तर तब राज्य परिवर्तन पर घटनाओं को उत्पन्न करने के लिए निचले स्तर का उपयोग करेगा, और तत्वों को कॉलबैक के लिए पंजीकरण करने की अनुमति देगा (C # घटनाक्रम शानदार हैं)। इन कॉलबैक में प्रेस, रिलीज़, टैप, लॉन्गहोल्ड इत्यादि की घटनाएँ शामिल होंगी। एक एनालॉग स्टिक के लिए, आप इशारों को शामिल कर सकते हैं, जैसे कि फाइटिंग गेम के लिए QCF। उजागर होने वाली घटनाओं की संख्या इस बात पर निर्भर करती है कि आपके द्वारा प्रेषित की जाने वाली घटना कितनी विस्तृत है। आप बस एक साधारण आग लगा सकते हैं ButtonStateChanged(InputIdentifier)यदि आप अलग तर्क में सब कुछ संभालना चाहते थे।

इसलिए, यदि आपको इनपुट बटन या नियंत्रण स्टिक की वर्तमान स्थिति की जांच करने की आवश्यकता है, तो निचले स्तर की जांच करें। यदि आप किसी इनपुट ईवेंट पर केवल एक फंक्शन को बंद करना चाहते हैं, तो दूसरी टियर से कॉलबैक के लिए पंजीकरण करें।

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