May the Force Be with You: UIDynamics, UIKit and OpenGL for the Star Wars iOS Animations

Have you ever thought that George Lucas’s epic space opera can, in fact, be implemented on iOS? We got inspired by the everlasting battle between the dark and light sides that bind the galaxy together and built our fantastic UI animation that features the Star Wars characters.

Creating our own Star Wars sequel was quite a challenge for both of our greatest Forces: design and development.

star wars animation

Designing the Star Wars animation

When we got down to making the animation, we wanted to create a unique solution for a standard switch and expand its influence to the entire screen. We came up with an interesting idea to make two different skins for a single user that would change by clicking on the switch. But what interface could we use to make sense of the double profile?

We remembered Star Wars and particularly Star Wars game franchises where a user could accept either the light side or the dark side. Skywalker and Darth Vader. Light and Dark. Bingo! We don’t know any characters that could convey our idea of an ambivalent personality so excellently.

star wars animation design by yalantis

Having spent a couple of hours researching interfaces, we created two photo-collages for each of the profiles and drew our own interface. We used Photoshop for creating the profiles and then animated them in Adobe After Effects.

Read also: How to Create an App Design That Works

After the two screens were ready, we thought they looked just too plain to be published on Dribbble. We took a glance at the screen with Darth Vader, and it finally came to us! Darth Vader in the picture is trying to reach the cross with his hand. We thought “what if the screen doesn’t only close, but crumble into small pieces as if it’s been hit by the Force?” This sounded cool! We researched how to implement this in After Effects, and did just what we had imagined. We used a Shatter effect which allowed us to implement the crumbling effect by applying a lot of different settings.

star wars animation design by yalantis 2

The only thing that was left to do was cycling the animation, because the component had no screen where a user could land on after the animation was over, and from where they could get back to the screen with profile settings. That’s why we created the third screen with a Star Wars logo, a button “Set up your profile,” and a starry sky. We made the sky with the help of CC Ball Action effect.

We put the video into a mockup device and made a shot for Dribbble. But the story isn’t over yet. Much to learn you still have, because great design plus talented development is where the real Force awakens.

Read also: How Can You Use Flinto to Create Cool Interactive Prototypes?

Developing the Star Wars animation in Swift

by Artem Sydorenko

There were two things in the Star Wars animation (see it on Github) that seemed hard to implement: flying stars on the main screen and the view crumbling into tiny pieces. We handled the first challenge with the help of CAEmitterLayer, а class that provides a particle emitter system. However, we had quite a hard time trying to break up the view into 4,000 pieces that fall down in different directions.

How we broke Star Wars into pieces

To break UIView into small pieces, we used the following methods:  snapshotViewAfterScreenUpdates() and resizableSnapshotViewFromRect (afterScreenUpdates:withCapInsets:). We also used an intermediate snapshot which allowed us to create small pieces much faster (creating a snapshot from a snapshot happens far quicker than making every small snapshot from the original view):

let fromViewSnapshot = fromView.snapshotViewAfterScreenUpdates(false)

for x in CGFloat(0).stride(through: size.width, by: width) {
    for y in CGFloat(0).stride(through: size.height, by: height) {
        let snapshotRegion = CGRect(x: x, y: y, width: width, height: height)
        let snapshot = fromViewSnapshot.resizableSnapshotViewFromRect(snapshotRegion, afterScreenUpdates: false, withCapInsets: UIEdgeInsetsZero)
        snapshot.frame = snapshotRegion

There are 3 ways to implement an animation like the Star Wars animation: by using UIDynamics, Core Animation (UIKit), or OpenGL. We made the animation using all of these methods, so let’s see the results.

Read also: How we created a ForceBlur animation for iOS and Android

Animation with UIDymanics

UIDynamics was our first guinea pig. We thought this tool would help us give the objects a natural falling effect. Here is what it looked like:

animator = UIDynamicAnimator(referenceView: containerView)
for snapshot in snapshots {                
    let push = UIPushBehavior(items: [snapshot], mode: .Instantaneous)
    push.pushDirection = CGVector(dx: randomFloatBetween(-0.15 , and: 0.15), dy: randomFloatBetween(-0.15 , and: 0)) = true
let gravity = UIGravityBehavior(items: snapshots)

But as it turned out the calculation of the physical movement of objects – given a large number of them – is very CPU-intensive. We had to move 4,000 objects simultaneously, and UIDynamics could hardly maintain this load.

See the results of our calculations below:

UIDymanics for creating user profile animation

Animation with UIKit (Core Animation)

Since using UIDynamics for the Star Wars animation wasn’t productive, we decided to rewrite it using UIView animations:

UIView.animateWithDuration(duration,  animations: {
    for view in snapshots {
        view.frame = view.frame.offsetBy(dx: randomFloatBetween(-200 , and: 200), 
            dy: randomFloatBetween(fromView.frame.height, and: fromView.frame.height * 1.3)

In this case, the CPU is affected only when cutting the animation into pieces, which created a small delay at the start. However, because of the load on the GPU, FPS (frame per second) couldn’t display more than 1,500 views at the same time. It could handle 26FPS, but to make the animation smooth we needed 60FPS.

Animating Star Wars with UIKit

Since we still weren't satisfied with the results, we decided to implement the Star Wars animation using OpenGL.

Animation with OpenGL

The majority of tutorials for iOS are designed for Objective-C, so we decided to start with that, and then, if the implementation was a success, we would rewrite the animation in Swift (which we did).

The results were stunning! We could animate the view breakup on iPhone 6 at 60 frames per second without any breaks or delays.

We wondered: what if we crumbled the animation into 40,000 pieces instead of 4,000? Would OpenGL cope with this load? Experimenting with these numbers, we got 4FPS. To trace the under-performing parts of the code, we launched the animation using time profiler. It allowed us to watch the load and reveal the methods that took the longest to implement.

With the time profiler the animation worked at 23FPS, but this can be easily explained. The time profiler launches a release configuration of the build, which means it optimizes the code being compiled.

After we rewrote the critical pieces of the code (we changed BlowSpriteclass to struct and replaced cycle for map), we could reach 60FPS in the release build configuration. We made the animation slightly more than two times faster! (In the debug configuration without compile optimizations we got 11FPS).

Using OpenGL to animate user profile interface

Read also: Video Recording and Video Editing App Development

The results of our experiments after implementing 3 types of animations: on UIDynamics, UIKit (Core Animation) and OpenGL are in the graph below. Only the OpenGL animation could cope with the necessary load so we chose this option for our component.

See the results of our experiments for CPU load below.

CPU performance measuring for UIDynamics, UIKit and OpenGL

And for Frames Per Second:

FPS performance results for UIDynamics, UIKit and OpenGL

How can you add Star Wars to your project?

Just implement a class of UIViewControllerTransitioningDelegate that will return our animation form the method animationControllerForDismissedController and assign it to transitioningDelegate of the viewController that you want to dismiss.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let destination = segue.destinationViewController
    destination.transitioningDelegate = self

func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return StarWarsGLAnimator()

How you can customize our component

There are two things you can customize in the Star Wars animation: duration and sprite sizes. Let’s see how you can do this.

Some code for duration:

func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    let animator = StarWarsGLAnimator()
    animator.duration = 2
    return animator

And 2 sprite sizes – changing sizes of the parties in points:

func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    let animator = StarWarsGLAnimator()
    animator.spriteWidth = 8
    return animator

Check out our Star Wars component on:

May the Force be with you!

4.4/ 5.0
Article rating
Remember those Facebook reactions? Well, we aren't Facebook but we love reactions too. They can give us valuable insights on how to improve what we're doing. Would you tell us how you feel about this article?
Excited to create something outstanding?

We share the same interests.

Contact us

We use cookies to personalize our service and to improve your experience on the website and its subdomains. We also use this information for analytics.