Path: blob/main/public/games/files/garbage-collector/js/utils.js
1036 views
/*globals define*/1define(function() {2'use strict';34var PI2 = 2 * Math.PI,5HALF_PI = 0.5 * Math.PI;67var RAD_TO_DEG = 180 / Math.PI,8DEG_TO_RAD = Math.PI / 180;910var EPSILON = 1e-1;1112function clamp( value, min, max ) {13return Math.min( Math.max( value, min ), max );14}1516function randomFloat( min, max ) {17return min + Math.random() * ( max - min );18}1920function randomInt( min, max ) {21return Math.round( randomFloat( min, max ) );22}2324/**25* Returns a float: value +/- spread.26*/27function floatSpread( value, spread ) {28return randomFloat( value - spread, value + spread );29}3031/**32* Returns an int: value +/- spread.33*/34function intSpread( value, spread ) {35return randomInt( value - spread, value + spread );36}3738function lerp( a, b, t ) {39return a + t * ( b - a );40}4142function inverseLerp( value, a, b ) {43return ( value - a ) / ( b - a );44}4546/**47* Project along the line given by [(x0, y0), (x1, y1)] by parameter.48*/49function lerp2d( x0, y0, x1, y1, parameter ) {50if ( parameter === null ) {51return null;52}5354return {55x: lerp( x0, x1, parameter ),56y: lerp( y0, y1, parameter )57};58}5960function distanceSquared( x0, y0, x1, y1 ) {61var dx = x1 - x0,62dy = y1 - y0;6364return dx * dx + dy * dy;65}6667function distance( x0, y0, x1, y1 ) {68return Math.sqrt( distanceSquared( x0, y0, x1, y1 ) );69}7071/**72* Rounds a value to the given precision, removes any trailing zeros produced73* by Number.prototype.toFixed().74*75* Example:76* var x = 100;77* x.toFixed(2); // "100.00"78* round( 100, 2 ); // "100"79*/80function round( value, precision ) {81return parseFloat( value.toFixed( precision ) );82}8384function roundNearZero( value, epsilon ) {85return Math.abs( value ) > ( epsilon || EPSILON ) ? value : 0;86}8788/**89* Assuming the line is CW, the normal of the line is (-dy, dx).90*/91function lineNormal( x0, y0, x1, y1 ) {92var dx = x1 - x0,93dy = y1 - y0;9495var lengthSquared = dx * dx + dy * dy;96if ( !lengthSquared ) {97return null;98}99100var invLength = 1 / Math.sqrt( lengthSquared );101return {102x: dy * invLength,103y: -dx * invLength104};105}106107function angleFrom( x0, y0, x1, y1 ) {108return Math.atan2( y1 - y0, x1 - x0 );109}110111/**112* Remove all values in array with an index in indices.113*/114function removeIndices( array, indices ) {115indices.sort();116117var index = indices.length;118while( index-- ) {119array.splice( indices[ index ], 1 );120}121}122123/**124* Set the pre-existing properties of a given object with the values in attrs.125* Recursively handles properties that are also objects.126*/127function set( object, attrs ) {128if ( !object || !attrs ) {129return;130}131132for ( var key in attrs ) {133if ( object.hasOwnProperty( key ) ) {134if ( typeof object[ key ] === 'object' &&135typeof attrs[ key ] === 'object' ) {136set( object[ key ], attrs[ key ] );137} else {138object[ key ] = attrs[ key ];139}140}141}142}143144/**145* Sets any undefined values to given default values.146* Can have more than one defaults object.147*148* This is pretty much underscore.js's defaults().149*/150function defaults( object ) {151var args = [].slice.call( arguments, 1 );152153args.forEach(function( arg ) {154if ( arg ) {155for ( var key in arg ) {156if ( typeof object[ key ] === 'undefined' ) {157object[ key ] = arg[ key ];158}159}160}161});162163return object;164}165166/**167* Rotates the axis-aligned bounding box defined by168* [(left, top), (right, bottom)] by rotation. Translates by (tx, ty).169*/170function rotateAABB( tx, ty, left, top, right, bottom, rotation ) {171var cos = Math.cos( -rotation ),172sin = Math.sin( -rotation );173174// Coordinates of rotated extents.175var x = [],176y = [];177178// Top left.179x.push( cos * left - sin * top );180y.push( sin * left + cos * top );181182// Bottom left.183x.push( cos * left - sin * bottom );184y.push( sin * left + cos * bottom );185186// Top right.187x.push( cos * right - sin * top );188y.push( sin * right + cos * top );189190// Bottom right.191x.push( cos * right - sin * bottom );192y.push( sin * right + cos * bottom );193194return {195xmin: Math.min.apply( null, x ) + tx,196ymin: Math.min.apply( null, y ) + ty,197xmax: Math.max.apply( null, x ) + tx,198ymax: Math.max.apply( null, y ) + ty199};200}201202function relativeExpandAABB( aabb, dw, dh ) {203dw *= 0.5;204dh *= 0.5;205206return {207xmin: aabb.xmin - dw,208ymin: aabb.ymin - dh,209xmax: aabb.xmax + dw,210ymax: aabb.ymax + dh211};212}213214function expandAABB( aabb, width, height ) {215var dw = width - ( aabb.xmax - aabb.xmin ),216dh = height - ( aabb.ymax - aabb.ymin );217218return relativeExpandAABB( aabb, dw, dh );219}220221function ratioExpandAABB( aabb, widthRatio, heightRatio ) {222var dw = aabb.xmax - aabb.xmin,223dh = aabb.ymax - aabb.ymin;224225dw = ( dw * widthRatio ) - dw;226dh = ( dh * heightRatio ) - dh;227228return relativeExpandAABB( aabb, dw, dh );229}230231232return {233PI2: PI2,234HALF_PI: HALF_PI,235236RAD_TO_DEG: RAD_TO_DEG,237DEG_TO_RAD: DEG_TO_RAD,238239EPSILON: EPSILON,240241clamp: clamp,242243randomFloat: randomFloat,244randomInt: randomInt,245246floatSpread: floatSpread,247intSpread: intSpread,248249lerp: lerp,250inverseLerp : inverseLerp,251lerp2d: lerp2d,252253distanceSquared: distanceSquared,254distance: distance,255256round: round,257roundNearZero: roundNearZero,258lineNormal: lineNormal,259angleFrom: angleFrom,260261removeIndices: removeIndices,262263set: set,264defaults: defaults,265266rotateAABB: rotateAABB,267268expandAABB: expandAABB,269ratioExpandAABB: ratioExpandAABB,270relativeExpandAABB: relativeExpandAABB271};272});273274275