diff --git a/res/pause-replay.png b/res/pause-replay.png
new file mode 100644
index 00000000..38c52bb9
Binary files /dev/null and b/res/pause-replay.png differ
diff --git a/res/ranking-back.png b/res/ranking-back.png
deleted file mode 100644
index a79a3c91..00000000
Binary files a/res/ranking-back.png and /dev/null differ
diff --git a/res/ranking-retry.png b/res/ranking-retry.png
deleted file mode 100644
index 8142dd30..00000000
Binary files a/res/ranking-retry.png and /dev/null differ
diff --git a/src/itdelatrisu/opsu/GameData.java b/src/itdelatrisu/opsu/GameData.java
index b6411213..2d9ba80e 100644
--- a/src/itdelatrisu/opsu/GameData.java
+++ b/src/itdelatrisu/opsu/GameData.java
@@ -349,7 +349,6 @@ public class GameData {
comboEnd = 0;
comboBurstIndex = -1;
scoreData = null;
- replay = null;
}
/**
@@ -1229,13 +1228,13 @@ public class GameData {
/**
* Returns a Replay object encapsulating all game data.
- * If a replay already exists, the existing object will be returned
- * (i.e. this will not overwrite existing data).
+ * If a replay already exists and frames is null, the existing object will
+ * be returned.
* @param frames the replay frames
- * @return the Replay object
+ * @return the Replay object, or null if none exists and frames is null
*/
public Replay getReplay(ReplayFrame[] frames) {
- if (replay != null)
+ if (replay != null && frames == null)
return replay;
if (frames == null)
@@ -1261,6 +1260,7 @@ public class GameData {
replay.timestamp = new Date();
replay.frames = frames;
replay.seed = 0; // TODO
+ replay.loaded = true;
return replay;
}
diff --git a/src/itdelatrisu/opsu/GameImage.java b/src/itdelatrisu/opsu/GameImage.java
index 96d6b9d4..f916bd24 100644
--- a/src/itdelatrisu/opsu/GameImage.java
+++ b/src/itdelatrisu/opsu/GameImage.java
@@ -87,6 +87,7 @@ public enum GameImage {
PAUSE_CONTINUE ("pause-continue", "png"),
PAUSE_RETRY ("pause-retry", "png"),
PAUSE_BACK ("pause-back", "png"),
+ PAUSE_REPLAY ("pause-replay", "png"),
PAUSE_OVERLAY ("pause-overlay", "png|jpg") {
@Override
protected Image process_sub(Image img, int w, int h) {
@@ -414,8 +415,6 @@ public enum GameImage {
return MUSIC_PLAY.process_sub(img, w, h);
}
},
- RANKING_RETRY ("ranking-retry", "png", false, false),
- RANKING_EXIT ("ranking-back", "png", false, false),
DOWNLOADS ("downloads", "png", false, false) {
@Override
protected Image process_sub(Image img, int w, int h) {
diff --git a/src/itdelatrisu/opsu/replay/Replay.java b/src/itdelatrisu/opsu/replay/Replay.java
index 1639512d..73d41a73 100644
--- a/src/itdelatrisu/opsu/replay/Replay.java
+++ b/src/itdelatrisu/opsu/replay/Replay.java
@@ -51,6 +51,9 @@ public class Replay {
/** The associated file. */
private File file;
+ /** Whether or not the replay data has been loaded from the file. */
+ public boolean loaded = false;
+
/** The game mode. */
public byte mode;
@@ -116,11 +119,15 @@ public class Replay {
* Loads the replay data.
*/
public void load() {
+ if (loaded)
+ return;
+
try {
OsuReader reader = new OsuReader(file);
loadHeader(reader);
loadData(reader);
reader.close();
+ loaded = true;
} catch (IOException e) {
ErrorHandler.error("Could not load replay data.", e, true);
}
diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java
index 86f67047..a78bf298 100644
--- a/src/itdelatrisu/opsu/states/Game.java
+++ b/src/itdelatrisu/opsu/states/Game.java
@@ -74,6 +74,8 @@ public class Game extends BasicGameState {
NEW,
/** Manual retry. */
MANUAL,
+ /** Replay. */
+ REPLAY,
/** Health is zero: no-continue/force restart. */
LOSE;
}
@@ -844,10 +846,11 @@ public class Game extends BasicGameState {
loadImages();
setMapModifiers();
retries = 0;
- } else {
+ } else if (restart == Restart.MANUAL) {
// retry
retries++;
- }
+ } else if (restart == Restart.REPLAY)
+ retries = 0;
// reset game data
resetGameData();
@@ -937,7 +940,7 @@ public class Game extends BasicGameState {
// sleep execution
try {
- Thread.sleep(0, 512000);
+ Thread.sleep(0, 256000);
} catch (InterruptedException e) {}
}
}
@@ -1159,16 +1162,21 @@ public class Game extends BasicGameState {
}
/**
- * Sets a replay to view.
+ * Sets a replay to view, or resets the replay if null.
* @param replay the replay
*/
public void setReplay(Replay replay) {
- if (replay.frames == null) {
- ErrorHandler.error("Invalid replay.", null, false);
- return;
+ if (replay == null) {
+ this.isReplay = false;
+ this.replay = null;
+ } else {
+ if (replay.frames == null) {
+ ErrorHandler.error("Invalid replay.", null, false);
+ return;
+ }
+ this.isReplay = true;
+ this.replay = replay;
}
- this.isReplay = true;
- this.replay = replay;
}
/**
diff --git a/src/itdelatrisu/opsu/states/GameRanking.java b/src/itdelatrisu/opsu/states/GameRanking.java
index 66462026..f7842b76 100644
--- a/src/itdelatrisu/opsu/states/GameRanking.java
+++ b/src/itdelatrisu/opsu/states/GameRanking.java
@@ -29,6 +29,7 @@ import itdelatrisu.opsu.Utils;
import itdelatrisu.opsu.audio.MusicController;
import itdelatrisu.opsu.audio.SoundController;
import itdelatrisu.opsu.audio.SoundEffect;
+import itdelatrisu.opsu.replay.Replay;
import org.lwjgl.opengl.Display;
import org.newdawn.slick.Color;
@@ -46,7 +47,7 @@ import org.newdawn.slick.state.transition.FadeOutTransition;
* "Game Ranking" (score card) state.
*
* - [Retry] - restart game (return to game state)
- *
- [Exit] - return to main menu state
+ *
- [Replay] - watch replay (return to game state)
*
- [Back] - return to song menu state
*
*/
@@ -54,8 +55,11 @@ public class GameRanking extends BasicGameState {
/** Associated GameData object. */
private GameData data;
- /** "Retry" and "Exit" buttons. */
- private MenuButton retryButton, exitButton;
+ /** "Retry" and "Replay" buttons. */
+ private MenuButton retryButton, replayButton;
+
+ /** Button coordinates. */
+ private float retryY, replayY;
// game-related variables
private GameContainer container;
@@ -78,18 +82,14 @@ public class GameRanking extends BasicGameState {
int height = container.getHeight();
// buttons
- Image retry = GameImage.RANKING_RETRY.getImage();
- Image exit = GameImage.RANKING_EXIT.getImage();
- retryButton = new MenuButton(retry,
- width - (retry.getWidth() / 2f),
- (height * 0.97f) - (exit.getHeight() * 1.5f)
- );
- exitButton = new MenuButton(exit,
- width - (exit.getWidth() / 2f),
- (height * 0.97f) - (exit.getHeight() / 2f)
- );
- retryButton.setHoverFade(0.6f);
- exitButton.setHoverFade(0.6f);
+ Image retry = GameImage.PAUSE_RETRY.getImage();
+ Image replay = GameImage.PAUSE_REPLAY.getImage();
+ replayY = (height * 0.985f) - replay.getHeight() / 2f;
+ retryY = replayY - (replay.getHeight() / 2f) - (retry.getHeight() / 1.975f);
+ retryButton = new MenuButton(retry, width - (retry.getWidth() / 2f), retryY);
+ replayButton = new MenuButton(replay, width - (replay.getWidth() / 2f), replayY);
+ retryButton.setHoverFade();
+ replayButton.setHoverFade();
}
@Override
@@ -108,10 +108,9 @@ public class GameRanking extends BasicGameState {
data.drawRankingElements(g, osu);
// buttons
- if (data.isGameplay()) {
+ replayButton.draw();
+ if (data.isGameplay())
retryButton.draw();
- exitButton.draw();
- }
UI.getBackButton().draw();
UI.draw(g);
@@ -122,10 +121,10 @@ public class GameRanking extends BasicGameState {
throws SlickException {
UI.update(delta);
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
- if (data.isGameplay()) {
+ replayButton.hoverUpdate(delta, mouseX, mouseY);
+ if (data.isGameplay())
retryButton.hoverUpdate(delta, mouseX, mouseY);
- exitButton.hoverUpdate(delta, mouseX, mouseY);
- } else
+ else
MusicController.loopTrackIfEnded(true);
UI.getBackButton().hoverUpdate(delta, mouseX, mouseY);
}
@@ -157,27 +156,38 @@ public class GameRanking extends BasicGameState {
if (button == Input.MOUSE_MIDDLE_BUTTON)
return;
- if (data.isGameplay()) {
- if (retryButton.contains(x, y)) {
- OsuFile osu = MusicController.getOsuFile();
- Display.setTitle(String.format("%s - %s", game.getTitle(), osu.toString()));
- ((Game) game.getState(Opsu.STATE_GAME)).setRestart(Game.Restart.MANUAL);
- SoundController.playSound(SoundEffect.MENUHIT);
- game.enterState(Opsu.STATE_GAME, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
- return;
- } else if (exitButton.contains(x, y)) {
- SoundController.playSound(SoundEffect.MENUBACK);
- ((MainMenu) game.getState(Opsu.STATE_MAINMENU)).reset();
- ((SongMenu) game.getState(Opsu.STATE_SONGMENU)).resetGameDataOnLoad();
- UI.resetCursor();
- game.enterState(Opsu.STATE_MAINMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
- return;
- }
- }
+ // back to menu
if (UI.getBackButton().contains(x, y)) {
returnToSongMenu();
return;
}
+
+ // replay
+ boolean returnToGame = false;
+ if (replayButton.contains(x, y)) {
+ Replay r = data.getReplay(null);
+ if (r != null) {
+ r.load();
+ ((Game) game.getState(Opsu.STATE_GAME)).setReplay(r);
+ ((Game) game.getState(Opsu.STATE_GAME)).setRestart(Game.Restart.REPLAY);
+ returnToGame = true;
+ }
+ }
+
+ // retry
+ else if (data.isGameplay() && retryButton.contains(x, y)) {
+ ((Game) game.getState(Opsu.STATE_GAME)).setReplay(null);
+ ((Game) game.getState(Opsu.STATE_GAME)).setRestart(Game.Restart.MANUAL);
+ returnToGame = true;
+ }
+
+ if (returnToGame) {
+ OsuFile osu = MusicController.getOsuFile();
+ Display.setTitle(String.format("%s - %s", game.getTitle(), osu.toString()));
+ SoundController.playSound(SoundEffect.MENUHIT);
+ game.enterState(Opsu.STATE_GAME, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
+ return;
+ }
}
@Override
@@ -188,11 +198,13 @@ public class GameRanking extends BasicGameState {
if (!data.isGameplay()) {
if (!MusicController.isTrackDimmed())
MusicController.toggleTrackDimmed(0.5f);
+ replayButton.setY(retryY);
} else {
SoundController.playSound(SoundEffect.APPLAUSE);
retryButton.resetHover();
- exitButton.resetHover();
+ replayButton.setY(replayY);
}
+ replayButton.resetHover();
}
@Override
diff --git a/src/itdelatrisu/opsu/states/SongMenu.java b/src/itdelatrisu/opsu/states/SongMenu.java
index c83c25c3..bc789141 100644
--- a/src/itdelatrisu/opsu/states/SongMenu.java
+++ b/src/itdelatrisu/opsu/states/SongMenu.java
@@ -1298,7 +1298,9 @@ public class SongMenu extends BasicGameState {
HitSound.setDefaultSampleSet(osu.sampleSet);
MultiClip.destroyExtraClips();
- ((Game) game.getState(Opsu.STATE_GAME)).setRestart(Game.Restart.NEW);
+ Game gameState = (Game) game.getState(Opsu.STATE_GAME);
+ gameState.setRestart(Game.Restart.NEW);
+ gameState.setReplay(null);
game.enterState(Opsu.STATE_GAME, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
}
}