GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2021-04-28 12:00:46

maras
Member
Registered: 2021-04-25
Posts: 28
Website

raycast

Another code from my "library" I actually use all the time

Expand/// raycast(x1, y1, x2, y2, obj/[obj], prec_mask, prec, single_point)
//
// A faster collision_line function
//
// @returns array[hit_inst_id, line_length, collision_x, collision_y]
//
//	x1		x from, real
//	y1		y from, real
//	x2		x to, real
//	y2		y to, real
//	obj		object to check, object index / instance id / array of objects
//	prec_mask	use precise masks for collision, bool
//	prec		line precision (check every xth position), real
//	single_point	check for single point (true) or a rectangle (false), bool
//
// prec is mainly for optimization, higher value makes it faster (tested on phones)
// if the prec value is too high it will become inaccurate and it may skip small objects and corners
// it always should be smaller than the size/2 of the the smallest object you want to check
//
/// GMLscripts.com/license

function raycast(x1, y1, x2, y2, obj, prec_mask, prec, single_point) {
	
	var len = point_distance(x1, y1, x2, y2);
	var rot = point_direction(x1, y1, x2, y2);
	var rect_w = ceil(prec * 0.5);
	var c = noone;
	var arr = [];
	
	// single object
	if !is_array(obj)
	    {
	    for(var l = 0; l < len; l += prec)
	        {
	        var xx = x1+dcos(rot)*l;
	        var yy = y1-dsin(rot)*l;

	        if single_point c = collision_point(xx, yy, obj, prec_mask, true);
	        else c = collision_rectangle(xx-rect_w, yy-rect_w, xx+rect_w, yy+rect_w, obj, prec_mask, true);
			
	        if c != noone // hit
	            {
	            arr[0] = c;
	            arr[1] = l;
	            arr[2] = xx;
	            arr[3] = yy;
	            return arr;
	            }
	        }
	    }
	else // array of objects
	    {
	    var arr_len = array_length(obj);
    
	    for(var l = 0; l < len; l += prec)
	        {
	        var xx = x1+dcos(rot)*l;
	        var yy = y1-dsin(rot)*l;

	        for(var a = 0; a < arr_len; a++)
	            {
	            var arr = obj;
	            if single_point c = collision_point(xx, yy, arr[a], prec_mask, true);
	            else c = collision_rectangle(xx-rect_w, yy-rect_w, xx+rect_w, yy+rect_w, arr[a], prec_mask, true);
            
	            if c != noone // hit
	                {
	                arr[0] = c;
	                arr[1] = l;
	                arr[2] = xx;
	                arr[3] = yy;
	                return arr;
	                }
	            }
	        }
	    }

	// no hit
	arr[0] = noone;
	arr[1] = len;
	arr[2] = x2;
	arr[3] = y2;
	return arr;
}

Last edited by maras (2021-05-25 15:53:41)


I'm on the official GM discord > maras_cz

Offline

#2 2021-05-25 14:21:59

xot
Administrator
Registered: 2007-08-18
Posts: 1,239

Re: raycast

I'll have to study this and see how it may improve on this existing script with a worse name:

https://www.gmlscripts.com/script/range_finder


Abusing forum power since 1986.

Offline

Board footer

Powered by FluxBB