Welcome to a brief introduction of springs and elasticity. This is part one of a series where we’ll tackle the mathematics and not-so-obvious applications of springs in game development. By the end of these lessons, you’ll have learned to make beautiful 2D dynamic water! But there’s plenty of other great uses of springs that we'll unravel along the way.
I’d like to give enormous credit to Michael Hoffman for his original C# and XNA tutorial on this subject. You can read his fantastic article here: https://gamedevelopment.tutsplus.com/tutorials/make-a-splash-with-dynamic-2d-water-effects--gamedev-236
I’m borrowing some of Hoffman's approaches and applying them to GameMaker Studio 1.4 & 2 through this series. But don’t worry, if you’re not using GameMaker, you should be able to follow my logic just fine!
The height of a spring when it's resting, not being compressed nor stretched, is the spring’s TargetHeight. When I stretch the spring, I’m causing displacement. Now, the height of the spring is now no longer its TargetHeight.
When I release the spring, just as we expect, its height will stabilize to its TargetHeight.
The base of the spring is (x, y). The current height of the spring is (x, y - Height). And the coordinate that the spring’s height will settle around is (x, y - TargetHeight).
And it’s not just stretching. I can compress the spring and it’ll settle at its TargetHeight. Pretty cool stuff. And like anything that’s cool, there’s some math behind it. There are two equations that we’ll need to know to make springs. If you don’t fully get the math, it’s okay! You’ll see some neat visualizations to help you understand.
The first is Hooke’s Law. Hooke’s Law is the force, the change in motion, provided by a spring.
Hooke’s Law is F = (k * x). Or, Force = (Tension * Displacement).
Displacement is simply the difference between the spring’s TargetHeight and Height. Or, its resting height and its current height, compressed or stretched. So, the more tension or greater the displacement, the more resulting force.
Next, we need to use Newton’s Second Law of Motion to actually move the spring. Newton’s Second Law of Motion if F = (m * a). Or, Force = (Mass * Acceleration). Using the power of math, we can fuse Hooke’s Law and Newton’s Second Law of Motion. A = (k/m)*x. Or, Acceleration = (Tension / Mass) * Displacement For simplicity’s sake, we can assume our object will have a Mass of 1. So we can condense the equation to just be Acceleration = (Tension * Displacement).
We want the spring to come to a stop over time, so we need to provide dampening to it. Or, force in the opposite direction. We can just subtract (Dampening * Velocity) from the original equation.
Finally, we can condense and translate all this to code. Acceleration is an increase in speed, so we can define variable Speed and increase it by everything to the right of the equal sign each game step, or frame. This constant change is called numerical integration using the Euler method. It’s not the most accurate, but it’s quick and easy.
Similarly, Velocity - which is speed and direction - can be condensed to simply Speed as we can manipulate the effect’s direction manually outside of this equation. All we’ll need to do is define variables Speed, Tension, TargetHeight, Height, and Dampening, and then put this math to use.
The higher the Tension, the more “stiff” it is. Lower, looser and more “springy”. The lower the dampening, the longer the spring will oscillate for.
There are some uses of the spring logic that might not be obvious at first. For example, a button’s size may neutralize at 100% scale. The variable we defined as TargetHeight would be TargetScale, and Height would be Scale. We can set the button’s image_xscale and image_yscale to Scale and apply Speed when we click it.
And grass! When we make the blades move, we're just manipulating the sprite’s image_angle! TargetHeight can be TargetAngle and Height can be Angle. And when we move past each blade, we can apply speed.
Stay tuned for part two where we’ll be taking what we learned here to make dynamic water! If you make anything cool with this effect, I’d love to see it!
If you found this tutorial useful and want to see more like it in the future, don’t forget to like and subscribe! You can also leave me a comment below with a suggestion for a future video topic you’d like me to cover.