कीबोर्ड इनपुट सिस्टम हैंडलिंग


13

नोट: मुझे API सीमाओं (SFML) के कारण कॉलबैक करने के बजाय चुनाव करना है। मैं एक 'सभ्य' शीर्षक की कमी के लिए भी माफी माँगता हूँ।

मुझे लगता है कि मेरे यहाँ दो प्रश्न हैं; मुझे प्राप्त होने वाले इनपुट को कैसे पंजीकृत करना है, और इसके साथ क्या करना है।

इनपुट संभालना

मैं इस तथ्य के बाद बात कर रहा हूं कि आपने पंजीकृत किया है कि 'ए' कुंजी को दबाया गया है, उदाहरण के लिए, और वहां से इसे कैसे करना है।

मैंने पूरे कीबोर्ड की एक सरणी देखी है, जैसे कुछ:

bool keyboard[256]; //And each input loop check the state of every key on the keyboard

लेकिन यह अक्षम लगता है। उदाहरण के लिए, न केवल आप 'ए' को 'प्लेयर को लेफ्ट मूव' कर रहे हैं, बल्कि यह हर कुंजी को 30-60 बार चेक करता है।

मैंने तब एक और प्रणाली की कोशिश की, जो सिर्फ चाबी की तलाश में थी।

std::map< unsigned char, Key> keyMap; //Key stores the keycode, and whether it's been pressed. Then, I declare a load of const unsigned char called 'Quit' or 'PlayerLeft'.
input->BindKey(Keys::PlayerLeft, KeyCode::A); //so now you can check if PlayerLeft, rather than if A.

हालाँकि, इसके साथ समस्या यह है कि मैं अब एक नाम नहीं लिख सकता, उदाहरण के लिए, हर एक कुंजी को बाँधने के बिना।

फिर, मेरे पास दूसरी समस्या है, जिसके लिए मैं वास्तव में एक अच्छा समाधान नहीं सोच सकता:

इनपुट भेज रहा है

अब मुझे पता है कि A कुंजी दबा दी गई है या वह खिलाड़ी है जो सही है। लेकिन मैं यहां से कैसे जाऊं?

