ड्राइंग Isometric खेल दुनिया


178

2 डी गेम में आइसोमेट्रिक टाइल्स खींचने का सही तरीका क्या है?

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

वहाँ या तो विधि के फायदे या नुकसान हैं?

जवाबों:


504

अद्यतन: सही नक्शा प्रतिपादन एल्गोरिथ्म, और अधिक चित्रण जोड़ा गया, परिवर्तित स्वरूप।

शायद टाइल को स्क्रीन पर मैप करने के लिए "ज़िग-ज़ैग" तकनीक के लिए लाभ यह कहा जा सकता है कि टाइल की xऔर yनिर्देशांक ऊर्ध्वाधर और क्षैतिज अक्षों पर हैं।

"एक हीरे में आरेखण" दृष्टिकोण:

"एक हीरे में ड्राइंग" का उपयोग करके एक आइसोमेट्रिक मानचित्र खींचकर, जो मेरा मानना ​​है forकि इस उदाहरण के रूप में दो-आयामी सरणी पर एक नेस्टेड- लूप का उपयोग करके केवल नक्शे का प्रतिपादन करना है :

tile_map[][] = [[...],...]

for (cellY = 0; cellY < tile_map.size; cellY++):
    for (cellX = 0; cellX < tile_map[cellY].size cellX++):
        draw(
            tile_map[cellX][cellY],
            screenX = (cellX * tile_width  / 2) + (cellY * tile_width  / 2)
            screenY = (cellY * tile_height / 2) - (cellX * tile_height / 2)
        )

फायदा:

दृष्टिकोण का लाभ यह है कि यह एक सरल नेस्टेड- forक्लूप है जिसमें काफी सीधे आगे के तर्क हैं जो सभी टाइलों में लगातार काम करते हैं।

हानि:

कि दृष्टिकोण के लिए एक नकारात्मक पक्ष यह है कि है xऔर yनक्शे पर टाइल्स के निर्देशांक विकर्ण लाइनों में वृद्धि होगी, इसे और अधिक मुश्किल नेत्रहीन एक सरणी के रूप में प्रतिनिधित्व नक्शा के लिए स्क्रीन पर स्थान मैप करने के लिए कर सकता है जो:

टाइल मानचित्र की छवि

हालांकि, उपरोक्त उदाहरण कोड को लागू करने के लिए एक नुकसान होने जा रहा है - रेंडरिंग ऑर्डर टाइल्स का कारण होगा जो सामने की टाइल के ऊपर खींची जाने वाली कुछ टाइलों के पीछे होना चाहिए:

गलत रेंडरिंग ऑर्डर से परिणामी छवि

इस समस्या को संशोधित करने के लिए, इनर- forलूप के आदेश को उलट देना चाहिए - उच्चतम मूल्य से शुरू करना, और निचले हिस्से की ओर प्रस्तुत करना:

tile_map[][] = [[...],...]

for (i = 0; i < tile_map.size; i++):
    for (j = tile_map[i].size; j >= 0; j--):  // Changed loop condition here.
        draw(
            tile_map[i][j],
            x = (j * tile_width / 2) + (i * tile_width / 2)
            y = (i * tile_height / 2) - (j * tile_height / 2)
        )

उपरोक्त फिक्स के साथ, नक्शे के प्रतिपादन को ठीक किया जाना चाहिए:

सही प्रतिपादन आदेश से परिणामी छवि

"ज़िग-ज़ैग" दृष्टिकोण:

फायदा:

शायद "ज़िग-ज़ैग" दृष्टिकोण का लाभ यह है कि प्रदान किया गया नक्शा "हीरा" दृष्टिकोण की तुलना में थोड़ा अधिक लंबवत दिखाई दे सकता है:

Zig-zag प्रतिपादन करने के लिए दृष्टिकोण कॉम्पैक्ट लगता है

हानि:

ज़िग-ज़ैग तकनीक को लागू करने की कोशिश करने से, नुकसान यह हो सकता है कि रेंडरिंग कोड को लिखना थोड़ा कठिन है क्योंकि यह forएक सरणी में प्रत्येक तत्व पर नेस्टेड- लूप के रूप में सरल नहीं लिखा जा सकता है :

tile_map[][] = [[...],...]

