By Mike Lyman
We've been working on a new bomb dodging game and felt that something was missing. Our character follows your finger as he moves around the screen. We decided to look at traditional animation principles to make our game more organic and dynamic, specifically squash and stretch techniques from the 12 basic principles of animation (The Illusion of Life: Disney Animation). Disney animators have been employing this effect since the early days of cartoons to add life to their animations.
Checkout G. Scott Owen's article on animation for computer graphics for more background information.
Notice how the ball on the right doesn’t stay perfectly spherical? It stretches in the direction of it's motion and squashes in the perpendicular direction. That creates a sense of weight and really sells the movement.
Implementing Squash and Stretch in iOS using Cocos2d
If you are fortunate enough to have an experienced animator working with you then you might not need to worry about squash and stretch animations yourself. You could build a system that dynamically switches between pre-rendered animations. Or, like us, you could programmatically deform your existing character sprites using 2d transforms.
We can achieve the squash and stretch animation effect easily in Cocos2d using both image scale along an axis and image skew.
In Cocos2d, CCSprite objects have the scaleX and scaleY properties that will stretch and squash the sprite. Typically most apps will scale with a 1:1 to ratio to prevent deforming, but we'll use something like 2:1 to deform the shape of the character.
Squash/Stretch Proportional to Velocity
We use a UIPanGestureRecognizer to move the character around the screen using the translationInView: method. We can also use the UIPanGestureRecognizer to get the velocity of a person's finger dragging across the screen. We'll use the velocityInView: method from as a way to control the scale of our character.
Conservation of Volume
When scaling your sprite you should treat it like a real world object: if you squash it in one direction, the volume needs to be displaced equally perpendicular to the squash direction. In the simple case of horizontal motion, the scale of the x axis would be inversely proportional to the scale of the y axis. If we don't do this, your sprite will appear to grow and gain volume. We want the character to compress like a bouncy ball in a cartoon.
Scaling the sprite works fine for movements along the horizontal and vertical directions, but it doesn't work on the diagonals. We'll need to do a skew transformation to make this work in all directions.
Cocos2d CCSprites have the skewX and skewY properties. We just need to use skewX on the sprite when it moves in the diagonal direction, and we can ignore skewY.
Combining Scaling and Skewing
Combining scaling and skewing allows us to draw the stretch and squash in any direction. We need this because motion in our game follows the player's finger as it moves. A player can move left, right, up, down, and at varying angles.
We've created a code snippet that you can use to achieve the same kind of effect in your game.
Download project from GitHub
Further Reading and Videos
- Visual explanation of squash and stretch animation
- Tutorial of hand-drawn squash and stretch
- SIGGRAPH Animation Reference
- Email Mike at: MikeMakesApps@gmail.com
- Watch the use of squash and stretch in Artwork Evolution's upcoming game, Bomb Dodge.