Open jack27121 opened 6 days ago
The alternative Stann is talking about here is collision_normal
from GMLScripts:
function collision_normal(_x, _y, _r, _obj, _prec=false, _notme=true, _res=0.25) {
// Returns a 2D "surface normal" (in degrees) at a given point
// on or near an instance detected within a circular test area.
// Makes approximately pi*(rad*rad)/(res*res) collision calls.
// If no collision is found, (-1) is returned.
//
// x1,y1 point on the surface, real
// rad radius of test area (default 4), real
// obj object or instance (or all), real
// res resolution of test (default 1), float
//
/// GMLscripts.com/license
var nx = 0;
var ny = 0;
if (collision_circle(_x, _y, _r, _obj, _prec, _notme)) {
var _length = _r*_res*2;
var _itterator = 1/_res;
var _i, _j;
_i=-_r; repeat(_length) {
_j=-_r; repeat(_length) {
if (point_distance(0, 0, _i, _j) <= _r) {
if (!collision_point(_x+_i, _y+_j, _obj, _prec, _notme)) { nx += _i; ny += _j; }
if (!collision_point(_x+_j, _y-_i, _obj, _prec, _notme)) { nx += _j; ny -= _i; }
if (!collision_point(_x-_i, _y-_j, _obj, _prec, _notme)) { nx -= _i; ny -= _j; }
if (!collision_point(_x-_j, _y+_i, _obj, _prec, _notme)) { nx -= _j; ny += _i; }
}
_j+=_itterator; }; //end inner repeat
_i+=_itterator; }; //end outer repeat
if (nx == 0 && ny == 0) return (-1);
return point_direction(0, 0, nx, ny);
}
else {
return (-1);
}
}
And yes, I'm in agreeance this is quite costly for devs to do, it may be rectified a bit by gmrt optimizations, but over all an inbuilt solution would be ideal here. Though I have no suggestions as to name or syntax for it as it's kind of unique, like move_and_collide
is.
Is your feature request related to a problem?
Say you want to do an involved platformer. For slopes, calculating speed, making different surfaces bouncy. if you collide with some slope, knowing the surface angle would allow you to a lot of control over different things
Describe the solution you'd like
When making sprite-masks or tiles, it would be very handy if you had the option to also define a collision shape. Similar to how you can define points on physics objects (but without needing the physics) and then when colliding with something, and easy way to get information about that collision. Contact point, surface normal. If you collide with a tile-layer, get the specific tile
Describe alternatives you've considered
different approaches have been, having a series of sensors all around the player, and checking the distance to a collision from each, and then comparing them and that way getting a surface normal.
Another way is trying to pre-calculate the surface-normal of different tiles, and making a system to get that back when you collide with a tile. Though you then have to do a bunch of extra steps depending on what side of the tile you collided with, and or if it's rotated/flipped/mirrored.
The same complications come if you want to know the surface normal of rotated objects. There is no easy solution for this problem currently. And requires a LOT of intensive work just to get this info.
Additional context
some steps could be easier if you just used the physics system, since you have to define physics shapes of objects (though not tiles), but more often than not you really don't want to use the physics system because it makes controlling platformer mechanics harder.