Animating the menu screen

Let's now discuss what we are actually going to animate in the menu screen. Basically, the first two bits of our animated menu involve the gold coins and the large bunny head.

Take a look at the following screenshot:

Animating the menu screen

In this screenshot, you can see a rough sketch of the final animation divided into four essential steps. The following actions need to be taken for the shown steps:

  1. The gold coins and bunny head are invisible at the beginning.
  2. The gold coins fade in and scale up from 0 percent to 100 percent from the center screen as if they were jumping out of the water.
  3. After a short pause, the bunny head appears in the top-right corner, which moves slightly until it reaches the edge of the rock that is visible in the background.
  4. The bunny head moves as if it was jumping over to the other rock in front of it.

Animating the gold coins and bunny head actors

Add the following (static) import lines to the MenuScreen class:

import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*;

import com.badlogic.gdx.math.Interpolation;

After this, make the following changes to the same class:

private Table buildObjectsLayer () {
  Table layer = new Table();
  // + Coins
  imgCoins = new Image(skinCanyonBunny, "coins");
  layer.addActor(imgCoins);
  imgCoins.setOrigin(imgCoins.getWidth() / 2,imgCoins.getHeight() / 2);
  imgCoins.addAction(sequence(moveTo(135, -20),scaleTo(0, 0),fadeOut(0),delay(2.5f),
  parallel(moveBy(0, 100, 0.5f, Interpolation.swingOut), scaleTo(1.0f, 1.0f, 0.25f, Interpolation.linear), alpha(1.0f, 0.5f))));
  // + Bunny
  imgBunny = new Image(skinCanyonBunny, "bunny");
  layer.addActor(imgBunny);
  imgBunny.addAction(sequence(moveTo(655, 510), delay(4.0f), moveBy(-70, -100, 0.5f, Interpolation.fade), moveBy(-100, -50, 0.5f, Interpolation.fade), moveBy(-150, -300, 1.0f, Interpolation.elasticIn)));
  return layer;
}

All of the four steps are now expressed as actions in the code of the buildObjectLayer() method. This code replaces the setPosition() for the corresponding images. The origin of the gold coins' image that is stored in imgCoins needs to be adjusted so that it now points to its center. In this way, the image does not only grow or shrink when scaled but it will never move away from its original position. The first action of imgCoins is sequence() that merely groups all other actions. Then, the animation is initialized through the first three actions: moveTo(), scaleTo(), and fadeOut(). Next, a delay() action follows that creates a short delay of 2.5 seconds before the parallel action is executed.

The parallel action contains three more actions, moveBy(), scaleTo(), and alpha(), which are all executed at the same time. These three actions, when played together, create the impression that the gold coins appear to jump out of the water by moving them a bit downwards as well as fading them in and scaling them up from 0 percent to 100 percent. Interpolations are also used to support this effect. Choosing the right interpolation algorithm is usually a little trial-and-error at first, but after a while you will have a better understanding and feel for which one could work best for certain kinds of effects.

The animation for the bunny head is not that much different to the gold coins. It starts with a grouping sequence() that comprises an initializing moveTo() action followed by a delay() of 4 seconds. Then, three subsequent moveBy() actions are executed that describe the complete movement we discussed earlier.

Animating the menu buttons and options window

Now, for a final touch to the menu screen, let's animate the menu buttons in the bottom-right corner of the scene as well as the Options window that appears when the Options button is clicked. We want to let both buttons move out of the scene when the Options button is clicked on and let them move back into the scene after the Options window is closed again.

Add the following import lines to the MenuScreen class:

import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction;
import com.badlogic.gdx.scenes.scene2d.Touchable;

Next, add the following lines of code to the same class:

