Line Thickness and Hit Testing pixel level behavior

I’m experiencing an unexpected issue with line thickness and hit testing in OpenFL. When I increase the line thickness using lineStyle(), the line visually appears thicker, but the hit testing does not seem to respect the line’s actual thickness at the pixel level.

Code example:

// inside Shape type instance:
graphics.lineStyle(10, 0xFF0000, 1);  // Thick line
graphics.moveTo(startX, startY);
graphics.lineTo(endX, endY);

Questions:

  • How can I make pixel level hit testing work correctly with thick lines? ( no matter how thick the line is, that does not affect the hitTestPoint results.
  • Is there a recommended approach to expand hit detection to match the visual line thickness?
  • Are there any known limitations or workarounds in OpenFL for line hit testing?

I’ve tried standard hit testing method hitTestPoint(p.x, p.y, true) , but they don’t seem to account for the line’s increased width.

Any insights or solutions would be greatly appreciated!

In a quick test, I wasn’t able to reproduce (but keep reading because I will reproduce in a moment). I can clearly see that the log switches from false to true when the mouse enters the circle’s large stroke:

var sprite = new Sprite();
sprite.x = 60;
sprite.y = 60;

sprite.graphics.lineStyle(100, 0xff0000);
sprite.graphics.drawCircle(100, 100, 100);

addChild(sprite);

stage.addEventListener(MouseEvent.MOUSE_MOVE, event -> {
	trace(sprite.hitTestPoint(stage.mouseX, stage.mouseY, true));
});

It’s similar when I simply draw a line instead, like in the code that you shared (it writes true to the log when the mouse is inside the line’s bounds):

var sprite = new Sprite();
sprite.x = 60;
sprite.y = 60;

sprite.graphics.lineStyle(50, 0x0000ff);
sprite.graphics.moveTo(20, 320);
sprite.graphics.lineTo(300, 280);

addChild(sprite);

stage.addEventListener(MouseEvent.MOUSE_MOVE, event -> {
	trace(sprite.hitTestPoint(stage.mouseX, stage.mouseY, true));
});

However, I tried drawing both a circle and a line, and that’s when things break down. In the log, hitTestPoint() is returning true only when the mouse is inside the line’s stroke, and the circle’s stroke is not detected, for some reason. That’s definitely a bug!

var sprite = new Sprite();
sprite.x = 60;
sprite.y = 60;

sprite.graphics.lineStyle(100, 0xff0000);
sprite.graphics.drawCircle(100, 100, 100);

sprite.graphics.lineStyle(50, 0x0000ff);
sprite.graphics.moveTo(20, 320);
sprite.graphics.lineTo(300, 280);

addChild(sprite);

stage.addEventListener(MouseEvent.MOUSE_MOVE, event -> {
	trace(sprite.hitTestPoint(stage.mouseX, stage.mouseY, true));
});

We use the isPointInStroke() and isPointInFill() methods from the CanvasRenderingContext2D in JS (and similar methods from Cairo for native targets). Those should be very well tested in all browsers (and Cairo), so it’s got to be a bug in OpenFL’s usage of them somehow. I guess it may have been tested only with simpler drawings, and not necessarily more complex ones with multiple fills or strokes in the same Graphics object. Someone will need to dive in and work out why it’s ignoring some of the strokes and/or fills.

1 Like

The following commit to OpenFL fixes the issue with the code from my previous reply.

Let me know if it fixes the issue for you too! If not, then I’ll take another look.

3 Likes

Thank you @joshtynjala, really appreciated!

1 Like