क्या यह स्क्रीन पर माउस की स्थिति को "मैप" करने के लिए एक बुरा विचार है ताकि टकराव का पता लगाने के संकल्प की परवाह किए बिना काम करे?


16

एक गेम पर विचार करें जिसका डिफ़ॉल्ट रिज़ॉल्यूशन 800x600 है। टकराव मास्क के साथ वस्तुओं को 800x600 आकार की गेम दुनिया में रखा गया है। जब माउस उनसे टकराता है तो टकराव के मुखौटे का पता लगा सकता है।

अब विचार करें कि हम 1024x768 तक गेम को स्केल करते हैं (मान लें कि हम ग्राफिक्स को एक परत तक सब कुछ प्रदान करके और फिर एक ही बार में पूरी परत को स्केल करते हैं)। इस नए रिज़ॉल्यूशन में माउस के ठीक से काम करने के लिए हमारे पास दो विकल्प हैं:

A.) दुनिया को 1024x768 तक स्केल करें और हर वस्तु के टकराव के हिसाब से स्केल करें।

बी) "मैप" मूल दुनिया (800x600) पर माउस की स्थिति।

"मानचित्र" से मेरा मतलब है कि मूल 800x600 दुनिया पर माउस की स्थिति को मापता है। उदाहरण के लिए, यदि स्क्रीन पर माउस की स्थिति (1024, 768) है, तो दुनिया में माउस की स्थिति (800, 600) है।

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

मुझे किस विधि के साथ जाना चाहिए: ए, बी, या कुछ और?


2
जैसा कि क्लासिक थंडर द्वारा बताया गया है, प्रदर्शन निर्देशांक दुनिया के निर्देशांक या ऑब्जेक्ट निर्देशांक के समान नहीं होना चाहिए। आमतौर पर आप रूपांतरण चाहते हैं (मूल रूप से, जैसा कि आप मैपिंग कहते हैं , लेकिन आमतौर पर मैट्रिक्स गणित के साथ किया जाता है)।
दान

जवाबों:


38

आमतौर पर (2 डी गेम के लिए भी) खेल के लिए एक अलग समन्वय प्रणाली है जो संकल्प से स्वतंत्र है, इसे आमतौर पर विश्व अंतरिक्ष के रूप में जाना जाता है। यह आपको एक मनमाना रिज़ॉल्यूशन स्केल करने की अनुमति देता है।

इसे प्राप्त करने का सबसे आसान तरीका 2 डी कैमरा है, जो अनिवार्य रूप से एक मैट्रिक्स है जो विश्व अंतरिक्ष (आपकी मनमानी इकाइयों) से स्क्रीन स्पेस (स्क्रीन पर पिक्सल) में संक्रमण को परिभाषित करता है। यह गणित के साथ काम करता है तुच्छ।

XNA 2d कैमरा स्क्रॉलिंग में नीचे के भाग पर एक नज़र डालें - मैट्रिक्स ट्रांसफ़ॉर्मेशन का उपयोग क्यों करें?

यह समन्वय प्रणाली परिभाषाओं के बीच रूपांतरण करना वास्तव में आसान बनाता है

स्क्रीन से वर्ल्ड स्पेस में जाने के लिए बस वेक्टर 2 का उपयोग करें। यह आमतौर पर ऑब्जेक्ट पिकिंग के लिए दुनिया में माउस का स्थान प्राप्त करने के लिए उपयोग किया जाता है।

Vector2.Transform(mouseLocation, Matrix.Invert(Camera.TransformMatrix));

दुनिया से स्क्रीन स्पेस में जाने के लिए बस इसके विपरीत करें।

Vector2.Transform(mouseLocation, Camera.TransformMatrix);

एक मैट्रिक्स का उपयोग करने के अलावा कोई कमियां नहीं है, क्योंकि इसमें थोड़ी सी सीख मिलती है।


... और वास्तव में, आम तौर पर बोलते हुए, आधुनिक हार्डवेयर SSE, NEON, आदि जैसे वेक्टराइजेशन आर्किटेक्चर के माध्यम से मैट्रिक्स संचालन के लिए डिज़ाइन किया गया है, इसलिए यह स्मार्ट पसंद है - आप गैर-वेक्टर किए गए दृष्टिकोणों पर सीपीयू चक्रों को बचाएंगे।
इंजीनियर

1
हल्का अस्वीकरण: XNA को Microsoft द्वारा बंद कर दिया गया था, लेकिन मोनोगेम एक ही एपीआई का उपयोग करता है।
छपरा

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