private void showMenuButtons (boolean visible) {
  float moveDuration = 1.0f;
  Interpolation moveEasing = Interpolation.swing;
  float delayOptionsButton = 0.25f;

  float moveX = 300 * (visible ? -1 : 1);
  float moveY = 0 * (visible ? -1 : 1);
  final Touchable touchEnabled = visible ? Touchable.enabled
    : Touchable.disabled;
  btnMenuPlay.addAction(moveBy(moveX, moveY, moveDuration, moveEasing));

  btnMenuOptions.addAction(sequence(delay(delayOptionsButton), moveBy(moveX, moveY, moveDuration, moveEasing)));

  SequenceAction seq = sequence();
  if (visible)
  seq.addAction(delay(delayOptionsButton + moveDuration));
  seq.addAction(run(new Runnable() {
    public void run () {
      btnMenuPlay.setTouchable(touchEnabled);
      btnMenuOptions.setTouchable(touchEnabled);
    }
  }));
  stage.addAction(seq);
}

private void showOptionsWindow (boolean visible, boolean animated) {
  float alphaTo = visible ? 0.8f : 0.0f;
  float duration = animated ? 1.0f : 0.0f;
  Touchable touchEnabled = visible ? Touchable.enabled : Touchable.disabled;
  winOptions.addAction(sequence(touchable(touchEnabled), alpha(alphaTo, duration)));
}

The two new methods, showMenuButtons() and showOptionsWindow(), will allow us to easily show or hide the menu buttons and the Options window in an animated fashion. Any logic involved in the showing and hiding animation is encapsulated in these methods, which make it much more convenient to use.

The showMenuButtons() method has one parameter (visible) to control whether to show or hide the menu buttons. At the beginning of this method, we not only set many variables that are used to control the overall behavior of the animation, such as duration and easing, but also set some other variables whose values obviously depend on the visible flag. After the position, duration, and easing have been computed, we head over and add a couple of actions to both the menu buttons. The Play button is going to be directly moved to a relative position while the Options button does exactly the same but with an added delay prior to its move action. We will now discuss a pretty exciting example of how flexible actions are. We create a new and empty sequence and store it in seq. What follows is a conditional delay() action, so to say, which is only going to be added to the new sequence if the visible flag is set to true.

This means you can create and script actor behaviors in code while also being able to dynamically adjust and put them together as needed at a later time as we just did! Albeit, as a result of the prior condition, we always add a run() action to the sequence. The run() action takes a Runnable that is used in Java to put the code that is going to be executed in a separate thread. We use this and the conditional delay() action to call setTouchable() on the Play and Options buttons, which control whether the buttons receive and respond to touches and mouse clicks. Finally, the sequence() action stored in seq is added as a new action to the stage.

Note

In this case, we can safely do this to enqueue the sequence() action for execution because the sequence does not modify the stage with the delay() and run() actions.

The showOptionsWindow() method animates the options menu in the same way as described for the menu buttons in showMenuButtons(). The only difference here is that it takes a second flag that can be used to skip the animation.

Now, make the following changes to the MenuScreen class:

private Table buildOptionsWindowLayer () {
  ...
  // Make options window slightly transparent
  winOptions.setColor(1, 1, 1, 0.8f);
  // Hide options window by default
  showOptionsWindow(false, false);
  if (debugEnabled) winOptions.debug();
  // Let TableLayout recalculate widget sizes and positions
  winOptions.pack();
  // Move options window to bottom right corner
  winOptions.setPosition(Constants.VIEWPORT_GUI_WIDTH - winOptions.getWidth() - 50, 50);
  return winOptions;
}

private void onOptionsClicked () {
  loadSettings();
  showMenuButtons(false);
  showOptionsWindow(true, true);
}

private void onCancelClicked () {
  showMenuButtons(true);
  showOptionsWindow(false, true);
  AudioManager.instance.onSettingsUpdated();
}

These changes simply put our animation methods in place where needed. The buildOptionsWindowLayer() method calls showOptionsWindow() with both parameters for visible and animated set to false. The reason for this is that we want the Options window to be hidden at the start like before and we also want this to happen in an instant. The onOptionsClicked() and onCancelClicked() methods call both show methods to either show or hide the menu buttons or the Options window, respectively.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset