Open Gregoor opened 1 year ago
Hey Gregoor, this is a really neat idea! Would you be able to elaborate a bit on the functionality you're imagining? Reading your description here, I can think of two directions to take:
Emulating a tween
When creating a spring, perhaps in addition to a target
, the user can specify an initial
(or anchor
or start
). The value
will immediately move towards the target
from the initial
/anchor
/start
.
Emulating a Physical spring Right now, the "spring" collapses to be infinitely small. A real spring does not do this, it has a start and end point that cannot be the same point. The spring has a natural resting distance between the start and end points. When the value is set to less than that resting distance, the spring pushes away. When the value is set further, the spring pulls back.
I will say both of these types of behaviors are accomplishable with the current API, so perhaps I'm misunderstanding your ask. Or, perhaps we can make the API clearer and make one of these a first-class concept in the library.
Thanks for the swift response, and good point, a concrete example might make my use case clearer:
I want to loop a spring value from its anchor a
to a value t
, and back. So in pseudo code it'd be sth like
spring.anchor = A
onLoop(delta => {
spring.simulate(delta)
if (spring.isAtAnchor()) {
spring.target = t
} else if (spring.isAtTarget()) {
spring.target = a
}
})
and when the spring is simulating movement towards t
, away from the anchor (the behavior I don't know how to accomplish with this lib yet), I'd expect velocity to decrease, the further it moves away from the anchor (the opposite of the current behavior, i.e. moving towards the anchor).
Maybe this is already accomplishable and I'm missing it? Maybe I could set the arrival behavior to bounce
and that'd do the trick (I'd need to abs()
the value then for my example, but that should be fine)? I guess I'll try that route next time I'm on it.
I think the easiest way to accomplish what you're talking about here is to maintain two targets and two configurations outside of the spring, and swap them out based on the state of the spring:
const bouncy: SpringConfig = {
mass: 3,
tension: 500,
friction: 25,
};
const smooth: SpringConfig = {
mass: 0.75,
tension: 300,
friction: 45,
};
const anchor = 0;
const target = 200;
const spring = createSpring(target, smooth);
createTicker().add((_, delta) => {
spring.simulate(delta);
if (spring.state === 'resting') {
if (spring.target === target) {
spring.target = anchor;
spring.config = smooth;
} else {
spring.target = target;
spring.config = bouncy;
}
}
});
Here's a working example: https://stackblitz.com/edit/spring-target-and-anchor?file=index.ts
Does this capture what you're looking to accomplish?
Thanks for the example! Where it still seems off, for my use case, is that it goes fast at first, and then slows down as it gets closer to the target (as spring relaxes), in both directions.
I'm starting to think I might not have enough of a springy motion in mind, sorry for loading it here then. I suppose what I'm looking to accomplish is more like a jumping motion where there is
Maybe that just does not map well to springs, and I should just go full-physics?
Anyway, thanks a lot for thinking this through with me, I really appreciate you taking some time for me rando on the internet. And ofc feel free to close this issue, I think I'm moving out-of-scope.
I think I'm understanding you better now, you basically want to simulate throwing a ball in the air and letting gravity bring the ball back down to the ground.
I think something that would help is a setVelocity()
method on the springs, along with maybe a constantAcceleration
option for the gravity bit.
Both of those should be relatively easy to implement. Even if you do end up implementing the physics here yourself, I think they would be valuable additions to the library so I'll get working on those. Would love your feedback if it would suit your needs in any event.
Hi, thanks for the lib! Exactly what I was looking for wrt API, though my use cases diverges a bit, which is why I am wondering if I should fork or whether you'd look at a PR. Here's the gist:
With the currrent value/target dichotomy, where one can only set the target, each step moves the value closer to the target, according to the spring's physics. But I am also looking for the opposite case, where a movement should happen opposite to the spring direction, dampened by its force.
I am also thinking that for this model the naming is a bit off, it would be more like anchor, value & target, where anchor would be what target is now and target would be optional, only needed when a movement opposite to anchor is desired.
I'll work on a fork now, but happy to PR, if desired.