for (i = 0; i < tile_map.size; i++):
    if i is odd:
        offset_x = tile_width / 2
    else:
        offset_x = 0

    for (j = 0; j < tile_map[i].size; j++):
        draw(
            tile_map[i][j],
            x = (j * tile_width) + offset_x,
            y = i * tile_height / 2
        )

साथ ही, रेंडरिंग क्रम की कंपित प्रकृति के कारण टाइल के समन्वय का पता लगाने की कोशिश करना थोड़ा मुश्किल हो सकता है:

ज़िग-ज़ैग ऑर्डर रेंडरिंग पर निर्देशांक

ध्यान दें: इस उत्तर में शामिल चित्र एक टाइल प्रस्तुतिकरण कोड के जावा कार्यान्वयन के साथ बनाए गए थे, जो निम्न intसरणी के साथ नक्शे के रूप में प्रस्तुत किए गए हैं:

tileMap = new int[][] {
    {0, 1, 2, 3},
    {3, 2, 1, 0},
    {0, 0, 1, 1},
    {2, 2, 3, 3}
};

टाइल चित्र हैं:

  • tileImage[0] -> एक बॉक्स के साथ एक बॉक्स के अंदर।
  • tileImage[1] -> एक ब्लैक बॉक्स।
  • tileImage[2] -> एक सफेद बॉक्स।
  • tileImage[3] -> इसमें एक लंबा ग्रे ऑब्जेक्ट के साथ एक बॉक्स।

टाइल की चौड़ाई और ऊँचाई पर एक नोट

उपरोक्त कोड उदाहरणों में उपयोग किए जाने वाले चर tile_widthऔर tile_heightटाइल की छवि का प्रतिनिधित्व करते हुए ग्राउंड टाइल की चौड़ाई और ऊंचाई का उल्लेख करते हैं:

टाइल की चौड़ाई और ऊंचाई दिखाने वाली छवि

छवि के आयामों का उपयोग करना काम करेगा, जब तक कि छवि आयाम और टाइल आयाम मेल खाते हैं। अन्यथा, टाइल मानचित्र को टाइलों के बीच अंतराल के साथ प्रदान किया जा सकता है।


136
आपने तस्वीरें भी खींचीं। यही प्रयास है।
ज़रातुस्तरा

चीयर्स कोबर्ड। मैं वर्तमान खेल के विकास के लिए हीरे के दृष्टिकोण का उपयोग कर रहा हूं और यह एक इलाज का काम कर रहा है। एक बार फिर धन्यवाद।
बेनी हैलट

3
कई ऊंचाई परतों के बारे में क्या? क्या मैं उन्हें न्यूनतम स्तर से शुरू करके, उच्चतम स्तर तक पहुंचने तक मुस्कुराता रह सकता हूं?
नागी

2
@ डॉमेनिकडैटी: अपनी तरह के शब्दों के लिए धन्यवाद :)
coobird

2
यह कमाल का है। मैं सिर्फ आपके हीरे के दृष्टिकोण का उपयोग करता था और, अगर किसी को स्क्रीन की स्थिति से ग्रिड कोर्डर्स प्राप्त करने की आवश्यकता होती है, तो मैंने ऐसा किया j = (2 * x - 4 * y) / tilewidth * 0.5; i = (p.x * 2 / tilewidth) - j;:।
किर डनकॉफ

10

किसी भी तरह से काम हो जाता है। मुझे लगता है कि zigzag द्वारा आप कुछ इस तरह से मतलब है: (संख्या प्रतिपादन के आदेश हैं)

..  ..  01  ..  ..
  ..  06  02  ..
..  11  07  03  ..
  16  12  08  04
21  17  13  09  05
  22  18  14  10
..  23  19  15  ..
  ..  24  20  ..
..  ..  25  ..  ..

और हीरे से आपका मतलब है:

..  ..  ..  ..  ..
  01  02  03  04
..  05  06  07  ..
  08  09  10  11
..  12  13  14  ..
  15  16  17  18
..  19  20  21  ..
  22  23  24  25
..  ..  ..  ..  ..

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


14
मैं वास्तव में चारों ओर का मतलब था। हीरे का आकार (जो नक्शे के किनारों को चिकना छोड़ देता है) और ज़िग-ज़ैग विधि, किनारों को छोड़ते हुए नुकीला
बेनी हैलेट

1

यदि आपके पास कुछ टाइलें हैं जो आपके हीरे की सीमा से अधिक हैं, तो मैं गहराई से ऑर्डर करने की सलाह देता हूं:

