diff --git a/src/itdelatrisu/opsu/ScoreData.java b/src/itdelatrisu/opsu/ScoreData.java index a9a1b673..3f01bf9b 100644 --- a/src/itdelatrisu/opsu/ScoreData.java +++ b/src/itdelatrisu/opsu/ScoreData.java @@ -23,6 +23,7 @@ import itdelatrisu.opsu.states.SongMenu; import itdelatrisu.opsu.ui.Colors; import itdelatrisu.opsu.ui.Fonts; import itdelatrisu.opsu.ui.UI; +import itdelatrisu.opsu.ui.animations.AnimationEquation; import java.sql.ResultSet; import java.sql.SQLException; @@ -225,46 +226,52 @@ public class ScoreData implements Comparable { * @param rank the score rank * @param prevScore the previous (lower) score, or -1 if none * @param focus whether the button is focused + * @param t the animation progress [0,1] */ - public void draw(Graphics g, int index, int rank, long prevScore, boolean focus) { - Image img = getGrade().getMenuImage(); - float textX = baseX + buttonWidth * 0.24f; - float edgeX = baseX + buttonWidth * 0.98f; + public void draw(Graphics g, int index, int rank, long prevScore, boolean focus, float t) { + float x = baseX - buttonWidth * (1 - AnimationEquation.OUT_BACK.calc(t)) / 2.5f; + float textX = x + buttonWidth * 0.24f; + float edgeX = x + buttonWidth * 0.98f; float y = baseY + index * (buttonOffset); float midY = y + buttonHeight / 2f; float marginY = Fonts.DEFAULT.getLineHeight() * 0.01f; + Color c = Colors.WHITE_FADE; + float alpha = t; + float oldAlpha = c.a; + c.a = alpha; // rectangle outline - g.setColor((focus) ? Colors.BLACK_BG_FOCUS : Colors.BLACK_BG_NORMAL); - g.fillRect(baseX, y, buttonWidth, buttonHeight); + Color rectColor = (focus) ? Colors.BLACK_BG_FOCUS : Colors.BLACK_BG_NORMAL; + float oldRectAlpha = rectColor.a; + rectColor.a *= AnimationEquation.IN_QUAD.calc(alpha); + g.setColor(rectColor); + g.fillRect(x, y, buttonWidth, buttonHeight); + rectColor.a = oldRectAlpha; // rank if (focus) { Fonts.LARGE.drawString( - baseX + buttonWidth * 0.04f, + x + buttonWidth * 0.04f, y + (buttonHeight - Fonts.LARGE.getLineHeight()) / 2f, - Integer.toString(rank + 1), Color.white + Integer.toString(rank + 1), c ); } // grade image - img.drawCentered(baseX + buttonWidth * 0.15f, midY); + Image img = getGrade().getMenuImage(); + img.setAlpha(alpha); + img.drawCentered(x + buttonWidth * 0.15f, midY); + img.setAlpha(1f); // score float textOffset = (buttonHeight - Fonts.MEDIUM.getLineHeight() - Fonts.SMALL.getLineHeight()) / 2f; - Fonts.MEDIUM.drawString( - textX, y + textOffset, - String.format("Score: %s (%dx)", NumberFormat.getNumberInstance().format(score), combo), - Color.white - ); + Fonts.MEDIUM.drawString(textX, y + textOffset, + String.format("Score: %s (%dx)", NumberFormat.getNumberInstance().format(score), combo), c); // hit counts (custom: osu! shows user instead, above score) String player = (playerName == null) ? "" : String.format(" (%s)", playerName); - Fonts.SMALL.drawString( - textX, y + textOffset + Fonts.MEDIUM.getLineHeight(), - String.format("300:%d 100:%d 50:%d Miss:%d%s", hit300, hit100, hit50, miss, player), - Color.white - ); + Fonts.SMALL.drawString(textX, y + textOffset + Fonts.MEDIUM.getLineHeight(), + String.format("300:%d 100:%d 50:%d Miss:%d%s", hit300, hit100, hit50, miss, player), c); // mods StringBuilder sb = new StringBuilder(); @@ -277,39 +284,30 @@ public class ScoreData implements Comparable { if (sb.length() > 0) { sb.setLength(sb.length() - 1); String modString = sb.toString(); - Fonts.DEFAULT.drawString( - edgeX - Fonts.DEFAULT.getWidth(modString), - y + marginY, modString, Color.white - ); + Fonts.DEFAULT.drawString(edgeX - Fonts.DEFAULT.getWidth(modString), y + marginY, modString, c); } // accuracy String accuracy = String.format("%.2f%%", getScorePercent()); - Fonts.DEFAULT.drawString( - edgeX - Fonts.DEFAULT.getWidth(accuracy), - y + marginY + Fonts.DEFAULT.getLineHeight(), - accuracy, Color.white - ); + Fonts.DEFAULT.drawString(edgeX - Fonts.DEFAULT.getWidth(accuracy), y + marginY + Fonts.DEFAULT.getLineHeight(), accuracy, c); // score difference String diff = (prevScore < 0 || score < prevScore) ? "-" : String.format("+%s", NumberFormat.getNumberInstance().format(score - prevScore)); - Fonts.DEFAULT.drawString( - edgeX - Fonts.DEFAULT.getWidth(diff), - y + marginY + Fonts.DEFAULT.getLineHeight() * 2, - diff, Color.white - ); + Fonts.DEFAULT.drawString(edgeX - Fonts.DEFAULT.getWidth(diff), y + marginY + Fonts.DEFAULT.getLineHeight() * 2, diff, c); // time since if (getTimeSince() != null) { Image clock = GameImage.HISTORY.getImage(); - clock.drawCentered(baseX + buttonWidth * 1.02f + clock.getWidth() / 2f, midY); + clock.drawCentered(x + buttonWidth * 1.02f + clock.getWidth() / 2f, midY); Fonts.DEFAULT.drawString( - baseX + buttonWidth * 1.03f + clock.getWidth(), + x + buttonWidth * 1.03f + clock.getWidth(), midY - Fonts.DEFAULT.getLineHeight() / 2f, - getTimeSince(), Color.white + getTimeSince(), c ); } + + c.a = oldAlpha; } /** diff --git a/src/itdelatrisu/opsu/states/SongMenu.java b/src/itdelatrisu/opsu/states/SongMenu.java index f76d841d..ef5e580d 100644 --- a/src/itdelatrisu/opsu/states/SongMenu.java +++ b/src/itdelatrisu/opsu/states/SongMenu.java @@ -224,7 +224,7 @@ public class SongMenu extends BasicGameState { private AnimatedValue bgAlpha = new AnimatedValue(800, 0f, 1f, AnimationEquation.OUT_QUAD); /** Timer for animations when a new song node is selected. */ - private AnimatedValue songChangeTimer = new AnimatedValue(900, 0f, 1f, AnimationEquation.OUT_QUAD); + private AnimatedValue songChangeTimer = new AnimatedValue(900, 0f, 1f, AnimationEquation.LINEAR); /** Timer for the music icon animation when a new song node is selected. */ private AnimatedValue musicIconBounceTimer = new AnimatedValue(350, 0f, 1f, AnimationEquation.LINEAR); @@ -425,45 +425,56 @@ public class SongMenu extends BasicGameState { marginX += 5; Color c = Colors.WHITE_FADE; float oldAlpha = c.a; - float t = songChangeTimer.getValue(); + float t = AnimationEquation.OUT_QUAD.calc(songChangeTimer.getValue()); float headerTextY = marginY * 0.2f; c.a = Math.min(t * songInfo.length / 1.5f, 1f); - Fonts.LARGE.drawString(marginX + iconWidth * 1.05f, headerTextY, songInfo[0], c); + if (c.a > 0) + Fonts.LARGE.drawString(marginX + iconWidth * 1.05f, headerTextY, songInfo[0], c); headerTextY += Fonts.LARGE.getLineHeight() - 6; c.a = Math.min((t - 1f / (songInfo.length * 1.5f)) * songInfo.length / 1.5f, 1f); - Fonts.DEFAULT.drawString(marginX + iconWidth * 1.05f, headerTextY, songInfo[1], c); + if (c.a > 0) + Fonts.DEFAULT.drawString(marginX + iconWidth * 1.05f, headerTextY, songInfo[1], c); headerTextY += Fonts.DEFAULT.getLineHeight() - 2; c.a = Math.min((t - 2f / (songInfo.length * 1.5f)) * songInfo.length / 1.5f, 1f); - float speedModifier = GameMod.getSpeedMultiplier(); - Color color2 = (speedModifier == 1f) ? c : - (speedModifier > 1f) ? Colors.RED_HIGHLIGHT : Colors.BLUE_HIGHLIGHT; - float oldAlpha2 = color2.a; - color2.a = c.a; - Fonts.BOLD.drawString(marginX, headerTextY, songInfo[2], color2); - color2.a = oldAlpha2; + if (c.a > 0) { + float speedModifier = GameMod.getSpeedMultiplier(); + Color color2 = (speedModifier == 1f) ? c : + (speedModifier > 1f) ? Colors.RED_HIGHLIGHT : Colors.BLUE_HIGHLIGHT; + float oldAlpha2 = color2.a; + color2.a = c.a; + Fonts.BOLD.drawString(marginX, headerTextY, songInfo[2], color2); + color2.a = oldAlpha2; + } headerTextY += Fonts.BOLD.getLineHeight() - 4; c.a = Math.min((t - 3f / (songInfo.length * 1.5f)) * songInfo.length / 1.5f, 1f); - Fonts.DEFAULT.drawString(marginX, headerTextY, songInfo[3], c); + if (c.a > 0) + Fonts.DEFAULT.drawString(marginX, headerTextY, songInfo[3], c); headerTextY += Fonts.DEFAULT.getLineHeight() - 4; c.a = Math.min((t - 4f / (songInfo.length * 1.5f)) * songInfo.length / 1.5f, 1f); - float multiplier = GameMod.getDifficultyMultiplier(); - Color color4 = (multiplier == 1f) ? c : - (multiplier > 1f) ? Colors.RED_HIGHLIGHT : Colors.BLUE_HIGHLIGHT; - float oldAlpha4 = color4.a; - color4.a = c.a; - Fonts.SMALL.drawString(marginX, headerTextY, songInfo[4], color4); - color4.a = oldAlpha4; + if (c.a > 0) { + float multiplier = GameMod.getDifficultyMultiplier(); + Color color4 = (multiplier == 1f) ? c : + (multiplier > 1f) ? Colors.RED_HIGHLIGHT : Colors.BLUE_HIGHLIGHT; + float oldAlpha4 = color4.a; + color4.a = c.a; + Fonts.SMALL.drawString(marginX, headerTextY, songInfo[4], color4); + color4.a = oldAlpha4; + } c.a = oldAlpha; } // score buttons if (focusScores != null) { - for (int i = 0; i < MAX_SCORE_BUTTONS; i++) { - int rank = startScore + i; - if (rank >= focusScores.length) - break; + int scoreButtons = Math.min(focusScores.length - startScore, MAX_SCORE_BUTTONS); + float timerScale = 1f - (1 / 3f) * ((MAX_SCORE_BUTTONS - scoreButtons) / (float) (MAX_SCORE_BUTTONS - 1)); + int duration = (int) (songChangeTimer.getDuration() * timerScale); + int segmentDuration = (int) ((2 / 3f) * songChangeTimer.getDuration()); + int time = songChangeTimer.getTime(); + for (int i = 0, rank = startScore; i < scoreButtons; i++, rank++) { long prevScore = (rank + 1 < focusScores.length) ? focusScores[rank + 1].score : -1; - focusScores[rank].draw(g, i, rank, prevScore, ScoreData.buttonContains(mouseX, mouseY, i)); + float t = Utils.clamp((time - (i * (duration - segmentDuration) / scoreButtons)) / (float) segmentDuration, 0f, 1f); + boolean focus = (t >= 0.9999f && ScoreData.buttonContains(mouseX, mouseY, i)); + focusScores[rank].draw(g, i, rank, prevScore, focus, t); } // scroll bar @@ -687,11 +698,9 @@ public class SongMenu extends BasicGameState { return; // tooltips - if (focusScores != null) { - for (int i = 0; i < MAX_SCORE_BUTTONS; i++) { - int rank = startScore + i; - if (rank >= focusScores.length) - break; + if (focusScores != null && ScoreData.areaContains(mouseX, mouseY)) { + int scoreButtons = Math.min(focusScores.length - startScore, MAX_SCORE_BUTTONS); + for (int i = 0, rank = startScore; i < scoreButtons; i++, rank++) { if (ScoreData.buttonContains(mouseX, mouseY, i)) { UI.updateTooltip(delta, focusScores[rank].getTooltipString(), true); break; @@ -804,10 +813,8 @@ public class SongMenu extends BasicGameState { // score buttons if (focusScores != null && ScoreData.areaContains(x, y)) { - for (int i = 0; i < MAX_SCORE_BUTTONS; i++) { - int rank = startScore + i; - if (rank >= focusScores.length) - break; + int scoreButtons = Math.min(focusScores.length - startScore, MAX_SCORE_BUTTONS); + for (int i = 0, rank = startScore; i < scoreButtons; i++, rank++) { if (ScoreData.buttonContains(x, y, i)) { SoundController.playSound(SoundEffect.MENUHIT); if (button != Input.MOUSE_RIGHT_BUTTON) {