大部分内容转载自 搬砖老男人 所撰写的 “Cocos2dx源码分析之JumpBy的实现”
原文链接:http://superclass.me/archives/83#comment-6
void JumpBy::update(float t)
{
// parabolic jump (since v0.8.2)
if (_target)
{
// 以下两行较难理解,下面单独分析。
float frac = fmodf( t * _jumps,1.0f );
float y = _height * 4 * frac * (1 - frac);
// 此时刻,从起始点到目的地y轴移动的分量,加上此时刻的跳跃动作y轴移动的分量。
y += _delta.y * t;
float x = _delta.x * t; // 此时刻,从起始点到目的地x轴移动的分量。
#if CC_ENABLE_STACKABLE_ACTIONS // 支持多个动作同时作用于同一物体上的效果。
Vec2 currentPos = _target->getPosition();
Vec2 diff = currentPos - _prevIoUsPos;
_startPosition = diff + _startPosition;
Vec2 newPos = _startPosition + Vec2(x,y);
_target->setPosition(newPos);
_prevIoUsPos = newPos;
#else
_target->setPosition(_startPosition + Vec2(x,y)); // 更新位置。
#endif // !CC_ENABLE_STACKABLE_ACTIONS
}
}
下面这两行比较难以理解,
float frac = fmodf( t * _jumps,1.0f );
float y = _height * 4 * frac * (1 - frac);
这里首先要弄清楚参数t的含义,通过查看源码可知,t是已过去的时间elapsed和动作总时间duration的比值,也就是说
t = elapsed/duration,表示整个动作进度的百分比,取值0~1。
由于我们需要在duration秒内跳jumps次,那么每次跳跃需要时间
t1 = duration/jumps,
可推出
t * jumps
= elapsed *jumps/duration
= elapsed /t1
假设当前已跳完n次,正在跳第n+1次,且第n+1次已过去p秒,则
elapsed=n*t1+p
于是,
t * jumps = (n*t1 + p)/t1=n+p/t1
于是就得出
float frac
=fmodf(t*jumps,1.0f)
=p/t1
=当前跳跃已完成的百分比
好,现在已经弄明白frac的含义了,下面就简单了,
以frac为横坐标,高度为纵坐标建立坐标系,考虑如上图的抛物线,y=a*x*x+b*x+c,我们以节点起跳的位置为原点,则
在x=0处,高度为0,因为还没起跳
在x=1处,高度为0,因为已经落地
在x=0.5处,高度达到最高点height
所以得出
c=0,
a+b+c=0,
a/4 +b/2+c=height,
解方程组得到
c=0,
a=-4*height,
b=4*height,
于是原方程可表示为
y=-4*height*x*x+ 4*height*x
=4*height*x*(1-x)
到此完全推导出代码中的公式