Skip to content

Instantly share code, notes, and snippets.

@gnysek
Created November 15, 2022 16:40
Show Gist options
  • Save gnysek/fcb2a35c3ed52a7abb4c2c61f5e026cd to your computer and use it in GitHub Desktop.
Save gnysek/fcb2a35c3ed52a7abb4c2c61f5e026cd to your computer and use it in GitHub Desktop.
mp_potential_step but in pure GML
//
// based on https://github.com/YoYoGames/GameMaker-HTML5/blob/develop/scripts/functions/Function_MotionPlanning.js#L232
//
global.__mp_settings = {
maxrot: 30,
rotstep: 10,
ahead: 3,
onspot: true,
}
// feather ignore GM2017 (name proposal)
/// @param {Real} _x
/// @param {Real} _y
/// @param {Asset.GMObject, Constant.All} _objind
/// @param {Bool} _checkall
function TestFree(_x, _y, _objind, _checkall) {
if ( _objind == all ) {
if ( _checkall ) {
return place_empty(_x,_y);
} else {
return place_free(_x, _y);
}
} else {
return (instance_place(_x, _y, _objind) == noone);
}
}
function TryDir(m, _dir, _speed, _objind, _checkall) {
var xnew = 0.0;
var ynew = 0.0;
// see whether angle is acceptable
if (DiffDir(_dir, direction) > global.__mp_settings.maxrot) {
return false;
}
// check position a bit ahead
xnew = x + _speed * global.__mp_settings.ahead * cos( pi * _dir / 180 );
ynew = y - _speed * global.__mp_settings.ahead * sin( pi * _dir / 180 );
if (true != TestFree(xnew, ynew, _objind, _checkall)) {
return false;
}
//check next position
xnew = x + _speed * cos(pi * _dir / 180);
ynew = y - _speed * sin(pi * _dir / 180);
if (true != TestFree(xnew, ynew, _objind, _checkall)) {
return false;
}
// OK, so set the position
direction = _dir;
x = xnew;
y = ynew;
return true;
}
function DiffDir(_dir1 , _dir2) {
var Result = 0.0;
while ( _dir1 <= 0.0 ) { _dir1 = _dir1 + 360; }
while ( _dir1 >= 360.0 ) { _dir1 = _dir1 - 360; }
while ( _dir2 < 0.0 ) { _dir2 = _dir2 + 360; }
while ( _dir2 >= 360. ) { _dir2 = _dir2 - 360; }
Result = _dir2 - _dir1;
if ( Result < 0 ) { Result = -Result; }
if ( Result > 180 ) { Result = 360-Result; }
return Result;
}
/// @param {Real} _x
/// @param {Real} _y
/// @param {Real} _stepsize
/// @param {Bool} _checkall
function scr_mp_potential_step(_x, _y, _stepsize, _checkall = false) {
return scr_mp_potential_step_object(_x, _y, _stepsize, all, _checkall);
}
/// @param {Real} _x
/// @param {Real} _y
/// @param {Real} _stepsize
/// @param {Asset.GMObject, Constant.All} _objindex
/// @param {Bool} _checkall
function scr_mp_potential_step_object(_x, _y, _stepsize, _objindex, _checkall = false) {
// check whether at the correct position
if ((x == _x) && (y == _y))
{
return true;
}
var dist = 0;
var goaldir = 0;
var curdir = 0;
// check whether close enough for a single step
dist = sqrt(sqr(x - _x) + sqr(y - _y));
if (dist <= _stepsize)
{
if (TestFree(_x, _y, _objindex, _checkall))
{
direction = point_direction(x, y, _x, _y);
x = _x;
y = _y;
}
return true;
}
// Try directions as much as possible towards the goal
goaldir = point_direction(x, y, _x, _y);
curdir = 0;
while ( curdir < 180 )
{
if (TryDir(TestFree, goaldir - curdir, _stepsize, _objindex, _checkall)) {
return false;
}
if (TryDir(TestFree, goaldir + curdir, _stepsize, _objindex, _checkall)) {
return false;
}
curdir = curdir + global.__mp_settings.rotstep;
}
// If we did not succeed a local minima was reached
// To avoid that the instance gets stuck we rotate on the spot
if (global.__mp_settings.onspot)
{
direction = direction + global.__mp_settings.maxrot;
}
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment