मैं XNA में हेक्सागोनल तिलमप पिकिंग को कैसे लागू कर सकता हूं?


13

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

क्या किसी को पता है कि मैं कैसे जांच कर सकता हूं कि क्या पूरी चीज़ को उलझाए बिना एक षट्भुज पर क्लिक किया जाता है?

जवाबों:


13

इस तस्वीर को देखिए

हेक्सागोनल अपघटन

जैसा कि आप देख सकते हैं कि x, y आयताकार समन्वय प्रणाली का मानचित्र हेक्सागोनल के लिए एक अपेक्षाकृत सहज तरीका है।

हम "रेक्ट" अनियमित हेक्सागोन्स के बारे में बात कर सकते हैं अर्थात नियमित रूप से हेक्सागोन्स से प्राप्त दीर्घवृत्त या हेक्सागोन्स में उत्कीर्ण हेक्सागोन्स दोनों दिशाओं में अनुपातहीन रूप से (कोई घुमाव-कतरन नहीं)।

एक आयताकार षट्भुज को परिमित आयत की ऊँचाई और चौड़ाई से परिभाषित किया जा सकता है और साथ ही शिलालेख की चौड़ाई। (डब्ल्यू, डब्ल्यू, ज)

आयतों का वर्णन / परिक्रमा करना

हेक्सागोनल इंडेक्स का पता लगाने का सबसे आसान तरीका यह है कि स्पेस को फॉलो करना है:

अंतरिक्ष विभाजन

आयत की चौड़ाई w + (W - w) / 2 = (w + W) / 2 है, इसकी ऊंचाई h / 2 है; हरी आयत की चौड़ाई (Ww) / 2 है। यह पता लगाना आसान है कि आयत कहाँ पर गिरती है:

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

यू और वी रिमाइंडर निर्देशांक हैं जो इंगित करते हैं कि बिंदु जहां i, j आयत है: w का उपयोग करते हुए हम कह सकते हैं कि क्या हम हरे क्षेत्र में हैं (u <(Ww) / 2) या नहीं।

यदि यह मामला है तो हम हरे क्षेत्र में हैं, हमें यह जानने की जरूरत है कि क्या हम षट्भुज के ऊपरी या निचले आधे हिस्से में हैं: हम ऊपरी आधे हिस्से में हैं अगर मैं और जम्मू दोनों समान हैं या दोनों विषम हैं; हम निचले आधे हिस्से में हैं अन्यथा।

दोनों मामलों में यह u और v को ट्रैसफॉर्म करने के लिए उपयोगी है, इसलिए वे 0 और 1 के बीच भिन्न होते हैं:

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

अगर हम निचले आधे और v <u में हैं

या

अगर हम ऊपरी आधे और (1-v)> u में हैं

तब हम एक-एक करके घटाते हैं

अब हमें बस एक-एक करके j को घटाना है अगर मुझे यह देखना अजीब है कि मैं क्षैतिज षट्भुज सूचकांक (स्तंभ) है और j / 2 का पूर्णांक ऊर्ध्वाधर षट्भुज सूचकांक (पंक्ति) है

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


धन्यवाद! वास्तव में मददगार, हरे खंड के विभाजन के साथ उत्पन्न होने वाली कुछ परेशानियां थीं (क्या मुझे 1 से घटाना चाहिए या नहीं), लेकिन मुझे लगता है कि यह मेरे हेक्सागोन्स के उन्मुखीकरण के कारण था। सभी काम कर रहे हैं, धन्यवाद!
जोएल

14

नियमित हेक्सागोन्स में समरूपता के छह अक्ष होते हैं, लेकिन मैं मानूंगा कि आपके हेक्सागोन्स में केवल समरूपता के दो अक्ष हैं ( यानी सभी कोण 60 डिग्री के बराबर नहीं हैं)। जरूरी नहीं है कि आपके पास पूर्ण समरूपता नहीं है, लेकिन क्योंकि यह किसी और के लिए उपयोगी हो सकता है।

यहाँ एक षट्भुज के पैरामीटर हैं। इसका केंद्र में है O, सबसे बड़ी चौड़ाई है 2a, ऊंचाई है 2b, और शीर्ष किनारे की लंबाई है 2c

         Y ^
           |
       ____|____
      /  b |   |\
     /     |   | \
    /      |   |  \
---(-------+---+---)------>
    \     O|   c  / a      X
     \     |     /
      \____|____/
           |

यह पंक्ति / स्तंभ लेआउट है, जिसमें निचले बाएँ षट्भुज के केंद्र में मूल है। यदि आपका सेटअप अलग है, तो (x,y)इस मामले में वापस आने के लिए अपने निर्देशांक का अनुवाद करें , या उदाहरण -yके yलिए उपयोग करें :

col 0
 | col 1
 |   | col 2
 |   |  |
 __  | __    __    __    __   
