phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
241 lines (205 loc) • 6.36 kB
JavaScript
/**
* @author Richard Davey <rich@phaser.io>
* @copyright 2013-2025 Phaser Studio Inc.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var GetEaseFunction = require('./GetEaseFunction');
var GetValue = require('../../utils/object/GetValue');
var MATH_CONST = require('../../math/const');
/**
* Creates a Stagger function to be used by a Tween property.
*
* The stagger function will allow you to stagger changes to the value of the property across all targets of the tween.
*
* This is only worth using if the tween has multiple targets.
*
* The following will stagger the delay by 100ms across all targets of the tween, causing them to scale down to 0.2
* over the duration specified:
*
* ```javascript
* this.tweens.add({
* targets: [ ... ],
* scale: 0.2,
* ease: 'linear',
* duration: 1000,
* delay: this.tweens.stagger(100)
* });
* ```
*
* The following will stagger the delay by 500ms across all targets of the tween using a 10 x 6 grid, staggering
* from the center out, using a cubic ease.
*
* ```javascript
* this.tweens.add({
* targets: [ ... ],
* scale: 0.2,
* ease: 'linear',
* duration: 1000,
* delay: this.tweens.stagger(500, { grid: [ 10, 6 ], from: 'center', ease: 'cubic.out' })
* });
* ```
*
* @function Phaser.Tweens.Builders.StaggerBuilder
* @since 3.19.0
*
* @param {(number|number[])} value - The amount to stagger by, or an array containing two elements representing the min and max values to stagger between.
* @param {Phaser.Types.Tweens.StaggerConfig} [config] - A Stagger Configuration object.
*
* @return {function} The stagger function.
*/
var StaggerBuilder = function (value, options)
{
if (options === undefined) { options = {}; }
var result;
var start = GetValue(options, 'start', 0);
var ease = GetValue(options, 'ease', null);
var grid = GetValue(options, 'grid', null);
var from = GetValue(options, 'from', 0);
var fromFirst = (from === 'first');
var fromCenter = (from === 'center');
var fromLast = (from === 'last');
var fromValue = (typeof(from) === 'number');
var isRange = (Array.isArray(value));
var value1 = (isRange) ? parseFloat(value[0]) : parseFloat(value);
var value2 = (isRange) ? parseFloat(value[1]) : 0;
var maxValue = Math.max(value1, value2);
if (isRange)
{
start += value1;
}
if (grid)
{
// Pre-calc the grid to save doing it for every TweenData update
var gridWidth = grid[0];
var gridHeight = grid[1];
var fromX = 0;
var fromY = 0;
var distanceX = 0;
var distanceY = 0;
var gridValues = [];
if (fromLast)
{
fromX = gridWidth - 1;
fromY = gridHeight - 1;
}
else if (fromValue)
{
fromX = from % gridWidth;
fromY = Math.floor(from / gridWidth);
}
else if (fromCenter)
{
fromX = (gridWidth - 1) / 2;
fromY = (gridHeight - 1) / 2;
}
var gridMax = MATH_CONST.MIN_SAFE_INTEGER;
for (var toY = 0; toY < gridHeight; toY++)
{
gridValues[toY] = [];
for (var toX = 0; toX < gridWidth; toX++)
{
distanceX = fromX - toX;
distanceY = fromY - toY;
var dist = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
if (dist > gridMax)
{
gridMax = dist;
}
gridValues[toY][toX] = dist;
}
}
}
var easeFunction = (ease) ? GetEaseFunction(ease) : null;
if (grid)
{
result = function (target, key, value, index)
{
var gridSpace = 0;
var toX = index % gridWidth;
var toY = Math.floor(index / gridWidth);
if (toX >= 0 && toX < gridWidth && toY >= 0 && toY < gridHeight)
{
gridSpace = gridValues[toY][toX];
}
var output;
if (isRange)
{
var diff = (value2 - value1);
if (easeFunction)
{
output = ((gridSpace / gridMax) * diff) * easeFunction(gridSpace / gridMax);
}
else
{
output = (gridSpace / gridMax) * diff;
}
}
else if (easeFunction)
{
output = (gridSpace * value1) * easeFunction(gridSpace / gridMax);
}
else
{
output = gridSpace * value1;
}
return output + start;
};
}
else
{
result = function (target, key, value, index, total)
{
// zero offset
total--;
var fromIndex;
if (fromFirst)
{
fromIndex = index;
}
else if (fromCenter)
{
fromIndex = Math.abs((total / 2) - index);
}
else if (fromLast)
{
fromIndex = total - index;
}
else if (fromValue)
{
fromIndex = Math.abs(from - index);
}
var output;
if (isRange)
{
var spacing;
if (fromCenter)
{
spacing = ((value2 - value1) / total) * (fromIndex * 2);
}
else
{
spacing = ((value2 - value1) / total) * fromIndex;
}
if (easeFunction)
{
output = spacing * easeFunction(fromIndex / total);
}
else
{
output = spacing;
}
}
else if (easeFunction)
{
output = (total * maxValue) * easeFunction(fromIndex / total);
}
else
{
output = fromIndex * value1;
}
return output + start;
};
}
return result;
};
module.exports = StaggerBuilder;