From c0b3da37c2fd92ea97521e5ea0ab33f4b94b65ac Mon Sep 17 00:00:00 2001 From: Jeffrey Han Date: Thu, 6 Aug 2015 00:53:30 -0500 Subject: [PATCH] Changed more messy animations to use AnimatedValue. Also finally refactored the main menu logo controller code... Signed-off-by: Jeffrey Han --- src/itdelatrisu/opsu/objects/Spinner.java | 2 +- src/itdelatrisu/opsu/states/MainMenu.java | 125 +++++++++++++--------- src/itdelatrisu/opsu/states/SongMenu.java | 42 ++++---- src/itdelatrisu/opsu/states/Splash.java | 19 ++-- 4 files changed, 106 insertions(+), 82 deletions(-) diff --git a/src/itdelatrisu/opsu/objects/Spinner.java b/src/itdelatrisu/opsu/objects/Spinner.java index 3f9cdcab..dfd138ba 100644 --- a/src/itdelatrisu/opsu/objects/Spinner.java +++ b/src/itdelatrisu/opsu/objects/Spinner.java @@ -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]; diff --git a/src/itdelatrisu/opsu/states/MainMenu.java b/src/itdelatrisu/opsu/states/MainMenu.java index dd022368..383557d3 100644 --- a/src/itdelatrisu/opsu/states/MainMenu.java +++ b/src/itdelatrisu/opsu/states/MainMenu.java @@ -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 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); } /** diff --git a/src/itdelatrisu/opsu/states/SongMenu.java b/src/itdelatrisu/opsu/states/SongMenu.java index d191d125..681035d6 100644 --- a/src/itdelatrisu/opsu/states/SongMenu.java +++ b/src/itdelatrisu/opsu/states/SongMenu.java @@ -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(); 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; diff --git a/src/itdelatrisu/opsu/states/Splash.java b/src/itdelatrisu/opsu/states/Splash.java index 14d8245a..c83db4a0 100644 --- a/src/itdelatrisu/opsu/states/Splash.java +++ b/src/itdelatrisu/opsu/states/Splash.java @@ -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();