...1...
..234..
.56789.
..abc..
...d...

1

कोबर्ड का जवाब सही है, एक को पूरा करें। हालांकि, मैंने अपने ऐप (iOS / ऑब्जेक्टिव-सी) में काम करने वाले कोड बनाने के लिए उनके संकेतों को उन अन्य लोगों के साथ जोड़ा, जिन्हें मैं यहां आने वाले किसी भी व्यक्ति के साथ साझा करना चाहता था। कृपया, यदि आप इस उत्तर को पसंद / अप-वोट करते हैं, तो मूल के लिए भी ऐसा ही करें; मैंने जो कुछ किया वह "दिग्गजों के कंधों पर खड़ा था।"

सॉर्ट-ऑर्डर के लिए, मेरी तकनीक एक संशोधित चित्रकार की एल्गोरिथ्म है: प्रत्येक ऑब्जेक्ट में (ए) आधार की ऊंचाई है (मैं "स्तर" कहता हूं) और (बी) "आधार" या "पैर" के लिए एक एक्स / वाई छवि (उदाहरण: अवतार का आधार उसके चरणों में है; वृक्ष का आधार उसके मूल में है; हवाई जहाज का आधार केंद्र-छवि है, आदि) फिर मैं सबसे कम उच्चतम स्तर पर छाँटता हूँ, फिर सबसे कम (उच्चतम ऑन-स्क्रीन) उच्चतम आधार- Y, तब उच्चतम बेस-एक्स के लिए सबसे कम (बाएं-सबसे)। यह टाइलों को उसी तरह प्रस्तुत करता है जिस तरह से कोई उम्मीद करता है।

कोड को स्क्रीन (बिंदु) को टाइल (सेल) और बैक में बदलने के लिए:

typedef struct ASIntCell {  // like CGPoint, but with int-s vice float-s
    int x;
    int y;
} ASIntCell;

// Cell-math helper here:
//      http://gamedevelopment.tutsplus.com/tutorials/creating-isometric-worlds-a-primer-for-game-developers--gamedev-6511
// Although we had to rotate the coordinates because...
// X increases NE (not SE)
// Y increases SE (not SW)
+ (ASIntCell) cellForPoint: (CGPoint) point
{
    const float halfHeight = rfcRowHeight / 2.;

    ASIntCell cell;
    cell.x = ((point.x / rfcColWidth) - ((point.y - halfHeight) / rfcRowHeight));
    cell.y = ((point.x / rfcColWidth) + ((point.y + halfHeight) / rfcRowHeight));

    return cell;
}


// Cell-math helper here:
//      http://stackoverflow.com/questions/892811/drawing-isometric-game-worlds/893063
// X increases NE,
// Y increases SE
+ (CGPoint) centerForCell: (ASIntCell) cell
{
    CGPoint result;

    result.x = (cell.x * rfcColWidth  / 2) + (cell.y * rfcColWidth  / 2);
    result.y = (cell.y * rfcRowHeight / 2) - (cell.x * rfcRowHeight / 2);

    return result;
}

1

आप बिंदु से उच्चतम और निकटतम, यूक्लिडियन दूरी का उपयोग कर सकते हैं, सिवाय इसके कि यह बहुत सही नहीं है। यह गोलाकार क्रमबद्ध क्रम में होता है। आप आगे से दूर देखकर उसे सीधा कर सकते हैं। इसके अलावा वक्रता दूर हो जाती है। तो बस x, y और z घटकों में से प्रत्येक को x ', y' और 'z' कहने के लिए 1000 जोड़ें। X '* x' + y '* y' + z '* z' की तरह।


0

असली समस्या तब होती है जब आपको कुछ टाइल / स्प्राइट्स को दो या दो से अधिक अन्य टाइलों को जोड़ने / फैलाने की आवश्यकता होती है।

समस्या के 2 (कठिन) महीनों के बाद मैं अपने नए cocos2d-js गेम के लिए "सही रेंडर ड्राइंग" को लागू कर पाया। प्रत्येक टाइल (अतिसंवेदनशील) के लिए समाधान में मानचित्रण होता है, जो स्प्राइट "सामने, पीछे, ऊपर और पीछे" होते हैं। एक बार ऐसा करने के बाद आप उन्हें "पुनरावर्ती तर्क" के बाद आकर्षित कर सकते हैं।

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