如何将点击拖动动作限制在某个区域?


11

对于某些通用标题,我深表歉意。我真的对如何完成我想做的事情并不了解,这甚至使研究可能的解决方案变得更加困难。

我正在尝试实现各种路径标记(也许有一个最合适的名称,但这是我能想到的最好的名称)。

在玩家前面将有一个路径标记,它将确定玩家完成转弯计划后的移动方式。玩家可以单击并拖动标记到他们选择的位置,但是标记只能在定义的工作区域(灰色位)内移动。

路径标记图

所以我现在遇到两个问题:

首先,我应该如何准确定义该可行区域?我可以想象,可能有两个向量以玩家为起点来形成可行的角度,也许这两个弧线可能来自以玩家为中心的圆,但是我绝对不知道如何将所有这些一起。

其次,在定义了可以放置标记的区域之后,如何强制标记应仅停留在该区域内?例如,如果玩家单击并拖动标记,则标记可以在工作区域内自由移动,但不能离开该区域的边界。因此,举例来说,如果玩家开始向上拖动标记,它将向上移动,直到碰到工作区域的末端(下面的第一张图),但是如果此后玩家开始侧向拖动,则标记必须跟随拖动同时在区域内(下面的第二张图)。

第一张图:向上移动 第二幅图:跟随阻力

我希望这不会太令人困惑。谢谢你们。

编辑:如果这有所作为,我将C + +与Marmalade SDK结合使用。


我认为您要查找的术语是“航路点”,您可以在数学上定义灰色区域吗?如果可以的话,解决问题的方法可能会容易得多。
约翰·麦当劳

与寻路相关的Arent航路点?另外,数学上定义灰色区域也是我的问题之一:PI认为我可以找出矩形或什至圆形之类的东西,但是形状像这样,在边上有两个弧形,在角度上有另外两个边……有点过头了
Vexille

您还需要指定所使用的语言和/或工具包,因为解决方案主要取决于平台。
Raceimaztion '10 -10-8

真?我认为算法解决方案甚至伪代码都将有所帮助。为了以防万一,我还是会编辑问题。
Vexille 2012年

在极坐标中定义形状(与角色的角度成最大角度,与角色的最小/最大距离)。如果鼠标在这些边界内,则仅将航路点更新到鼠标所在的位置。如果超过任何这些extreems,则将其捕捉到最大可能的extreem值。在区域内单击时开始更新,并在释放鼠标时停止。
ClassicThunder 2012年

Answers:


8

您可以使用三个值定义一个可行的区域,如您的问题中的一个:

float innerRadius;
float outerRadius;
float maxAngle;

这些值将基于一个中心点,该中心点可能是也可能不是玩家的位置。可工作区域的形状取决于放置此点的位置。

在此处输入图片说明

在上面的示例中,中心位置位于玩家后面一定距离(假设为50个单位)。可以很容易地计算为:

float offset = -50;
Vector2 centerPosition = playerPosition + offset * playerForward;

要将标记的位置限制在该可行区域内,请首先像平常一样移动标记。然后验证中心点和标记之间的距离

Vector2 direction = markerPosition - centerPosition;
float distance = direction.Length();
direction.Normalize();
markerPosition = centerPosition + direction * clamp(distance, innerRadius, outerRadius);

最后,将标记的角度验证到指定范围。我将为此使用伪代码:

- Find angle between vector C->M and vector playerForward
- If abs(angle) <= maxAngle Then do nothing
- Else If angle > 0 Then rotate M around C by maxAngle-angle
- Else If angle < 0 Then rotate M around C by -maxAngle-angle

环顾四周如何旋转一个点。可以使用三角函数或变换矩阵来完成。

您可能还需要考虑标记的大小,并使半径和角度稍小以进行补偿。

编辑:再三考虑,如果您先验证角度,然后再验证距离,则看起来会更自然,因此请尝试两种方法!


很好的解决方案!我遇到了涉及两个圆和一个三角形的事物,但是您的解决方案优雅地简化了这一过程。关于角度验证,我想到了一些类似的事情:具有一个规范化矢量,该矢量位于playerForward的maxAngle(另一个位于-maxAngle)处,如果它是有界的,则可以乘以C-> M的长度角度。我假设您将M绕C旋转的解决方案的成本较低,是吗?
Vexille

@Vexille好吧,旋转涉及到cossin运算,所以我不确定。但是,要计算这两个向量,还需要旋转它们,尽管仅在正向向量发生变化时才需要进行旋转。无论如何都没关系,选择您喜欢实施的那个。
David Gouveia,2012年

10

我在想如果形状不规则怎么解决问题,而又不能用数学的方式定义它。警告:这是一个肮脏的解决方案,而不是胆小者。

1.前往您所在的地区:

在此处输入图片说明

2.并将其转换为单色位图:

在此处输入图片说明 并命名为scale_0

3.克隆位图并将其缩小到50%:

在此处输入图片说明 并命名为scale_1

4.依此类推,直到位图的宽度小于/等于4个像素为止:

在此处输入图片说明 在此处输入图片说明 在此处输入图片说明 在此处输入图片说明 在此处输入图片说明 规模:2,3,4,5,6

5.现在我们有了不同分辨率的单色位图区域: 在此处输入图片说明

6.拍摄最后一张图像(此处为“ scale_6”)并遍历所有像素。

  • 将每个像素的坐标转换为屏幕坐标:x = Math.pow ( 2, scale_level );其中scale_level是我们在“ scale_”之后添加的数字。我们也可以称其为四叉树级别,尽管我们实际上并没有使用四叉树。与y相同。
  • 检查在平移的x和y处的像素是否为黑色。如果不是,那么它就不是形状的一部分,您应该只是continue循环的下一步
  • 检查像素是否比以前检查的像素更接近鼠标光标-如果是,请保存像素的坐标-使用转换前的坐标,即位图内部的坐标。
  • 在循环结束时,将这些坐标乘以2:x *= 2; y*=2;将其转换为下一幅图像(以前的比例)中的坐标

7.拍摄前一张图片(此处为“ scale_5”),但不要遍历所有像素;从x = saved_x开始,以x = saved_x + 2结尾,与y相同。也就是说,从现在开始,您将只为每个级别循环遍历4个像素!其余的如p。6。

8.拍摄第一个图像(最大=分辨率最高的图像),再次循环显示4个像素,最后得到最接近鼠标光标的像素:

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

9.但是,我在这里将“ M”视为要点。如果希望它是一个完全适合的圆,则需要先按circle.radius像素缩小(缩小)形状。

我以为我要补充一点,该算法仅在不使用单色而是灰度图像的情况下才有效,如果不是白色,则将像素视为“完整”,如果完全是白色,则将像素视为“空” ...或者调整大小每当这4个像素中的至少一个不是白色时,算法会将每4个像素的组更改为1个黑色像素。


2
+1表示难以(如果不是不可能)数学表达的形状的答案。
Cypher 2012年

哇,非常有趣。也是+1:D
Vexille 2012年

我在实际项目中实现了它,我必须说出现了一些问题。基本上,您需要列出一个网格单元格列表,在其中采用最接近的网格单元格命名closest,然后检查到最远点的距离closest-我们将其命名为distance furthest_dist。现在,您需要从列表中删除所有最近点(比位置更远)的单元格,furthest_dist然后再进行更深层次的设置。所以不要这样:i.imgur.com/4UuFo.png就像这样:i.imgur.com/dyTT3.png
Markus von Broady
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.