"क्या यह स्क्रीन पर माउस की स्थिति को" मैप "करने के लिए एक बुरा विचार है ताकि टकराव का पता लगाने के संकल्प की परवाह किए बिना काम करे?" द्वारा उत्तर दिया गया है "दो समन्वय प्रणालियों के बीच अनुवाद करने के लिए
मैट्रिस

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

2

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

आपको स्पष्ट रूप से किसी भी इनपुट माउस आंदोलन की घटनाओं को केंद्र में लाने के कारण अनदेखा करना होगा, और यदि आपके गेम में सभी कर्सर में कोई इनपुट लैग है, तो गैर-जिम्मेदाराना सबसे अधिक घबराहट और ध्यान देने योग्य पहलू होगा।

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


0

ClassicThunder का उत्तर सही है, लेकिन मैं वांछित प्रभाव को प्राप्त करने के लिए वैकल्पिक / सरल साधनों का एक उदाहरण प्रदान करना चाहता हूं। यह तेजी से प्रोटोटाइप के लिए एक सरल समाधान है, ऐसे मामले जहां आप पूरी तरह से चित्रित पुस्तकालय तक पहुंच प्राप्त नहीं करते हैं, या ऐसे मामलों के लिए जहां आपको जीपीयू तक पहुंच नहीं है (जैसे एम्बेडेड सिस्टम में)।

कहा गया मानचित्रण करने के लिए, आप निम्नलिखित फ़ंक्शन का उपयोग कर सकते हैं (मान लें कि इसे स्थिर वर्ग में परिभाषित किया गया है Helper):

static float Map(float value, float fromLow, float fromHigh, float toLow, float toHigh)
{
    return ((value - fromLow) / (fromHigh - fromLow) * (toHigh - toLow)) + toLow;
}

(आपने कोई भाषा निर्दिष्ट नहीं की है, लेकिन मैं देख रहा हूं कि आपको C # का कुछ ज्ञान है, इसलिए मेरा उदाहरण C # में है।)

आप तब इस फ़ंक्शन का उपयोग कर सकते हैं:

float mouseXInWorld = Helper.Map(Mouse.X, 0, Screen.Width - 1, camera.Bounds.X, camera.Bounds.X + camera.Bounds.Width - 1);
float mouseYInWorld = Helper.Map(Mouse.Y, 0, Screen.Height - 1, camera.Bounds.Y, camera.Bounds.Y + camera.Bounds.Height - 1);

जहां camera.Boundsएक आयत है जो दुनिया के उस क्षेत्र का प्रतिनिधित्व करता है जिसे कैमरा देख सकता है (यानी स्क्रीन पर अनुमानित क्षेत्र)।

यदि आपके पास एक Vectorया Pointकक्षा है, तो आप इस प्रक्रिया को और भी सरल बना सकते हैं, जैसे मानचित्र फ़ंक्शन का 2 डी समकक्ष बनाकर।

static Vector Map(Vector value, Rectangle fromArea, Rectangle toArea)
{
    Vector result = new Vector();
    result.X = Map(value.X, fromArea.X, fromArea.X + fromArea.Width - 1, toArea.X, toArea.X + toArea.Width - 1);
    result.Y = Map(value.Y, fromArea.Y, fromArea.Y + fromArea.Height - 1, toArea.Y, toArea.Y + toArea.Height - 1);
    return result;
}

जो आपके मैपिंग कोड को एक साधारण लाइनर बना देगा:

Vector mousePosInWorld = Map(Mouse.Pos, Screen.Bounds, camera.Bounds);

-1

विकल्प (C): स्क्रीन रिज़ॉल्यूशन को वापस 800x600 पर बदलें।

यदि आप ऐसा नहीं करते हैं, तो भी इसे एक सोचा प्रयोग मानें। उस स्थिति में, ग्राफिक्स के आकार को उसके भौतिक आकार में फिट करने के लिए प्रदर्शन की जिम्मेदारी है, और फिर आपको 800x600 रिज़ॉल्यूशन पर सूचक घटनाओं को देने के लिए ऑपरेटिंग सिस्टम की ज़िम्मेदारी है।

मुझे लगता है कि यह सब इस बात पर निर्भर करता है कि आपके ग्राफिक्स बिटमैप हैं या वेक्टर। यदि वे बिटमैप हैं, और आप 800x600 बफर का प्रतिपादन कर रहे हैं, तो हाँ माउस को स्क्रीन स्पेस में रीमैप करना और वास्तविक स्क्रीन रिज़ॉल्यूशन को अनदेखा करना बहुत आसान है। हालाँकि इसका बड़ा नकारात्मक पहलू यह है कि अपसंस्कृति बदसूरत दिख सकती है, खासकर यदि आप "8-बिट" शैली के ग्राफिक्स को अवरुद्ध कर रहे हैं।

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