Animation Design (Part 2/3)

Become a Subscriber

Login to access video

Picking up where we left off

In part one of this series (that was going to be two parts, but is now three), we learned about quickly prototyping animations using illustrator and photoshop. Our focus was on creating an animation in photoshop using keyframes and basic shapes to create a smooth animation. We ended with having our zombie bunny jump forward in a cool photoshop animation. In this part, we are going to actually export our assets and see our animation in a simple Swift game.

Animating in place

Our zombie bunny jumps up and forward in a smooth, graceful fashion (hopefully). You’d probably think we’d be able to export this sucker and dump it into an iOS game as-is. Well, we could do that, but that’s really limiting. Sprite Kit, the 2d gaming framework we’ll be using to create our game, has an awesome built-in physics engine that allows us to create effects like gravity and impulse. What we should do is leave all the jumping of our bunny to Sprite Kit. We made the bunny jump forward to help prototype an authentic animation, but now we need to edit our animation so that the bunny’s limbs move exactly as they do now, but the bunny doesn’t cover any ground.

In order to have our bunny jump in place, we are going to set up a few guides to frame our animation. We want to border the first frame with guides so we know where we originated from as we edit our animation. Our first guide we are going to create is some sort of ground. I usually use a rectangle as the guide for the ground, rather than an actual guide. Using the rectangle tool (u), create a rectangle below our bunny’s feet.

Next we create two vertical guides by going to View > New Guide… and selecting the vertical option.

Position the guides at the head and tail of the bunny.

Now we are all set up to edit our animation. Select all of the layers that make up your animation (no ground or background) from the layers pane on the right side. If your layers aren’t visible, go to Window > Layers to reveal the layers pane.

Next we want to move our timeline slider to our second keyframe. Notice our bunny hasn’t left the ground yet or moved horizontally. This means we don’t have to touch anything in this keyframe! Move the timeline slider to the third keyframe, where they bunny actually leaves the ground. Use the free transform tool (cmd + t) to free transform all of our selected layers. Drag the bunny back down to earth and align the head and tail to our guides. What we’ve done here is we’ve preserved the animation of the bunny’s limbs, but removed any displacement.

Move your timeline slider to the fourth keyframe and repeat for each of the remaining keyframes until our bunny jumps in place. See the example below for what your animation should now look like.

Now just hide the background layer and the ground layer by clicking the layer visibility toggle button next to those layers in the layers pane (the icon is an eye) and we should be left with our animation on a transparent background. Now we’re ready to export our animation as still frames.

Exporting and formatting our frames

We need to export our animation as a set of still frames for the iOS rendering engine to display in quick succession in our apps. In iOS we can control the speed of these frames get rendered, among various other things. To export our frames from Photoshop, go to File > Export > Render Video. This is going to bring up a render video modal with export options. The key here is to make sure you select Photoshop Image Sequence as your format, the work area as your range, and a Straight - Unmatted alpha channel from the render options. The work area option restricts our frames to frames in our animation so we don’t get any extraneous frames and the alpha channel option preserves transparency on export. For the frame rate, we suggest going with 23.976 fps, but you can choose a higher one if you’d like.

Once your options are selected, hit the export button and select a destination folder. That folder will be populated with all of the frames that make up our animation saved as .psd files. Now we need to convert all of those into image files that iOS can handle. In order to that, open up the first frame from the exported files. It should look something like this:

Now we want to trim our document to get rid of the extra transparent pixels around our bunny. To do that, go to _Image > Trim _ and select trim based on transparent pixels and hit the OK button.

This will crop our document around our image. Now all we need to do is save this image as a .png file. Go to _File > Save for web _ and save this file as a PNG-24.

Now that we’ve got our first frame as a .PNG file, we need to repeat the process with the other frames in our animation. I know there are a ton of frames, mine had 50. It doesn’t take that long to export all of the frames once you get the hang of using the hotkeys. Use shift + option + cmd + s as a shortcut to Save for web.

The last thing we need to do is make sure all of our PNGs are in a dedicated folder because we will be importing the entire folder of frames into our Xcode project.

Adding our animation into a Xcode Project…finally!

Now we are finally ready to create our game! Open Xcode and select “Create a Xcode Project” from the home screen. On the next screen select the “Game” option from the templates available.

Let’s name our project “zombunnies”. Set our language to Swift, game technology to SpriteKit, and devices to iPhone and hit next.

After you’ve chosen the location to save your project, you’ll see plenty of code already generated for you. In order to see our bunny animation in this game, all we need to worry about is the GameScene.swift file. Before we dive into that, we need to actually import our image assets. Take the folder containing the PNG frames for our bunny animations and append .atlas to the name.

Now drag the file into the your Xcode project

Adding the .atlas suffix has already done us a few favors. The .atlas suffix tells iOS to turn the images in that folder into a texture atlas. A texture atlas is a giant single image file (similar to a sprite sheet) that contains all of your images at various coordinates in that larger compiled image. This boosts performance because the rendering engine only needs to render one image instead of many for each draw call.

