मैं स्क्रीन से दूर किसी वस्तु की ओर एक तीर कैसे खींच सकता हूं जो स्क्रीन से दूर है?


12

मैं इस विषय में वर्णित वर्णन करना चाहता हूं:

http://www.allegro.cc/forums/print-thread/283220

मैंने यहां बताए गए विभिन्न तरीकों का प्रयास किया है।

पहले मैंने Carrus85 द्वारा वर्णित विधि का उपयोग करने की कोशिश की:

बस दो त्रिभुज हाइपोन्टेन्यूज़ के अनुपात को लें (इससे कोई फर्क नहीं पड़ता कि आप दूसरे के लिए किस त्रिभुज का उपयोग करते हैं, मैं आपके द्वारा गणना की जाने वाली दूरी के रूप में बिंदु 1 और बिंदु 2 का सुझाव देता हूं)। यह आपको बड़े त्रिभुज से कोने में त्रिभुज का पहलू अनुपात प्रतिशत देगा। तब आप x- समन्वित ऑफ़सेट प्राप्त करने के लिए केवल उस मूल्य से डेल्टैक्स को गुणा करते हैं, और उस मान द्वारा y-निर्देशांक ऑफ़सेट प्राप्त करने के लिए deltay करते हैं।

लेकिन मुझे यह गणना करने का कोई तरीका नहीं मिला कि स्क्रीन के किनारे से ऑब्जेक्ट कितनी दूर है।

फिर मैंने 23yrold3yrold ​​द्वारा सुझाए गए रे कास्टिंग (जो मैंने पहले कभी नहीं किया था) का उपयोग करने की कोशिश की:

स्क्रीन के केंद्र से ऑफ़स्क्रीन ऑब्जेक्ट तक किरण को फायर करें। गणना करें कि आयत पर कहाँ रे चौराहे हैं। आपके निर्देशांक हैं।

मैंने पहले दो बिंदुओं के x और y पदों में अंतर द्वारा गठित त्रिकोण के कर्ण की गणना की। मैंने इसका इस्तेमाल उस लाइन के साथ एक यूनिट वेक्टर बनाने के लिए किया। मैंने उस वेक्टर के माध्यम से लूप किया जब तक कि x समन्वय नहीं करता या y निर्देशांक स्क्रीन से दूर था। दो वर्तमान x और y मान तब तीर का x और y बनाते हैं।

यहाँ मेरी किरण कास्टिंग विधि के लिए कोड है (C ++ और Allegro 5 में लिखा गया है)

void renderArrows(Object* i)
{
    float x1 = i->getX() + (i->getWidth() / 2);
    float y1 = i->getY() + (i->getHeight() / 2);

    float x2 = screenCentreX;
    float y2 = ScreenCentreY;

    float dx = x2 - x1;
    float dy = y2 - y1;
    float hypotSquared = (dx * dx) + (dy * dy);
    float hypot = sqrt(hypotSquared);

    float unitX = dx / hypot;
    float unitY = dy / hypot;

    float rayX = x2 - view->getViewportX();
    float rayY = y2 - view->getViewportY();
    float arrowX = 0;
    float arrowY = 0;

    bool posFound = false;
    while(posFound == false)
    {
        rayX += unitX;
        rayY += unitY;

        if(rayX <= 0 ||
            rayX >= screenWidth ||
            rayY <= 0 ||
            rayY >= screenHeight)
        {
            arrowX = rayX;
            arrowY = rayY;
            posFound = true;
        }               
    }

    al_draw_bitmap(sprite, arrowX - spriteWidth, arrowY - spriteHeight, 0);
}

यह अपेक्षाकृत सफल रहा। तीर स्क्रीन के निचले दाएं भाग में प्रदर्शित होते हैं जब ऑब्जेक्ट स्क्रीन के ऊपर और बाईं ओर स्थित होते हैं जैसे कि जहां तीर खींचे जाते हैं उन स्थानों को स्क्रीन के केंद्र के चारों ओर 180 डिग्री घुमाया गया हो।

मैंने माना कि यह इस तथ्य के कारण था कि जब मैं त्रिभुज के कर्ण की गणना कर रहा था, तो यह हमेशा सकारात्मक होगा चाहे एक्स में अंतर या वाई में अंतर नकारात्मक हो या नहीं।

इसके बारे में सोचते हुए, रे कास्टिंग समस्या को हल करने के एक अच्छे तरीके की तरह नहीं लगती (इस तथ्य के कारण कि इसमें sqrt का उपयोग करना शामिल है) और (लूप के लिए एक बड़ा)।

जवाबों:


6

तो आपके पास दो निर्देशांक या वैक्टर हैं, एक स्क्रीन का केंद्र है (अब से सी) और दूसरा आपकी वस्तु (अभी से पी) है।

