import Action from './Action';
import { isNumber, deg2radian, radian2deg, hex2color, hex2rgb, rgb2hex } from '../../utils';
/**
* @static
* @memberof Tiny
* @function MoveBy
* @param {number} duration
* @param {object} to
* @param {number} to.x
* @param {number} to.y
* @return {Tiny.Action}
*/
export function MoveBy(duration, to) {
const _to = {};
Object.assign(_to, to);
const action = new Action(duration, _to);
action._to = to;
action._onStart = function(tween, object) {
action.to.x = object.x + to.x;
action.to.y = object.y + to.y;
};
action._onUpdate = function(tween, object) {
object.setPosition(tween.x, tween.y);
};
action._type = 'MoveBy';
return action;
}
/**
* @static
* @memberof Tiny
* @function MoveTo
* @param {number} duration
* @param {object} to
* @param {number} to.x
* @param {number} to.y
* @return {Tiny.Action}
*/
export function MoveTo(duration, to) {
const action = new Action(duration, to);
action._onUpdate = function(tween, object) {
object.setPosition(tween.x, tween.y);
};
action._type = 'MoveTo';
return action;
}
/**
* @static
* @memberof Tiny
* @function ScaleBy
* @param {number} duration
* @param {object} to
* @param {object} to.scaleX
* @param {object} to.scaleY
* @return {Tiny.Action}
*/
export function ScaleBy(duration, to) {
const _to = {};
Object.assign(_to, to);
const action = new Action(duration, _to);
action._to = to;
action._onStart = function(tween, object) {
action.to.scaleX = object.scale.x * to.scaleX;
action.to.scaleY = object.scale.y * to.scaleY;
};
action._onUpdate = function(tween, object) {
object.setScale(tween.scaleX, tween.scaleY);
};
action._type = 'ScaleBy';
return action;
}
/**
* @static
* @memberof Tiny
* @function ScaleTo
* @param {number} duration
* @param {object} to
* @param {object} to.scaleX
* @param {object} to.scaleY
* @return {Tiny.Action}
*/
export function ScaleTo(duration, to) {
const action = new Action(duration, to);
action._onUpdate = function(tween, object) {
object.setScale(tween.scaleX, tween.scaleY);
};
action._type = 'ScaleTo';
return action;
}
/**
* @static
* @memberof Tiny
* @function RotateBy
* @param {number} duration
* @param {object} to
* @param {number} to.rotation
* @return {Tiny.Action}
*/
export function RotateBy(duration, to) {
const _to = {};
Object.assign(_to, to);
const action = new Action(duration, _to);
action._to = to;
action._onStart = function(tween, object) {
action.to.rotation = deg2radian(radian2deg(object.rotation) + radian2deg(to.rotation));
};
action._onUpdate = function(tween, object) {
object.rotation = tween.rotation;
};
action._type = 'RotateBy';
return action;
}
/**
* @static
* @memberof Tiny
* @function RotateTo
* @param {number} duration
* @param {object} to
* @param {number} to.rotation
* @return {Tiny.Action}
*/
export function RotateTo(duration, to) {
const action = new Action(duration, to);
action._onUpdate = function(tween, object) {
object.rotation = tween.rotation;
};
action._type = 'RotateTo';
return action;
}
/**
* @static
* @memberof Tiny
* @function JumpTo
* @param {number} duration
* @param {object} to
* @param {number} height
* @param {number} times
* @return {Tiny.Action}
*/
export function JumpTo(duration, to, height, times) {
const _to = {};
Object.assign(_to, to);
const newY = [];
for (let i = 0; i < times * 2; i++) {
if (i % 2 === 0) {
newY.push(_to.y - height);
} else {
newY.push(_to.y);
}
}
_to.y = newY;
const action = new Action(duration, _to);
action._to = to;
action.yoyo = false;
action.repeatTimes = 0;
action._onUpdate = function(tween, object) {
object.setPosition(tween.x, tween.y);
};
action._type = 'JumpTo';
action._arg = [height, times];
return action;
}
/**
* @static
* @memberof Tiny
* @function Blink
* @param {number} hideDuration
* @param {number} showDuration
* @return {Tiny.Action}
*/
export function Blink(hideDuration, showDuration) {
const newVisible = [];
for (let i = 0; i < hideDuration; i++) {
newVisible.push(false);
}
for (let i = 0; i < showDuration; i++) {
newVisible.push(true);
}
const action = new Action(showDuration + hideDuration, {
visible: newVisible,
});
action.yoyo = false;
action.repeatTimes = 0;
action._onUpdate = function(tween, object) {
object.visible = ~~tween.visible;
};
action._type = 'Blink';
action._arg = [hideDuration, showDuration];
return action;
}
/**
* @static
* @memberof Tiny
* @function FadeTo
* @param {number} duration
* @param {number} to
* @return {Tiny.Action}
*/
export function FadeTo(duration, to) {
const action = new Action(duration, {
alpha: to,
});
action._to = to;
action.yoyo = false;
action.repeatTimes = 0;
action._onUpdate = function(tween, object) {
object.setOpacity(tween.alpha);
};
action._type = 'FadeTo';
return action;
}
/**
* @static
* @memberof Tiny
* @function FadeIn
* @param {number} duration
* @return {Tiny.Action}
*/
export function FadeIn(duration) {
return FadeTo(duration, 1);
}
/**
* @static
* @memberof Tiny
* @function FadeOut
* @param {number} duration
* @return {Tiny.Action}
*/
export function FadeOut(duration) {
return FadeTo(duration, 0);
}
/**
* 注意:差值计算时,R、G、B三个通道,无论加减多少,最后的结果最少是0,最多是255。
*
* @example
* var action = Tiny.TintBy(1000, Tiny.color(-85, 0, 85));
* sprite.runAction(action);
* //=> sprite.tint 等于 0xaaffff(即:[170, 255, 255])
*
* @static
* @memberof Tiny
* @function TintBy
* @param {number} duration
* @param {number|Tiny.color} color - 此处的 color 虽然是 Tiny.color 类型,但是并不代表某个色值,而是色值与色值直接要做的差值
* @return {Tiny.Action}
*/
export function TintBy(duration, color) {
if (isNumber(color)) {
color = hex2color(color);
}
const _to = {};
Object.assign(_to, color);
const action = TintTo(duration, _to);
action._to = color;
action._onStart = function(tween, object) {
const oc = hex2rgb(object.tint);
action.to.colorR = oc[0] * 255 + color.colorR;
action.to.colorG = oc[1] * 255 + color.colorG;
action.to.colorB = oc[2] * 255 + color.colorB;
action.to.colorR <= 0 && (action.to.colorR = 0);
action.to.colorG <= 0 && (action.to.colorG = 0);
action.to.colorB <= 0 && (action.to.colorB = 0);
action.to.colorR >= 255 && (action.to.colorR = 255);
action.to.colorG >= 255 && (action.to.colorG = 255);
action.to.colorB >= 255 && (action.to.colorB = 255);
};
action._type = 'TintBy';
action._arg = [duration, color];
return action;
}
/**
* @example
* var action = Tiny.TintTo(1000, 0xFFFF00);
* sprite.tint = 0xFF0000;
* sprite.runAction(action);
*
* @example
* // [255, 102, 0] 即橙色(#FF6600)
* var action = Tiny.TintTo(1000, Tiny.color(255, 102, 0));
* sprite.runAction(action);
*
* @static
* @memberof Tiny
* @function TintTo
* @param {number} duration
* @param {number|Tiny.color} color
* @return {Tiny.Action}
*/
export function TintTo(duration, color) {
if (isNumber(color)) {
color = hex2color(color);
}
const action = new Action(duration, color);
action._onUpdate = function(tween, object) {
object.tint = rgb2hex([tween.colorR / 255, tween.colorG / 255, tween.colorB / 255]);
};
action._type = 'TintTo';
action._arg = [duration, color];
return action;
}
/**
* 永久重复
*
* @static
* @memberof Tiny
* @function RepeatForever
* @param {Tiny.Action} action - 要重复的 Action
* @param {number} delay - 延迟(ms)
* @return {Tiny.Action}
*/
export function RepeatForever(action, delay) {
return Repeat(Infinity, action, delay);
}
/**
* 重复
*
* @static
* @memberof Tiny
* @function Repeat
* @param {number} times - 重复次数
* @param {Tiny.Action} action - 要重复的 Action
* @param {number} delay - 延迟(ms)
* @return {Tiny.Action}
*/
export function Repeat(times, action, delay) {
!delay && action.repeatDelayTime && (delay = action.repeatDelayTime);
if (action._type && ['MoveBy', 'ScaleBy', 'RotateBy', 'TintBy'].indexOf(action._type) !== -1) {
action._onComplete = function(tween, object) {
if (!object.__tmp_times) {
object.__tmp_times = 1;
}
object.__tmp_times++;
if (object.__tmp_times > times) {
return;
}
if (action._caller === 'runAction') {
let fn;
switch (action._type) {
case 'MoveBy':
fn = MoveBy;
break;
case 'ScaleBy':
fn = ScaleBy;
break;
case 'RotateBy':
fn = RotateBy;
break;
case 'TintBy':
fn = TintBy;
break;
}
if (!fn) {
return;
}
const act = fn(action.duration, Object.assign(Object.create(Object.prototype), action._to || action.to));
act._onComplete = action._onComplete;
delay && act.setDelay(delay);
act.onStart = action.onStart;
act.onUpdate = action.onUpdate;
act.onComplete = action.onComplete;
object.runAction(act);
}
};
return action;
}
action.repeatDelayTime = delay;
action.repeatTimes = times - 1;
action._type = 'Repeat';
return action;
}
/**
* 原动作返回
*
* @static
* @memberof Tiny
* @function Back
* @param {Tiny.Action} action
* @return {Tiny.Action}
*/
export function Back(action) {
action.yoyo = true;
if (!action.repeatTimes) {
action.repeatTimes = 1;
}
if (action._type === 'Repeat') {
action.repeatTimes = (action.repeatTimes - 1) * 2 + 1;
}
action._type = 'Back';
return action;
}