"use strict";
/**
* Return a new Tily.utility.vec2 object with the specified x/y coordinates. If the first argument is an array,
* the Tily.utility.vec2 will be initialised using the first 2 elements of the array. If the first argument is
* an object with x and y properties, these will be used instead (this is useful for copying Tily.utility.vec2
* instances). If no arguments are provided, or the arguments are invalid, a zero-vector will be
* returned instead.
* @param {number|Array|Object} x The x-coordinate, or an array with at least 2 elements, or an
* object with x and y properties.
* @param {number} [y] The y-coordinate, if an x-coordinate has also been provided.
* @returns {Object} A Tily.utility.vec2 instance.
* @example
* var v1 = Tily.utility.vec2(2, 1); // v1 == { x: 2, y: 1 }
* var v2 = Tily.utility.vec2([2, 1]); // v2 == { x: 2, y: 1 }
* var v3 = Tily.utility.vec2(v1); // v3 == { x: 2, y: 1 }
*/
Tily.utility.vec2 = function(x, y) {
if (arguments.length == 1) {
if (x instanceof Array && x.length > 1) { // Tily.utility.vec2 from array
return { x: x[0], y: x[1] };
} else if (x.x !== undefined && x.y !== undefined) {
return { x: x.x, y: x.y }; // Tily.utility.vec2 from Tily.utility.vec2 (copy)
}
return { x: 0, y: 0 }; // Arguments incorrect, return [0, 0]
}
return { x: x || 0, y: y || 0 };
};
/**
* @callback mapCallback
* @param {number} x The x or y component of the vector.
* @param {...*} arguments Any additional arguments passed to Tily.utility.vec2.map.
* @returns {boolean} True if the current element is the one being searched for.
*/
/**
* Return a new vector from v by mapping it's components to f.
* @param {Tily.utility.vec2} v The vector to transform.
* @param {mapCallback} f A callback that will be called for both the x and y components.
* @param {...*} arguments Additional arguments will be passed to f for each component.
* @returns {Tily.utility.vec2} The transformed vector.
* @example
* var v = Tily.utility.vec2(1.5, 2.5);
* v = Tily.utility.vec2.map(v, Math.floor); // v == { x: 1, y: 2 }
*/
Tily.utility.vec2.map = function(v, f) {
var args = arguments.length == 1 ? [arguments[0]] : Array.apply(null, arguments);
args = Array.prototype.slice.call(args, 2);
return Tily.utility.vec2(f.apply(this, [v.x].concat(args)), f.apply(this, [v.y].concat(args)));
};
/**
* Get the length of a vector.
* @param {Tily.utility.vec2} v The vector.
* @returns {number} The vector's length.
*/
Tily.utility.vec2.len = function(v) {
return Math.sqrt(v.x * v.x + v.y * v.y);
};
/**
* Get the angle of a vector in radians.
* @param {Tily.utility.vec2} v The vector.
* @returns {number} The angle of the vector in radians.
*/
Tily.utility.vec2.rad = function(v) {
return Math.atan2(v.y, v.x);
};
/**
* Get the dot product of two vectors.
* @param {Tily.utility.vec2} v1 The first vector.
* @param {Tily.utility.vec2} v2 The second vector.
* @returns {number} The dot product of v1 and v2.
*/
Tily.utility.vec2.dot = function(v1, v2) {
return v1.x * v2.x + v1.y * v2.y;
};
/**
* Normalise a vector
* @param {Tily.utility.vec2} v The vector.
* @returns {Tily.utility.vec2} The normalised vector.
*/
Tily.utility.vec2.norm = function(v) {
var length = Tily.utility.vec2.len(v);
if (length) {
return Tily.utility.vec2.div(v, length);
}
return Tily.utility.vec2();
};
/**
* Reflect a vector across a plane with normal n
* @param {Tily.utility.vec2} v The vector.
* @param {Tily.utility.vec2} n The plane normal vector.
* @returns {Tily.utility.vec2} The reflected vector.
*/
Tily.utility.vec2.reflect = function(v, n) {
return Tily.utility.vec2.add(v, Tily.utility.vec2.mul(Tily.utility.vec2.mul(n, Tily.utility.vec2.dot(v, n)), -2));
};
/**
* Get the cross product of two vectors. The z-coord is assumed to be 0, since these are 2d vectors.
* @param {Tily.utility.vec2} v1 The first vector.
* @param {Tily.utility.vec2} v2 The second vector.
* @returns {number} The cross product of v1 and v2.
*/
Tily.utility.vec2.cross = function(v1, v2) {
return v1.x * v2.y - v1.y * v2.x;
};
/**
* Rotate a vector.
* @param {Tily.utility.vec2} v The vector.
* @param {number} r The amount to rotate the vector by, in radians.
* @returns {Tily.utility.vec2} The rotated vector.
*/
Tily.utility.vec2.rot = function(v, r) {
var sinAngle = Math.sin(r),
cosAngle = Math.cos(r),
x = cosAngle * v.x - sinAngle * v.y,
y = sinAngle * v.x + cosAngle * v.y;
return Tily.utility.vec2(x, y);
};
/**
* Add two vectors or add a scalar to each component.
* @param {Tily.utility.vec2} v1 The first vector.
* @param {Tily.utility.vec2|number} v2 The second vector, or a scalar value to add to each component of v1.
* @returns {Tily.utility.vec2} The sum of v1 and v2.
*/
Tily.utility.vec2.add = function(v1, v2) {
if (v2.x !== undefined && v2.y !== undefined) {
return Tily.utility.vec2(v1.x + v2.x, v1.y + v2.y);
} else {
return Tily.utility.vec2(v1.x + v2, v1.y + v2);
}
};
/**
* Subtract two vectors.
* @param {Tily.utility.vec2} v1 The first vector.
* @param {Tily.utility.vec2|number} v2 The second vector, or a scalar value to subtract from each component of
* v1.
* @returns {Tily.utility.vec2} The difference of v1 and v2.
*/
Tily.utility.vec2.sub = function(v1, v2) {
if (v2.x !== undefined && v2.y !== undefined) {
return Tily.utility.vec2(v1.x - v2.x, v1.y - v2.y);
} else {
return Tily.utility.vec2(v1.x - v2, v1.y - v2);
}
};
/**
* Multiply two vectors.
* @param {Tily.utility.vec2} v1 The first vector.
* @param {Tily.utility.vec2|number} v2 The second vector, or a scalar value to multiply each component of v1 by.
* @returns {Tily.utility.vec2} The product of v1 and v2.
*/
Tily.utility.vec2.mul = function(v1, v2) {
if (v2.x !== undefined && v2.y !== undefined) {
return Tily.utility.vec2(v1.x * v2.x, v1.y * v2.y);
} else {
return Tily.utility.vec2(v1.x * v2, v1.y * v2);
}
};
/**
* Divide two vectors.
* @param {Tily.utility.vec2} v1 The first vector.
* @param {Tily.utility.vec2|number} v2 The second vector, or a scalar value to divide each component of v1 by.
* @returns {Tily.utility.vec2} The quotient of v1 and v2.
*/
Tily.utility.vec2.div = function(v1, v2) {
if (v2.x !== undefined && v2.y !== undefined) {
return Tily.utility.vec2(v1.x / v2.x, v1.y / v2.y);
} else {
return Tily.utility.vec2(v1.x / v2, v1.y / v2);
}
};
/**
* Check if two vectors are equal.
* @param {Tily.utility.vec2} v1 The first vector.
* @param {Tily.utility.vec2} v2 The second vector.
* @returns {boolean} True if the vectors are equal.
*/
Tily.utility.vec2.eq = function(v1, v2) {
return (v1.x == v2.x && v1.y == v2.y);
};
/**
* Convert a string representation of a vector (like '0,0' or '0, 0') into a Tily.utility.vec2.
* @param {string} s The string representation of the vector.
* @returns {Tily.utility.vec2} The resulting Tily.utility.vec2, or a zero-vector if the string couldn't be parsed.
*/
Tily.utility.vec2.fromString = function(s) {
var values = s.split(",", 2);
if (values.length == 2) {
var x = parseFloat(values[0]),
y = parseFloat(values[1]);
return Tily.utility.vec2(x, y);
}
return Tily.utility.vec2(0, 0);
};
/**
* Convert a Tily.utility.vec2 into a string.
* @param {Tily.utility.vec2} v The vector to convert.
* @param {string} [s=','] An optional separator string.
* @returns {string} The string representation of v.
*/
Tily.utility.vec2.toString = function(v, s) {
return v.x + (s !== undefined ? s : ",") + v.y;
};