कंपित Isometric मानचित्र: स्क्रीन पर बिंदु के लिए मानचित्र निर्देशांक की गणना करें


12

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

यहाँ एक छवि है जो मेरे समन्वय प्रणाली को दिखाती है:

यहाँ छवि विवरण दर्ज करें

मैं इस समन्वय प्रणाली के लिए स्क्रीन पर एक बिंदु को कैसे बदलूं?



मैं यह नहीं देख सकता कि यह किसी भी तरह से कैसे सहायक है। मुझे लगता है कि आप मेरा मतलब नहीं समझ पाए।
क्रिस

यह परिवर्तन करता है, बस दूसरे तरीके के आसपास, इसलिए आपको इसे उलटने की आवश्यकता है।
मार्कस वॉन ब्रॉडी

जवाबों:


23

सबसे पहले, यहां कोड है। एक स्पष्टीकरण का पालन करेंगे:

/*
 * tw, th contain the tile width and height.
 *
 * hitTest contains a single channel taken from a tile-shaped hit-test
 * image. Data was extracted with getImageData()
 */

worldToTilePos = function(x, y) {

    var eventilex = Math.floor(x%tw);
    var eventiley = Math.floor(y%th);

    if (hitTest[eventilex + eventiley * tw] !== 255) {
        /* On even tile */

        return {
            x: Math.floor((x + tw) / tw) - 1,
            y: 2 * (Math.floor((y + th) / th) - 1)
        };
    } else {
        /* On odd tile */

        return {
            x: Math.floor((x + tw / 2) / tw) - 1,
            y: 2 * (Math.floor((y + th / 2) / th)) - 1
        };
    }
};

ध्यान दें कि यह कोड आपके प्रश्न में दिखाए गए नक्शे के लिए बॉक्स से बाहर काम नहीं करेगा। इसका कारण यह है कि आपके पास बाईं ओर विषम टाइल ऑफ़सेट हैं, जबकि विषम टाइल आमतौर पर दाईं ओर ऑफ़सेट होती है (जैसा कि टाइल किए गए मानचित्र संपादक में मामला है )। आपको विषम-टाइल के मामले में लौटाए गए x मान को हटाकर इसे आसान करने में सक्षम होना चाहिए।

व्याख्या

यह इस कार्य को पूरा करने के लिए थोड़ा अधिक ब्रूट-फोर्स विधि प्रतीत हो सकता है, लेकिन इसमें पिक्सेल परफेक्ट और थोड़ा अधिक लचीला होने का कम से कम लाभ है।

चाल एक एकल कंपित ग्रिड के रूप में नक्शे को देखने में नहीं है, लेकिन दो ग्रिड के रूप में एक दूसरे के ऊपर ओवरले। वहाँ विषम पंक्तियों ग्रिड और समान पंक्तियों ग्रिड है, लेकिन चलो उन्हें लाल और हरे रंग के बजाय कॉल करें ताकि हम एक सुंदर आरेख बना सकें ...

दो ग्रिड, लाल और हरे

उस छवि के दाईं ओर सूचना मैंने एक बिंदु को बैंगनी डॉट के साथ चिह्नित किया है। यह वह उदाहरण बिंदु है जिसे हम अपने मूल टाइल-स्थान में खोजने का प्रयास करेंगे।

दुनिया में किसी भी बिंदु के बारे में नोटिस करने की बात यह है कि यह हमेशा दो क्षेत्रों में झूठ होगा - एक लाल एक और एक हरा (जब तक कि यह एक किनारे पर न हो, लेकिन आप वैसे भी दांतेदार किनारे सीमा के भीतर क्लिपिंग करेंगे)। आइए जानें वो क्षेत्र ...

दो उम्मीदवार क्षेत्र

अब दोनों क्षेत्रों में से किसे चुनना सही है। हमेशा एक ही उत्तर होगा।

यहाँ से हम कुछ और सरल अंकगणित कर सकते हैं और अपने नमूने बिंदु से दो क्षेत्रों के प्रत्येक केंद्र बिंदु तक चौकोर दूरी तय कर सकते हैं। जो भी सबसे करीब होगा, वह हमारा जवाब होगा।

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

बिंदु नमूने

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

हम फिर इस निष्कर्ष पर पहुँचते हैं कि हमारे पास 1,1 पर विषम टाइल में एक हिट है। यह समन्वय मूल टाइल के नक्शे के लिए सरल होना चाहिए जो विषम और यहां तक ​​कि पंक्तियों के लिए एक अलग परिवर्तन का उपयोग कर निर्देशांक करता है।

यह विधि आपको पिक्सेल परीक्षण बिटमैप (ओं) पर सरल प्रति पिक्सेल गुण रखने की भी अनुमति देती है। जैसे सफेद ऑफ-टाइल है, काला हिट है, नीला पानी है, लाल ठोस है।


2
यह बहुत बढ़िया है!
14

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

1