/  \__/  \__/  \__/  \__/  \__
\__/  \__/  \__/  \__/  \__/  \
/  \__/  \__/  \__/  \__/  \__/
\__/  \__/  \__/  \__/  \__/  \
/  \__/  \__/  \__/  \__/  \__/_ _ line 2
\__/  \__/  \__/  \__/  \__/  \ _ _ _ line 1
/ .\__/  \__/  \__/  \__/  \__/_ _ line 0
\__/  \__/  \__/  \__/  \__/

निम्न कोड तब आपको षट्भुज युक्त बिंदु की पंक्ति और स्तंभ देगा (x,y):

static void GetHex(float x, float y, out int row, out int column)
{
  // Find out which major row and column we are on:
  row = (int)(y / b);
  column = (int)(x / (a + c));

  // Compute the offset into these row and column:
  float dy = y - (float)row * b;
  float dx = x - (float)column * (a + c);

  // Are we on the left of the hexagon edge, or on the right?
  if (((row ^ column) & 1) == 0)
      dy = b - dy;
  int right = dy * (a - c) < b * (dx - c) ? 1 : 0;

  // Now we have all the information we need, just fine-tune row and column.
  row += (column ^ row ^ right) & 1;
  column += right;
}

आप जांच सकते हैं कि उपरोक्त कोड इस IdeOne रन पर एकदम सही हेक्सागोन्स खींचता है ।


पहली बार मैंने ideOne के बारे में सुना है, लेकिन यह वास्तव में उपयोगी लगता है!
डेविड गौवेया

@davidluzgouveia: हाँ, यह कमाल है। मैं वेब या क्लाउड सेवाओं का शौकीन नहीं हूं लेकिन यह मददगार है।
sam hocevar 15

1

आप हेक्सागोन के क्षेत्र के अंदर 3 घुमाए गए आयतों को फिट कर सकते हैं, और यदि ठीक से किया जाता है तो यह क्षेत्र को बिल्कुल भर देगा। तब यह केवल तीन आयतों पर टकराने की जाँच का विषय होगा।


1

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

उपरोक्त करने के लिए, आप बस सभी हेक्स के केंद्रों को प्लॉट कर सकते हैं, और फिर सभी हेक्सों के विमान पर क्लिक करने पर माउस के सबसे पास का पता लगा सकते हैं। Tessellated hexagons के एक विमान पर निकटतम केंद्र हमेशा वही होगा जो आप पर मंडरा रहे हैं।


1

मैंने पहले से ही एक समान प्रश्न का उत्तर दिया है, समान लक्ष्यों के साथ, स्टैक ओवरफ्लो पर मैं इसे यहाँ पुनर्विचार के लिए आश्वस्त करूँगा: (एनबी - सभी कोड जावा में लिखा और परीक्षण किया गया है)

ओवरलेड स्क्वायर ग्रिड के साथ हेक्सागोनल ग्रिड

यह छवि एक हेक्सागोनल ग्रिड के ऊपरी बाएं कोने को दिखाती है और ओवरलैड एक नीला वर्ग ग्रिड है। यह पता लगाना आसान है कि कौन से वर्ग के अंदर एक बिंदु है और यह एक मोटा अंदाजा देता है कि षट्भुज भी है। हेक्सागोन्स के सफेद हिस्से दिखाते हैं कि वर्ग और हेक्सागोनल ग्रिड एक ही निर्देशांक साझा करते हैं और हेक्सागोन्स के ग्रे हिस्से दिखाते हैं कि वे कहां नहीं हैं।

समाधान अब उतना ही सरल है जितना कि एक बिंदु किस बॉक्स में है, तो यह देखने के लिए जाँच करें कि बिंदु त्रिकोण में से किसी में है या नहीं, और यदि आवश्यक हो तो उत्तर को सही करें।

private final Hexagon getSelectedHexagon(int x, int y)
{
    // Find the row and column of the box that the point falls in.
    int row = (int) (y / gridHeight);
    int column;

    boolean rowIsOdd = row % 2 == 1;

    // Is the row an odd number?
    if (rowIsOdd)// Yes: Offset x to match the indent of the row
        column = (int) ((x - halfWidth) / gridWidth);
    else// No: Calculate normally
        column = (int) (x / gridWidth);

इस बिंदु पर हमारे पास बॉक्स की पंक्ति और कॉलम है, जो हमारे बगल में है, हमें अपने बिंदु को हेक्सागोन के दो शीर्ष किनारों के खिलाफ परीक्षण करने की आवश्यकता है, यह देखने के लिए कि क्या हमारी बात ऊपर के दोनों हेक्सागोन्स में निहित है:

    // Work out the position of the point relative to the box it is in
    double relY = y - (row * gridHeight);
    double relX;

    if (rowIsOdd)
        relX = (x - (column * gridWidth)) - halfWidth;
    else
        relX = x - (column * gridWidth);

सापेक्ष निर्देशांक होने से अगला कदम आसान हो जाता है।

एक सीधी रेखा के लिए सामान्य समीकरण

जैसे ऊपर की छवि में, अगर हमारी बात का y > mx + c है, तो हम जानते हैं कि हमारी बात रेखा के ऊपर है, और हमारे मामले में, ऊपर और वर्तमान पंक्ति और स्तंभ के बाईं ओर षट्भुज है। ध्यान दें कि java में निर्देशांक प्रणाली स्क्रीन के ऊपर बाईं ओर 0 से शुरू हो रही है और नीचे बाईं तरफ नहीं है जैसा कि सामान्य रूप से गणित में होता है, इसलिए बाएं किनारे के लिए उपयोग किए जाने वाले नकारात्मक ढाल और दाईं ओर उपयोग किए गए सकारात्मक ढाल के लिए है।

    // Work out if the point is above either of the hexagon's top edges
    if (relY < (-m * relX) + c) // LEFT edge
        {
            row--;
            if (!rowIsOdd)
                column--;
        }
    else if (relY < (m * relX) - c) // RIGHT edge
        {
            row--;
            if (rowIsOdd)
                column++;
        }

    return hexagons[column][row];
}

