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. * */ @@ -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)); } }