यदि आप कुछ गणित जानते हैं, तो आप जान सकते हैं कि एक लाइन को मूल और एक दिशा वेक्टर के रूप में व्यक्त किया जा सकता है। मूल आपका स्क्रीन-केंद्र है, जबकि दिशा सदिश P से C को घटाकर पाया जा सकता है। इस समीकरण को पैरामीट्रिक रूप में भी व्यक्त किया जा सकता है, जो अनिवार्य रूप से समान है:

x = (P.x - C.x)t + C.x;
y = (P.y - C.y)t + C.y;

देखें (P.? - C.?)सा? यह आपकी दिशा वेक्टर है (जैसा कि मैंने कहा, पी से सी घटाएं)। अंतिम C.?बिट लाइन की उत्पत्ति है।

tएक वैरिएबल है, जो भिन्न हो सकता 0है 1, 0वेक्टर की उत्पत्ति होने के नाते (यदि आप संचालित करते हैं, xऔर yवुल्ल्ड बन जाते हैं C.xऔर C.y), तो 1आपकी वस्तु का समन्वय हो जाता है (फिर से, संचालन, यह बन जाएगा P.xऔर P.y, या वेक्टर के "अंत", यदि आप चाहते हैं) और आपके खंड के दोनों सिरों के बीच के बीच का मान। आप बाहरी मान भी निर्दिष्ट कर सकते हैं: नीचे 0आप अपनी वेक्टर दिशा उलट 1पाएंगे और ऊपर आप अपने वेक्टर को उसी दिशा में "विस्तारित" करेंगे।

एक बार जब आप इसे प्राप्त करते हैं, तो यह बहुत आसान हो जाता है। आपका उद्देश्य इस वेक्टर के बिंदु ( xऔर yदिए गए मूल्य के लिए t) को ढूंढना है जहां X=WIDTHया Y=HEIGHT, जो भी पहले आता है। जैसा कि आप देख सकते हैं, tक्या आपका एकमात्र चर यहाँ है:

(0)
WIDTH = (P.x - C.x)t + C.x;
and
HEIGHT = (P.y - C.y)t + C.y;

या इसे फिर से व्यक्त करना:

(1)
t = (WIDTH - C.x)/(P.x - C.x)
and
t = (HEIGHT - C.y)/(P.y - C.y)

यह आपके दाईं और शीर्ष सीमाओं पर आपके वेक्टर द्वारा परिभाषित रेखा का कटिंग पॉइंट प्राप्त करेगा। वही आपकी स्क्रीन की बाईं और नीचे की सीमाओं के लिए जाता है, जहां आपको 0दोनों मामलों के लिए जाँच करने की आवश्यकता है , न कि WIDTHऔर HEIGHT

चूंकि यह अंततः सीमाओं को काट देगा, यहां तक ​​कि ऑफ-स्क्रीन भी, सबसे कम tमूल्य आपके संपर्क का पहला बिंदु होगा। ऑपरेशन को उलटने और tसमीकरणों पर अपना पाया मूल्य लागू करने पर (0)(दोनों के लिए समान मूल्य!) एक नया लाएगा (x,y), जो आपके काटने के निर्देशांक होंगे।

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


धन्यवाद। मैं इसे जाने दूँगा। संपादित करें: बस जिज्ञासा से बाहर, क्या आपको लगता है कि यह विधि वह है जिसे कार्र्स 85 ने वर्णित किया है (कर्ण के अनुपात का उपयोग करके)?
एडम हेंडरसन

1
@AdamHenderson मुझे मदद करने में खुशी हो रही है :) याद रखें कि आप अपनी दिशा वेक्टर रख सकते हैं ताकि आप बाद में अपना तीर खींच सकें। आप अपनी एकात्मक दिशा वेक्टर प्राप्त करने के लिए इसे सामान्य कर सकते हैं, arrow-lengthकटिंग वेक्टर "एट वॉयला" से इसे घटा सकते हैं, आपके पास अपने तीर के लिए एक मूल और गंतव्य है।
koD

1
@AdamHenderson नेत्रहीन यह एक ही बात है, क्योंकि आपकी रेखा वह कर्ण है जिसके बारे में वह बात कर रहा है। व्यावहारिक रूप से, यह समान नहीं है, क्योंकि उनके सुझाव में कोण (और त्रिकोणमिति इसलिए) शामिल हैं, जो मुझे लगता है कि इसके लिए ओवरकिल है। इसमें बिल्कुल भी त्रिकोण शामिल नहीं है (हालाँकि आप अपने वेक्टर को एक त्रिकोण के रूप में सोच सकते हैं जहां कर्ण वेक्टर है और दोनों पक्ष xऔर yघटक हैं।)
kaD

एक बार फिर धन्यवाद! आपने तीर को इंगित करने की मेरी अगली समस्या को सही दिशा में हल किया।
एडम हेंडरसन

1
@AdamHenderson हां, नीचे अगर धुरी फ़्लिप है। BTW, मैं भविष्य में संदर्भ के लिए एलेग्रो के फोरम में इस सवाल का लिंक पोस्ट करने का सुझाव दूंगा।
कावड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.