Leonardo Maia Pugliese
Holy Swift

Holy Swift

Making pixel art animations with UIImageView in Swift

Making pixel art animations with UIImageView in Swift

Mega animations now!

Leonardo Maia Pugliese's photo
Leonardo Maia Pugliese
·Jan 11, 2022·

5 min read

Subscribe to my newsletter and never miss my upcoming articles

Hallo heksen en tovenaars, leo hier.

Today we will explore an API that I discovered recently. Last week I had to animate the pin of a map. But it's not animate it's changing in a path, that I already covered in this article. I had to animate the pin itself.

So to do that I used a timer that changed the image on a regular basis in a UIImageView, and that's when my colleague Mike Dammers told me about an API on the UIImageView that does exactly what I was performing with the timer.

Disclosure: I do not own the mega man sprites, this post is for educational purposes only and was picked up from a DMCA compliant website.

Let's dive into that API with mega man sprite animations. But first... The Painting!

The Painting

This painting is an 1878 art piece called Winding the Skein from Frederic Leighton. Frederic Leighton, 1st Baron Leighton, PRA (3 December 1830 – 25 January 1896), known as Sir Frederic Leighton between 1878 and 1896, was an English painter and sculptor. His works depicted historical, biblical, and classical subject matter. Leighton was the bearer of the shortest-lived peerage in history; after only one day his hereditary peerage became extinct upon his death.

I chose this piece because the girl helping the woman is not very animated to help the woman.

The Problem

You have to repeatedly change images from a UIImageView on regular basis.

First, download all the mega man sprites and cut four of them, the static pose, and 3 running, call them mega, mega1, mega2, and mega3.

Mega.png - Static: Screenshot 2022-01-10 at 08.49.30.png

Mega1.png - First running pose : Screenshot 2022-01-10 at 08.50.15.png

Mega2.png - Second running pose: Screenshot 2022-01-10 at 08.50.47.png

And Mega3.png - Third running pose: Screenshot 2022-01-10 at 08.51.36.png

Create a SingleView playgrounds and Copy and paste all of them to the Resources folder:

Screenshot 2022-01-10 at 08.52.31.png

Now let's try just one static image with the code below:

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let imageView = UIImageView()
        imageView.frame = CGRect(x: 20, y: 120, width: 300, height: 300)
        imageView.image = UIImage(named: "mega")
        imageView.contentMode = .scaleAspectFit

        view.addSubview(imageView)
        self.view = view
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

The result is: Screenshot 2022-01-10 at 08.54.17.png

Ok... perfect. Now let's start to introduce the animation API.

Animation Images in UIImageView

To animate images with your UIImageView you have to do 3 steps:

  1. Set an array of UIImage in the animation images UIImageView property.
  2. Set the duration of all images in the animation-duration UIImageView property. For example: if you put 2 images and set the animation duration to 1 second, each image will be on the screen for 0.5 seconds. Or if you set 4 images with the same 1-second duration, each image will be on the screen for 0.25 seconds.
  3. Call startAnimating() function in UIImageView.

Let's do that:

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let imageView = UIImageView()
        imageView.frame = CGRect(x: 20, y: 120, width: 300, height: 300)
        imageView.image = UIImage(named: "mega")
        imageView.contentMode = .scaleAspectFit


        let allMegas: [UIImage] = [1,2,3].compactMap { x in // Mark 1
            return UIImage(named: "mega\(x)")
        }

        imageView.animationImages = allMegas // step 1
        imageView.animationDuration = 0.3 // step 2
        imageView.startAnimating() // step 3

        view.addSubview(imageView)
        self.view = view
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

Mark 1 is necessary because the UIImage initialization returns an Optional, this way need somehow unwrap it. And for our luck, we already called all the images in a way that is easy to call them sequentially. So we just need to use a compactMap function to get the image array.

On the steps above we execute what we explained before.

The result of this code should be:

Improving the animation

Would be nice if the mega man stopped a little bit and after starting to run. Let's do that.

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let imageView = UIImageView()
        imageView.frame = CGRect(x: 20, y: 120, width: 300, height: 300)
        imageView.contentMode = .scaleAspectFit

        let allMegas: [UIImage] = (1...3).compactMap { x in
            return UIImage(named: "mega\(x)")
        }

        var runningMega = allMegas + allMegas + allMegas

        (1...8).forEach { _ in
            guard let megaImage = UIImage(named: "mega") else { return }
            runningMega.insert(megaImage, at: 0) // Mark 1
        }

        imageView.animationImages = runningMega
        imageView.animationDuration = 1
        imageView.startAnimating()

        view.addSubview(imageView)
        self.view = view
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

The only difference now is that we are inserting at position zero, at Mark 1, the initial mega man still frames. We could have used compactMap to generate the array of UIImage but I don't want to traverse two times.

The result should be this:

And that's it!

Summary

Today you learned that we can make cool animations with just an UIImageView and a bit of pixel art. It's always important to seek native ways to do whatever we are doing. Remember the old phrase: less code, less problems.

That's all my people, I hope you liked it as I enjoyed writing this article. If you want to support this blog you can Buy Me a Coffee or just leave a comment saying hello. You can also sponsor posts and I'm open to writing freelancing! Just reach me in LinkedIn or Twitter for details.

Thanks for the reading and... That's all folks.

credits: image

Did you find this article valuable?

Support Leonardo Maia Pugliese by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
 
Share this