2D Vectors in Javascript
Before I start actually trying to code the laws of physics, it's useful to remind ourselves about vectors and vector maths, since moving things about on a 2D plane is a lot easier using vector maths.
What is a vector?
I shall not explain what vectors are since there is plenty of web-sites that give far better explanation that I ever could. This page here for example gives a concise but easy to understand explanation of all the vector maths that you would require in basic collision handling.
Phaser 3 vector class
Phaser 3 actually provides class for defining vectors, together with methods to carry out vector mathematics.
Be careful about the way you apply methods
Typically the method changes the vector that the method is applied to it, as opposed to returning a new vector. So if you want to apply different methods to the same vector but want to keep the original vector intact, you need to use either:
clone(): returns a copy as a new vector,
copy(src): copies the content of the src vector to the vector that the method is applied to it, or
new Vector2(originalVec.x, originalVec.y): create a new vector directly with the relevant components of the vector you want to manipulate
Particularly useful methods for physics engine
Phaser 3 provides pretty much all the typical vector calculation methods, including the following
length() returns the magnitude of the vector
lengthSq() returns the squared of the magnitude of the vector
scale(src); multiples the x and y components by src -- this is not the same as multiply(src) which carries out a component-wise multiplication between this vector and the given vector.
negate() simply changes the sign of the x and y components of this vector
normalize() means makes the vector's magnitude to 1, but keep the same direction
setLength() -- this is NOT the same as scale(), as is clear by the underlying code.
setLength: function (length) {
return this.normalize().scale(length);
},
Graphical illustration of the vector methods
Below picture gives a graphical representation of various vector methods applied between VecA in BLUE and VecB in RED (in drawing the lines, I have shifted everything so that the "origin" is the middle of the screen, so that is it easier to understand).
YELLOW: reflection = vecA.clone().reflect(vecB);
GREY: mirror = vecA.clone().mirror(vecB);
PINK: leftNormal = vecB.clone().normalizeLeftHand();
CYAN: rightNormal = vecB.clone().normalizeRightHand();
GREEN POINT: projected = Phaser.Geom.Point.Project(vecA, vecB);
Above method can be replicated using vector maths
vecBUnit = vecB.clone().normalize();
projected = vecBUnit.clone().scale(vecA.dot(vecBUnit))
"Projection" of a vector onto another (illustrated by the BLUE vector projected onto the RED vector in the above diagram) is a really important in physics engines, more specifically it is important to understand the dot product, which I will explore in a separate post next.
Adding "immutable" variation of existing methods
Sometimes you want the operation to return a new vector without changing the original vector.
I have done this mainly via 2 variations: (i) by adding an "i" to the end of the equivalent method like below:
addi(vec) {
return new Vector2(this.x + vec.x, this.x + vec.y)
}
Using the above extended Vector class, is easy.
var a = new Vector2(3,5);
var b = new Vector2(5,8);
var c = a.addi(b)
console.log("a=",a,"c=",c);
will return c as {x: 8, y: 11} but will retain a as { x:3, y:5 }
and a static method with the first letter of the method capitalised, like below;
static Add(vec1, vec2) {
return new Vector2(vec1.x + vec2.x, vec1.x + vec2.y)
}
I have included the code in Codepen below.
Useful References
https://youtu.be/-n_C7tD55_A (a practical look at the cross product in 2D)
Comments