Gunroar:Cannon() wrote: ↑Tue Feb 23, 2021 11:03 pm
I really want to just find out how to get the
inverse square of a distance and then
weigh it against intitial subtracted vector.
A point in 2-dimensional space is defined by two coordinates, x and y.
The distance between two points is:
Code: Select all
-- returns the distance between points x1,y1 and x2,y2
function distance(x1, y1, x2, y2)
return math.sqrt(((x2-x1)^2)+((y2-y1)^2))
end
The square of a number n is n^2, or n*n (n raised to the 2nd power, or multiplied by itself)
The root of a squared number n, i.e. the square root of n, is
math.sqrt(n)
The inverse of a number n is
1/n
Therefore, the inverse square root of a number n is
1/math.sqrt(n)
Putting it all together, the
inverse square root of distance is therefore:
Code: Select all
function inv_sqrt_distance(x1, y1, x2, y2)
return 1/math.sqrt(((x2-x1)^2)+((y2-y1)^2))
end
To
weigh a vector by it is to
multiply its components by it.
So if I have a vector
{x,y}, the weighted vector is
{x*d,y*d} where d is the inverse square distance.
Oh and to subtract one vector from another is to subtract the matching components:
Code: Select all
vector_one = {x1,y1}
vector_two = {x2,y2}
subtracted_vector = {vector_one[1]-vector_two[1], vector_one[2]-vector_two[2]}
What I like to do myself is use these...:
Code: Select all
-- returns the direction from point x1,y1 to x2,y2 (in radians)
function direction(x1, y1, x2, y2)
return math.atan2(y2-y1, x2-x1)
end
-- returns the distance between points x1,y1 and x2,y2
function distance(x1, y1, x2, y2)
return math.sqrt(((x2-x1)^2)+((y2-y1)^2))
end
-- returns the point located at x,y moved in direction by distance
function transposition(x, y, direction, distance)
return distance*math.cos(direction)+x, distance*math.sin(direction)+y
end
First, the basic behavior; moving the actor towards the goal at some constant speed, making sure not to overshoot it:
Code: Select all
local dir = direction(actor_x, actor_y, goal_x, goal_y)
local dist = math.min(actor_speed, distance(actor_x, actor_y, goal_x, goal_y))
actor_x, actor_y = transposition(actor_x, actor_y, dir, dist)
Second, the avoidance behavior; moving the actor away from an obstacle at full speed:
Code: Select all
local dir = direction(obst_x, obst_y, actor_x, actor_y) -- note we reversed the coordinates.
-- before we got the direction from actor to goal, now we get direction from obstacle to actor
actor_x, actor_y = transposition(actor_x, actor_y, dir, actor_speed)
Third, weighted avoidance. We multiply the speed by the inverse square of the distance:
Code: Select all
local dir = direction(obst_x, obst_y, actor_x, actor_y)
local dist = 1/math.sqrt(distance(obst_x, obst_y, actor_x, actor_y)) * obst_radius
local speed = math.max(actor_speed, dist)
actor_x, actor_y = transposition(actor_x, actor_y, dir, speed)
obst_radius is a value >=1 that makes the avoidance behavior
stronger the bigger it is. If the distance between actor and obstacle is
less or equal to this radius, the actor will flee at full speed. The further away the actor is from the obstacle, the slower it will avoid it.
Finally, we combine everything:
Code: Select all
local goal_dir = direction(actor_x, actor_y, goal_x, goal_y)
local goal_dist = math.min(actor_speed, distance(actor_x, actor_y, goal_x, goal_y))
local avoid_dir = direction(obst_x, obst_y, actor_x, actor_y)
local avoid_dist = 1/math.sqrt(distance(obst_x, obst_y, actor_x, actor_y)) * obst_radius
local avoid_speed = math.max(actor_speed, avoid_dist)
local vector_x, vector_y = transposition(actor_x, actor_y, goal_dir, goal_dist) --towards goal
vector_x, vector_y = transposition(vector_x, vector_y, avoid_dir, avoid_speed) --away from obstacle
local dir = direction(actor_x, actor_y, vector_x, vector_y)
local dist = distance(actor_x, actor_y, vector_x, vector_y)
-- finally move the actor:
actor_x, actor_y = transposition(actor_x, actor_y, dir, math.min(dist, actor_speed))
...I think I got that right, anyway.
Note that this combined behavior will always move towards the goal, while also avoiding the obstacle. Which means that in theory if the obstacle is exactly between the actor and goal, the actor will stand still, not smart enough to go around it.