मुझे लगता है कि आपके पास जो समस्या है वह आपके समन्वय स्थान के साथ है। आपने जो निर्देश दिए हैं, वे टाइलें वास्तव में एक सममितीय प्रक्षेपण नहीं हैं - आपको xAxis के बारे में सोचना चाहिए कि तिरछे नीचे-दाएं और yAxis को तिरछे नीचे-बाएँ (या उस के कुछ प्रकार) के रूप में जाना चाहिए।

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

आप जिस रूपांतरण मैट्रिक्स की तलाश कर रहे हैं, वह उन x और y अक्षों में से एक है। यह प्रभावी रूप से निम्नलिखित गणना करने के समान है।

screenOffsetXY = screenPointXY - tileOriginXY;
tileX = dot(screenOffsetXY, xAxis) / tileWidth;
tileY = dot(screenOffsetXY, yAxis) / tileWidth;

संपादित करें: मैं बस एक ही सवाल पर आया था (लेकिन मैं जिस समन्वय प्रणाली के बारे में बात कर रहा था) और किसी ने यहाँ बहुत अधिक जवाब दिया:

माउस निर्देशांक को आइसोमेट्रिक इंडेक्स में कैसे बदलें?


0

मूल रूप से आप एक इवेंट श्रोता का उपयोग करके खिड़की में माउस की स्थिति प्राप्त करना चाहते हैं, आपको माउस स्थिति से विंडो में कैनवास की स्थिति की ऑफसेट को हटाने की आवश्यकता है, इसलिए माउस की स्थिति कैनवास के सापेक्ष है।

function mouseTwoGridPosition(e){

var mousex = e.pageX; //mouse position x
var mouseY = e.pageY;  //mouse position y
var canvas_width = 1000; //pixels
var offset_left = 100; //offset of canvas to window in pixels
var offset_top = 150; //offset of canvas to window in pixels

var isotile = 64; //if iso tile is 64 by 64

//get mouse position relative to canvas rather than window
var x = mousex - canvas_width/2 - offset_left;
var y = mousey - offset_top;


//convert to isometric grid
var tx = Math.round( (x + y * 2) / isotile) - 1;
var ty = Math.round((y * 2 - x) / isotile) - 1;

 //because your grid starts at 0/0 not 1/1 we subtract 1 
 // this is optional based on what grid number you want to start at



   return [tx,ty];
}

मुझे लगता है कि आप जानते हैं कि कैसे मूसमव के लिए कैनवस पर ईवेंट सुनने का तरीका है, अन्यथा आप आइसोमेट्रिक गेम डिज़ाइन पर विचार करने से पहले अधिक जेएस सीखना चाह सकते हैं: डी


क्या यह बहुत आसान नहीं है? मैं चाहता हूं कि यह पूरी तरह से आइसो टाइल के रूप से मेल खाए। आप सिर्फ एक आयताकार क्षेत्र की जाँच कर रहे हैं यदि मैं इसे सही ढंग से समझता हूं।
क्रिस

इसोटाइल के "रूप" से आपका क्या तात्पर्य है ... उदाहरण के लिए कहें कि आपका माउस 0: 1 के हीरे के आकार की सीमा के भीतर है, जब तक कि आपका माउस उस सीमा से बाहर नहीं निकल जाता, तब तक 0: 1 रिटर्न होगा। यदि आपकी टाइलें आकार में बदलती हैं - तो मेरा तरीका काम नहीं करेगा। प्रदान किया गया फ़ंक्शन वह है जो मैं उपयोग करता हूं और यह मेरे लिए ठीक काम करता है।
डेव

बस सोच रहा था, क्योंकि अन्य सभी समाधान अधिक जटिल हैं। टाइलें निश्चित रूप से एक ही आकार की हैं, इसलिए मैं इसकी जांच करूंगा।
क्रिस

इसके साथ अच्छी तरह से टिंकर यह सुनिश्चित करता है कि आपको कैनवस के बाएं और ऊपर - और कैनवास की चौड़ाई के सही ऑफसेट मिलते हैं, जब आप करते हैं तो गणित ठीक काम करेगा (आइसोटाइल आकार की चौड़ाई भी)।
डेव

क्या आप वाकई मेरे जैसा ही समन्वय प्रणाली का उपयोग कर रहे हैं? यह अभी भी पूरी तरह से बंद है।
क्रिस

0

मैंने इसे समन्वय स्थान बदलकर हल किया। यह अब पहली पंक्ति में एक ऑफसेट के बिना शुरू होता है और इसके लिए मुझे एक कार्यशील उदाहरण मिला, जिसे मैं थोड़ा समायोजित करने में सक्षम था।

    hWidth = this.tileset.tileSize.width / 2;
    hHeight = this.tileset.tileSize.height / 2;

    pX = point.x - halfWidth;
    pY = point.y - halfHeight;

    x = Math.floor((pX + (pY - hHeight) * 2) / this.tileset.tileSize.width);
    y = Math.floor((pY - (pX - hWidth) * 0.5) / this.tileset.tileSize.height);

    tx = Math.floor((x - y) / 2) + 1 + this.camera.x;
    ty = y + x + 2 + this.camera.y;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.