Added scrolling animation to "random" song selection.

Involves temporarily changing the kinetic scrolling speed, so it's a little messy...

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2015-09-18 18:49:01 -04:00
parent 14496050ea
commit eb331360b9
2 changed files with 68 additions and 13 deletions

View File

@ -262,6 +262,9 @@ public class SongMenu extends BasicGameState {
/** The star stream. */ /** The star stream. */
private StarStream starStream; private StarStream starStream;
/** Whether the menu is currently scrolling to the focus node (blocks other actions). */
private boolean isScrollingToFocus = false;
// game-related variables // game-related variables
private GameContainer container; private GameContainer container;
private StateBasedGame game; private StateBasedGame game;
@ -679,15 +682,25 @@ public class SongMenu extends BasicGameState {
searchTransitionTimer = SEARCH_TRANSITION_TIME; searchTransitionTimer = SEARCH_TRANSITION_TIME;
} }
// Scores // scores
if (focusScores != null) { if (focusScores != null) {
startScorePos.setMinMax(0, (focusScores.length - MAX_SCORE_BUTTONS) * ScoreData.getButtonOffset()); startScorePos.setMinMax(0, (focusScores.length - MAX_SCORE_BUTTONS) * ScoreData.getButtonOffset());
startScorePos.update(delta); startScorePos.update(delta);
} }
// mouse hover // scrolling
songScrolling.update(delta); songScrolling.update(delta);
if (isScrollingToFocus) {
float distanceDiff = Math.abs(songScrolling.getPosition() - songScrolling.getTargetPosition());
if (distanceDiff <= buttonOffset / 8f) { // close enough, stop blocking input
songScrolling.scrollToPosition(songScrolling.getTargetPosition());
songScrolling.setSpeedMultiplier(1f);
isScrollingToFocus = false;
}
}
updateDrawnSongPosition(); updateDrawnSongPosition();
// mouse hover
boolean isHover = false; boolean isHover = false;
if (mouseY > headerY && mouseY < footerY) { if (mouseY > headerY && mouseY < footerY) {
BeatmapSetNode node = startNode; BeatmapSetNode node = startNode;
@ -733,12 +746,18 @@ public class SongMenu extends BasicGameState {
@Override @Override
public void mousePressed(int button, int x, int y) { public void mousePressed(int button, int x, int y) {
if (isScrollingToFocus)
return;
songScrolling.pressed(); songScrolling.pressed();
startScorePos.pressed(); startScorePos.pressed();
} }
@Override @Override
public void mouseReleased(int button, int x, int y) { public void mouseReleased(int button, int x, int y) {
if (isScrollingToFocus)
return;
songScrolling.released(); songScrolling.released();
startScorePos.released(); startScorePos.released();
} }
@ -750,7 +769,7 @@ public class SongMenu extends BasicGameState {
return; return;
// block input // block input
if (reloadThread != null || beatmapMenuTimer > -1) if (isInputBlocked())
return; return;
// back // back
@ -869,7 +888,7 @@ public class SongMenu extends BasicGameState {
@Override @Override
public void keyPressed(int key, char c) { public void keyPressed(int key, char c) {
// block input // block input
if ((reloadThread != null && !(key == Input.KEY_ESCAPE || key == Input.KEY_F12)) || beatmapMenuTimer > -1) if ((reloadThread != null && !(key == Input.KEY_ESCAPE || key == Input.KEY_F12)) || beatmapMenuTimer > -1 || isScrollingToFocus)
return; return;
switch (key) { switch (key) {
@ -1022,7 +1041,7 @@ public class SongMenu extends BasicGameState {
@Override @Override
public void mouseDragged(int oldx, int oldy, int newx, int newy) { public void mouseDragged(int oldx, int oldy, int newx, int newy) {
// block input // block input
if (reloadThread != null || beatmapMenuTimer > -1) if (isInputBlocked())
return; return;
int diff = newy - oldy; int diff = newy - oldy;
@ -1056,7 +1075,7 @@ public class SongMenu extends BasicGameState {
} }
// block input // block input
if (reloadThread != null || beatmapMenuTimer > -1) if (isInputBlocked())
return; return;
int shift = (newValue < 0) ? 1 : -1; int shift = (newValue < 0) ? 1 : -1;
@ -1082,7 +1101,9 @@ public class SongMenu extends BasicGameState {
selectOptionsButton.resetHover(); selectOptionsButton.resetHover();
hoverOffset.setTime(0); hoverOffset.setTime(0);
hoverIndex = null; hoverIndex = null;
isScrollingToFocus = false;
songScrolling.released(); songScrolling.released();
songScrolling.setSpeedMultiplier(1f);
startScorePos.setPosition(0); startScorePos.setPosition(0);
beatmapMenuTimer = -1; beatmapMenuTimer = -1;
searchTransitionTimer = SEARCH_TRANSITION_TIME; searchTransitionTimer = SEARCH_TRANSITION_TIME;
@ -1333,10 +1354,9 @@ public class SongMenu extends BasicGameState {
startScorePos.setPosition(0); startScorePos.setPosition(0);
if (oldFocus != null && oldFocus.getBeatmapSet() != node.getBeatmapSet()) { if (oldFocus != null && oldFocus.getBeatmapSet() != node.getBeatmapSet()) {
// Close previous node // close previous node
if (node.index > oldFocus.index) { if (node.index > oldFocus.index) {
float offset = (oldFocus.getBeatmapSet().size() - 1) * buttonOffset; float offset = (oldFocus.getBeatmapSet().size() - 1) * buttonOffset;
//updateSongPos(-offset);
songScrolling.addOffset(-offset); songScrolling.addOffset(-offset);
} }
@ -1354,8 +1374,15 @@ public class SongMenu extends BasicGameState {
} }
// change the focus node // change the focus node
if (changeStartNode || (startNode.index == 0 && startNode.beatmapIndex == -1 && startNode.prev == null)) if (changeStartNode || (startNode.index == 0 && startNode.beatmapIndex == -1 && startNode.prev == null)) {
if (startNode == null || game.getCurrentStateID() != Opsu.STATE_SONGMENU)
songScrolling.setPosition((node.index - 1) * buttonOffset); songScrolling.setPosition((node.index - 1) * buttonOffset);
else {
isScrollingToFocus = true;
songScrolling.setSpeedMultiplier(2f);
songScrolling.released();
}
}
updateDrawnSongPosition(); updateDrawnSongPosition();
@ -1519,6 +1546,14 @@ public class SongMenu extends BasicGameState {
reloadThread.start(); reloadThread.start();
} }
/**
* Returns whether a delayed/animated event is currently blocking user input.
* @return true if blocking input
*/
private boolean isInputBlocked() {
return (reloadThread != null || beatmapMenuTimer > -1 || isScrollingToFocus);
}
/** /**
* Calculates all star ratings for a beatmap set. * Calculates all star ratings for a beatmap set.
* @param beatmapSet the set of beatmaps * @param beatmapSet the set of beatmaps

View File

@ -28,7 +28,7 @@ public class KineticScrolling {
/** The moving averaging constant. */ /** The moving averaging constant. */
private static final float AVG_CONST = 0.2f, ONE_MINUS_AVG_CONST = 1 - AVG_CONST; private static final float AVG_CONST = 0.2f, ONE_MINUS_AVG_CONST = 1 - AVG_CONST;
/** The constant used to determine how fast the target position will be reach. */ /** The constant used to determine how fast the target position will be reached. */
private static final int TIME_CONST = 200; private static final int TIME_CONST = 200;
/** The constant used to determine how much of the velocity will be used to launch to the target. */ /** The constant used to determine how much of the velocity will be used to launch to the target. */
@ -58,12 +58,21 @@ public class KineticScrolling {
/** The moving average of the velocity. */ /** The moving average of the velocity. */
private float avgVelocity; private float avgVelocity;
/** The speed multiplier (divides {@link #TIME_CONST}). */
private float speedMultiplier = 1f;
/** /**
* Returns the current Position. * Returns the current position.
* @return the position * @return the position
*/ */
public float getPosition() { return position; } public float getPosition() { return position; }
/**
* Returns the target position.
* @return the target position
*/
public float getTargetPosition() { return target; }
/** /**
* Updates the scrolling. * Updates the scrolling.
* @param delta the elapsed time since the last update * @param delta the elapsed time since the last update
@ -71,7 +80,7 @@ public class KineticScrolling {
public void update(float delta) { public void update(float delta) {
if (!pressed) { if (!pressed) {
totalDelta += delta; totalDelta += delta;
position = target + (float) (-amplitude * Math.exp(-totalDelta / TIME_CONST)); position = target + (float) (-amplitude * Math.exp(-totalDelta / (TIME_CONST / speedMultiplier)));
} else { } else {
avgVelocity = (ONE_MINUS_AVG_CONST * avgVelocity + AVG_CONST * (deltaPosition * 1000f / delta)); avgVelocity = (ONE_MINUS_AVG_CONST * avgVelocity + AVG_CONST * (deltaPosition * 1000f / delta));
@ -165,4 +174,15 @@ public class KineticScrolling {
this.min = min; this.min = min;
this.max = max; this.max = max;
} }
/**
* Sets the multiplier for how fast the target position will be reached.
* @param multiplier the speed multiplier (e.g. 1f = normal speed, 2f = reaches in half the time)
* @throws IllegalArgumentException if the multiplier is negative or zero
*/
public void setSpeedMultiplier(float multiplier) {
if (multiplier <= 0f)
throw new IllegalArgumentException("Speed multiplier must be above zero.");
this.speedMultiplier = multiplier;
}
} }