collision_normal
The purpose of this script is to determine what direction the sprite of an instance is facing at a particular point on or near the sprite, ie. a 2D analogue of a surface normal.
It does this by sampling an area around a given point. As each point is sampled, if there is no collision, a vector is generated from the center of the sample area to the sampled point. These vectors are summed to produce an overall directional vector pointing away from any detected surface within the sampled area.
Sampling can be quite intensive for even modest sized areas. Use the
spacing
argument to reduce the number of samples.
- collision_normal(x, y, obj, radius, spacing)
- Returns a 2D "surface normal" at a point on or near an instance within a test area.
COPY/// @func collision_normal(x, y, obj, radius, spacing)
///
/// @desc Returns a 2D "surface normal" at a point on or near an
/// instance within a test area. The test area is circular
/// and the detected normal direction is returned in degrees.
/// If no collision is found, (-1) is returned. Uses about
/// pi*(radius*radius)/(spacing*spacing) collision checks.
///
/// @param {real} x x-coordinate of point near an instance
/// @param {real} y y-coordinate of point near an instance
/// @param {object} obj object or instance (or all)
/// @param {real} radius radius of test area (default 4)
/// @param {real} spacing space between each sample (default 1)
///
/// @return {real} direction pointing away from the detected surface
///
/// GMLscripts.com/license
function collision_normal(x, y, obj, radius=4, spacing=1)
{
var nx = 0;
var ny = 0;
if (collision_circle(x, y, radius, obj, true, true) != noone) {
for (var j=spacing; j<=radius; j+=spacing) {
for (var i=0; i<radius; i+=spacing) {
if (point_distance(0, 0, i, j) <= radius) {
if (collision_point(x+i, y+j, obj, true, true) == noone) { nx += i; ny += j; }
if (collision_point(x+j, y-i, obj, true, true) == noone) { nx += j; ny -= i; }
if (collision_point(x-i, y-j, obj, true, true) == noone) { nx -= i; ny -= j; }
if (collision_point(x-j, y+i, obj, true, true) == noone) { nx -= j; ny += i; }
}
}
}
if (nx == 0 && ny == 0) return (-1);
return point_direction(0, 0, nx, ny);
}
return (-1);
}
Contributors: xot, strawbryjam
GitHub: View · Commits · Blame · Raw