Follow-up to #99: replay seeking improvements.
- Added on/off option for replay seeking in the "custom" menu. - Mute sounds while seeking. - Draw a bar on the left of the screen during replays for seeking (instead of just clicking near the top of the screen). Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
495a7e7f8b
commit
2167698740
|
@ -453,7 +453,8 @@ public class Options {
|
|||
val - TimeUnit.MINUTES.toSeconds(TimeUnit.SECONDS.toMinutes(val)));
|
||||
}
|
||||
},
|
||||
ENABLE_THEME_SONG ("Enable Theme Song", "MenuMusic", "Whether to play the theme song upon starting opsu!", true);
|
||||
ENABLE_THEME_SONG ("Enable Theme Song", "MenuMusic", "Whether to play the theme song upon starting opsu!", true),
|
||||
REPLAY_SEEKING ("Replay Seeking", "ReplaySeeking", "Enable a seeking bar on the left side of the screen during replays.", false);
|
||||
|
||||
/** Option name. */
|
||||
private String name;
|
||||
|
@ -958,6 +959,12 @@ public class Options {
|
|||
*/
|
||||
public static boolean isThemeSongEnabled() { return GameOption.ENABLE_THEME_SONG.getBooleanValue(); }
|
||||
|
||||
/**
|
||||
* Returns whether or not replay seeking is enabled.
|
||||
* @return true if enabled
|
||||
*/
|
||||
public static boolean isReplaySeekingEnabled() { return GameOption.REPLAY_SEEKING.getBooleanValue(); }
|
||||
|
||||
/**
|
||||
* Sets the track checkpoint time, if within bounds.
|
||||
* @param time the track position (in ms)
|
||||
|
|
|
@ -59,6 +59,9 @@ public class SoundController {
|
|||
/** Sample volume multiplier, from timing points [0, 1]. */
|
||||
private static float sampleVolumeMultiplier = 1f;
|
||||
|
||||
/** Whether all sounds are muted. */
|
||||
private static boolean isMuted;
|
||||
|
||||
/** The name of the current sound file being loaded. */
|
||||
private static String currentFileName;
|
||||
|
||||
|
@ -261,7 +264,7 @@ public class SoundController {
|
|||
if (clip == null) // clip failed to load properly
|
||||
return;
|
||||
|
||||
if (volume > 0f) {
|
||||
if (volume > 0f && !isMuted) {
|
||||
try {
|
||||
clip.start(volume, listener);
|
||||
} catch (LineUnavailableException e) {
|
||||
|
@ -317,6 +320,12 @@ public class SoundController {
|
|||
playClip(s.getClip(), Options.getHitSoundVolume() * sampleVolumeMultiplier * Options.getMasterVolume(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutes or unmutes all sounds (hit sounds and sound effects).
|
||||
* @param mute true to mute, false to unmute
|
||||
*/
|
||||
public static void mute(boolean mute) { isMuted = mute; }
|
||||
|
||||
/**
|
||||
* Returns the name of the current file being loaded, or null if none.
|
||||
*/
|
||||
|
|
|
@ -220,6 +220,15 @@ public class Game extends BasicGameState {
|
|||
/** Whether the game is currently seeking to a replay position. */
|
||||
private boolean isSeeking;
|
||||
|
||||
/** Music position bar coordinates and dimensions (for replay seeking). */
|
||||
private float musicBarX, musicBarY, musicBarWidth, musicBarHeight;
|
||||
|
||||
/** Music position bar background colors. */
|
||||
private static final Color
|
||||
MUSICBAR_NORMAL = new Color(12, 9, 10, 0.25f),
|
||||
MUSICBAR_HOVER = new Color(12, 9, 10, 0.35f),
|
||||
MUSICBAR_FILL = new Color(255, 255, 255, 0.75f);
|
||||
|
||||
// game-related variables
|
||||
private GameContainer container;
|
||||
private StateBasedGame game;
|
||||
|
@ -245,6 +254,12 @@ public class Game extends BasicGameState {
|
|||
gOffscreen = offscreen.getGraphics();
|
||||
gOffscreen.setBackground(Color.black);
|
||||
|
||||
// initialize music position bar location
|
||||
musicBarX = width * 0.01f;
|
||||
musicBarY = height * 0.05f;
|
||||
musicBarWidth = Math.max(width * 0.005f, 7);
|
||||
musicBarHeight = height * 0.9f;
|
||||
|
||||
// create the associated GameData object
|
||||
data = new GameData(width, height);
|
||||
}
|
||||
|
@ -525,6 +540,18 @@ public class Game extends BasicGameState {
|
|||
if (isReplay || GameMod.AUTO.isActive())
|
||||
playbackSpeed.getButton().draw();
|
||||
|
||||
// draw music position bar (for replay seeking)
|
||||
if (isReplay && Options.isReplaySeekingEnabled()) {
|
||||
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||
g.setColor((musicPositionBarContains(mouseX, mouseY)) ? MUSICBAR_HOVER : MUSICBAR_NORMAL);
|
||||
g.fillRoundRect(musicBarX, musicBarY, musicBarWidth, musicBarHeight, 4);
|
||||
if (!isLeadIn()) {
|
||||
g.setColor(MUSICBAR_FILL);
|
||||
float musicBarPosition = Math.min((float) trackPosition / beatmap.endTime, 1f);
|
||||
g.fillRoundRect(musicBarX, musicBarY, musicBarWidth, musicBarHeight * musicBarPosition, 4);
|
||||
}
|
||||
}
|
||||
|
||||
// returning from pause screen
|
||||
if (pauseTime > -1 && pausedMouseX > -1 && pausedMouseY > -1) {
|
||||
// darken the screen
|
||||
|
@ -613,7 +640,7 @@ public class Game extends BasicGameState {
|
|||
if (replayIndex >= replay.frames.length)
|
||||
updateGame(replayX, replayY, delta, MusicController.getPosition(), lastKeysPressed);
|
||||
|
||||
//TODO probably should to disable sounds then reseek to the new position
|
||||
// seeking to a position earlier than original track position
|
||||
if (isSeeking && replayIndex - 1 >= 1 && replayIndex < replay.frames.length &&
|
||||
trackPosition < replay.frames[replayIndex - 1].getTime()) {
|
||||
replayIndex = 0;
|
||||
|
@ -633,7 +660,6 @@ public class Game extends BasicGameState {
|
|||
timingPointIndex++;
|
||||
}
|
||||
}
|
||||
isSeeking = false;
|
||||
}
|
||||
|
||||
// update and run replay frames
|
||||
|
@ -648,6 +674,12 @@ public class Game extends BasicGameState {
|
|||
}
|
||||
mouseX = replayX;
|
||||
mouseY = replayY;
|
||||
|
||||
// unmute sounds
|
||||
if (isSeeking) {
|
||||
isSeeking = false;
|
||||
SoundController.mute(false);
|
||||
}
|
||||
}
|
||||
|
||||
data.updateDisplays(delta);
|
||||
|
@ -923,9 +955,10 @@ public class Game extends BasicGameState {
|
|||
MusicController.setPitch(GameMod.getSpeedMultiplier() * playbackSpeed.getModifier());
|
||||
}
|
||||
|
||||
// TODO
|
||||
else if (!GameMod.AUTO.isActive() && y < 50) {
|
||||
float pos = (float) x / container.getWidth() * beatmap.endTime;
|
||||
// replay seeking
|
||||
else if (Options.isReplaySeekingEnabled() && !GameMod.AUTO.isActive() && musicPositionBarContains(x, y)) {
|
||||
SoundController.mute(true); // mute sounds while seeking
|
||||
float pos = (y - musicBarY) / musicBarHeight * beatmap.endTime;
|
||||
MusicController.setPosition((int) pos);
|
||||
isSeeking = true;
|
||||
}
|
||||
|
@ -1188,6 +1221,8 @@ public class Game extends BasicGameState {
|
|||
MusicController.setPosition(0);
|
||||
MusicController.setPitch(GameMod.getSpeedMultiplier());
|
||||
MusicController.pause();
|
||||
|
||||
SoundController.mute(false);
|
||||
}
|
||||
|
||||
skipButton.resetHover();
|
||||
|
@ -1753,4 +1788,14 @@ public class Game extends BasicGameState {
|
|||
gameObjects[i].updatePosition();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the coordinates are within the music position bar bounds.
|
||||
* @param cx the x coordinate
|
||||
* @param cy the y coordinate
|
||||
*/
|
||||
private boolean musicPositionBarContains(float cx, float cy) {
|
||||
return ((cx > musicBarX && cx < musicBarX + musicBarWidth) &&
|
||||
(cy > musicBarY && cy < musicBarY + musicBarHeight));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,8 @@ public class OptionsMenu extends BasicGameState {
|
|||
GameOption.FIXED_HP,
|
||||
GameOption.FIXED_AR,
|
||||
GameOption.FIXED_OD,
|
||||
GameOption.CHECKPOINT
|
||||
GameOption.CHECKPOINT,
|
||||
GameOption.REPLAY_SEEKING
|
||||
});
|
||||
|
||||
/** Total number of tabs. */
|
||||
|
|
Loading…
Reference in New Issue
Block a user