Yesterday we styled our character; now it's time to animate it! First, let’s change our character map name to adamSalute and add a new map for Adam.

$pixel-character: (
  ...
  adam: (
    ( t t t t t t t t t t t t t d d d d d d t t t t t t t t )
    ( t t t t t t t t t t t d d s s s s s s d d t t t t t t )
    ( t t t t t t t t t t d s s s s s s s s s d t t t t t t )
    ( t t t t t t t t d d s s s s s s s s s s s d d t t t t )
    ( t t t t t t t t d s s s s s s s s s s s s s s d t t t )
    ( t t t t t t t t d s s s s s s s s s s s s s s d t t t )
    ( t t t t t t t t d b b b b b b b b b b b b b b d t t t )
    ( t t t t t t t t d s s b b b b b b b b b b s s d t t t )
    ( t t t t t t t d s s s s b b b s s b b b s s s s d t t )
    ( t t t t t t t d s d s s s b s s s s b s s s d s d t t )
    ( t t t t t t t d s d s s s s s s s s s s s s d s d t t )
    ( t t t t t t t t d d s m m m m m m m m m m s d d t t t )
    ( t t t t t t t t t d m m m s s s s s s m m m d t t t t )
    ( t t t t t t t t t d m m m s b b b b s m m m d t t t t )
    ( t t t t t t t t t t d m m s s s s s s m m d t t t t t )
    ( t t t t t t t t t d d f m m m m m m m m f d d t t t t )
    ( t t t t t t t t d f f f f m m m m m m f f f f d t t t )
    ( t t t t t t t d s d d f f f m m m m f f f d d s d t t )
    ( t t t t t t t d s s s d f f d m m d f f d s s s d t t )
    ( t t t t t t t d s s s d f f d d d d f f d s s s d t t )
    ( t t t t t t t t d s s d f f f f f f f f d s s d t t t )
    ( t t t t t t t t t d d f f f f f f f f f f d d t t t t )
    ( t t t t t t t t t d n n n n n n n n n n n n d t t t t )
    ( t t t t t t t t t d n n n n n n n n n n n n d t t t t )
    ( t t t t t t t t d n n n n n n n n n n n n n n d t t t )
    ( t t t t t t t t d n n n n n j j j j n n n n n d t t t )
    ( t t t t t t d d d n n n n j j j j j j n n n n d d d t )
    ( t t t t t d b b b b b b b b d t t d b b b b b b b b d )
    ( t t t t t d d b b b b b b d d t t d d b b b b b b d d )
    ( t t t t t t d d d d d d d d t t t t d d d d d d d d t )
  )

Then we open our _tools.scss file and create a @kreyframe with the name salute. What we want is to see our character in normal position half of the time and saying "peace" the other half; to do so, we define four time points in our keyframe: 0% - 45% - 50% - 100% . Why four? Because we want to control the velocity and the moment of the transition. If we just use two — for example, 0% - 50% — the transition will be slow. We don't want that; we want to make it look like a natural action. We could use a low time duration like 1s, but that would be too repetitive, and it's better to just define the time points we want with the behavior we want. So the value for 0% and 45% will be our normal character, and the value for 50% and 100% will be our salute character. We just have to change the value of box-shadow using our function build_character and pass the maps for both characters.

@keyframes salute {
  0%,
  45% {
    box-shadow: build_character(map-get($pixel-character, adam), $pixel-size);
  }
  50%,
  100% {
    box-shadow: build_character(
      map-get($pixel-character, adamsalute),
      $pixel-size
    );
  }
}

Now we add the animation to pixel-adam to make our character say peace; nice! We can still make it even more interesting, though. Let's make our character fall and produce an earthquake, and salute after that.

  &:after {
    animation: salute 6s infinite alternate;
    ...
  }

To achieve that, we come back to our _tools.scss and create a couple more animations. The first animation will be the fall; we just need two time points, so we can use from and to. The first one will have a negative top to hide our character and simulate the fall, and the second one will be the "floor"; to maintain the final state of the animations, we'll use animation-fill-mode with fordwars; as value.

@keyframes fall {
  from {
    top: -60rem;
  }
  to {
    top: 4rem;
  }
}

The second animation is the earthquake. Just like before, we will use various time points, in this case eight: 0% 15%, 30%, 45%, 60%, 75%, 90% and 100%. We set the normal position of the container in the first and last time point, and we simulate the "vibrations" of the earthquake with the others, using transform: rotate;.

@keyframes earthquake {
  0%,
  100% {
    transform: rotate(0);
  }
  15%,
  45%,
  75% {
    transform: rotate(2.5deg);
  }
  30%,
  60%,
  90% {
    transform: rotate(-2.5deg);
  }
}

Now we add both animations

//--assets/components/_pixel-adam.scss/

.pixel-adam {
  animation: fall .5s forwards;
  ...
}

//--assets/components/_character-container.scss/

.character-container {
  animation: earthquake .5s forwards;
  ...
}

And we have some problems: the earthquake and the fall aren't synchronized. To fix that, we're going to use animation-delay.

It's time to do some math. I'll give a delay of 3s to our fall animation, which means a total time of 3.5s for the delay plus the duration of the animation itself. This means our earthquake should start after that time. If we set the start a little early, it will look like the earthquake is caused by the force of the fall; 3.4s should be good.

//--assets/components/_pixel-adam.scss/

.pixel-adam {
  animation: fall .5s forwards;
  animation-delay: 3s;
  ...
}

//--assets/components/_character-container.scss/

.character-container {
  animation: earthquake .5s forwards;
  animation-delay: 3.4s;
  ...
}

We have another problem now: the character is not hidden from the start, and it's making the salute while falling. Not good, so let's fix that by changing the top of pixel-adam to a negative value high enough to hide the draw; then we define an animation-delay of 3s.

.pixel-adam {
  animation: fall .5s forwards;
  animation-delay: 3s;
  ...
  top: -60rem;
  &:after {
    animation: salute 6s infinite alternate;
    animation-delay: 3s;
    ...
  }
}

Now it looks a lot better, but the shadow has some issues. It should come from the bottom, at the same time our character falls. To fix that, we're going to make another animation called up, which is basically the inverted version of fall. Up also modifies opacity, which makes it looks like a real shadow.

@keyframes up {
  from {
    opacity: 0;
    top: 80rem;
  }
  to {
    opacity: 1;
    top: 35%;
  }
}

Now we add the animation to our boots-shadow, set the opacity to 0, and change the top to 60rem. We’ll also set the same delay as the fall, so they synchronize.

.boots-shadow {
  ...
  &:after,
  &:before {
    animation: up .5s forwards;
    animation-delay: 3s;
    ...
    opacity: 0;
    top: 60rem;
    ...
  }
}

And we have our character animated! But what if we have various characters? Well, that’s a problem we’re going to fix in tomorrow’s video!