Changed more messy animations to use AnimatedValue.

Also finally refactored the main menu logo controller code...

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2015-08-06 00:53:30 -05:00
parent c91146b024
commit c0b3da37c2
4 changed files with 106 additions and 82 deletions

View File

@ -162,7 +162,7 @@ public class Spinner implements GameObject {
final int maxVel = 48;
final int minTime = 2000;
final int maxTime = 5000;
maxStoredDeltaAngles = (int) Utils.clamp((hitObject.getEndTime() - hitObject.getTime() - minTime)
maxStoredDeltaAngles = Utils.clamp((hitObject.getEndTime() - hitObject.getTime() - minTime)
* (maxVel - minVel) / (maxTime - minTime) + minVel, minVel, maxVel);
storedDeltaAngle = new float[maxStoredDeltaAngles];

View File

@ -33,8 +33,9 @@ import itdelatrisu.opsu.downloads.Updater;
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 itdelatrisu.opsu.ui.animations.AnimatedValue;
import itdelatrisu.opsu.ui.animations.AnimationEquation;
import java.awt.Desktop;
import java.io.IOException;
@ -62,7 +63,7 @@ import org.newdawn.slick.state.transition.FadeOutTransition;
*/
public class MainMenu extends BasicGameState {
/** Idle time, in milliseconds, before returning the logo to its original position. */
private static final short MOVE_DELAY = 5000;
private static final short LOGO_IDLE_DELAY = 10000;
/** Max alpha level of the menu background. */
private static final float BG_MAX_ALPHA = 0.9f;
@ -70,12 +71,21 @@ public class MainMenu extends BasicGameState {
/** Logo button that reveals other buttons on click. */
private MenuButton logo;
/** Whether or not the logo has been clicked. */
private boolean logoClicked = false;
/** Logo states. */
private enum LogoState { DEFAULT, OPENING, OPEN, CLOSING }
/** Current logo state. */
private LogoState logoState = LogoState.DEFAULT;
/** Delay timer, in milliseconds, before starting to move the logo back to the center. */
private int logoTimer = 0;
/** Logo horizontal offset for opening and closing actions. */
private AnimatedValue logoOpen, logoClose;
/** Logo button alpha levels. */
private AnimatedValue logoButtonAlpha;
/** Main "Play" and "Exit" buttons. */
private MenuButton playButton, exitButton;
@ -98,7 +108,7 @@ public class MainMenu extends BasicGameState {
private Stack<Integer> previous;
/** Background alpha level (for fade-in effect). */
private float bgAlpha = 0f;
private AnimatedValue bgAlpha = new AnimatedValue(1100, 0f, BG_MAX_ALPHA, AnimationEquation.LINEAR);
/** Whether or not a notification was already sent upon entering. */
private boolean enterNotification = false;
@ -154,7 +164,7 @@ public class MainMenu extends BasicGameState {
logo.setHoverAnimationEquation(logoAnimationEquation);
playButton.setHoverAnimationEquation(logoAnimationEquation);
exitButton.setHoverAnimationEquation(logoAnimationEquation);
final float logoHoverScale = 1.1f;
final float logoHoverScale = 1.08f;
logo.setHoverExpand(logoHoverScale);
playButton.setHoverExpand(logoHoverScale);
exitButton.setHoverExpand(logoHoverScale);
@ -203,6 +213,12 @@ public class MainMenu extends BasicGameState {
updateButton = new MenuButton(bangImg, startX - bangImg.getWidth(), startY - bangImg.getHeight());
updateButton.setHoverExpand(1.15f);
// logo animations
float centerOffsetX = container.getWidth() / 5f;
logoOpen = new AnimatedValue(400, 0, centerOffsetX, AnimationEquation.OUT_QUAD);
logoClose = new AnimatedValue(2200, centerOffsetX, 0, AnimationEquation.OUT_QUAD);
logoButtonAlpha = new AnimatedValue(300, 0f, 1f, AnimationEquation.LINEAR);
reset();
}
@ -215,11 +231,11 @@ public class MainMenu extends BasicGameState {
// draw background
Beatmap beatmap = MusicController.getBeatmap();
if (Options.isDynamicBackgroundEnabled() &&
beatmap != null && beatmap.drawBG(width, height, bgAlpha, true))
beatmap != null && beatmap.drawBG(width, height, bgAlpha.getValue(), true))
;
else {
Image bg = GameImage.MENU_BG.getImage();
bg.setAlpha(bgAlpha);
bg.setAlpha(bgAlpha.getValue());
bg.draw();
}
@ -235,7 +251,7 @@ public class MainMenu extends BasicGameState {
downloadsButton.draw();
// draw buttons
if (logoTimer > 0) {
if (logoState == LogoState.OPEN || logoState == LogoState.CLOSING) {
playButton.draw();
exitButton.draw();
}
@ -336,46 +352,44 @@ public class MainMenu extends BasicGameState {
MusicController.toggleTrackDimmed(0.33f);
// fade in background
if (bgAlpha < BG_MAX_ALPHA) {
bgAlpha += delta / 1000f;
if (bgAlpha > BG_MAX_ALPHA)
bgAlpha = BG_MAX_ALPHA;
}
bgAlpha.update(delta);
// buttons
if (logoClicked) {
if (logoTimer == 0) { // shifting to left
if (logo.getX() > container.getWidth() / 3.3f)
logo.setX(logo.getX() - delta);
else
logoTimer = 1;
} else if (logoTimer >= MOVE_DELAY) // timer over: shift back to center
logoClicked = false;
else { // increment timer
int centerX = container.getWidth() / 2;
float currentLogoButtonAlpha;
switch (logoState) {
case DEFAULT:
break;
case OPENING:
if (logoOpen.update(delta)) // shifting to left
logo.setX(centerX - logoOpen.getValue());
else {
logoState = LogoState.OPEN;
logoTimer = 0;
logoButtonAlpha.setTime(0);
}
break;
case OPEN:
if (logoButtonAlpha.update(delta)) { // fade in buttons
currentLogoButtonAlpha = logoButtonAlpha.getValue();
playButton.getImage().setAlpha(currentLogoButtonAlpha);
exitButton.getImage().setAlpha(currentLogoButtonAlpha);
} else if (logoTimer >= LOGO_IDLE_DELAY) { // timer over: shift back to center
logoState = LogoState.CLOSING;
logoClose.setTime(0);
logoTimer = 0;
} else // increment timer
logoTimer += delta;
if (logoTimer <= 500) {
// fade in buttons
playButton.getImage().setAlpha(logoTimer / 400f);
exitButton.getImage().setAlpha(logoTimer / 400f);
}
}
} else {
// fade out buttons
if (logoTimer > 0) {
float alpha = playButton.getImage().getAlpha();
if (alpha > 0f) {
playButton.getImage().setAlpha(alpha - (delta / 200f));
exitButton.getImage().setAlpha(alpha - (delta / 200f));
} else
logoTimer = 0;
}
// move back to original location
if (logo.getX() < container.getWidth() / 2) {
logo.setX(logo.getX() + (delta / 3f));
if (logo.getX() > container.getWidth() / 2)
logo.setX(container.getWidth() / 2);
break;
case CLOSING:
if (logoButtonAlpha.update(-delta)) { // fade out buttons
currentLogoButtonAlpha = logoButtonAlpha.getValue();
playButton.getImage().setAlpha(currentLogoButtonAlpha);
exitButton.getImage().setAlpha(currentLogoButtonAlpha);
}
if (logoClose.update(delta)) // shifting to right
logo.setX(centerX - logoClose.getValue());
break;
}
// tooltips
@ -471,7 +485,7 @@ public class MainMenu extends BasicGameState {
SongMenu menu = (SongMenu) game.getState(Opsu.STATE_SONGMENU);
menu.setFocus(BeatmapSetList.get().getBaseNode(previous.pop()), -1, true, false);
if (Options.isDynamicBackgroundEnabled())
bgAlpha = 0f;
bgAlpha.setTime(0);
} else
MusicController.setPosition(0);
UI.sendBarNotification("<< Previous");
@ -511,9 +525,10 @@ public class MainMenu extends BasicGameState {
}
// start moving logo (if clicked)
else if (!logoClicked) {
else if (logoState == LogoState.DEFAULT || logoState == LogoState.CLOSING) {
if (logo.contains(x, y, 0.25f)) {
logoClicked = true;
logoState = LogoState.OPENING;
logoOpen.setTime(0);
logoTimer = 0;
playButton.getImage().setAlpha(0f);
exitButton.getImage().setAlpha(0f);
@ -522,7 +537,7 @@ public class MainMenu extends BasicGameState {
}
// other button actions (if visible)
else if (logoClicked) {
else if (logoState == LogoState.OPEN || logoState == LogoState.OPENING) {
if (logo.contains(x, y, 0.25f) || playButton.contains(x, y, 0.25f)) {
SoundController.playSound(SoundEffect.MENUHIT);
enterSongMenu();
@ -546,8 +561,9 @@ public class MainMenu extends BasicGameState {
break;
case Input.KEY_P:
SoundController.playSound(SoundEffect.MENUHIT);
if (!logoClicked) {
logoClicked = true;
if (logoState == LogoState.DEFAULT || logoState == LogoState.CLOSING) {
logoState = LogoState.OPENING;
logoOpen.setTime(0);
logoTimer = 0;
playButton.getImage().setAlpha(0f);
exitButton.getImage().setAlpha(0f);
@ -595,8 +611,11 @@ public class MainMenu extends BasicGameState {
public void reset() {
// reset logo
logo.setX(container.getWidth() / 2);
logoClicked = false;
logoOpen.setTime(0);
logoClose.setTime(0);
logoButtonAlpha.setTime(0);
logoTimer = 0;
logoState = LogoState.DEFAULT;
logo.resetHover();
playButton.resetHover();
@ -625,7 +644,7 @@ public class MainMenu extends BasicGameState {
previous.add(node.index);
}
if (Options.isDynamicBackgroundEnabled() && !sameAudio && !MusicController.isThemePlaying())
bgAlpha = 0f;
bgAlpha.setTime(0);
}
/**

View File

@ -41,6 +41,8 @@ import itdelatrisu.opsu.db.ScoreDB;
import itdelatrisu.opsu.states.ButtonMenu.MenuState;
import itdelatrisu.opsu.ui.MenuButton;
import itdelatrisu.opsu.ui.UI;
import itdelatrisu.opsu.ui.animations.AnimatedValue;
import itdelatrisu.opsu.ui.animations.AnimationEquation;
import java.io.File;
import java.util.Map;
@ -138,8 +140,8 @@ public class SongMenu extends BasicGameState {
/** Button coordinate values. */
private float buttonX, buttonY, buttonOffset, buttonWidth, buttonHeight;
/** Current x offset of song buttons for mouse hover, in pixels. */
private float hoverOffset = 0f;
/** Horizontal offset of song buttons for mouse hover, in pixels. */
private AnimatedValue hoverOffset = new AnimatedValue(250, 0, MAX_HOVER_OFFSET, AnimationEquation.OUT_QUART);
/** Current index of hovered song button. */
private int hoverIndex = -1;
@ -307,7 +309,7 @@ public class SongMenu extends BasicGameState {
g.setClip(0, (int) (headerY + DIVIDER_LINE_WIDTH / 2), width, (int) (footerY - headerY));
for (int i = songButtonIndex; i <= MAX_SONG_BUTTONS && node != null; i++, node = node.next) {
// draw the node
float offset = (i == hoverIndex) ? hoverOffset : 0f;
float offset = (i == hoverIndex) ? hoverOffset.getValue() : 0f;
ScoreData[] scores = getScoreDataForNode(node, false);
node.draw(buttonX - offset, buttonY + (i*buttonOffset) + DIVIDER_LINE_WIDTH / 2,
(scores == null) ? Grade.NULL : scores[0].getGrade(), (node == focusNode));
@ -560,15 +562,11 @@ public class SongMenu extends BasicGameState {
float cx = (node.index == BeatmapSetList.get().getExpandedIndex()) ? buttonX * 0.9f : buttonX;
if ((mouseX > cx && mouseX < cx + buttonWidth) &&
(mouseY > buttonY + (i * buttonOffset) && mouseY < buttonY + (i * buttonOffset) + buttonHeight)) {
if (i == hoverIndex) {
if (hoverOffset < MAX_HOVER_OFFSET) {
hoverOffset += delta / 3f;
if (hoverOffset > MAX_HOVER_OFFSET)
hoverOffset = MAX_HOVER_OFFSET;
}
} else {
if (i == hoverIndex)
hoverOffset.update(delta);
else {
hoverIndex = i;
hoverOffset = 0f;
hoverOffset.setTime(0);
}
isHover = true;
break;
@ -576,7 +574,7 @@ public class SongMenu extends BasicGameState {
}
}
if (!isHover) {
hoverOffset = 0f;
hoverOffset.setTime(0);
hoverIndex = -1;
} else
return;
@ -660,7 +658,7 @@ public class SongMenu extends BasicGameState {
float cx = (node.index == expandedIndex) ? buttonX * 0.9f : buttonX;
if ((x > cx && x < cx + buttonWidth) &&
(y > buttonY + (i * buttonOffset) && y < buttonY + (i * buttonOffset) + buttonHeight)) {
float oldHoverOffset = hoverOffset;
int oldHoverOffsetTime = hoverOffset.getTime();
int oldHoverIndex = hoverIndex;
// clicked node is already expanded
@ -685,7 +683,7 @@ public class SongMenu extends BasicGameState {
}
// restore hover data
hoverOffset = oldHoverOffset;
hoverOffset.setTime(oldHoverOffsetTime);
hoverIndex = oldHoverIndex;
// open beatmap menu
@ -820,11 +818,11 @@ public class SongMenu extends BasicGameState {
if (next != null) {
SoundController.playSound(SoundEffect.MENUCLICK);
BeatmapSetNode oldStartNode = startNode;
float oldHoverOffset = hoverOffset;
int oldHoverOffsetTime = hoverOffset.getTime();
int oldHoverIndex = hoverIndex;
setFocus(next, 0, false, true);
if (startNode == oldStartNode) {
hoverOffset = oldHoverOffset;
hoverOffset.setTime(oldHoverOffsetTime);
hoverIndex = oldHoverIndex;
}
}
@ -836,11 +834,11 @@ public class SongMenu extends BasicGameState {
if (prev != null) {
SoundController.playSound(SoundEffect.MENUCLICK);
BeatmapSetNode oldStartNode = startNode;
float oldHoverOffset = hoverOffset;
int oldHoverOffsetTime = hoverOffset.getTime();
int oldHoverIndex = hoverIndex;
setFocus(prev, (prev.index == focusNode.index) ? 0 : prev.getBeatmapSet().size() - 1, false, true);
if (startNode == oldStartNode) {
hoverOffset = oldHoverOffset;
hoverOffset.setTime(oldHoverOffsetTime);
hoverIndex = oldHoverIndex;
}
}
@ -938,7 +936,7 @@ public class SongMenu extends BasicGameState {
selectRandomButton.resetHover();
selectMapOptionsButton.resetHover();
selectOptionsButton.resetHover();
hoverOffset = 0f;
hoverOffset.setTime(0);
hoverIndex = -1;
startScore = 0;
beatmapMenuTimer = -1;
@ -1076,7 +1074,7 @@ public class SongMenu extends BasicGameState {
oldFocusNode = null;
randomStack = new Stack<SongNode>();
songInfo = null;
hoverOffset = 0f;
hoverOffset.setTime(0);
hoverIndex = -1;
search.setText("");
searchTimer = SEARCH_DELAY;
@ -1157,7 +1155,7 @@ public class SongMenu extends BasicGameState {
break;
}
if (shifted) {
hoverOffset = 0f;
hoverOffset.setTime(0);
hoverIndex = -1;
}
return;
@ -1175,7 +1173,7 @@ public class SongMenu extends BasicGameState {
if (node == null)
return null;
hoverOffset = 0f;
hoverOffset.setTime(0);
hoverIndex = -1;
songInfo = null;
BeatmapSetNode oldFocus = focusNode;

View File

@ -29,13 +29,14 @@ import itdelatrisu.opsu.beatmap.BeatmapParser;
import itdelatrisu.opsu.beatmap.BeatmapSetList;
import itdelatrisu.opsu.replay.ReplayImporter;
import itdelatrisu.opsu.ui.UI;
import itdelatrisu.opsu.ui.animations.AnimatedValue;
import itdelatrisu.opsu.ui.animations.AnimationEquation;
import java.io.File;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
@ -47,6 +48,9 @@ import org.newdawn.slick.state.StateBasedGame;
* Loads game resources and enters "Main Menu" state.
*/
public class Splash extends BasicGameState {
/** Minimum time, in milliseconds, to display the splash screen (and fade in the logo). */
private static final int MIN_SPLASH_TIME = 300;
/** Whether or not loading has completed. */
private boolean finished = false;
@ -59,6 +63,9 @@ public class Splash extends BasicGameState {
/** Whether the skin being loaded is a new skin (for program restarts). */
private boolean newSkin = false;
/** Logo alpha level. */
private AnimatedValue logoAlpha;
// game-related variables
private int state;
private GameContainer container;
@ -80,6 +87,8 @@ public class Splash extends BasicGameState {
// load Utils class first (needed in other 'init' methods)
Utils.init(container, game);
// fade in logo
this.logoAlpha = new AnimatedValue(MIN_SPLASH_TIME, 0f, 1f, AnimationEquation.LINEAR);
GameImage.MENU_LOGO.getImage().setAlpha(0f);
}
@ -144,13 +153,11 @@ public class Splash extends BasicGameState {
}
// fade in logo
Image logo = GameImage.MENU_LOGO.getImage();
float alpha = logo.getAlpha();
if (alpha < 1f)
logo.setAlpha(alpha + (delta / 500f));
if (logoAlpha.update(delta))
GameImage.MENU_LOGO.getImage().setAlpha(logoAlpha.getValue());
// change states when loading complete
if (finished && alpha >= 1f) {
if (finished && logoAlpha.getValue() >= 1f) {
// initialize song list
if (BeatmapSetList.get().size() > 0) {
BeatmapSetList.get().init();