รู้จัก clickbox หกเหลี่ยม


17

ฉันกำลังทำงานในเกมที่จะเกี่ยวข้องกับอ้าปากค้างรูปหกเหลี่ยม

ในปัจจุบันฉันมีรูปหกเหลี่ยมที่ฉันใช้ (ทุกด้านยาวเท่ากัน ... มันพอดีกับภาพ 50px คูณ 50px)

ฉันค่อนข้างใหม่กับ C # และใหม่จริง ๆ กับ XNA แต่มีวิธีการง่ายๆที่ฉันสามารถโทรหาได้มากกว่าที่จะทำข้อตกลงที่ซับซ้อนหากคำสั่งอิงตามจุดและมุม?


ดูgamedev.stackexchange.com/questions/6382/…ซึ่งใช้การตรวจจับการคลิกฐานสิบหก
ทิมโฮลท์

4
ฉัน Googled ทั้งหมด "อ้าปากค้างรูปหกเหลี่ยม" ฉันก็ชอบ "รูปหกเหลี่ยมแบบนั้นคืออะไร?!" คิดว่าฉันมีวันที่ช้า
MichaelHouse

2
อืมจะเกิดอะไรขึ้นถ้าคุณคลิกที่อ้าปากค้างแทนที่จะเป็นรูปหกเหลี่ยม?
ทิมโฮลท์

1
ขึ้นอยู่กับความต้องการของคุณวงกลมที่เรียบง่ายจะทำถ้ามันเป็นเพียงสำหรับพื้นที่การคลิก มิฉะนั้นคุณจะต้องใช้จุดในเทคนิครูปหลายเหลี่ยมเช่นผลรวมที่คดเคี้ยวหรือผลรวม
PhilCK

หากไม่มีการหมุนแผนที่ฐานสิบหกจุดบนรูปหลายเหลี่ยมจะเป็น MAJOR มากเกินไป คุณทำอะไรกับแผนที่ที่มีความกว้าง 1,000x1000 hex ตรวจสอบทุกคน? RE: แวดวงพวกเขาจะไม่ทำงาน ใกล้จุดยอดทางแยกระหว่างสามเหลี่ยมคุณจะมีวงกลมสามวงซ้อนกัน วงกลมขนาดเล็กที่อยู่ในรูปหกเหลี่ยมจะมีช่องว่างซึ่งการคลิกที่ถูกต้องจะไม่อยู่ในแวดวงใด ๆ
ทิมโฮลท์

คำตอบ:


18

รูปหกเหลี่ยมเป็นรูปสี่เหลี่ยมผืนผ้าที่มีมุมที่ถูกตัด วิธีที่ฉันเห็นสิ่งนี้ทำและฉันได้ยินชุดอารยธรรมทำอย่างนี้กับแผนที่มุมฉากคือการสร้างบิตแมปที่มีพื้นที่สีขาว (มุมฉากหรือหกเหลี่ยม) และสีแดงสีเขียวสีฟ้าและสีเหลือง มุม. (หรือสีอะไรก็ได้ที่คุณชอบ)

หกเหลี่ยม: หน้ากาก Hexหรือป้อนคำอธิบายรูปภาพที่นี่

ฉาก: ป้อนคำอธิบายรูปภาพที่นี่

จากนั้นให้ตรวจสอบว่าเคอร์เซอร์สี่เหลี่ยมใดอยู่เหนือและทดสอบสีของพิกเซลที่ตำแหน่งนั้น ถ้าเป็นสีขาวพวกมันจะโฉบเหนือพื้นที่นั้น แต่ละสีอื่น ๆ ถูกแมปกับออฟเซ็ตและพวกเขาวางเมาส์เหนือหกเหลี่ยมนั้น วิธีนี้มีประสิทธิภาพใช้รูปทรงเรขาคณิตเพียงเล็กน้อยและสามารถใช้กับพื้นที่ทดสอบใดก็ได้โดยพลการ


เพียงแค่ทราบ: หกเหลี่ยมมีความยาวเท่ากัน 6 ด้าน ไม่มีภาพที่คุณนำเสนอจริง ๆ ประกอบด้วยรูปหกเหลี่ยม แต่มันมีรูปหลายเหลี่ยม 6 ด้าน นอกจากนั้นวิธีนี้ใช้ได้ผล มันอาจจะช้ากว่าการคำนวณขอบเขตของรูปหกเหลี่ยมสำหรับรูปหกเหลี่ยมที่ใหญ่กว่าเนื่องจากวิธีนี้ต้องใช้พื้นที่มากขึ้นสำหรับรูปหกเหลี่ยมที่มีขนาดใหญ่กว่า (หากคุณต้องการรักษาความแม่นยำต่อพิกเซล) สำหรับรูปหกเหลี่ยมขนาดเล็ก (และขึ้นอยู่กับฮาร์ดแวร์) วิธีนี้อาจเร็วกว่าการคำนวณขอบเขต
Olhovsky

