You are not logged in.
Pages: 1
This is a set of scripts i call the "pie move" wander system. It uses "scan rays" aligned like pie slices or tire spokes. It scans for a suitable and desirable direction, then travels there. repeating this process as quickly as possible. Scanning is automatically done only when the instance is stationary, as per intentional limitations. if the instance scans outside the station, it must try to get back. The station location can be unbound, enabling unrestricted wandering.
The "pie move" wander system consists of five scripts, but only the top four are required.
The fifth script is to visualize the data so you can see what the script is doing.
Example of use: (also in init script)
Create event:
pie_move_init(48)
Step event:
var var_wander_speed; var_wander_speed=3;
pie_move_update(4,140,2)
pie_move_point(xstart,ystart,100,var_wander_speed)
mp_potential_step(loc_ret_x,loc_ret_y,var_wander_speed,false);
Draw event: (optional, for visualization only)
pie_move_draw(xstart,ystart,100)
EDIT 2/22/20: Bugfix in pie_move_init.
EDIT 4/6/20: added pie_move_reset and mp_grid_add_solids
Only needed if you want to use pathfinding
///mp_grid_add_solids(id, x, y, grid_width, grid_height, cell_width, cell_height);
//
// Checks for collision in an area, and sets an mp_grid accordingly
// Collisions are checked with the calling instance's sprite mask.
//
// id id of mp_grid, real
// x x position of the mp_grid, real
// y y position of the mp_grid, real
// grid_width width of the grid in cells, real
// grid_height height of the grid in cells, real
// grid_width width of a single cell, real
// grid_height height of a single cell, real
//
///gmlscripts.com/license
var var_id, var_iix, var_iiy, var_x, var_y, var_grid_width, var_grid_height, var_cell_width, var_cell_height, var_solid_revert;
var_id=argument[0];
var_x=argument[1];
var_y=argument[2];
var_grid_width=argument[3];
var_grid_height=argument[4];
var_cell_width=16;
if argument_count>5 var_cell_width=argument[5];
var_cell_height=16;
if argument_count>6 var_cell_height=argument[6];
var_iiy=0;
while var_iiy<var_grid_height {
var_iix=0;
while var_iix<var_grid_width {
if not place_free(var_x+(var_iix*var_cell_width),var_y+(var_iiy*var_cell_height)) {
mp_grid_add_cell(var_id,var_iix,var_iiy);
//show_message('cell added at '+string(var_iix)+', '+string(var_iiy))
}
var_iix+=1;
}
var_iiy+=1;
}
Only needed of you want to use pathfinding
///pie_move_reset()
// * arguments are optinal
//
// resets the pie_move system
// call this when restarting an idle pie_move system
//
// used for a wander system called "pie move"
//
///gmlscripts.com/license
loc_startup_timer=0;
loc_pie_offset=0;
loc_ret_x=x;
loc_ret_y=y;
REQUIRED
///distance_to_solid(maxdist,direction,not_me,precision*,x*,y*)
//
// returns distance until solid from x and y
//
// maxdist maximum distance
// direction direction to check
// not_me set to true to exclude local instance
// precision distance precision for checking
// x x location to scan from
// y y location to scan from
//
///gmlscripts.com/license
var Amaxdist=argument[0];
var Adirection=argument[1];
var Anot_me=1;
if argument_count>2 Anot_me=argument[2];
var Aprec=1;
if argument_count>3 Aprec=argument[3];
var Ax=x;
if argument_count>5 Ax=argument[5];
var Ay=y;
if argument_count>6 Ay=argument[6];
var seen_solid=false;
var solid_revert; solid_revert=solid;
if Anot_me solid=0;
var ii_len=0;
while (ii_len<Amaxdist and seen_solid=false) {
if not place_free(Ax+lengthdir_x(ii_len,Adirection),Ay+lengthdir_y(ii_len,Adirection)) {
seen_solid=true;
}
ii_len+=Aprec;
}
ii_len-=Aprec;
solid=solid_revert;
return ii_len;
REQUIRED
///pie_move_init(raw_slice_count, goal_reach_distance, ray_distance, x, y)
// all arguments are optional
//
// initializes a wander system
// should be executed only once
//
// raw_slice_count total spoke-styled scan rays, real (integer)
// ray_distance maximum scan ray distance, real
// x x position of wandering instance
// y y position of wandering instance
//
// used for a wander system called "pie move"
// raw_slice_count should be a multiple of "sub_slice_count"
// - "sub_slice_count" is an argument specified in the script "pie_move_update"
// see below for an example of use of the "pie-move" wander system.
//
///gmlscripts.com/license
/* example of "pie-move" use:
Create event:
pie_move_init(48)
Step event:
var var_wander_speed; var_wander_speed=3;
pie_move_update(4,140,2)
pie_move_point(xstart,ystart,100,var_wander_speed)
mp_potential_step(loc_ret_x,loc_ret_y,var_wander_speed,false);
Draw event: (optional, for visualization only)
pie_move_draw(xstart,ystart,100)
*/
var var_y, var_x, var_ii;
loc_stop_timer=-1;
loc_raw_slice_count=90
if argument_count>0 loc_raw_slice_count=argument[0]
loc_goal_reach_distance=9
if argument_count>1 loc_goal_reach_distance=argument[1]
loc_ray_distance=120;
if argument_count>2 loc_ray_distance=argument[2]
var_x=x
if argument_count>3 var_x=argument[3]
var_y=y
if argument_count>4 var_y=argument[4]
loc_startup_timer=-1;
loc_pie_offset=0;
var_ii=0;
repeat loc_raw_slice_count {
loc_pie_data[var_ii]=0;
var_ii+=1;
}
loc_ret_x=var_x;
loc_ret_y=var_y;
loc_dir=direction;
loc_interesting_direction_threshold=17
REQUIRED
///pie_move_update(precision, ray_distance*, sub_slice_count*, x*, y*)
// * arguments are optinal
//
// updates scan rays ONLY.
// should be used in a step event.
//
// precision precision to use for rays, real
// sub_slice_count number of rays to scan per step, real (integer)
// ray_distance maximum scan ray distance, real
// x x position of wandering instance, real
// y y position of wandering instance, real
//
// used for a wander system called "pie move"
// sub_slice_count must devide into "raw_slice_count" without remainder
// - "raw_slice_count" is an argument in the script "pie_move_init"
// see script "pie_move_update" for an example of use
//
///gmlscripts.com/license
var var_x, var_y, var_slice_space, var_raw_slice_size;
loc_sub_slice_count=6;
if argument_count>2 loc_sub_slice_count=argument[2];
if argument_count>1 loc_ray_distance=argument[1];
var_x=x;
if argument_count>3 var_x=argument[3];
var_y=y;
if argument_count>4 var_y=argument[4];
var var_slice_space;
var_slice_space=loc_raw_slice_count/loc_sub_slice_count;
var_raw_slice_size=360/loc_raw_slice_count;
if loc_startup_timer<360 loc_startup_timer+=1;
if point_distance(loc_ret_x,loc_ret_y,var_x,var_y)=0 {
// sub slice update onto raw slices
var var_slice_ii, var_subslice_index; var_slice_ii=0
repeat loc_sub_slice_count {
var_subslice_index=(var_slice_ii*var_slice_space)+loc_pie_offset;
loc_pie_data[var_subslice_index]=distance_to_solid(loc_ray_distance,var_subslice_index*var_raw_slice_size,true,argument[0]);
var_slice_ii+=1;
}
// update sub slice pie offset location
loc_pie_offset=(loc_pie_offset+1) mod var_slice_space;
}
REQUIRED
///pie_move_point(station_x, station_y, travel_distance, speed, x*, y*)
// * arguments are optional
//
// reacts to "scan ray" data and will "point" to the chosen "interesting direction"
// instance is allowed to walk outside station, but must walk toward station after leaving it
// should be used in a step event
//
// station_x x location of station to wander around
// station_y y location of station to wander around
// travel_distance station's unrestricted movement distance
// speed speed by which to wander
// x x position of wandering instance
// y y position of wandering instance
//
// if station_x is set to undefined, wandering will be unbound, and station_y will be ignored
// see script "pie_move_update" for an example of use
// customization notes below (marked "Custom:")
//
///gmlscripts.com/license
var var_sx, var_sy, var_speed, var_go_distance, var_x, var_y, var_exception;
var_sx=argument[0];
var_sy=argument[1];
var_go_distance=argument[2];
var_speed=argument[3];
var_x=x;
if argument_count>4 var_x=argument[4];
var_y=y;
if argument_count>5 var_y=argument[5];
var var_station_direction, var_chosen_direction_raw_index, var_station_distance_exceeded,
var_goal_distance;
var_station_direction=point_direction(var_x,var_y,var_sx,var_sy);
if var_sx!=undefined var_station_distance_exceeded=point_distance(var_x,var_y,var_sx,var_sy)>var_go_distance
else var_station_distance_exceeded=false;
var_goal_distance=point_distance(loc_ret_x,loc_ret_y,var_x,var_y);
if var_goal_distance>=loc_goal_reach_distance {
loc_startup_timer=-1;
}
else {
loc_ret_x=x;
loc_ret_y=y;
}
if loc_startup_timer>=loc_raw_slice_count/loc_sub_slice_count
and var_goal_distance<loc_goal_reach_distance {
var var_raw_slice_size, var_ii;
var_raw_slice_size=360/loc_raw_slice_count;
var_ii=0;
var var_align_direction_min_diff, var_align_direction, var_align_direction_diff;
if var_station_distance_exceeded var_align_direction=var_station_direction;
else {
// Custom: chance of trying to maintain approximate direction
// |----------|
if irandom(4)=0 var_align_direction=irandom(359);
// Custom: feild of random direction offset for approximation
// |-------------|
else var_align_direction=direction-30+irandom(60);
}
var_align_direction_min_diff=1000;
repeat loc_raw_slice_count {
var var_last_slice; var_last_slice=var_ii-1;
if var_last_slice<0 var_last_slice+=loc_raw_slice_count;
var var_last_slice2; var_last_slice2=var_ii-2;
if var_last_slice2<0 var_last_slice2+=loc_raw_slice_count;
var var_next_slice; var_next_slice=var_ii+1;
if var_next_slice>=loc_raw_slice_count var_next_slice-=loc_raw_slice_count;
var var_next_slice2; var_next_slice2=var_ii+2;
if var_next_slice2>=loc_raw_slice_count var_next_slice2-=loc_raw_slice_count;
// dont walk away from the station for an "interesting direction"
if var_station_distance_exceeded var_exception=abs(angle_difference(var_ii*var_raw_slice_size,var_align_direction+180))>75;
else var_exception=true;
// Custom: 30 is the far neighbor "interesting direction" threshold
if (loc_pie_data[var_last_slice2]<=loc_pie_data[var_ii]-(loc_interesting_direction_threshold*2)
or loc_pie_data[var_next_slice2]<=loc_pie_data[var_ii]-(loc_interesting_direction_threshold*2))
// Custom: 17 is the close neighbor "interesting direction" threshold
if (loc_pie_data[var_last_slice]<=loc_pie_data[var_ii]-loc_interesting_direction_threshold
or loc_pie_data[var_next_slice]<=loc_pie_data[var_ii]-loc_interesting_direction_threshold)
// Custom: 40 is the minimum acceptable scan ray distance.
and loc_pie_data[var_ii]>40
and var_exception {
var_align_direction_diff=abs(angle_difference(var_align_direction,var_ii*var_raw_slice_size));
if var_align_direction_min_diff>var_align_direction_diff {
var_align_direction_min_diff=var_align_direction_diff;
var_chosen_direction_raw_index=var_ii;
}
}
var_ii+=1
}
if var_align_direction_min_diff=1000 {
if var_station_distance_exceeded direction=floor(var_station_direction/var_raw_slice_size)*var_raw_slice_size;
else direction=irandom(loc_raw_slice_count-1)*var_raw_slice_size;
var_chosen_direction_raw_index=direction/var_raw_slice_size
}
else direction=var_chosen_direction_raw_index*var_raw_slice_size;
var var_max_dist, var_chosen_length;
var_max_dist=loc_pie_data[var_chosen_direction_raw_index];
// Custom: 0.6 is a multiple of a scan-ray's distance for the chosen direction
// Custom: 16 is padding to avoid having the wander target go into a solid
// they both specify walk distance randomization paramiters
var_chosen_length=irandom_range(var_max_dist*0.6,var_max_dist-16)
loc_ret_x=var_x+lengthdir_x(var_chosen_length,direction);
loc_ret_y=var_y+lengthdir_y(var_chosen_length,direction);
}
optional
///pie_move_draw(station_x, station_y, travel_distance)
//
// this script is only intended for visualizing how "pie move" works
// - This script is not synced with any data from the "pie_move_point" script
// this script should be called in a draw event
//
// station_x x location of station to wander around
// station_y y location of station to wander around
// travel_distance station's unrestricted movement distance
//
// see script "pie_move_update" for an example of use
//
///gmlscripts.com/license
var_sx=argument[0]
var_sy=argument[1]
var_go_distance=argument[2]
draw_set_color(c_fuchsia);
draw_circle(var_sx,var_sy,var_go_distance,1);
draw_circle(var_sx,var_sy,3,1);
var_raw_slice_size=360/loc_raw_slice_count;
var var_ii; var_ii=0;
repeat loc_raw_slice_count {
var var_last_slice; var_last_slice=var_ii-1;
if var_last_slice<0 var_last_slice+=loc_raw_slice_count;
var var_last_slice2; var_last_slice2=var_ii-2;
if var_last_slice2<0 var_last_slice2+=loc_raw_slice_count;
var var_next_slice; var_next_slice=var_ii+1;
if var_next_slice>=loc_raw_slice_count var_next_slice-=loc_raw_slice_count;
var var_next_slice2; var_next_slice2=var_ii+2;
if var_next_slice2>=loc_raw_slice_count var_next_slice2-=loc_raw_slice_count;
// 30 is the far neighbor "interesting direction" threshold
//if (loc_pie_data[var_last_slice2]<=loc_pie_data[var_ii]-30
//or loc_pie_data[var_next_slice2]<=loc_pie_data[var_ii]-30)
// 17 is the close neighbor "interesting direction" threshold
if (loc_pie_data[var_last_slice]<=loc_pie_data[var_ii]-17
or loc_pie_data[var_next_slice]<=loc_pie_data[var_ii]-17)
// 40 is the minimum acceptable scan ray distance.
and loc_pie_data[var_ii]>40 {
if loc_startup_timer>(loc_raw_slice_count/loc_sub_slice_count) {
draw_set_color(c_red)
}
else draw_set_color(c_yellow)
}
else draw_set_color(c_aqua)
draw_line(x,y,x+lengthdir_x(loc_pie_data[var_ii],var_ii*var_raw_slice_size),y+lengthdir_y(loc_pie_data[var_ii],var_ii*var_raw_slice_size))
var_ii+=1;
}
draw_set_color(c_lime);
draw_rectangle(loc_ret_x-1,loc_ret_y-1,loc_ret_x+1,loc_ret_y+1,0)
Last edited by lostdarkwolf (2020-04-07 00:13:18)
Offline
Pages: 1