【问题标题】:Clamping an arrow with a circle shape for mini map用圆形夹住小地图的箭头
【发布时间】:2021-02-07 20:31:41
【问题描述】:

我目前正在为一款游戏制作一个小地图,在该地图中跟踪屏幕内外不同的重要项目。当我第一次通过渲染到纹理上并以微型显示器显示在屏幕上的辅助相机创建迷你地图时,它是矩形的。我能够确保当重要项目离开地图视图时,会出现一个指向目标的箭头并保持在地图边缘。它基本上将箭头的 x 和 y 位置限制为相机视图宽度和长度的一半(具有一些合适的边距空间)。

无论如何。现在我正在尝试使迷你地图成为圆形,虽然我有适当的渲染蒙版来保证迷你地图的形状,但我很难将箭头夹在新迷你地图的形状上。在矩形小地图中,箭头在夹住的时候一直停留在角落里,但是很明显,圆形是没有角落的。

我认为夹紧箭头的 x 和 y 位置与圆的半径(屏幕/小地图高度的一半)有关,但是因为我在数学方面有点弱,所以我很友好请求一些帮助。如何将箭头夹在新圆形的边缘?

我现在的代码如下:

let {width: canvasWidth, height: canvasHeight} = cc.Canvas.instance.node,  // 960, 640
targetScreenPoint = cc.Camera.main.getWorldToScreenPoint(this.targetNode.position)

// other code for rotation of arrow, etc...

// FIXME: clamp the the edge of the minimap mask which is circular
// This is the old clamping code for a rectangle shape.

let arrowPoint = targetScreenPoint;
arrowPoint.x = utils.clamp(arrowPoint.x, (-canvasWidth / 2) + this.arrowMargin,
                                          (canvasWidth / 2) - this.arrowMargin);
arrowPoint.y = utils.clamp(arrowPoint.y, (-canvasHeight / 2) + this.arrowMargin,
                                         (canvasHeight /2) - this.arrowMargin);
            
this.node.position = cc.v2(arrowPoint.x, arrowPoint.y);

我可能还应该注意到,从技术上讲,所有小地图符号和箭头都在屏幕上,但仅通过剔除蒙版显示在辅助摄像头上……你知道,以防万一它有帮助。

【问题讨论】:

  • 还记得学校里的毕达哥拉斯定理吗?直角三角形长边的长度与另外两条有关。具体来说,Sqrt(lengthHypotenuse) = Sqrt(lengthShortest^2 + lengthMiddle^2)... 这有帮助吗?另一种方法是在将向量乘以地图的半径之前对其进行归一化。这就是您如何将二维向量的末端以随机方向放置在圆的圆周上。想一想 - 圆周是一组起源于中心的向量的末端,所有向量的长度都等于半径。
  • 直角三角形@enhzflep提到的关键是要意识到圆上的所有点都可以用它来表示,其中斜边是圆的半径。也许是一种更简单的观察方式,圆的方程(原点 0,0)是 x^2 + y^2 = 半径^2。因此,通过一些巧妙的几何操作,您可以计算出圆形小地图所覆盖的区域。
  • 或者再简单一点,计算你的标记与小地图中心 (abs(marker.x - mapCentre.x)) 的 x/y 偏移量,看看标记半径是否为
  • 我明白你们俩的意思,@enhzflep 和 @Ian!我根本不需要使用钳位函数,只需对方向向量进行归一化并将其乘以蒙版的半径,减去 c 的边距空间。非常感谢!

标签: javascript game-development cocoscreator


【解决方案1】:

对于其他希望这样做的人,我基本上将箭头指向的目标节点的方向归一化,并将其乘以图像蒙版的半径(具有适当的边距空间)。

由于播放器节点和蒙版的中心在原点,我只是从播放器那里得到了差异。 (640/2) 是直径,当然,它不应该是硬编码的,但现在就不行了。感谢那些评论并让我朝着正确方向思考的人。

let direction = this.targetNode.position.sub(this.playerNode.position).normalize();
let arrowPos = direction.mul((640/2) - this.arrowMargin);
this.node.position = arrowPos;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 2016-05-12
    相关资源
    最近更新 更多