9
\$\begingroup\$

I want to simulate a rope with a weight attached, swinging back and forth like a pendulum. Any actual physics is overkill; it's just endlessly repeating the same motion.

JQuery has a the "swing" ease similar to what I'm looking for. How does it work?

I was thinking of rotating from one angle to another with Math.easeOutExpo, but real pendulums ease differently...

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Have a sine curve feed into the angular velocity of the pendulum, such that the zero-point is at the peaks, and the highest velocity value is at the bottom. \$\endgroup\$ Commented Jul 12, 2013 at 14:05

2 Answers 2

10
\$\begingroup\$

Well, you'll have to use a little bit of physics, but you don't need to simulate any physics. There are formulas for pendulum motion you can easily use to set the rotation of your pendulum. For small swings, the motion can be approximated with simple harmonic motion.

The angular displacement at a specific time can be approximated with:

enter image description here

This is most accurate for a small maximum θ, but will likely be accurate enough for your purposes. Create a function that takes the current time, and outputs the angle for which your pendulum should be rotated, and rotate your sprite by that amount.

\$\endgroup\$
4
\$\begingroup\$

Here is a no-trig calculation, derived from straight-forward Grade 11 Trig and Physics. It assumes that the origin is the lowest point of the pendulum bob's suspension, that L is the length of the pendulum, and that the normal graphics convention of y increasing down, and x increasing to the right is adopted:

Update: I messed up yAcceleration initially; this is easier.
Update #2: Added explicit time control, and added units of measure.

const float gravity = 9.8;     // units of metres/sec/sec
const float deltaT  = 0.001;   // equals 0.001 sec or 1 millisecond

var xVelocity = 0.010;         // units metres/sec equals 10 cm/sec 
var x = 0.0;                   // units metres
var y = 0.0;                   // units metres

while (true) {
  var xAcceleration = -gravity * (x/L) * (L-y)/L;

  x += (xVelocity + (xAcceleration/2 * deltaT)) * deltaT;
  y  = Math.SQRT(L*L - x*x) - L; 

  xVelocity += xAcceleration * deltaT;
}
\$\endgroup\$
8
  • 2
    \$\begingroup\$ Time is missing in the equation. \$\endgroup\$ Commented Jul 13, 2013 at 18:44
  • \$\begingroup\$ @MaikSemder: The unit of time is defined to be the animation cycle, whatever that is. Why would one do it any other way? \$\endgroup\$ Commented Jul 13, 2013 at 20:30
  • \$\begingroup\$ Right now your acceleration integration uses an implicit time of 1 unit. If your game time unit is seconds, you could only have 1 simulation frame per second, just plugin the time explicitely and you get rid of that problem. Time is already in there, just make it explicit. For instance the frame time is varying but you need a stable constant speed of the animation independent of the frame time, also between different platforms, or you want a slomo effect, lots of reasons. \$\endgroup\$ Commented Jul 13, 2013 at 20:55
  • 1
    \$\begingroup\$ That was my point, g comes from outside or "the game". Now you have the time unit. Delta t right now is 1 of that time unit. For a real time simulation thats just not very convenient, since your game has its own "idea" of elapsed time. Making it an explicit parameter rather than an implicit constant can make your answer useful for a game. \$\endgroup\$ Commented Jul 13, 2013 at 22:50
  • 2
    \$\begingroup\$ Nice :) velocity must be multiplied with "deltaT" as well, in order to get the "displacement" out of the velocity, so it can be added to "x", upvoted \$\endgroup\$ Commented Jul 14, 2013 at 6:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .