Skip to content

Commit

Permalink
Added easing functions for all-around better animations.
Browse files Browse the repository at this point in the history
These are Robert Penner's easing functions (http://robertpenner.com/easing/), refactored by CharlotteGore to only take a t parameter (https://github.com/CharlotteGore/functional-easing). Licensed under BSD (the former) and MIT (the latter).

Related changes:
- Added "AnimatedValue" utility class for updating values used in animations.
- MenuButton now uses AnimatedValue to handle its animations (still linear by default).
- Added in-out-back easings on logo, mods, and various other elements; added out-bounce easings on button menu.

Signed-off-by: Jeffrey Han <[email protected]>
  • Loading branch information
itdelatrisu committed Aug 6, 2015
1 parent 6a4c6a8 commit c91146b
Show file tree
Hide file tree
Showing 10 changed files with 588 additions and 78 deletions.
3 changes: 3 additions & 0 deletions src/itdelatrisu/opsu/GameMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package itdelatrisu.opsu;

import itdelatrisu.opsu.ui.MenuButton;
import itdelatrisu.opsu.ui.animations.AnimationEquation;

import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -199,6 +200,8 @@ public static void init(int width, int height) {
mod.button = new MenuButton(img,
baseX + (offsetX * mod.categoryIndex) + img.getWidth() / 2f,
mod.category.getY());
mod.button.setHoverAnimationDuration(300);
mod.button.setHoverAnimationEquation(AnimationEquation.IN_OUT_BACK);
mod.button.setHoverExpand(1.2f);
mod.button.setHoverRotate(10f);

Expand Down
16 changes: 16 additions & 0 deletions src/itdelatrisu/opsu/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,22 @@ else if (val > max)
return val;
}

/**
* Clamps a value between a lower and upper bound.
* @param val the value to clamp
* @param low the lower bound
* @param high the upper bound
* @return the clamped value
* @author fluddokt
*/
public static int clamp(int val, int low, int high) {
if (val < low)
return low;
if (val > high)
return high;
return val;
}

/**
* Clamps a value between a lower and upper bound.
* @param val the value to clamp
Expand Down
24 changes: 13 additions & 11 deletions src/itdelatrisu/opsu/states/ButtonMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import itdelatrisu.opsu.beatmap.BeatmapSetNode;
import itdelatrisu.opsu.ui.MenuButton;
import itdelatrisu.opsu.ui.UI;
import itdelatrisu.opsu.ui.animations.AnimatedValue;
import itdelatrisu.opsu.ui.animations.AnimationEquation;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -261,8 +263,11 @@ public void scroll(GameContainer container, StateBasedGame game, int newValue) {
/** The actual title string list, generated upon entering the state. */
private List<String> actualTitle;

/** The horizontal center offset, used for the initial button animation. */
private AnimatedValue centerOffset;

/** Initial x coordinate offsets left/right of center (for shifting animation), times width. (TODO) */
private static final float OFFSET_WIDTH_RATIO = 1 / 18f;
private static final float OFFSET_WIDTH_RATIO = 1 / 25f;

/**
* Constructor.
Expand Down Expand Up @@ -336,18 +341,14 @@ public void draw(GameContainer container, StateBasedGame game, Graphics g) {
*/
public void update(GameContainer container, int delta, int mouseX, int mouseY) {
float center = container.getWidth() / 2f;
boolean centerOffsetUpdated = centerOffset.update(delta);
float centerOffsetX = centerOffset.getValue();
for (int i = 0; i < buttons.length; i++) {
menuButtons[i].hoverUpdate(delta, mouseX, mouseY);

// move button to center
float x = menuButtons[i].getX();
if (i % 2 == 0) {
if (x < center)
menuButtons[i].setX(Math.min(x + (delta / 5f), center));
} else {
if (x > center)
menuButtons[i].setX(Math.max(x - (delta / 5f), center));
}
if (centerOffsetUpdated)
menuButtons[i].setX((i % 2 == 0) ? center + centerOffsetX : center - centerOffsetX);
}
}

Expand Down Expand Up @@ -404,9 +405,10 @@ public void scroll(GameContainer container, StateBasedGame game, int newValue) {
*/
public void enter(GameContainer container, StateBasedGame game) {
float center = container.getWidth() / 2f;
float centerOffset = container.getWidth() * OFFSET_WIDTH_RATIO;
float centerOffsetX = container.getWidth() * OFFSET_WIDTH_RATIO;
centerOffset = new AnimatedValue(700, centerOffsetX, 0, AnimationEquation.OUT_BOUNCE);
for (int i = 0; i < buttons.length; i++) {
menuButtons[i].setX(center + ((i % 2 == 0) ? centerOffset * -1 : centerOffset));
menuButtons[i].setX(center + ((i % 2 == 0) ? centerOffsetX : centerOffsetX * -1));
menuButtons[i].resetHover();
}

Expand Down
3 changes: 3 additions & 0 deletions src/itdelatrisu/opsu/states/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import itdelatrisu.opsu.replay.ReplayFrame;
import itdelatrisu.opsu.ui.MenuButton;
import itdelatrisu.opsu.ui.UI;
import itdelatrisu.opsu.ui.animations.AnimationEquation;

import java.io.File;
import java.util.LinkedList;
Expand Down Expand Up @@ -1425,6 +1426,8 @@ private void loadImages() {
Image skip = GameImage.SKIP.getImage();
skipButton = new MenuButton(skip, width - skip.getWidth() / 2f, height - (skip.getHeight() / 2f));
}
skipButton.setHoverAnimationDuration(350);
skipButton.setHoverAnimationEquation(AnimationEquation.IN_OUT_BACK);
skipButton.setHoverExpand(1.1f, MenuButton.Expand.UP_LEFT);

// load other images...
Expand Down
9 changes: 9 additions & 0 deletions src/itdelatrisu/opsu/states/GamePauseMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import itdelatrisu.opsu.audio.SoundEffect;
import itdelatrisu.opsu.ui.MenuButton;
import itdelatrisu.opsu.ui.UI;
import itdelatrisu.opsu.ui.animations.AnimationEquation;

import org.lwjgl.input.Keyboard;
import org.newdawn.slick.Color;
Expand Down Expand Up @@ -227,6 +228,14 @@ public void loadImages() {
continueButton = new MenuButton(GameImage.PAUSE_CONTINUE.getImage(), width / 2f, height * 0.25f);
retryButton = new MenuButton(GameImage.PAUSE_RETRY.getImage(), width / 2f, height * 0.5f);
backButton = new MenuButton(GameImage.PAUSE_BACK.getImage(), width / 2f, height * 0.75f);
final int buttonAnimationDuration = 300;
continueButton.setHoverAnimationDuration(buttonAnimationDuration);
retryButton.setHoverAnimationDuration(buttonAnimationDuration);
backButton.setHoverAnimationDuration(buttonAnimationDuration);
final AnimationEquation buttonAnimationEquation = AnimationEquation.IN_OUT_BACK;
continueButton.setHoverAnimationEquation(buttonAnimationEquation);
retryButton.setHoverAnimationEquation(buttonAnimationEquation);
backButton.setHoverAnimationEquation(buttonAnimationEquation);
continueButton.setHoverExpand();
retryButton.setHoverExpand();
backButton.setHoverExpand();
Expand Down
20 changes: 17 additions & 3 deletions src/itdelatrisu/opsu/states/MainMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import itdelatrisu.opsu.states.ButtonMenu.MenuState;
import itdelatrisu.opsu.ui.MenuButton;
import itdelatrisu.opsu.ui.MenuButton.Expand;
import itdelatrisu.opsu.ui.animations.AnimationEquation;
import itdelatrisu.opsu.ui.UI;

import java.awt.Desktop;
Expand Down Expand Up @@ -145,9 +146,18 @@ public void init(GameContainer container, StateBasedGame game)
exitButton = new MenuButton(exitImg,
width * 0.75f - exitOffset, (height / 2) + (exitImg.getHeight() / 2f)
);
logo.setHoverExpand(1.05f);
playButton.setHoverExpand(1.05f);
exitButton.setHoverExpand(1.05f);
final int logoAnimationDuration = 350;
logo.setHoverAnimationDuration(logoAnimationDuration);
playButton.setHoverAnimationDuration(logoAnimationDuration);
exitButton.setHoverAnimationDuration(logoAnimationDuration);
final AnimationEquation logoAnimationEquation = AnimationEquation.IN_OUT_BACK;
logo.setHoverAnimationEquation(logoAnimationEquation);
playButton.setHoverAnimationEquation(logoAnimationEquation);
exitButton.setHoverAnimationEquation(logoAnimationEquation);
final float logoHoverScale = 1.1f;
logo.setHoverExpand(logoHoverScale);
playButton.setHoverExpand(logoHoverScale);
exitButton.setHoverExpand(logoHoverScale);

// initialize music buttons
int musicWidth = GameImage.MUSIC_PLAY.getImage().getWidth();
Expand All @@ -170,6 +180,8 @@ public void init(GameContainer container, StateBasedGame game)
// initialize downloads button
Image dlImg = GameImage.DOWNLOADS.getImage();
downloadsButton = new MenuButton(dlImg, width - dlImg.getWidth() / 2f, height / 2f);
downloadsButton.setHoverAnimationDuration(350);
downloadsButton.setHoverAnimationEquation(AnimationEquation.IN_OUT_BACK);
downloadsButton.setHoverExpand(1.03f, Expand.LEFT);

// initialize repository button
Expand All @@ -179,6 +191,8 @@ public void init(GameContainer container, StateBasedGame game)
repoButton = new MenuButton(repoImg,
startX - repoImg.getWidth(), startY - repoImg.getHeight()
);
repoButton.setHoverAnimationDuration(350);
repoButton.setHoverAnimationEquation(AnimationEquation.IN_OUT_BACK);
repoButton.setHoverExpand();
startX -= repoImg.getWidth() * 1.75f;
} else
Expand Down
Loading

0 comments on commit c91146b

Please sign in to comment.