2

I'm currently working on a mini map for a game in which keeps track of different items of importance on and off the screen. When I first created the mini map through a secondary camera rendered onto a texture and displayed on screen in a miniature display, it was rectangle shape. I was able to ensure when the item of importance left the view of the map, an arrow pointing to the target showed up and remained on the edge of the map. It was basically clamping the x & y positions of the arrow to half the camera view's width and length (with some suitable margin space).

Anyway. Now I am trying to make the mini map circular and while I have the proper render mask on to guarantee that shape of the mini map, I am having difficulties in clamping the arrows to the shape of the new mini-map. In the rectangular mini map, the arrows stayed in the corners while clamped, but obviously, circles don't have corners.

I am thinking clamping the arrow's x & y positions have to do with the radius of the circle (half of the height of the screen/minimap), but because I'm a little weak on the math side, I am kindly requesting some help. How would I clamp the arrows to the edge of a new circle shape?

The code I have now is as follows:

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);

I should probably also note that all mini-map symbols and arrows technically are on screen but only are displayed in on the secondary camera through a culling mask... you know, just in case it helps.

ACour008
  • 83
  • 8
  • 2
    Remember pythagoras' theorem from school? The length of the long side of a right-angled triangle is related to the other two. Specifically, Sqrt(lengthHypotenuse) = Sqrt( lengthShortest^2 + lengthMiddle^2)... Does this help at all? Another way would involve normalizing a vector before multiplying it by the radius of your map. That's how you'd place the end of a 2d vector in a random direction on the circumference of a circle. Think - the circumference is the end of a bunch of vectors originating at the center, all with length equal to the radius. – enhzflep Feb 07 '21 at 20:57
  • 1
    The key with the right-angle triangle @enhzflep mentioned is to realise that all points on the circle can be represented by it, where hypotenuse is the radius of the circle. Perhaps a simpler way of looking at it, the equation for a circle (at origin 0,0) is x^2 + y^2 = radius^2. So with some clever geometry manipulations, you can work out the area your circular minimap covers. – Ian Feb 07 '21 at 22:16
  • 2
    Or simpler again, work out the x/y offset of your marker from the minimap centre (`abs(marker.x - mapCentre.x)`) and see if the marker radius is < map radius. – Ian Feb 07 '21 at 22:20
  • I get what both you were saying, @enhzflep and @Ian! I didn't need to use a clamp function at all but just normalized the direction vector and multiplied it by the radius of the mask, minus the margin space ofc. Big thanks!! – ACour008 Feb 08 '21 at 03:09

1 Answers1

1

Just for anyone else looking to do the same, I basically normalized the direction from the target node that the arrow points at and multiplied it by the radius of the image mask (with appropriate margin space).

Since the player node and the centre of the mask is at origin, I just got the difference from the player. The (640/2) is the diameter, which of course, shouldn't be hardcoded, but meh for now. Thanks to those who commented and got me thinking in the right direction.

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