9
รูปหกเหลี่ยมคือรูปหลายเหลี่ยม 6 ด้านใด ๆ สิ่งที่คุณคิดคือรูปหกเหลี่ยมด้านเท่ากันหมด (จริง ๆ แล้วคุณอาจนึกถึงรูปหกเหลี่ยมปกติซึ่งเป็นรูปหกเหลี่ยมรูปหกเหลี่ยมด้านเท่ากันหมดและรูปสามเหลี่ยม)
Random832

โปรดทราบว่าฉันไม่ได้บอกว่าคำตอบของคุณไม่ดี ฉันคิดว่ามันเป็นคำตอบที่ดีและทางออกที่มี ที่กล่าวว่าฉันจะไม่เลือกวิธีนี้ในการคำนวณขอบเขตหกเหลี่ยมเนื่องจากการคำนวณขอบเขตหกเหลี่ยมบนแพลตฟอร์มสมัยใหม่ใด ๆ เนื่องจากการคำนวณขอบเขตนั้นเป็นวิธีที่สามารถขยายได้มากขึ้น เช่นสมมติว่าคุณต้องการเปลี่ยนขนาดหกเหลี่ยม - ตอนนี้คุณต้องสร้างภาพใหม่หรือไม่ การผลิตหน้ากากหกเหลี่ยมที่สมบูรณ์แบบของพิกเซลเป็นความเจ็บปวด ความจริงที่ว่าคุณยังไม่ได้สร้างขึ้นมาตรงนี้เป็นข้อพิสูจน์ถึงเรื่องนั้นฉันคิดว่า
Olhovsky

2
@Olhovsky - ฉันยังไม่ได้ผลิตหน้ากากรูปหกเหลี่ยมที่สมบูรณ์แบบที่นี่เพราะฉันตอบคำถามเป็นบริการชุมชนในช่วงพักไม่กี่นาทีระหว่างที่ทำงานและไม่ได้เขียนวิดีโอเกมจริงๆ สหกรณ์กำลังมองหาวิธีการแก้ปัญหาทางคณิตศาสตร์ที่มีน้อยและผมคิดว่านี่คือเรียบร้อยดังนั้นฉันคิดว่าฉันต้องการแบ่งปันเพราะมันเป็นสิ่งที่ฉันแน่นอนจะไม่ได้คิดของตัวเอง
dlras2

18

ไม่มีวิธี XNA ที่ทำการทดสอบแบบหกเหลี่ยม

บทความนี้จะอธิบายวิธีการเขียนฟังก์ชั่นที่ทำการทดสอบและให้ฟังก์ชัน:

วิธีการตรวจสอบว่าจุดนั้นอยู่ในรูปหกเหลี่ยมหรือไม่

นี่คือบทสรุปจากบทความนั้น: กล่องคลิกหกเหลี่ยม

และฟังก์ชั่นที่ทำการทดสอบจะเป็นดังนี้:

  1. ทดสอบกล่องขอบรอบหกเหลี่ยมก่อนถ้ามันไม่ตัดกัน
  2. เปลี่ยนจุดให้เป็นจตุภาคท้องถิ่นดังที่แสดงไว้ด้านบน
  3. ทำการisInsideทดสอบต่อไปนี้สำหรับ Quadrant ท้องถิ่น

public function isInside(pos:Vec2Const):Boolean
{
    const q2x:Number = Math.abs(pos.x - _center.x);       
    const q2y:Number = Math.abs(pos.y - _center.y);
    if (q2x > _hori || q2y > _vert*2) 
        return false;
    return 2 * _vert * _hori - _vert * q2x - _hori * q2y >= 0;
}

ดูบทความสำหรับรายละเอียดทั้งหมด


นี่คือแหล่งข้อมูลที่เกี่ยวข้องที่เป็นประโยชน์อื่น ๆ :


1

ที่นี่ฉันมีวิธีที่สามารถใช้ในการตรวจจับการคลิกภายในรูปหลายเหลี่ยมใด ๆ :

public bool PointInPolygon( Vector2 p, Vector2[] poly )
    {
        Vector2 p1, p2;
        bool inside = false;

        if( poly.Length < 3 )
        {
            return inside;
        }

        Vector2 oldPoint = new Vector2( poly[poly.Length - 1].X, poly[poly.Length - 1].Y );

        for( int i = 0; i < poly.Length; i++ )
        {
            Vector2 newPoint = new Vector2( poly[i].X, poly[i].Y );

            if( newPoint.X > oldPoint.X )
            {
                p1 = oldPoint;
                p2 = newPoint;
            }
            else
            {
                p1 = newPoint;
                p2 = oldPoint;
            }

            if( ( newPoint.X < p.X ) == ( p.X <= oldPoint.X )
                && ( (long)p.Y - (long)p1.Y ) * (long)( p2.X - p1.X )
                 < ( (long)p2.Y - (long)p1.Y ) * (long)( p.X - p1.X ) )
            {
                inside = !inside;
            }

            oldPoint = newPoint;
        }

        return inside;
    }

คุณต้องให้มุมของรูปหกเหลี่ยมของคุณในอาร์เรย์ vector2 (โพลี) และตำแหน่งที่ถูกคลิก (p) กับวิธีการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.