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