识别六角形Clickbox


17

我工作的一个游戏,将涉及喘气六边形。

目前,我正在使用一个六边形图像(所有边的长度相同...适合50px x 50px的图像)。

我是C#的新手,还是XNA的新手,但是有没有一种我可以调用的简单方法,而不是根据点和角度进行复杂的if语句?


请参阅gamedev.stackexchange.com/questions/6382/…,它实现了十六进制点击检测。
蒂姆·霍尔特

4
我完全在Google搜寻“ gasp六角形”,就像是“那是什么样的六角形?!” 猜猜我今天过得很慢。
MichaelHouse

2
嗯,如果您单击喘气而不是单击六角形会发生什么?
蒂姆·霍尔特

1
根据您的需要,如果只是单击区域,则可以做一个简单的圆圈。否则,您将不得不在多边形技术上使用一个点,例如缠绕和或sumsum。
PhilCK,2011年

除非要任意旋转十六进制贴图,否则多边形上的点将是大材小用。您如何处理十六进制为1000x1000的地图?检查每个吗?RE:圈子,它们将不起作用。在三个十六进制之间的交界点附近,您将有三个重叠的圆。完全位于六边形内的较小的圆将具有间隙,在该间隙中,合法点击不会在任何圆内。
蒂姆·霍尔特

Answers:


18

六边形是带有夹角的矩形。我所看到的方式以及我听到的《文明》系列都是通过正交图做到这一点的,是创建一个带有白色空间(正交或六边形)以及红色,绿色,蓝色和黄色的位图角。(或您喜欢的任何颜色。)

六角形:六角面罩在此处输入图片说明

正交的: 在此处输入图片说明

然后,只需确定光标在哪个矩形上,然后测试该位置上像素的颜色即可。如果是白色,则它们将悬停在该空间上。每种颜色都映射到一个偏移量,它们悬停在那个六边形上。这种方法是有效的,几乎不需要几何形状,并且可以用于任何任意细分的空间。


只需注意:六角形有6个相等长度的边。您呈现的图像均未包含六边形。相反,它们包含6个侧面多边形。除此之外,此方法有效。但是,对于较大的六边形而言,它可能比计算六边形的边界要慢,因为此方法需要较大的六边形(如果要保持每个像素的精度)需要更多空间。对于较小的六边形(并取决于硬件),此方法可能比计算边界更快。
Olhovsky

9
六边形是任意6面的多边形。您正在考虑的是等边六边形(实际上,您可能正在考虑六边形,这是等边六边形等角六边形的一种)
Random832

请注意,我并不是说您的答案是错误的。我认为这是一个很好的答案,并且有解决方案。就是说,我不会选择这种方法来计算六边形边界,因为在任何现代平台上都可以计算六边形边界,因为计算边界是一种更可扩展的方法。例如,假设您要更改六边形的大小-现在必须重建图像了吗?制作像素完美的六角形蒙版很痛苦。我认为您尚未在这里生产一个事实证明了这一点。
Olhovsky

2
@Olhovsky-我在这里还没有制作出完美的六角形面具,因为我在工作中的几分钟休息时间是在作为社区服务来回答问题,而不是实际上在编写视频游戏。OP一直在寻找一种数学运算更少的解决方案,我认为这很简洁,因此我想与大家分享,因为这是我自己绝对不会想到的东西。
dlras2 2011年

18

没有XNA方法可以执行六边形命中测试。

本文介绍了如何编写执行测试的函数,并为您提供了该函数:

如何检查一个点是否在六角形内

这是该文章的摘要: 六角点击框

进行测试的功能如下:

  1. 测试围绕六边形的边界框,如果边界不相交,请尽早测试。
  2. 如上所示,将点转换为局部象限。
  3. isInside对本地象限执行以下测试。

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)赋予方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.