Now let’s turn our attention to *GameScene.swift. *You’ll see there is already some code in our didMoveToView and touchesBegan methods. As the comments in each method will tell you, the didMoveToView method is where we do our setup and the touchesBegan method is called when a user touches anywhere on the screen. The template code already in the project is not going to be of use to us, so go ahead and delete the code in the didMoveToView and touchesBegan methods. Your *GameScene.swift *should look exactly like the image below.

Let’s begin coding in GameScene.swift *by setting up our scene. We need to define our bunny and texture atlas where we are going to pull images from. You could do it inside the didMoveToView method, but we are going to create some variables outside of the didMoveToView method so we can use them in other methods that we write outside of didMoveToView. We want to define a constant for our texture atlas and a variable for our bunny hero. Our definitions will go right after the import SpriteKit statement at the top of the *GameScene.swift file.

let heroAtlas = SKTextureAtlas(named: “bunny_frames.atlas”)

var hero = SKSpriteNode(texture: heroAtlas.textureNamed(“jumping0000.png”))

Our heroAtlas constant is assigned to our bunny_frames.atlas and our hero variable is instance of the SKNode class. For more on nodes and what they are, read the “adding nodes” section of our Introduction to Sprite Kit (http://www.swiftcast.tv/articles/introduction-to-sprite-kit)

hero.position = CGPointMake(frame.size.width/2.5 , hero.size.height * 2)

Now in our didMoveToView method, we will scale our hero node by 50% using the setScale method. Next we position our hero at middle of the screen vertically and left-of-center horizontally. We use the frame.size.width and frame.size.height to position our hero in the same place relative to the size of the screen, regardless of the absolute pixel size of that screen. Lastly we add the hero node to the view.

In the touchesBegan method we are just going to call a function called makeBunnyJump().

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
 /* Called when a touch begins */ 
 makeBunnyJump()
 }

You’ll notice you get an error because we haven’t defined the makeBunnyJump() method. Outside of the touchsBegan method, we can write a makeBunnyJump() function that will define our animation and run the animation every time the function is called.

func makeBunnyJump() {
 let bunnyjumpinganim = SKAction.animateWithTextures([
 heroAtlas.textureNamed("jumping0000.png"),
 heroAtlas.textureNamed("jumping0001.png"),
 heroAtlas.textureNamed("jumping0002.png"),
 heroAtlas.textureNamed("jumping0003.png"),
 heroAtlas.textureNamed("jumping0004.png"),
 heroAtlas.textureNamed("jumping0005.png"),
 heroAtlas.textureNamed("jumping0006.png"),
 heroAtlas.textureNamed("jumping0007.png"),
 heroAtlas.textureNamed("jumping0008.png"),
 heroAtlas.textureNamed("jumping0009.png"),
 heroAtlas.textureNamed("jumping0010.png"),
 heroAtlas.textureNamed("jumping0011.png"),
 heroAtlas.textureNamed("jumping0012.png"),
 heroAtlas.textureNamed("jumping0013.png"),
 heroAtlas.textureNamed("jumping0014.png"),
 heroAtlas.textureNamed("jumping0015.png"),
 heroAtlas.textureNamed("jumping0016.png"),
 heroAtlas.textureNamed("jumping0017.png"),
 heroAtlas.textureNamed("jumping0018.png"),
 heroAtlas.textureNamed("jumping0019.png"),
 heroAtlas.textureNamed("jumping0020.png"),
 heroAtlas.textureNamed("jumping0021.png"),
 heroAtlas.textureNamed("jumping0022.png"),
 heroAtlas.textureNamed("jumping0023.png"),
 heroAtlas.textureNamed("jumping0024.png"),
 heroAtlas.textureNamed("jumping0025.png"),
 heroAtlas.textureNamed("jumping0026.png"),
 heroAtlas.textureNamed("jumping0027.png"),
 heroAtlas.textureNamed("jumping0028.png"),
 heroAtlas.textureNamed("jumping0029.png"),
 heroAtlas.textureNamed("jumping0030.png"),
 heroAtlas.textureNamed("jumping0031.png"),
 heroAtlas.textureNamed("jumping0032.png"),
 heroAtlas.textureNamed("jumping0033.png"),
 heroAtlas.textureNamed("jumping0034.png"),
 heroAtlas.textureNamed("jumping0035.png"),
 heroAtlas.textureNamed("jumping0036.png"),
 heroAtlas.textureNamed("jumping0037.png"),
 heroAtlas.textureNamed("jumping0038.png"),
 heroAtlas.textureNamed("jumping0039.png"),
 heroAtlas.textureNamed("jumping0040.png"),
 heroAtlas.textureNamed("jumping0000.png"),
 ], timePerFrame: 0.06)
 let jumpingaction = SKAction.repeatActionForever(bunnyjumpinganim)
 hero.runAction(bunnyjumping_anim)
 }

First we define a constant as an SKAction, which is an action that is executed by a node in an SKScene (notice our GameScene class is off type SKScene). The action that wil be executed will an animation using some frames from our hero atlas. In order to do that, we call the animateWithTextures method of SKAction and pass an array of frames we want animated and a timePerFrame, which controls how long each frame is visible. After that, we envoke the runAction method of the SKNode class to have our hero node run the action the next time the scene’s animation loop runs.

Now run the app by hitting the play button and anytime you tap the screen in the iOS simulator, our bunny is going to jump!