मैंने सोचा कि बस if(input->IsKeyDown(Key::PlayerLeft) { player.MoveLeft(); }
इस कपल ने संस्थाओं के लिए इनपुट की बहुत जाँच की है, और मुझे यह गड़बड़ लगता है। जब यह अद्यतन हो जाता है तो मैं अपने स्वयं के आंदोलन को संभालना पसंद करूंगा। मुझे लगा कि किसी प्रकार की घटना प्रणाली काम कर सकती है, लेकिन मुझे नहीं पता कि इसके साथ कैसे जाना है। (मैंने सुना है कि इस तरह के काम के लिए सिग्नल और स्लॉट अच्छे थे, लेकिन यह स्पष्ट रूप से बहुत धीमा है और मैं यह नहीं देख सकता कि यह कैसे फिट होगा)।

धन्यवाद।

जवाबों:


7

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

आम तौर पर गेम ऑब्जेक्ट में एक इनपुट हैंडलिंग घटक होता है जो इनपुट क्लास के साथ खुद को पंजीकृत करने और उन घटनाओं को संभालने के लिए तरीके प्रदान करने के लिए ज़िम्मेदार है जो इसमें रुचि रखते हैं। आंदोलन के लिए, मेरे पास एक इनपुट मूवर घटक है जिसमें एक चाल (x, y) विधि है। यह इनपुट प्रणाली के साथ खुद को पंजीकृत करता है और आंदोलन की घटनाओं (जहां x और y बाएं चलने को सूचित करने के लिए -1 और 0 होगा) पर अधिसूचित हो जाता है, मूवर घटक फिर आंदोलन की दिशा और ऑब्जेक्ट वेग के आधार पर अपने मूल खेल ऑब्जेक्ट निर्देशांक को बदलता है।

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


यह निश्चित रूप से मुझे दिलचस्पी देता है; क्या इनपुट घटक कुछ घटनाओं के लिए खुद को पंजीकृत करेगा (खिलाड़ी इनपुट रजिस्टरों की तरह 'लेफ्ट', 'राइट' इत्यादि) या हर इनपुट घटक जो पंजीकृत है, सभी संदेश प्राप्त करेगा?
कम्युनिस्ट डक

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

6

मुझे लगता है कि ओपी की चर्चा एक साथ चीजों का एक समूह है, और यह कि समस्या को थोड़ा सा तोड़कर काफी हद तक सरल किया जा सकता है।

मेरा सुझाव:

अपनी चाबियों की स्थिति रखें। क्या एक बार में संपूर्ण कीबोर्ड स्थिति प्राप्त करने के लिए API कॉल नहीं है? (मेरा अधिकांश काम कंसोल पर है, और यहां तक ​​कि विंडोज पर कनेक्टेड कंट्रोलर के लिए आपको एक ही बार में पूरा कंट्रोलर स्टेट मिल जाता है।) आपकी की-बोर्ड कीबोर्ड की चाबी पर एक "हार्ड" मैप है। अनट्रांसलेटेड सबसे अच्छा है, लेकिन फिर भी आप इसे एपीआई से आसानी से प्राप्त कर सकते हैं।

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

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

अंत में, उन प्रमुख क्रियाओं को किसी तरह संभालें। गति के लिए आप कुछ मुश्किल करना चाहते हैं, "आगे बढ़ने के लिए" W 'नीचे अनुवाद करें, "लेकिन यह एक द्विआधारी समाधान होने की आवश्यकता नहीं है; आपके पास "W डाउन डाउन" का मतलब है "X द्वारा वेलोसिटी बढ़ाना जब तक कि अधिकतम Y नहीं," और "W अप" हो, "Z द्वारा वेलोसिटी को घटाएं जब तक कि यह शून्य को हिट न कर दे।" सामान्यतया- आप चाहते हैं कि आपका "गेम सिस्टम में कंट्रोलर हैंडलिंग इंटरफ़ेस" बहुत संकीर्ण हो; सभी प्रमुख अनुवाद एक ही स्थान पर करें और फिर हर जगह के परिणामों का उपयोग करें। यह देखने के लिए सीधे जाँच के विपरीत है कि क्या स्पेसबार को कोड में कहीं भी यादृच्छिक रूप से दबाया गया है, क्योंकि यदि यह किसी यादृच्छिक स्थान पर है तो संभवत: यह कुछ यादृच्छिक समय पर हिट हो जाएगा जब आप इसे नहीं चाहते हैं, और आप बस डॉन ' टी उस से निपटने के लिए चाहते हैं ...

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


क्या आपको नहीं लगता कि ग्राफिक फ़्रेमों में घटनाओं को बाँधना गंदा है? मुझे लगता है कि अलग हो जाना चाहिए।
जो तो

मेरा मतलब है, मुझे लगता है कि लगभग सभी मामलों में खिलाड़ी इनपुट कार्ड की तुलना में धीमी हो जाएगी ग्राफिक्स कार्ड से फ्रेम निकल जाएगा, लेकिन वास्तव में उन्हें स्वतंत्र होना चाहिए, और वास्तव में वे अन्य प्रकार के इवेंट के लिए हैं, जैसे कि नेटवर्क से एकत्र किए गए हैं। ।
जो तो

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

3

SFML में, आपके पास KeyPressed इवेंट प्रकार के साथ दबाए गए क्रम में चाबियाँ हैं। आप प्रत्येक कुंजी को थोड़ी देर में संसाधित करते हैं (getNextEvent ())।

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

आपके दूसरे प्रश्न के बारे में, मैं आपको इसे इस तरह रखने की सलाह दूंगा क्योंकि यह आपके गेमप्ले को ट्विस्ट करना आसान बनाता है। यदि आप सिग्नल या इस तरह का उपयोग करते हैं, तो आपको "RunKeyDown" के लिए एक स्लॉट बनाना होगा और दूसरा "JumpKeySlot" के लिए। लेकिन क्या होगा अगर आपके खेल में, दोनों को दबाए जाने पर एक विशेष कार्रवाई की जाती है?

यदि आप इनपुट और संस्थाओं को सजाने के लिए चाहते हैं, तो आप अपने इनपुट को एक राज्य बना सकते हैं (RunKey = true, FireKey = false, ...) और इसे खिलाड़ी को भेजें जैसे कि आप अपने AI पर कोई अन्य ईवेंट भेजें।


मैं कीबोर्ड इवेंट्स को sf :: इवेंट, बल्कि sf :: इनपुट के साथ हैंडल नहीं कर रहा हूं, क्योंकि यह रीयल-टाइम डिटेक्शन IIRC है। मैंने इसे एपीआई-अज्ञेय के रूप में संभव रखने की कोशिश की। : पी (प्रश्न, वह है)
द कम्युनिस्ट डक

1
लेकिन मुझे लगता है कि Calvin1602 की बात यह है कि "मुझे चुनाव करना है, बल्कि API सीमाओं (SFML) के कारण कॉलबैक करने के प्रश्न में आपका मूल कथन सही नहीं है" आपके पास ईवेंट हैं, इसलिए जब आप किसी ईवेंट को हैंडल करते हैं तो कॉलबैक जारी कर सकते हैं।
काइलोटन

3

सही समाधान अक्सर आपके द्वारा चर्चा की जाने वाली दो विधियों का एक संयोजन है:

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

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

तो, आप गेमप्ले इनपुट के लिए चयनात्मक मतदान का उपयोग करना चाहते हैं, और नाम टाइपिंग इनपुट के लिए इवेंट हैंडलिंग (या यदि इवेंट हैंडलिंग उपलब्ध नहीं है तो सभी कीबोर्ड मतदान)।


1

मुझे डैश-टॉम-बैंग का जवाब बहुत पसंद है, यह वास्तव में कुछ पहलुओं पर प्रकाश डालता है जिन्हें आपको इनपुट सिस्टम को डिज़ाइन करते समय ध्यान में रखना चाहिए।

मैं थोड़ा ट्यूटोरियल जोड़ना चाहूंगा, जिस पर मैं एक ही दिशा में जाता हूं (इनपुट संदर्भों, 3 परतों सहित ...):

http://www.gamedev.net/blog/355/entry-2250186-designing-a-robust-input-handling-system-for-games/

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