उपरोक्त उदाहरण में प्रयुक्त चर की त्वरित व्याख्या:

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

m ढाल है, इसलिए m = c / halfWidth


NeoShamam उपरोक्त के अतिरिक्त है

यह सेबस्टियनट्रॉ के जवाब का एक परिशिष्ट है। मैं इसे एक टिप्पणी के रूप में छोड़ दूंगा, लेकिन अभी तक मेरी पर्याप्त प्रतिष्ठा नहीं है।

यदि आप यहां वर्णित के रूप में एक अक्षीय समन्वय प्रणाली लागू करना चाहते हैं: http://www.redblobgames.com/grids/hexagons/

आप कोड में थोड़ा संशोधन कर सकते हैं।

के बजाय

// Is the row an odd number?
if (rowIsOdd)// Yes: Offset x to match the indent of the row
    column = (int) ((x - halfWidth) / gridWidth);
else// No: Calculate normally
    column = (int) (x / gridWidth);

इसे इस्तेमाल करो

float columnOffset = row * halfWidth;
column = (int)(x + columnOffset)/gridWidth; //switch + to - to align the grid the other way

इससे निर्देशांक (0, 2) समान विकर्ण स्तंभ पर होगा (0, 0) और (0, 1) सीधे नीचे (0, 0) होने के बजाय।


मुझे लगता है कि यह हेक्सागोन्स के बीच अंतराल को ध्यान में नहीं रखता है, लेकिन इससे आपकी समस्या को कम करने में मदद मिलेगी।
ट्रॉयसेफ

0

यदि आपके सभी षट्भुज एक ही अनुपात और रखने का उपयोग करके बनाए गए हैं, तो आप टकराव के लिए किसी तरह की ओवरले संपत्ति का उपयोग कर सकते हैं, कुछ की तर्ज पर: एक षट्भुज के लिए टक्कर ओवरले

फिर, आपको बस इतना करना है कि टक्कर की छवि को रखें जहां आपका षट्भुज है, बाएं कोने के सापेक्ष माउस की स्थिति प्राप्त करें, और देखें कि क्या सापेक्ष स्थिति का पिक्सेल सफेद नहीं है (जिसका अर्थ टक्कर है)।

कोड (परीक्षण नहीं किया गया):

bool IsMouseTouchingHexagon(Vector2 mousePosition, Vector2 hexagonPosition,
    Rectangle hexagonRectangle, Texture2D hexagonImage)
{
    Vector2 mousePositionToTopLeft = mousePosition - hexagonPosition;

    // We make sure that the mouse is over the hexagon's rectangle.
    if (mousePositionToTopLeft.X >= 0 && mousePositionToTopLeft.X < hexagonRectangle.Width && 
        mousePositionToTopLeft.Y >= 0 && mousePositionToTopLeft.Y < hexagonRectangle.Height)
    {
        // Where "PixelColorAt" returns the color of a pixel of an image at a certain position.
        if (PixelColorAt(hexagonImage, mousePositionToTopLeft) == Color.White)
        {
            // If the color is not white, we are colliding with the hexagon
            return true;
        }
    }

    // if we get here, it means that we did not find a collision.
    return false;
}

आप पूरी प्रक्रिया के प्रदर्शन को बेहतर बनाने के लिए स्पष्ट रूप से (आपकी पूरी षट्भुज छवि की) पहले से एक आयत टकराव की जाँच कर सकते हैं।

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

अगर यह एक बहुत ही सरल समाधान हो सकता है जो एक बहुत अधिक पूर्ण और पुन: प्रयोज्य हो सकता है (वास्तव में टकराव को खोजने के लिए गणित का उपयोग करके) लेकिन यह निश्चित रूप से मेरी राय में एक कोशिश के लायक है।


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

0

गेम प्रोग्रामिंग गम 7 पर एक लेख है, जिसे मधुमक्खियों और गेमरों के लिए कहा जाता है : हेक्सागोनल टाइलों को कैसे संभालना है जो वास्तव में आपकी आवश्यकता होगी।

दुर्भाग्य से मेरे पास पुस्तक की मेरी प्रति फिलहाल मेरे पास नहीं है, अन्यथा मैं इसका थोड़ा वर्णन कर सकता था।

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