242 lines
13 KiB
HTML
242 lines
13 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
|
|
<html>
|
|
<head>
|
|
<title>Motion planning</title>
|
|
<link href="style.css" rel="stylesheet" type="text/css">
|
|
</head>
|
|
<body background="images/back.gif">
|
|
<!--START-->
|
|
|
|
<h3>Motion planning</h3>
|
|
|
|
Motion planning helps you to move certain instances from a given location
|
|
to a different location while avoiding collisions with certain other instances
|
|
(e.g. walls). Motion planning is a difficult problem. It is impossible to
|
|
give general functions that will work properly in all situations. Also,
|
|
computing collision free motions is a time-consuming operation. So you have
|
|
be careful how and when you apply it. Please keep these remarks in mind when
|
|
you use any of the following functions.
|
|
|
|
<P>
|
|
Different forms of motion planning are provided by <I>Game Maker</I>.
|
|
The simplest form lets an instance take a step towards a particular goal
|
|
position, trying to go straight if possible but taking a different direction
|
|
if required. These functions should be used in the step event of an instance.
|
|
They correspond to the motion planning actions that are also available:
|
|
|
|
<p>
|
|
<blockquote>
|
|
<tt><b>mp_linear_step(x,y,stepsize,checkall)</b></tt>
|
|
This function lets the instance take a step straight towards the indicated
|
|
position (x,y). The size of the step is indicated by the <TT>stepsize</TT>.
|
|
If the instance is already at the position it will not move any further.
|
|
If <TT>checkall</TT> is true the instance will stop when it hits an instance
|
|
of any object. If it is false it only stops when hitting a solid instance.
|
|
Note that this function does not try to make detours if it meets an obstacle.
|
|
It simply fails in that case. The function returns whether or not the goal position
|
|
was reached.<br>
|
|
<tt><b>mp_linear_step_object(x,y,stepsize,obj)</b></tt>
|
|
Same as the function above but this time only instances of <tt>obj</tt> are
|
|
considered as obstacles. <tt>obj</tt> can be an object or an instance id.<br>
|
|
<tt><b>mp_potential_step(x,y,stepsize,checkall)</b></tt>
|
|
Like the previous function, this function lets the instance take a step towards
|
|
a particular position. But in this case it tries to avoid obstacles. When the
|
|
instance would run into a solid instance (or any instance when checkall is true)
|
|
it will change the direction of motion to try to avoid the instance and move
|
|
around it. The approach is not guaranteed to work but in most easy cases it
|
|
will effectively move the instance towards the goal. The function returns
|
|
whether or not the goal was reached.<br>
|
|
<tt><b>mp_potential_step_object(x,y,stepsize,obj)</b></tt>
|
|
Same as the function above but this time only instances of <tt>obj</tt> are
|
|
considered as obstacles. <tt>obj</tt> can be an object or an instance id.<br>
|
|
<tt><b>mp_potential_settings(maxrot,rotstep,ahead,onspot)</b></tt>
|
|
The previous function does its work using a number of parameters that can
|
|
be changed using this function. Globally the method works as follows. It
|
|
first tries to move straight towards the goal. It looks a number of steps
|
|
ahead which can be set with the parameter <TT>ahead</TT> (default 3).
|
|
Reducing this value means that the instance will start changing direction
|
|
later. Increasing it means it will start changing direction earlier. If
|
|
this check leads to a collision it starts looking at directions more to
|
|
the left and to the right of the best direction. It does this in steps of
|
|
size <TT>rotstep</TT> (default 10). Reducing this gives the instance more
|
|
movement possibilities but will be slower. The parameter <TT>maxrot</TT>
|
|
is a bit more difficult to explain. The instance has a current direction.
|
|
<TT>maxrot</TT> (default 30) indicates how much it is allowed to change its
|
|
current direction in a step. So even if it can move e.g. straight to the goal
|
|
it will only do so if it does not violate this maximal change of direction.
|
|
If you make <TT>maxrot</TT> large the instance can change a lot in each step.
|
|
This will make it easier to find a short path but the path will be uglier.
|
|
If you make the value smaller the path will be smoother but it might take
|
|
longer detours (and sometimes even fail to find the goal). When no step can
|
|
be made the behavior depends on the value of the parameter <TT>onspot</TT>.
|
|
If <TT>onspot</TT> is true (the default value), the instance will rotate on
|
|
its spot by the amount indicated with <TT>maxrot</TT>. If it is false it
|
|
will not move at all. Setting it to false is useful for e.g. cars but reduces
|
|
the chance of finding a path.<br>
|
|
</blockquote>
|
|
|
|
<p>
|
|
Please note that the potential approach uses only local information. So it will only
|
|
find a path if this local information is enough to determine the right direction of
|
|
motion. For example, it will fail to find a path out of a maze (most of the time).
|
|
|
|
<P>
|
|
The second kind of functions computes a collision-free path for the instance.
|
|
Once this path has been computed you can assign it to the instance to move
|
|
towards the goal. The computation of the path will take some time but after
|
|
that the execution of the path will be fast. Of course this is only valid if
|
|
the situation has not changed in the meantime. For example, if obstacles
|
|
change you possibly will need to recompute the path. Again notice that these functions
|
|
might fail.
|
|
<B><I>These functions are only available in the Pro Edition of Game Maker.</I></B>
|
|
|
|
<P>
|
|
The first two functions use the linear motion and potential field approach that
|
|
were also used for the step functions.
|
|
|
|
<p>
|
|
<blockquote>
|
|
<tt><b>mp_linear_path(path,xg,yg,stepsize,checkall)</b></tt>
|
|
This function computes a straight-line path for the instance from its
|
|
current position to the position (xg,yg) using the indicated step size.
|
|
It uses steps as in the function <TT>mp_linear_step()</TT>. The indicated
|
|
path must already exist and will be overwritten by the new path. (See a
|
|
later chapter on how to create and destroy paths.) The function will
|
|
return whether a path was found. The function will stop and report failure
|
|
if no straight path exists between start and goal. If it fails a
|
|
path is still created that runs till the position where the instance was blocked.<br>
|
|
<tt><b>mp_linear_path_object(path,xg,yg,stepsize,obj)</b></tt>
|
|
Same as the function above but this time only instances of <tt>obj</tt> are
|
|
considered as obstacles. <tt>obj</tt> can be an object or an instance id.<br>
|
|
<tt><b>mp_potential_path(path,xg,yg,stepsize,factor,checkall)</b></tt>
|
|
This function computes a path for the instance from its current position
|
|
and orientation to the position (xg,yg) using the indicated step size
|
|
trying to avoid collision with obstacles. It uses potential field steps,
|
|
like in the function <TT>mp_potential_step()</TT> and also the parameters
|
|
that can be set with <TT>mp_potential_settings()</TT>. The indicated path
|
|
must already exist and will be overwritten by the new path. (See a later
|
|
chapter on how to create and destroy paths.) The function will return
|
|
whether a path was found. To avoid the function continuing to compute
|
|
forever you need to provide a length factor larger than 1. The function
|
|
will stop and report failure if it cannot find a path shorter than this
|
|
factor times the distance between start and goal. A factor of 4 is normally
|
|
good enough but if you expect long detours you might make it longer. If
|
|
it fails a path is still created that runs in the direction of the goal
|
|
but it will not reach it.<br>
|
|
<tt><b>mp_potential_path_object(path,xg,yg,stepsize,factor,obj)</b></tt>
|
|
Same as the function above but this time only instances of <tt>obj</tt> are
|
|
considered as obstacles. <tt>obj</tt> can be an object or an instance id.<br>
|
|
</blockquote>
|
|
|
|
<p>
|
|
The other functions use a much more complex mechanism using a grid-based
|
|
approach (sometimes called an A* algorithm). It will be more successful
|
|
in finding paths (although it still might fail) and will find shorter paths
|
|
but it required more work on your side. The global idea is as follows.
|
|
First of all we put a grid on (the relevant part of) the room. You can
|
|
choose to use a fine grid (which will be slower) or a coarse grid. Next,
|
|
for all relevant objects we determine the grid cells they overlap (either
|
|
using bounding boxes or precise checking) and mark these cells as being
|
|
forbidden. So a cell will be marked totally forbidden, even if it only
|
|
partially overlaps with an obstacle. Finally we specify a start and a goal
|
|
position (which must lie in free cells) and the function computes the
|
|
shortest path (actually close to the shortest) between these. The path
|
|
will run between centers of free cells. So if the cells are large enough
|
|
so that the instance placed at its center will lie completely inside
|
|
it this will be successful. This path you can now give to an instance
|
|
to follow.
|
|
|
|
<P>
|
|
The grid-based approach is very powerful (and is used in many professional
|
|
games) but it requires that you do some careful thinking. You must determine
|
|
which area and cell size are good enough for solving the game. Also you must
|
|
determine which objects must be avoided and whether precise checking is
|
|
important. All these parameters strongly influence the efficiency of the approach.
|
|
|
|
<P>
|
|
In particular the size of the cells is crucial. Remember that the cells
|
|
must be large enough so that the moving object placed with its origin
|
|
on the center of a cell must lie completely inside the cell. (Be careful
|
|
about the position of the origin of the object. Also realize that you can
|
|
shift the path if the origin of the object is not in its center!) On the
|
|
other hand, the smaller the cells the more possible paths exist. If you
|
|
make cells too large, openings between obstacles may get closed because
|
|
all cells intersect an obstacle.
|
|
|
|
<p>
|
|
The actual functions for the grid-based approach are as follows:
|
|
|
|
<p>
|
|
<blockquote>
|
|
<tt><b>mp_grid_create(left,top,hcells,vcells,cellwidth,cellheight)</b></tt>
|
|
This function creates the grid. It returns an index that must be used in
|
|
all other calls. You can create and maintain multiple grid structures at
|
|
the same moment. left and top indicate the position of the top-left corner
|
|
of the grid. hcells and vcells indicate the number of horizontal and vertical
|
|
cells. Finally cellwidth and cellheight indicate the size of the cells.<br>
|
|
<tt><b>mp_grid_destroy(id)</b></tt>
|
|
Destroys the indicated grid structure and frees its memory. Don't forget to
|
|
call this if you don't need the structure anymore.<br>
|
|
<tt><b>mp_grid_clear_all(id)</b></tt>
|
|
Mark all cells in the grid to be free.<br>
|
|
<tt><b>mp_grid_clear_cell(id,h,v)</b></tt>
|
|
Clears the indicated cell. Cell 0,0 is the top left cell.<br>
|
|
<tt><b>mp_grid_clear_rectangle(id,left,top,right,bottom)</b></tt>
|
|
Clears all cells that intersect the indicated rectangle (in room coordinates).<br>
|
|
<tt><b>mp_grid_add_cell(id,h,v)</b></tt>
|
|
Marks the indicated cell as being forbidden. Cell 0,0 is the top left cell.<br>
|
|
<tt><b>mp_grid_add_rectangle(id,left,top,right,bottom)</b></tt>
|
|
Marks all cells that intersect the indicated rectangle as being forbidden.<br>
|
|
<tt><b>mp_grid_add_instances(id,obj,prec)</b></tt>
|
|
Marks all cells that intersect an instance of the indicated object as
|
|
being forbidden. You can also use an individual instance by making obj
|
|
the id of the instance. Also you can use the keyword <TT><B>all</b></tt>
|
|
to indicate all instances of all objects. prec indicates whether precise
|
|
collision checking must be used (will only work if precise checking is
|
|
enabled for the sprite used by the instance).<br>
|
|
<tt><b>mp_grid_path(id,path,xstart,ystart,xgoal,ygoal,allowdiag)</b></tt>
|
|
Computes a path through the grid. path must indicate an existing path that
|
|
will be replaced by the computer path. xstart and ystart indicate the start
|
|
of the path and xgoal and ygoal the goal. allowdiag indicates whether
|
|
diagonal moves are allowed instead of just horizontal or vertical. The
|
|
function returns whether it succeeded in finding a path. (Note that the
|
|
path is independent of the current instance; It is a path through the g
|
|
rid, not a path for a specific instance.) <br>
|
|
<tt><b>mp_grid_draw(id)</b></tt>
|
|
This function draws the grid with green cells being free and red cells being
|
|
forbidden. This function is slow and only provided as a debug tool.<br>
|
|
</blockquote>
|
|
|
|
|
|
<!--END-->
|
|
</body>
|
|
</html>
|
|
|
|
<!-- KEYWORDS
|
|
motion planning
|
|
potential fields
|
|
A* algorithm
|
|
finding paths
|
|
|
|
mp_linear_step()
|
|
mp_potential_step()
|
|
mp_linear_step_object()
|
|
mp_potential_step_object()
|
|
mp_potential_settings()
|
|
mp_linear_path()
|
|
mp_potential_path()
|
|
mp_linear_path_object()
|
|
mp_potential_path_object()
|
|
mp_grid_create()
|
|
mp_grid_destroy()
|
|
mp_grid_clear_all()
|
|
mp_grid_clear_cell()
|
|
mp_grid_clear_rectangle()
|
|
mp_grid_add_cell()
|
|
mp_grid_add_rectangle()
|
|
mp_grid_add_instances()
|
|
mp_grid_path()
|
|
mp_grid_draw()
|
|
|
|
--> |