GameMaker Collision_line spacing glitch through corners

Q

QuinnlanVos

Guest
I was creating a custom script to find the exact point a line hits an object.
so i made one tracking a line to the mouse coordinates

however sometimes collision_line wouldn't register a collision (returns -4, or 0 for collision_line_list)
when going through the corners of a rectangle

It is only when the distance is very specific, if I made the mouse closer of farther, and the same angle it then registers.

So thinking I'm making some silly mistake, i used YellowAfterLifes code that he wrote here
https://yal.cc/gamemaker-collision-line-point/

and the same thing happens....
Screens and Codes below


I tired it with the code and sprite being precise and not.
Am I missing something obvious or is this a possible glitch

Code:
var dir, dist, obj, xx, yy, col_x,col_y, i, o, p;
ds_list_clear(global.OBJ_LIST)
obj = collision_line_list(x,y,mouse_x,mouse_y,obj_block,true,true,global.OBJ_LIST,true);

if obj = 0
{
draw_set_color(c_green);
draw_line(x,y,mouse_x,mouse_y);
}
else
{
obj = ds_list_find_value(global.OBJ_LIST,0);
dist = point_distance(x,y,obj.x,obj.y)+100
dir = point_direction(x,y,mouse_x,mouse_y);
dist = 1

while collision_line(x,y,x+lengthdir_x(dist,dir),y+lengthdir_y(dist,dir),obj,false,false) < 0
{
    dist += 1;
}
draw_set_color(c_red);
draw_line(x,y,x+lengthdir_x(dist,dir),y+lengthdir_y(dist,dir));
}
There's my Code, and of course YellowAfterLifes is in the link above.

Both have the same outcome....not_working.png working.png
 
Q

QuinnlanVos

Guest
Yes, its just a simple 64x64 rectangle. I've tried both precise and rectangle bbox.
The give-away is that line will work or not work depending on the distance.
 
M

MirthCastle

Guest
Im struggling to understand what it is that you are doing here... I think you are implementing this function incorrectly... this looks like way overkill.

Why are you using LengthDir and the while statement with the point distance and dir?? What are you looking for that the collision_line_list doesn't give you already?

I notice you set dist to some number based on point distance + 100, then you set it back to 1? Then you increase distance by 1 pixel during the while statement?

this code below works perfectly for me, and does the same\similar as your code intends (i think).
If you are trying to get more information about the object, just return obj variable??


ds_list_clear(global.OBJ_LIST)
var obj = collision_line_list(x, y, mouse_x, mouse_y, obj_block, true, true, global.OBJ_LIST, true);

if ( obj < 1 ) {
draw_set_color(c_green);
draw_line(x, y, mouse_x, mouse_y);​

} else {
obj = ds_list_find_value(global.OBJ_LIST, 0);
draw_set_color(c_red);
draw_line(x, y, obj.x, obj.y);
//draw_line(x, y, mouse_x, mouse_y);​
}
 
Q

QuinnlanVos

Guest
I notice you set dist to some number based on point distance + 100, then you set it back to 1? Then you increase distance by 1 pixel during the while statement?
yes ignore the first dist setting variable. that was a first attempt.


I think you are implementing this function incorrectly... this looks like way overkill.

Why are you using LengthDir and the while statement with the point distance and dir?? What are you looking for that the collision_line_list doesn't give you already?
It seems like overkill, but your code only draws a line directly to the object origin
my code, when it works, dras a line to the exact pixel the line crosses the object
which is why i am using lengthdir_x based on the line to mouse_x,mouse_y
and using the while loop to mimic a ray trace.


But regardless, forget the whole drawling line thing, that part works fine

Ill upload my game file in a minute, and itt'l show GMS2 is not registering collision_line at certain line lengths
 
M

MirthCastle

Guest
Yeah there is definitely a bug with the collision line, and list functions.

I altered your code for both and found it making a mistake with either one.

let's find another way to do this: stand by.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
When using non-rotated non-precise rectangle masks for objects, collision_line can hit through bottom/right side pixels at very specific angles. I've had some issues with this in past on Nuclear Throne.
 
M

MirthCastle

Guest
Got it: This works perfectly and is more efficient. I adapted it from a line of sight script I wrote.

xx, yy is the location of collision
you can change prog += n to whatever number satisfies you - I used += 2 here (don't go below 1)

you can raise it pretty high depending on how accurate you want to be... the higher it is the faster the check. Use INTs.

you can also change the starting prog - I set mine to halfway the length of the line

Code:
draw_set_color(c_white)
draw_line(x, y, mouse_x, mouse_y);

var dist = point_distance(x, y, mouse_x, mouse_y);
var obj = noone;
var prog = dist div 2;

while ( prog < dist && obj = noone ) {
 
        var lerpD = prog / dist;
 
        var xx = lerp(x, mouse_x, lerpD);
        var yy = lerp(y, mouse_y, lerpD);
 
        obj = instance_position(xx, yy, obj_block);
 
        prog += 2;
}

if ( obj = noone ) {
    draw_set_color(c_green);
    draw_line(x, y, mouse_x, mouse_y);
    
} else {
    draw_set_color(c_red);
    draw_line(x, y, xx, yy);
 
}
 
Last edited by a moderator:
Q

QuinnlanVos

Guest
Got it: This works perfectly and is more efficient. I adapted it from a line of sight script I wrote.
[/CODE]
Yay! Thank you so much.
You confirmed I am not going crazy, and gave me a work-around :)
I assume there is already a bug report on this out there somewhere? Because is kinda frustrating to not be able to trust a built in function like that.

before its 100% solved though, since there is no master check to see what to set "prog" too
I set mine to halfway the length of the line
i just always have to set it 0 (which takes up memory), or do a very basic check like point_distance to the nearest instance of an object
Because my char is going to move obviously, i can just set to halfway to the mouse.

But regardless I should be able to get it to work now thanks again!
 
M

MirthCastle

Guest
All good, im glad it works for you.

"prog" is just a measurement for the lerp function:

If prog = 0, the position is the player x, y
If prog = dist, the position is the mouse_x, mouse_y

when I say "halfway the length of the line" - I actually meant what you said and set it to "halfway to the mouse". :D which is the var prog = dist div 2;

I use something very similar for testing LOS for attacking and hiding - against tiles AND objects in a Turned Based Strategy im making. :)
 
Top