ID:1982082
 
(See the best response by Kaiochao.)
Code:
mob/Archer/proc/Volley(obj/Target/trg)
var/mob/Arrow/arrow=new(src.loc)//creates an arrow on archers loc
walk_towards(arrow,trg,0,1)


Problem description:

In my game I want some archers to fire a volley of arrows to a target. The problem is that the arrows change direction to reach it. Is there a lib on 360 degrees movement? Or is there something that can help me fix this issue? btw I use pixel movement
Best response
I basically have a library for this: absolute positions

What you want is for the arrow to move along the vector from the archer to the target. In DM, a vector could be represented by a pair of variables containing the x and y components.
var vector_x = // some number of pixels along the horizontal axis
var vector_y = // some number of pixels along the vertical axis

The vector from the archer to the target is simply the target's position - the archer's position. This is called the displacement vector. In DM, to subtract positions, you first have to get the positions. It might be most natural to use the centers of each object's bounding box, so our displacement is:
// these values are in units of pixels
var dx = target.Cx() - archer.Cx()
var dy = target.Cy() - archer.Cy()

Note: If you add this vector to the archer's position, then you end up at the target's position. In other words, if you start at the archer's position, go east by dx pixels, and go north by dy pixels, you end up at your target. The arrow could do that, but you want to slow it down so it's not an instant thing. (Bullets might do that, though.)

The arrow needs to move by its velocity vector every frame. The velocity vector is calculated by scaling the displacement vector by a number, called a scalar, such that the magnitude of the result is a desired speed.

The magnitude of a vector (dx, dy) has been proven for our purposes is defined to be:
var magnitude = sqrt(dx*dx + dy*dy)

The scalar ends up being:
// since dx and dy are in units of pixels,
// desired_speed must also be defined in units of pixels (pixels per movement, technically)
var scalar = desired_speed / magnitude

I think of it this way: dividing a vector by its magnitude will make its magnitude 1, but it will still point in the same direction (since scaling a vector only changes its length). When you multiply 1 by any number S, you end up with a result of S. Therefore, if you divide a vector by its magnitude and then multiply it by S, the resulting magnitude of the vector will be S.

So the arrow's velocity vector will be:
var velocity_x = dx * scalar
var velocity_y = dy * scalar

With that, you can move the arrow every frame with my library's Translate() method.
// this effectively replaces walk_towards():
var dx = trg.Cx() - Cx()
var dy = trg.Cy() - Cy()
var arrow_speed = 1 // or whatever
var scalar = arrow_speed / sqrt(dx*dx + dy*dy)
var velocity_x = dx * scalar
var velocity_y = dy * scalar

// this loop ends when the arrow is deleted or the arrow's loc is set to null
// it repeats every frame, which is as fast as animations can go
spawn(-1) while(arrow && arrow.loc)
// this moves the arrow by a certain number of pixels along the x and y axes
arrow.Translate(velocity_x, velocity_y)
sleep world.tick_lag

A good read for using vectors in games is the Unity manual's Vector Cookbook. DM doesn't currently support Unity's vector syntax, but its explanations and figures can still help with understanding.
In response to Kaiochao
Kaiochao wrote:
The magnitude of a vector (dx, dy) has been proven to be:
var magnitude = sqrt(dx*dx + dy*dy)


Though it doesn't detract from the rest of your post, I just want to clarify that this is in general wrong, in that typically you start with a distance function or magnitude function as a first principle and move on from there. I.e., it's more typical to say that we define the length of a vector as the square root of the sum of the squares if it's components, rather than to prove that this is the length of a vector as a consequence of some other assumptions.
In response to Popisfizzy
Interdasting. I thought that since the vector is assumed to be in Euclidean R^2 space, we could just use the distance formula using the proven Pythagorean theorem and call the result "proven". That's what I get for avoiding pure math classes.
Well, in a sense it is. The parallel postulate is equivalent to the Euclidean inner product, in the sense that you can prove either one from the other. I.e., if you assume that all straight lines in a plane which are parallel somewhere never intersect then you can prove the Pythagorean theorem and get the Euclidean norm and inner product, and if you assume lengths are given by the Euclidean norm you can prove the parallel postulate.

The reason it's usually now considered natural to start with an inner product or a norm is because without them you need to come up with a way of answering questions like, "What is an angle between two lines?" or, "When are two lines parallel?" or, "What is length and distance?". The Ancient Greek geometers took these ideas as a given because they implicitly assumed that all geometry is Euclidean. We now of course know this to not be true, and have for a century and a half. In many spaces, questions of what angles and distances mean are not as easily-resolved as in Euclidean geometry, hence the importance of norms and inner products.

Which isn't to say that Euclidean geometry is not important or special in any way. As the natural geometry of the real and complex numbers, it still holds very great importance.

As an interesting aside in this matter, it is no coincidence that |x| = sqrt(x2) and ||<x,y>|| = sqrt(x2 + y2) have very similar forms. Likewise that x·y = xy and <w,x>·<y,z> = wy + xz look very similar.
In response to Popisfizzy
Just recently a former classmate of mine was talking about the parallel postulate because he's in a class called "Mathematical Systems" where "topics are likely to include abstract algebra, real analysis, geometry, and topology." I kind of tuned him out.

I did notice that parallel with the absolute value and magnitude. The "absolute value" of a scalar x, written |x| is its "distance" from 0 on the number line, just like a the magnitude of a vector v, written |v| (or ||v||) is its "distance" from the origin 0.

It's nice when things are consistent. Makes things easier to study.
In response to Kaiochao
It's not so much that it's just consistent in the cases. See, a vector space is a very abstract notion in mathematics, and include things that most people would be surprised at are still vectors. For example, the set of all m×n matrices over the reals are vectors. Polynomials are vectors. Even functions are vectors.

In fact, the real numbers are a vector space over themselves (meaning that the field of R is itself, though what a field is is incidental here). As such, it is possible to define an inner product on the reals, which naturally produces a norm and thus a metric (a norm essentially defines what the length of a vector is, while a metric defines what the distance between two vector is). A very, very natural inner product on R is just multiplication. Every inner product <·,·> induces a norm ||·|| as ||x|| = sqrt(<x,x>), and so we end up getting that the norm of a real number x is ||x|| = sqrt(xx) = sqrt(x2) = |x|. Thus, the absolute value isn't just like it's distance from the origin, i.e. it's length. The absolute distance exactly is the length of a real number.