Skip to content

Commit

Permalink
Animate the game ranking screen elements.
Browse files Browse the repository at this point in the history
Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
  • Loading branch information
itdelatrisu committed Jan 5, 2017
1 parent fb87a97 commit e49ca3c
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 60 deletions.
199 changes: 141 additions & 58 deletions src/itdelatrisu/opsu/GameData.java
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ public GameData(int width, int height) {
/**
* Constructor for score viewing.
* This will initialize all parameters and images needed for the
* {@link #drawRankingElements(Graphics, Beatmap)} method.
* {@link #drawRankingElements(Graphics, Beatmap, int)} method.
* @param s the ScoreData object
* @param width container width
* @param height container height
Expand Down Expand Up @@ -782,86 +782,144 @@ else if (health >= 25f)
* Draws ranking elements: score, results, ranking, game mods.
* @param g the graphics context
* @param beatmap the beatmap
* @param time the animation time
*/
public void drawRankingElements(Graphics g, Beatmap beatmap) {
public void drawRankingElements(Graphics g, Beatmap beatmap, int time) {
// TODO Version 2 skins
float rankingHeight = 96;
float scoreTextScale = 1.33f;
float symbolTextScale = 1.15f;
float rankResultScale = 0.5f;
float uiScale = GameImage.getUIscale();
Image zeroImg = getScoreSymbolImage('0');

// animation timings
int animationTime = 400, offsetTime = 150, gradeAnimationTime = 1000, whiteAnimationTime = 2200;
int rankStart = 50, comboStart = 1800, perfectStart = 2700, gradeStart = 2800, whiteStart = 3800;

// ranking panel
GameImage.RANKING_PANEL.getImage().draw(0, (int) (102 * uiScale));

// score
float scoreTextScale = 1.33f;
drawFixedSizeSymbolString(
(score < 100000000) ? String.format("%08d", score) : Long.toString(score),
180 * uiScale, 120 * uiScale,
scoreTextScale, 1f, getScoreSymbolImage('0').getWidth() * scoreTextScale, false
scoreTextScale, 1f, zeroImg.getWidth() * scoreTextScale, false
);

// result counts
float resultHitInitialX = 64;
float resultHitInitialY = 256;
float resultInitialX = 128;
float resultInitialY = resultHitInitialY - (getScoreSymbolImage('0').getHeight() * symbolTextScale) / 2f;
float resultOffsetX = 320;
float resultOffsetY = 96;

int[] rankDrawOrder = { HIT_300, HIT_300G, HIT_100, HIT_100K, HIT_50, HIT_MISS };
int[] rankResultOrder = {
hitResultCount[HIT_300], hitResultCount[HIT_300G],
hitResultCount[HIT_100], hitResultCount[HIT_100K] + hitResultCount[HIT_300K],
hitResultCount[HIT_50], hitResultCount[HIT_MISS]
};

for (int i = 0; i < rankDrawOrder.length; i += 2) {
float offsetY = (resultOffsetY * (i / 2));
hitResults[rankDrawOrder[i]].getScaledCopy(rankResultScale).drawCentered(
resultHitInitialX * uiScale, (resultHitInitialY + offsetY) * uiScale
);
hitResults[rankDrawOrder[i+1]].getScaledCopy(rankResultScale).drawCentered(
(resultHitInitialX + resultOffsetX) * uiScale, (resultHitInitialY + offsetY) * uiScale
);
drawSymbolString(String.format("%dx", rankResultOrder[i]),
resultInitialX * uiScale, (resultInitialY + offsetY) * uiScale, symbolTextScale, 1f, false
);
drawSymbolString(String.format("%dx", rankResultOrder[i+1]),
(resultInitialX + resultOffsetX) * uiScale, (resultInitialY + offsetY) * uiScale, symbolTextScale, 1f, false
);
if (time >= rankStart) {
float rankResultScale = 0.5f;
float resultHitInitialX = 64, resultHitInitialY = 256;
float resultInitialX = 128;
float resultInitialY = resultHitInitialY - (zeroImg.getHeight() * symbolTextScale) / 2f;
float resultOffsetX = 320, resultOffsetY = 96;
int[] rankDrawOrder = { HIT_300, HIT_100, HIT_50, HIT_300G, HIT_100K, HIT_MISS };
int[] rankResultOrder = {
hitResultCount[HIT_300], hitResultCount[HIT_100],
hitResultCount[HIT_50], hitResultCount[HIT_300G],
hitResultCount[HIT_100K] + hitResultCount[HIT_300K], hitResultCount[HIT_MISS]
};
for (int i = 0; i < rankDrawOrder.length; i++) {
float offsetX = i < 3 ? 0 : resultOffsetX;
float offsetY = (resultOffsetY * (i % 3));
int startTime = rankStart + i * animationTime;
if (time >= startTime) {
float t = Math.min((float) (time - startTime) / animationTime, 1f);
float tp = AnimationEquation.OUT_CUBIC.calc(t);
float scale = 2f - tp;
float alpha = tp;
Image img = hitResults[rankDrawOrder[i]].getScaledCopy(rankResultScale * scale);
img.setAlpha(alpha);
img.drawCentered(
(resultHitInitialX + offsetX) * uiScale, (resultHitInitialY + offsetY) * uiScale
);
}
if (time >= startTime + offsetTime) {
float t = Math.min((float) (time - startTime) / animationTime, 1f);
float tp = AnimationEquation.OUT_CUBIC.calc(t);
float alpha = tp;
offsetX += -64f * (1f - tp);
drawSymbolString(String.format("%dx", rankResultOrder[i]),
(resultInitialX + offsetX) * uiScale, (resultInitialY + offsetY) * uiScale, symbolTextScale, alpha, false
);
}
}
}

// combo and accuracy
float accuracyX = 291;
float textY = 480;
float numbersY = textY + 48;
drawSymbolString(
String.format("%dx", comboMax),
24 * uiScale, numbersY * uiScale, symbolTextScale, 1f, false
);
drawSymbolString(
String.format("%02.2f%%", getScorePercent()),
(accuracyX + 20) * uiScale, numbersY * uiScale, symbolTextScale, 1f, false
);
GameImage.RANKING_MAXCOMBO.getImage().draw(8 * uiScale, textY * uiScale);
GameImage.RANKING_ACCURACY.getImage().draw(accuracyX * uiScale, textY * uiScale);
if (time >= comboStart) {
float t = Math.min((float) (time - comboStart) / animationTime, 1f);
float alpha = t;
Image img = GameImage.RANKING_MAXCOMBO.getImage();
img.setAlpha(alpha);
img.draw(8 * uiScale, textY * uiScale);
img.setAlpha(1f);
}
if (time >= comboStart + offsetTime) {
float t = Math.min((float) (time - (comboStart + offsetTime)) / animationTime, 1f);
float tp = AnimationEquation.OUT_CUBIC.calc(t);
float alpha = tp;
float offsetX = -15f * (1f - tp);
drawSymbolString(
String.format("%dx", comboMax),
(24 + offsetX) * uiScale, numbersY * uiScale, symbolTextScale, alpha, false
);
}
if (time >= comboStart + animationTime) {
float t = Math.min((float) (time - (comboStart + animationTime)) / animationTime, 1f);
float alpha = t;
Image img = GameImage.RANKING_ACCURACY.getImage();
img.setAlpha(alpha);
img.draw(accuracyX * uiScale, textY * uiScale);
img.setAlpha(1f);
}
if (time >= comboStart + animationTime + offsetTime) {
float t = Math.min((float) (time - (comboStart + animationTime + offsetTime)) / animationTime, 1f);
float tp = AnimationEquation.OUT_CUBIC.calc(t);
float alpha = tp;
float offsetX = -62f * (1f - tp);
drawSymbolString(
String.format("%02.2f%%", getScorePercent()),
(accuracyX + 20 + offsetX) * uiScale, numbersY * uiScale, symbolTextScale, alpha, false
);
}

// full combo
if (comboMax == fullObjectCount)
GameImage.RANKING_PERFECT.getImage().draw(177 * uiScale, 613 * uiScale);
if (time >= perfectStart) {
float t = Math.min((float) (time - perfectStart) / animationTime, 1f);
float tp = AnimationEquation.OUT_CUBIC.calc(t);
float scale = 1.1f - 0.1f * tp;
float alpha = tp;
if (comboMax == fullObjectCount) {
Image img = GameImage.RANKING_PERFECT.getImage().getScaledCopy(scale);
img.setAlpha(alpha);
img.drawCentered(416 * uiScale, 688 * uiScale);
}
}

// grade
Grade grade = getGrade();
if (grade != Grade.NULL) {
Image gradeImg = grade.getLargeImage();
gradeImg.draw(width - 8 * uiScale - gradeImg.getWidth(), 100 * uiScale);
if (time >= gradeStart) {
float t = Math.min((float) (time - gradeStart) / gradeAnimationTime, 1f);
float tp = AnimationEquation.IN_CUBIC.calc(t);
float scale = 1.5f - 0.5f * tp;
float alpha = tp;
Grade grade = getGrade();
if (grade != Grade.NULL) {
Image img = grade.getLargeImage();
float x = width - 8 * uiScale - img.getWidth() / 2f;
float y = 100 * uiScale + img.getHeight() / 2f;
img = img.getScaledCopy(scale);
img.setAlpha(alpha);
img.drawCentered(x, y);
}
}

// header
Image rankingTitle = GameImage.RANKING_TITLE.getImage();
g.setColor(Colors.BLACK_ALPHA);
g.fillRect(0, 0, width, rankingHeight * uiScale);
g.fillRect(0, 0, width, 96 * uiScale);
rankingTitle.draw(width - 24 * uiScale - rankingTitle.getWidth(), 0);
float marginX = width * 0.01f, marginY = height * 0.002f;
Fonts.LARGE.drawString(marginX, marginY,
Expand All @@ -873,15 +931,40 @@ public void drawRankingElements(Graphics g, Beatmap beatmap) {
String.format("Played%s on %s.", player, scoreData.getTimeString()), Color.white);

// mod icons
int modWidth = GameMod.AUTO.getImage().getWidth();
float modX = (width * 0.98f) - modWidth;
int modCount = 0;
for (GameMod mod : GameMod.VALUES_REVERSED) {
if ((mod.getBit() & scoreData.mods) > 0) {
mod.getImage().draw(modX - (modCount * (modWidth / 2f)), height / 2f);
modCount++;
if (scoreData.mods != 0) {
int modWidth = GameMod.AUTO.getImage().getWidth();
int modHeight = GameMod.AUTO.getImage().getHeight();
float modX = (width * 0.98f) - modWidth;
int modCount = 0;
for (GameMod mod : GameMod.VALUES_REVERSED) {
if ((scoreData.mods & mod.getBit()) > 0) {
if (time >= animationTime * modCount) {
float t = Math.min((float) (time - animationTime * modCount) / animationTime, 1f);
float tp = AnimationEquation.OUT_CUBIC.calc(t);
float scale = 2f - tp;
float alpha = tp;
Image img = mod.getImage().getScaledCopy(scale);
img.setAlpha(alpha);
img.drawCentered(
modX - (modCount * (modWidth / 2f)) + modWidth / 2f,
height / 2f + modHeight / 2f
);
modCount++;
}
}
}
}

// white flash
if (time >= whiteStart && time < whiteStart + whiteAnimationTime) {
float t = (float) (time - whiteStart) / whiteAnimationTime;
float alpha = 0.75f - 0.75f * AnimationEquation.OUT_CUBIC.calc(t);
float oldWhiteAlpha = Colors.WHITE_FADE.a;
Colors.WHITE_FADE.a = alpha;
g.setColor(Colors.WHITE_FADE);
g.fillRect(0, 0, width, height);
Colors.WHITE_FADE.a = oldWhiteAlpha;
}
}

/**
Expand Down
15 changes: 13 additions & 2 deletions src/itdelatrisu/opsu/states/GameRanking.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import itdelatrisu.opsu.replay.Replay;
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.FileNotFoundException;
import java.io.IOException;
Expand All @@ -43,8 +45,8 @@
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.state.transition.FadeInTransition;
import org.newdawn.slick.state.transition.EasedFadeOutTransition;
import org.newdawn.slick.state.transition.FadeInTransition;
import org.newdawn.slick.util.Log;

/**
Expand All @@ -64,6 +66,9 @@ public class GameRanking extends BasicGameState {
/** Button coordinates. */
private float retryY, replayY;

/** Animation progress. */
private AnimatedValue animationProgress = new AnimatedValue(6000, 0f, 1f, AnimationEquation.LINEAR);

// game-related variables
private GameContainer container;
private StateBasedGame game;
Expand Down Expand Up @@ -108,7 +113,7 @@ public void render(GameContainer container, StateBasedGame game, Graphics g)
GameImage.PLAYFIELD.getImage().draw(0,0);

// ranking screen elements
data.drawRankingElements(g, beatmap);
data.drawRankingElements(g, beatmap, animationProgress.getTime());

// buttons
replayButton.draw();
Expand All @@ -130,6 +135,7 @@ public void update(GameContainer container, StateBasedGame game, int delta)
else
MusicController.loopTrackIfEnded(true);
UI.getBackButton().hoverUpdate(delta, mouseX, mouseY);
animationProgress.update(delta);
}

@Override
Expand Down Expand Up @@ -209,6 +215,9 @@ else if (data.isGameplay() &&
game.enterState(Opsu.STATE_GAME, new EasedFadeOutTransition(), new FadeInTransition());
return;
}

// otherwise, finish the animation
animationProgress.setTime(animationProgress.getDuration());
}

@Override
Expand All @@ -220,10 +229,12 @@ public void enter(GameContainer container, StateBasedGame game)
if (!MusicController.isTrackDimmed())
MusicController.toggleTrackDimmed(0.5f);
replayButton.setY(retryY);
animationProgress.setTime(animationProgress.getDuration());
} else {
SoundController.playSound(SoundEffect.APPLAUSE);
retryButton.resetHover();
replayButton.setY(!GameMod.AUTO.isActive() ? replayY : retryY);
animationProgress.setTime(0);
}
replayButton.resetHover();
}
Expand Down

0 comments on commit e49ca3c

Please sign in to comment.