• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GML "Point in line?"

MeBoingus

Member
Howdy guys and gals,


I'm in the process of making a small editing tool that allows users to create 'objects' and rotate, scale and move these objects around.

I'm trying to implement the ability for the user to scale the object by clicking on a side/corner of the 'box' and dragging to size it (similar to how an image editing tool handles this same problem).

I got some help from another user in regards to drawing the 'box' around the object. This is the code I'm using for that:

Code:
var _x0 = x + _left * _c +  _top * _s;
var _y0 = y + _left * -_s + _top * _c;
var _x1 = x + _right * _c +  _top * _s;
var _y1 = y + _right * -_s + _top * _c;
var _x2 = x + _right * _c +  _bottom * _s;
var _y2 = y + _right * -_s + _bottom * _c;
var _x3 = x + _left * _c +  _bottom * _s;
var _y3 = y + _left * -_s + _bottom * _c;


draw_set_color(c_gui_decor);

draw_line_width(_x0, _y0, _x1, _y1, 2);
draw_line_width(_x1, _y1, _x2, _y2, 2);
draw_line_width(_x2, _y2, _x3, _y3, 2);
draw_line_width(_x3, _y3, _x0, _y0, 2);
This works as intended, along side some other code I'm using to allow the user to click a point to the bottom left of the sprite the sprite and begin rotating it.


The issue I'm having is that I cannot work out a simple way to detect if the cursor is 'inside of' or 'along' one of those lines. I.E. If the cursor is on the right-hand-side line of the box, regardless of it's current angle.

Does anyone know of a way to achieve this effect? A 'point_in_line' type script that would work within a few pixels of the 'edge' of each line?


Thanks in advance :).
 
There's a couple of things you could try that I think would be pretty straightforward.

The first would be to transform the mouse position into the rectangle's space.
var _x = (mouse_x - x) * _c + (mouse_y - y) * -_s;
var _y = (mouse_x - x) * _s + (mouse_y - y) * _s;
Notice the signs of the "_s" terms have been reversed.
From there it would be pretty straightforward to test the mouse's transformed position against the top, left, right, and bottom sides of the rectangle.

Alternatively, you could use vector projection to find the point on a line closest to the mouse position. And then you could check to see if the distance between that point and the mouse position is less than some value.
Here's an example of using vector projection to get the closest point to the mouse position on the line between the vertices (_x0,_y0) and (_x1,_y1). (_ux,_uy) is that point.
var _vx = _x1 - _x0;
var _vy = _y1 - _y0;
var _sc = ((mouse_x - _x0)*_vx + (mouse_y - _y0)*_vy)/(_vx*_vx+_vy*_vy);
var _ux = _x0 + _vx * _sc;
var _uy = _y0 + _vy * _sc;

EDIT: Forgot to add (_x0,_y0) to (_ux,_uy). We were looking for a point in the world. Fixed.

EDIT2: You'll also want to know if the point lies within the line segment. To determine that check that _sc is greater than 0 and less than 1.

EIDT3: The first method is less complicated and more efficient. It's the way I'd go.
 
Last edited:

MeBoingus

Member
There's a couple of things you could try that I think would be pretty straightforward.

The first would be to transform the mouse position into the rectangle's space.
var _x = (mouse_x - x) * _c + (mouse_y - y) * -_s;
var _y = (mouse_x - x) * _s + (mouse_y - y) * _s;
Notice the signs of the "_s" terms have been reversed.
From there it would be pretty straightforward to test the mouse's transformed position against the top, left, right, and bottom sides of the rectangle.

Alternatively, you could use vector projection to find the point on a line closest to the mouse position. And then you could check to see if the distance between that point and the mouse position is less than some value.
Here's an example of using vector projection to get the closest point to the mouse position on the line between the vertices (_x0,_y0) and (_x1,_y1). (_ux,_uy) is that point.
var _vx = _x1 - _x0;
var _vy = _y1 - _y0;
var _sc = ((mouse_x - _x0)*_vx + (mouse_y - _y0)*_vy)/(_vx*_vx+_vy*_vy);
var _ux = _x0 + _vx * _sc;
var _uy = _y0 + _vy * _sc;

EDIT: Forgot to add (_x0,_y0) to (_ux,_uy). We were looking for a point in the world. Fixed.

EDIT2: You'll also want to know if the point lies within the line segment. To determine that check that _sc is greater than 0 and less than 1.
Thanks for the reply :) I actually worked out something quite similar to this a few minutes back, but also ended up finding a script from GMLScripts that happens to tackle this exact problem quite eloquently.
Here's a link in case anyone runs into this thread down the line: https://www.gmlscripts.com/script/point_line_distance.

As always, thanks a bunch!
 
Top