跳到主要内容

弹簧动画 (spring)

基于物理弹簧模型的动画模块,通过张力和摩擦力参数模拟弹簧运动,产生自然的回弹效果。

原理

弹簧运动由两个物理参数控制:

  • 张力(tension) — 弹簧刚度,值越大回弹越快
  • 摩擦力(friction) — 阻尼系数,值越大振荡衰减越快

运动方程:加速度 = tension × (目标位置 - 当前位置) - friction × 当前速度

通过欧拉积分以固定步长(1ms)推进仿真,自动处理过冲和振荡。

数据结构

struct spring_t {
float start; /* 当前位置 */
float stop; /* 目标位置 */
float velocity; /* 当前速度 */
float tension; /* 张力 */
float friction; /* 摩擦力 */
float acc; /* 时间累计余量 */
};

API

void spring_init(struct spring_t * s, float start, float stop, float velocity, float tension, float friction);

初始化弹簧。start 为起始位置,stop 为目标位置,velocity 为初始速度,tension 为张力,friction 为摩擦力。

int spring_step(struct spring_t * s, float dt);

推进 dt 秒,内部以 1ms 步长积分。运动未结束返回 1,到达目标(位置和速度均小于 0.005 精度)返回 0。dt 上限为 83ms,超过则截断。

float spring_position(struct spring_t * s);

获取当前位置。

float spring_velocity(struct spring_t * s);

获取当前速度。

参数参考

效果tensionfriction
快速回弹40030
中等回弹20020
缓慢回弹10015
几乎无振荡20040
明显振荡20010

使用示例

基本弹簧动画

struct spring_t s;
spring_init(&s, 0, 300, 0, 200, 20);

while(spring_step(&s, 0.016))
{
float pos = spring_position(&s);
set_position(pos);
}
float final_pos = spring_position(&s); /* ≈ 300 */

带初始速度

struct spring_t s;
spring_init(&s, 0, 100, 500, 180, 15); /* 初速度 500 向目标冲 */

链式动画

spring_init(&s, current_pos, new_target, 0, 200, 20);
/* 每次目标改变时重新初始化即可 */