diff --git a/src/itdelatrisu/opsu/Opsu.java b/src/itdelatrisu/opsu/Opsu.java index ab738061..131178b8 100644 --- a/src/itdelatrisu/opsu/Opsu.java +++ b/src/itdelatrisu/opsu/Opsu.java @@ -89,7 +89,7 @@ public class Opsu extends StateBasedGame { //addState(new MainMenu(STATE_MAINMENU)); //addState(new ButtonMenu(STATE_BUTTONMENU)); //addState(new SongMenu(STATE_SONGMENU)); - addState(new Game(STATE_GAME)); + //addState(new Game(STATE_GAME)); addState(new GamePauseMenu(STATE_GAMEPAUSEMENU)); //addState(new GameRanking(STATE_GAMERANKING)); //addState(new OptionsMenu(STATE_OPTIONSMENU)); diff --git a/src/itdelatrisu/opsu/objects/Circle.java b/src/itdelatrisu/opsu/objects/Circle.java index 7c0d5756..56d393b2 100644 --- a/src/itdelatrisu/opsu/objects/Circle.java +++ b/src/itdelatrisu/opsu/objects/Circle.java @@ -64,10 +64,9 @@ public class Circle extends GameObject { /** * Initializes the Circle data type with map modifiers, images, and dimensions. - * @param container the game container * @param circleDiameter the circle diameter */ - public static void init(GameContainer container, float circleDiameter) { + public static void init(float circleDiameter) { diameter = circleDiameter * HitObject.getXMultiplier(); // convert from Osupixels (640x480) int diameterInt = (int) diameter; GameImage.HITCIRCLE.setImage(GameImage.HITCIRCLE.getImage().getScaledCopy(diameterInt, diameterInt)); diff --git a/src/itdelatrisu/opsu/objects/Slider.java b/src/itdelatrisu/opsu/objects/Slider.java index f8ad3441..6ffaee19 100644 --- a/src/itdelatrisu/opsu/objects/Slider.java +++ b/src/itdelatrisu/opsu/objects/Slider.java @@ -37,6 +37,7 @@ import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Image; import yugecin.opsudance.Dancer; +import yugecin.opsudance.core.DisplayContainer; /** * Data type representing a slider object. @@ -127,13 +128,12 @@ public class Slider extends GameObject { /** * Initializes the Slider data type with images and dimensions. - * @param container the game container * @param circleDiameter the circle diameter * @param beatmap the associated beatmap */ - public static void init(GameContainer container, float circleDiameter, Beatmap beatmap) { - containerWidth = container.getWidth(); - containerHeight = container.getHeight(); + public static void init(DisplayContainer displayContainer, float circleDiameter, Beatmap beatmap) { + containerWidth = displayContainer.width; + containerHeight = displayContainer.height; diameter = circleDiameter * HitObject.getXMultiplier(); // convert from Osupixels (640x480) int diameterInt = (int) diameter; diff --git a/src/itdelatrisu/opsu/objects/Spinner.java b/src/itdelatrisu/opsu/objects/Spinner.java index 551c80f8..bb3ed811 100644 --- a/src/itdelatrisu/opsu/objects/Spinner.java +++ b/src/itdelatrisu/opsu/objects/Spinner.java @@ -35,6 +35,7 @@ import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Image; +import yugecin.opsudance.core.DisplayContainer; /** * Data type representing a spinner object. @@ -109,12 +110,11 @@ public class Spinner extends GameObject { /** * Initializes the Spinner data type with images and dimensions. - * @param container the game container * @param difficulty the map's overall difficulty value */ - public static void init(GameContainer container, float difficulty) { - width = container.getWidth(); - height = container.getHeight(); + public static void init(DisplayContainer displayContainer, float difficulty) { + width = displayContainer.width; + height = displayContainer.height; overallDifficulty = difficulty; } diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index 49bb6c95..1dd3c7dd 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -18,11 +18,9 @@ package itdelatrisu.opsu.states; -import itdelatrisu.opsu.ErrorHandler; import itdelatrisu.opsu.GameData; import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.GameMod; -import itdelatrisu.opsu.Opsu; import itdelatrisu.opsu.Options; import itdelatrisu.opsu.ScoreData; import itdelatrisu.opsu.Utils; @@ -59,26 +57,28 @@ import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.Display; import org.newdawn.slick.Animation; import org.newdawn.slick.Color; -import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Image; import org.newdawn.slick.Input; import org.newdawn.slick.SlickException; -import org.newdawn.slick.state.BasicGameState; -import org.newdawn.slick.state.StateBasedGame; -import org.newdawn.slick.state.transition.DelayedFadeOutTransition; -import org.newdawn.slick.state.transition.EasedFadeOutTransition; -import org.newdawn.slick.state.transition.EmptyTransition; -import org.newdawn.slick.state.transition.FadeInTransition; +import org.newdawn.slick.util.Log; import yugecin.opsudance.*; +import yugecin.opsudance.core.DisplayContainer; +import yugecin.opsudance.core.inject.InstanceContainer; +import yugecin.opsudance.core.state.ComplexOpsuState; +import yugecin.opsudance.events.BubbleNotificationEvent; import yugecin.opsudance.objects.curves.FakeCombinedCurve; import yugecin.opsudance.sbv2.MoveStoryboard; -import yugecin.opsudance.ui.SBOverlay; +import yugecin.opsudance.ui.OptionsOverlay; +import yugecin.opsudance.ui.StoryboardOverlay; /** * "Game" state. */ -public class Game extends BasicGameState { +public class Game extends ComplexOpsuState { + + private final InstanceContainer instanceContainer; + public static boolean isInGame; // TODO delete this when #79 is fixed /** Game restart states. */ public enum Restart { @@ -307,101 +307,95 @@ public class Game extends BasicGameState { 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; - private Input input; - private final int state; - private final Cursor mirrorCursor; - private MoveStoryboard msb; - private SBOverlay sbOverlay; + private final MoveStoryboard moveStoryboardOverlay; + private final StoryboardOverlay storyboardOverlay; + private final OptionsOverlay optionsOverlay; private FakeCombinedCurve knorkesliders; private boolean skippedToCheckpoint; - public Game(int state) { - this.state = state; + public Game(DisplayContainer displayContainer, InstanceContainer instanceContainer) { + super(displayContainer); + this.instanceContainer = instanceContainer; mirrorCursor = new Cursor(true); - } - - public void loadCheckpoint(int checkpoint) { - try { - restart = Restart.MANUAL; - checkpointLoaded = true; - skippedToCheckpoint = true; - enter(container, game); - if (isLeadIn()) { - leadInTime = 0; - epiImgTime = 0; - MusicController.resume(); - } - // skip to checkpoint - MusicController.setPosition(checkpoint); - while (objectIndex < gameObjects.length && beatmap.objects[objectIndex].getTime() <= checkpoint) { - objectIndex++; - } - if (objectIndex > 0) { - objectIndex--; - } - if (Options.isMergingSliders()) { - int obj = objectIndex; - while (obj < gameObjects.length) { - if (gameObjects[obj] instanceof Slider) { - slidercurveFrom = slidercurveTo = ((Slider) gameObjects[obj]).baseSliderFrom; - break; - } - obj++; - } - spliceSliderCurve(-1, -1); - } - Dancer.instance.setObjectIndex(objectIndex); - sbOverlay.updateIndex(objectIndex); - lastReplayTime = beatmap.objects[objectIndex].getTime(); - } catch (SlickException e) { - e.printStackTrace(); - } + this.moveStoryboardOverlay = new MoveStoryboard(displayContainer); + this.optionsOverlay = new OptionsOverlay(displayContainer, OptionsMenu.storyboardOptions, 0); + this.storyboardOverlay = new StoryboardOverlay(displayContainer, moveStoryboardOverlay, optionsOverlay, this); + storyboardOverlay.show(); + moveStoryboardOverlay.show(); + optionsOverlay.setListener(storyboardOverlay); } @Override - public void init(GameContainer container, StateBasedGame game) - throws SlickException { - this.msb = new MoveStoryboard(container); - this.sbOverlay = new SBOverlay(this, msb, container); - this.container = container; - this.game = game; - input = container.getInput(); - - int width = container.getWidth(); - int height = container.getHeight(); - + public void revalidate() { // create offscreen graphics - offscreen = new Image(width, height); - gOffscreen = offscreen.getGraphics(); - gOffscreen.setBackground(Color.black); + try { + offscreen = new Image(displayContainer.width, displayContainer.height); + gOffscreen = offscreen.getGraphics(); + gOffscreen.setBackground(Color.black); + } catch (SlickException e) { + Log.error("could not create offscreen graphics", e); + displayContainer.eventBus.post(new BubbleNotificationEvent("Exception while creating offscreen graphics. See logfile for details.", BubbleNotificationEvent.COMMONCOLOR_RED)); + } // initialize music position bar location - musicBarX = width * 0.01f; - musicBarY = height * 0.05f; - musicBarWidth = Math.max(width * 0.005f, 7); - musicBarHeight = height * 0.9f; + musicBarX = displayContainer.width * 0.01f; + musicBarY = displayContainer.height * 0.05f; + musicBarWidth = Math.max(displayContainer.width * 0.005f, 7); + musicBarHeight = displayContainer.height * 0.9f; // initialize scoreboard star stream - scoreboardStarStream = new StarStream(0, height * 2f / 3f, width / 4, 0, 0); - scoreboardStarStream.setPositionSpread(height / 20f); + scoreboardStarStream = new StarStream(0, displayContainer.height * 2f / 3f, displayContainer.width / 4, 0, 0); + scoreboardStarStream.setPositionSpread(displayContainer.height / 20f); scoreboardStarStream.setDirectionSpread(10f); scoreboardStarStream.setDurationSpread(700, 100); // create the associated GameData object - data = new GameData(width, height); + data = new GameData(displayContainer.width, displayContainer.height); + } + + + public void loadCheckpoint(int checkpoint) { + restart = Restart.MANUAL; + checkpointLoaded = true; + skippedToCheckpoint = true; + enter(); + if (isLeadIn()) { + leadInTime = 0; + epiImgTime = 0; + MusicController.resume(); + } + // skip to checkpoint + MusicController.setPosition(checkpoint); + while (objectIndex < gameObjects.length && beatmap.objects[objectIndex].getTime() <= checkpoint) { + objectIndex++; + } + if (objectIndex > 0) { + objectIndex--; + } + if (Options.isMergingSliders()) { + int obj = objectIndex; + while (obj < gameObjects.length) { + if (gameObjects[obj] instanceof Slider) { + slidercurveFrom = slidercurveTo = ((Slider) gameObjects[obj]).baseSliderFrom; + break; + } + obj++; + } + spliceSliderCurve(-1, -1); + } + Dancer.instance.setObjectIndex(objectIndex); + storyboardOverlay.updateIndex(objectIndex); + lastReplayTime = beatmap.objects[objectIndex].getTime(); } @Override - public void render(GameContainer container, StateBasedGame game, Graphics g) - throws SlickException { - int width = container.getWidth(); - int height = container.getHeight(); + public void render(Graphics g) { + int width = displayContainer.width; + int height = displayContainer.height; + int trackPosition = MusicController.getPosition(); if (isLeadIn()) { trackPosition -= leadInTime - currentMapMusicOffset - Options.getMusicOffset(); @@ -475,7 +469,7 @@ public class Game extends BasicGameState { } } - float[] sbPosition = sbOverlay.getPoint(trackPosition); + float[] sbPosition = moveStoryboardOverlay.getPoint(trackPosition); if (sbPosition != null) { autoPoint.x = sbPosition[0]; autoPoint.y = sbPosition[1]; @@ -510,8 +504,8 @@ public class Game extends BasicGameState { mouseX = replayX; mouseY = replayY; } else { - mouseX = input.getMouseX(); - mouseY = input.getMouseY(); + mouseX = displayContainer.mouseX; + mouseY = displayContainer.mouseY; } int alphaRadius = flashlightRadius * 256 / 215; int alphaX = mouseX - alphaRadius / 2; @@ -686,7 +680,7 @@ public class Game extends BasicGameState { float animation = AnimationEquation.IN_OUT_QUAD.calc( Utils.clamp((trackPosition - lastRankUpdateTime) / SCOREBOARD_ANIMATION_TIME, 0f, 1f) ); - int scoreboardPosition = 2 * container.getHeight() / 3; + int scoreboardPosition = 2 * displayContainer.height / 3; // draw star stream behind the scores scoreboardStarStream.draw(); @@ -727,8 +721,7 @@ public class Game extends BasicGameState { // 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.setColor((musicPositionBarContains(displayContainer.mouseX, displayContainer.mouseY)) ? MUSICBAR_HOVER : MUSICBAR_NORMAL); g.fillRoundRect(musicBarX, musicBarY, musicBarWidth, musicBarHeight, 4); if (!isLeadIn()) { g.setColor(MUSICBAR_FILL); @@ -770,24 +763,27 @@ public class Game extends BasicGameState { else UI.draw(g); - sbOverlay.render(container, g); - if (!Options.isHideWM()) { Fonts.SMALL.drawString(0.3f, 0.3f, "opsu!dance " + Updater.get().getCurrentVersion() + " by robin_be | https://github.com/yugecin/opsu-dance"); } + + super.render(g); } @Override - public void update(GameContainer container, StateBasedGame game, int delta) - throws SlickException { + public void preRenderUpdate() { + super.preRenderUpdate(); + + int delta = displayContainer.renderDelta; + UI.update(delta); Pippi.update(delta); if (epiImgTime > 0) { epiImgTime -= delta; } yugecin.opsudance.spinners.Spinner.update(delta); - int mouseX = input.getMouseX(), mouseY = input.getMouseY(); - sbOverlay.update(delta, mouseX, mouseY); + int mouseX = displayContainer.mouseX; + int mouseY = displayContainer.mouseY; skipButton.hoverUpdate(delta, mouseX, mouseY); if (isReplay || GameMod.AUTO.isActive()) playbackSpeed.getButton().hoverUpdate(delta, mouseX, mouseY); @@ -805,8 +801,8 @@ public class Game extends BasicGameState { } // focus lost: go back to pause screen - else if (!container.hasFocus()) { - game.enterState(Opsu.STATE_GAMEPAUSEMENU); + else if (!Display.isActive()) { + // TODO d displayContainer.switchState(GamePauseMenu.class); pausePulse = 0f; } @@ -918,10 +914,13 @@ public class Game extends BasicGameState { // game finished: change state after timer expires if (gameFinished && !gameFinishedTimer.update(delta)) { - if (checkpointLoaded) // if checkpoint used, skip ranking screen - game.closeRequested(); - else // go to ranking screen - game.enterState(Opsu.STATE_GAMERANKING, new EasedFadeOutTransition(), new FadeInTransition()); + if (checkpointLoaded) { + // if checkpoint used, skip ranking screen + onCloseRequest(); + } else { + // go to ranking screen + displayContainer.switchState(GameRanking.class); + } } } @@ -949,7 +948,7 @@ public class Game extends BasicGameState { // save score and replay if (!checkpointLoaded) { boolean unranked = (GameMod.AUTO.isActive() || GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive()); - ((GameRanking) game.getState(Opsu.STATE_GAMERANKING)).setGameData(data); + instanceContainer.provide(GameRanking.class).setGameData(data); if (isReplay) data.setReplay(replay); else if (replayFrames != null) { @@ -1027,14 +1026,15 @@ public class Game extends BasicGameState { } // pause game if focus lost - if (!container.hasFocus() && !GameMod.AUTO.isActive() && !isReplay) { + if (!Display.isActive() && !GameMod.AUTO.isActive() && !isReplay) { if (pauseTime < 0) { pausedMousePosition = new Vec2f(mouseX, mouseY); pausePulse = 0f; } - if (MusicController.isPlaying() || isLeadIn()) + if (MusicController.isPlaying() || isLeadIn()) { pauseTime = trackPosition; - game.enterState(Opsu.STATE_GAMEPAUSEMENU, new EmptyTransition(), new FadeInTransition()); + } + // TODO d displayContainer.switchState(GamePauseMenu.class); } // drain health @@ -1058,13 +1058,10 @@ public class Game extends BasicGameState { failTrackTime = MusicController.getPosition(); MusicController.fadeOut(MUSIC_FADEOUT_TIME); MusicController.pitchFadeOut(MUSIC_FADEOUT_TIME); - rotations = new IdentityHashMap(); + rotations = new IdentityHashMap<>(); SoundController.playSound(SoundEffect.FAIL); - // fade to pause menu - game.enterState(Opsu.STATE_GAMEPAUSEMENU, - new DelayedFadeOutTransition(Color.black, MUSIC_FADEOUT_TIME, MUSIC_FADEOUT_TIME - LOSE_FADEOUT_TIME), - new FadeInTransition()); + // TODO d displayContainer.switchState(GamePauseMenu.class, FadeOutTransitionState.class, MUSIC_FADEOUT_TIME - LOSE_FADEOUT_TIME, FadeInTransitionState.class, 300); } } } @@ -1088,7 +1085,7 @@ public class Game extends BasicGameState { if (gameObjects[objectIndex].update(overlap, delta, mouseX, mouseY, keyPressed, trackPosition)) { skippedObject = true; objectIndex++; // done, so increment object index - sbOverlay.updateIndex(objectIndex); + storyboardOverlay.updateIndex(objectIndex); if (objectIndex >= mirrorTo) { Options.setMirror(false); } @@ -1099,20 +1096,25 @@ public class Game extends BasicGameState { } @Override - public int getID() { return state; } + public boolean onCloseRequest() { + instanceContainer.provide(SongMenu.class).resetGameDataOnLoad(); + displayContainer.switchState(SongMenu.class); + return false; + } @Override - public void keyPressed(int key, char c) { - if (gameFinished) - return; + public boolean keyPressed(int key, char c) { + if (super.keyPressed(key, c)) { + return true; + } - if (sbOverlay.keyPressed(key, c)) { - return; + if (gameFinished) { + return true; } int trackPosition = MusicController.getPosition(); - int mouseX = input.getMouseX(); - int mouseY = input.getMouseY(); + int mouseX = displayContainer.mouseX; + int mouseY = displayContainer.mouseY; // game keys if (!Keyboard.isRepeatEvent()) { @@ -1129,7 +1131,7 @@ public class Game extends BasicGameState { case Input.KEY_ESCAPE: // "auto" mod or watching replay: go back to song menu if (GameMod.AUTO.isActive() || isReplay) { - game.closeRequested(); + onCloseRequest(); break; } @@ -1138,9 +1140,10 @@ public class Game extends BasicGameState { pausedMousePosition = new Vec2f(mouseX, mouseY); pausePulse = 0f; } - if (MusicController.isPlaying() || isLeadIn()) + if (MusicController.isPlaying() || isLeadIn()) { pauseTime = trackPosition; - game.enterState(Opsu.STATE_GAMEPAUSEMENU, new EmptyTransition(), new FadeInTransition()); + } + // TODO d displayContainer.switchStateNow(GamePauseMenu.class); break; case Input.KEY_SPACE: // skip intro @@ -1148,23 +1151,21 @@ public class Game extends BasicGameState { break; case Input.KEY_R: // restart - if (input.isKeyDown(Input.KEY_RCONTROL) || input.isKeyDown(Input.KEY_LCONTROL)) { - try { - if (trackPosition < beatmap.objects[0].getTime()) - retries--; // don't count this retry (cancel out later increment) - restart = Restart.MANUAL; - enter(container, game); - skipIntro(); - } catch (SlickException e) { - ErrorHandler.error("Failed to restart game.", e, false); + if (displayContainer.input.isKeyDown(Input.KEY_RCONTROL) || displayContainer.input.isKeyDown(Input.KEY_LCONTROL)) { + if (trackPosition < beatmap.objects[0].getTime()) { + retries--; // don't count this retry (cancel out later increment) } + restart = Restart.MANUAL; + enter(); + skipIntro(); } break; case Input.KEY_S: // save checkpoint - if (input.isKeyDown(Input.KEY_RCONTROL) || input.isKeyDown(Input.KEY_LCONTROL)) { - if (isLeadIn()) + if (displayContainer.input.isKeyDown(Input.KEY_RCONTROL) || displayContainer.input.isKeyDown(Input.KEY_LCONTROL)) { + if (isLeadIn()) { break; + } int position = (pauseTime > -1) ? pauseTime : trackPosition; if (Options.setCheckpoint(position / 1000)) { @@ -1175,7 +1176,7 @@ public class Game extends BasicGameState { break; case Input.KEY_L: // load checkpoint - if (input.isKeyDown(Input.KEY_RCONTROL) || input.isKeyDown(Input.KEY_LCONTROL)) { + if (displayContainer.input.isKeyDown(Input.KEY_RCONTROL) || displayContainer.input.isKeyDown(Input.KEY_LCONTROL)) { int checkpoint = Options.getCheckpoint(); if (checkpoint == 0 || checkpoint > beatmap.endTime) break; // invalid checkpoint @@ -1197,16 +1198,6 @@ public class Game extends BasicGameState { case Input.KEY_DOWN: UI.changeVolume(-1); break; - case Input.KEY_F7: - // TODO d - //Options.setNextFPS(container); - break; - case Input.KEY_F10: - Options.toggleMouseDisabled(); - break; - case Input.KEY_F12: - Utils.takeScreenShot(); - break; case Input.KEY_TAB: if (!Options.isHideUI()) { scoreboardVisible = !scoreboardVisible; @@ -1243,29 +1234,33 @@ public class Game extends BasicGameState { currentMapMusicOffset -= 5; UI.sendBarNotification("Current map offset: " + currentMapMusicOffset); } + + return true; } @Override - public void mouseDragged(int oldx, int oldy, int newx, int newy) { - if (sbOverlay.mouseDragged(oldx, oldy, newx, newy)) { - //noinspection UnnecessaryReturnStatement - return; + public boolean mouseDragged(int oldx, int oldy, int newx, int newy) { + if (super.mouseDragged(oldx, oldy, newx, newy)) { + return true; } + return true; } @Override - public void mousePressed(int button, int x, int y) { - if (gameFinished) - return; + public boolean mousePressed(int button, int x, int y) { + if (super.mousePressed(button, x, y)) { + return true; + } - if (sbOverlay.mousePressed(button, x, y)) { - return; + if (gameFinished) { + return true; } // watching replay if (isReplay || GameMod.AUTO.isActive()) { - if (button == Input.MOUSE_MIDDLE_BUTTON) - return; + if (button == Input.MOUSE_MIDDLE_BUTTON) { + return true; + } // skip button if (skipButton.contains(x, y)) @@ -1284,11 +1279,12 @@ public class Game extends BasicGameState { MusicController.setPosition((int) pos); isSeeking = true; } - return; + return true; } - if (Options.isMouseDisabled()) - return; + if (Options.isMouseDisabled()) { + return true; + } // mouse wheel: pause the game if (button == Input.MOUSE_MIDDLE_BUTTON && !Options.isMouseWheelDisabled()) { @@ -1297,10 +1293,11 @@ public class Game extends BasicGameState { pausedMousePosition = new Vec2f(x, y); pausePulse = 0f; } - if (MusicController.isPlaying() || isLeadIn()) + if (MusicController.isPlaying() || isLeadIn()) { pauseTime = trackPosition; - game.enterState(Opsu.STATE_GAMEPAUSEMENU, new EmptyTransition(), new FadeInTransition()); - return; + } + // TODO d displayContainer.switchStateNow(GamePauseMenu.class); + return true; } // game keys @@ -1311,6 +1308,8 @@ public class Game extends BasicGameState { keys = ReplayFrame.KEY_M2; if (keys != ReplayFrame.KEY_NONE) gameKeyPressed(keys, x, y, MusicController.getPosition()); + + return true; } /** @@ -1353,19 +1352,22 @@ public class Game extends BasicGameState { } @Override - public void mouseReleased(int button, int x, int y) { - if (gameFinished) - return; - - if (sbOverlay.mouseReleased(button, x, y)) { - return; + public boolean mouseReleased(int button, int x, int y) { + if (super.mouseReleased(button, x, y)) { + return true; } - if (Options.isMouseDisabled()) - return; + if (gameFinished) { + return true; + } - if (button == Input.MOUSE_MIDDLE_BUTTON) - return; + if (Options.isMouseDisabled()) { + return true; + } + + if (button == Input.MOUSE_MIDDLE_BUTTON) { + return true; + } int keys = ReplayFrame.KEY_NONE; if (button == Input.MOUSE_LEFT_BUTTON) @@ -1374,12 +1376,19 @@ public class Game extends BasicGameState { keys = ReplayFrame.KEY_M2; if (keys != ReplayFrame.KEY_NONE) gameKeyReleased(keys, x, y, MusicController.getPosition()); + + return true; } @Override - public void keyReleased(int key, char c) { - if (gameFinished) - return; + public boolean keyReleased(int key, char c) { + if (super.keyReleased(key, c)) { + return true; + } + + if (gameFinished) { + return true; + } int keys = ReplayFrame.KEY_NONE; if (key == Options.getGameKeyLeft()) @@ -1387,7 +1396,9 @@ public class Game extends BasicGameState { else if (key == Options.getGameKeyRight()) keys = ReplayFrame.KEY_K2; if (keys != ReplayFrame.KEY_NONE) - gameKeyReleased(keys, input.getMouseX(), input.getMouseY(), MusicController.getPosition()); + gameKeyReleased(keys, displayContainer.input.getMouseX(), displayContainer.input.getMouseY(), MusicController.getPosition()); + + return true; } /** @@ -1405,26 +1416,41 @@ public class Game extends BasicGameState { } @Override - public void mouseWheelMoved(int newValue) { - if (sbOverlay.mouseWheelMoved(newValue)) { - return; + public boolean mouseWheelMoved(int newValue) { + if (super.mouseWheelMoved(newValue)) { + return true; + } + + if (Options.isMouseWheelDisabled()) { + return true; } - if (Options.isMouseWheelDisabled()) - return; UI.changeVolume((newValue < 0) ? -1 : 1); + return true; } @Override - public void enter(GameContainer container, StateBasedGame game) - throws SlickException { + public void enter() { + super.enter(); + + overlays.clear(); + if (Options.isEnableSB()) { + overlays.add(optionsOverlay); + overlays.add(moveStoryboardOverlay); + overlays.add(storyboardOverlay); + storyboardOverlay.onEnter(); + optionsOverlay.revalidate(); + } + isInGame = true; if (!skippedToCheckpoint) { UI.enter(); } - if (beatmap == null || beatmap.objects == null) - throw new RuntimeException("Running game with no beatmap loaded."); + if (beatmap == null || beatmap.objects == null) { + displayContainer.eventBus.post(new BubbleNotificationEvent("Game was running without a beatmap", BubbleNotificationEvent.COMMONCOLOR_RED)); + displayContainer.switchStateInstantly(SongMenu.class); + } Dancer.instance.reset(); MoverDirection.reset(beatmap.beatmapID); @@ -1451,10 +1477,10 @@ public class Game extends BasicGameState { epiImgTime = Options.getEpilepsyWarningLength(); if (epiImgTime > 0) { epiImg = GameImage.EPILEPSY_WARNING.getImage(); - float desWidth = container.getWidth() / 2; + float desWidth = displayContainer.width / 2; epiImg = epiImg.getScaledCopy(desWidth / epiImg.getWidth()); - epiImgX = (container.getWidth() - epiImg.getWidth()) / 2; - epiImgY = (container.getHeight() - epiImg.getHeight()) / 2; + epiImgX = (displayContainer.width - epiImg.getWidth()) / 2; + epiImgY = (displayContainer.height - epiImg.getHeight()) / 2; } // load mods @@ -1522,9 +1548,9 @@ public class Game extends BasicGameState { else if (hitObject.isSpinner()) gameObjects[i] = new Spinner(hitObject, this, data); } catch (Exception e) { - // try to handle the error gracefully: substitute in a dummy GameObject - ErrorHandler.error(String.format("Failed to create %s at index %d:\n%s", - hitObject.getTypeName(), i, hitObject.toString()), e, true); + String message = String.format("Failed to create %s at index %d:\n%s", hitObject.getTypeName(), i, hitObject.toString()); + Log.error(message, e); + displayContainer.eventBus.post(new BubbleNotificationEvent(message, BubbleNotificationEvent.COMMONCOLOR_RED)); gameObjects[i] = new DummyObject(hitObject); } } @@ -1550,8 +1576,8 @@ public class Game extends BasicGameState { // load replay frames if (isReplay) { // load initial data - replayX = container.getWidth() / 2; - replayY = container.getHeight() / 2; + replayX = displayContainer.width / 2; + replayY = displayContainer.height / 2; replayKeyPressed = false; replaySkipTime = -1; for (replayIndex = 0; replayIndex < replay.frames.length; replayIndex++) { @@ -1572,8 +1598,8 @@ public class Game extends BasicGameState { else { lastKeysPressed = ReplayFrame.KEY_NONE; replaySkipTime = -1; - replayFrames = new LinkedList(); - replayFrames.add(new ReplayFrame(0, 0, input.getMouseX(), input.getMouseY(), 0)); + replayFrames = new LinkedList<>(); + replayFrames.add(new ReplayFrame(0, 0, displayContainer.mouseX, displayContainer.mouseY, 0)); } for (int i = 0; i < gameObjects.length; i++) { @@ -1635,10 +1661,10 @@ public class Game extends BasicGameState { slidercurveTo = 0; Dancer.instance.setGameObjects(gameObjects); - sbOverlay.setGameObjects(gameObjects); + storyboardOverlay.setGameObjects(gameObjects); if (!skippedToCheckpoint) { - sbOverlay.enter(); - sbOverlay.updateIndex(0); + storyboardOverlay.onEnter(); + storyboardOverlay.updateIndex(0); } Pippi.reset(); @@ -1652,15 +1678,23 @@ public class Game extends BasicGameState { } @Override - public void leave(GameContainer container, StateBasedGame game) - throws SlickException { + public void leave() { + super.leave(); + + MusicController.pause(); + MusicController.setPitch(1f); + MusicController.resume(); + + if (Options.isEnableSB()) { + storyboardOverlay.onLeave(); + } + isInGame = false; // container.setMouseGrabbed(false); skippedToCheckpoint = false; knorkesliders = null; - sbOverlay.leave(); Dancer.instance.setGameObjects(null); Cursor.lastObjColor = Color.white; @@ -1726,7 +1760,7 @@ public class Game extends BasicGameState { trackPosition = failTrackTime + (int) (System.currentTimeMillis() - failTime); // get hit objects in reverse order, or else overlapping objects are unreadable - Stack stack = new Stack(); + Stack stack = new Stack<>(); for (int index = objectIndex; index < gameObjects.length && beatmap.objects[index].getTime() < trackPosition + approachTime; index++) { stack.add(index); @@ -1739,7 +1773,7 @@ public class Game extends BasicGameState { } if (lastObjectIndex != -1 && !beatmap.objects[index].isNewCombo()) { // calculate points - final int followPointInterval = container.getHeight() / 14; + final int followPointInterval = displayContainer.height / 14; int lastObjectEndTime = gameObjects[lastObjectIndex].getEndTime() + 1; int objectStartTime = beatmap.objects[index].getTime(); Vec2f startPoint = gameObjects[lastObjectIndex].getPointAt(lastObjectEndTime); @@ -1828,7 +1862,7 @@ public class Game extends BasicGameState { g.pushTransform(); // translate and rotate the object - g.translate(0, dt * dt * container.getHeight()); + g.translate(0, dt * dt * displayContainer.height); Vec2f rotationCenter = gameObj.getPointAt((beatmap.objects[idx].getTime() + beatmap.objects[idx].getEndTime()) / 2); g.rotate(rotationCenter.x, rotationCenter.y, rotSpeed * dt); gameObj.draw(g, trackPosition, false); @@ -1847,7 +1881,7 @@ public class Game extends BasicGameState { currentMapMusicOffset = 0; } this.beatmap = beatmap; - Display.setTitle(String.format("%s - %s", game.getTitle(), beatmap.toString())); + Display.setTitle(String.format("opsu!dance - %s", beatmap.toString())); if (beatmap.breaks == null) BeatmapDB.load(beatmap, BeatmapDB.LOAD_ARRAY); BeatmapParser.parseHitObjects(beatmap); @@ -1879,7 +1913,7 @@ public class Game extends BasicGameState { lastReplayTime = 0; autoMousePosition = new Vec2f(); autoMousePressed = false; - flashlightRadius = container.getHeight() * 2 / 3; + flashlightRadius = displayContainer.height * 2 / 3; scoreboardStarStream.clear(); gameFinished = false; gameFinishedTimer.setTime(0); @@ -1917,9 +1951,6 @@ public class Game extends BasicGameState { * Loads all game images. */ private void loadImages() { - int width = container.getWidth(); - int height = container.getHeight(); - // set images File parent = beatmap.getFile().getParentFile(); for (GameImage img : GameImage.values()) { @@ -1932,17 +1963,17 @@ public class Game extends BasicGameState { // skip button if (GameImage.SKIP.getImages() != null) { Animation skip = GameImage.SKIP.getAnimation(120); - skipButton = new MenuButton(skip, width - skip.getWidth() / 2f, height - (skip.getHeight() / 2f)); + skipButton = new MenuButton(skip, displayContainer.width - skip.getWidth() / 2f, displayContainer.height - (skip.getHeight() / 2f)); } else { Image skip = GameImage.SKIP.getImage(); - skipButton = new MenuButton(skip, width - skip.getWidth() / 2f, height - (skip.getHeight() / 2f)); + skipButton = new MenuButton(skip, displayContainer.width - skip.getWidth() / 2f, displayContainer.height - (skip.getHeight() / 2f)); } skipButton.setHoverAnimationDuration(350); skipButton.setHoverAnimationEquation(AnimationEquation.IN_OUT_BACK); skipButton.setHoverExpand(1.1f, MenuButton.Expand.UP_LEFT); // load other images... - ((GamePauseMenu) game.getState(Opsu.STATE_GAMEPAUSEMENU)).loadImages(); + // TODO d instanceContainer.provide(GamePauseMenu.class).loadImages(); data.loadImages(); } @@ -1974,10 +2005,10 @@ public class Game extends BasicGameState { HitObject.setStackOffset(diameter * STACK_OFFSET_MODIFIER); // initialize objects - Circle.init(container, diameter); - Slider.init(container, diameter, beatmap); - Spinner.init(container, overallDifficulty); - Curve.init(container.getWidth(), container.getHeight(), diameter, (Options.isBeatmapSkinIgnored()) ? + Circle.init(diameter); + Slider.init(displayContainer, diameter, beatmap); + Spinner.init(displayContainer, overallDifficulty); + Curve.init(displayContainer.width, displayContainer.height, diameter, (Options.isBeatmapSkinIgnored()) ? Options.getSkin().getSliderBorderColor() : beatmap.getSliderBorderColor()); // approachRate (hit object approach time) @@ -2096,7 +2127,7 @@ public class Game extends BasicGameState { this.replay = null; } else { if (replay.frames == null) { - ErrorHandler.error("Attempting to set a replay with no frames.", null, false); + displayContainer.eventBus.post(new BubbleNotificationEvent("Attempting to set a replay with no frames.", BubbleNotificationEvent.COLOR_ORANGE)); return; } this.isReplay = true; @@ -2191,30 +2222,29 @@ public class Game extends BasicGameState { if (!GameMod.FLASHLIGHT.isActive()) return; - int width = container.getWidth(), height = container.getHeight(); boolean firstObject = (objectIndex == 0 && trackPosition < beatmap.objects[0].getTime()); if (isLeadIn()) { // lead-in: expand area float progress = Math.max((float) (leadInTime - beatmap.audioLeadIn) / approachTime, 0f); - flashlightRadius = width - (int) ((width - (height * 2 / 3)) * progress); + flashlightRadius = displayContainer.width - (int) ((displayContainer.width - (displayContainer.height * 2 / 3)) * progress); } else if (firstObject) { // before first object: shrink area int timeDiff = beatmap.objects[0].getTime() - trackPosition; - flashlightRadius = width; + flashlightRadius = displayContainer.width; if (timeDiff < approachTime) { float progress = (float) timeDiff / approachTime; - flashlightRadius -= (width - (height * 2 / 3)) * (1 - progress); + flashlightRadius -= (displayContainer.width - (displayContainer.height * 2 / 3)) * (1 - progress); } } else { // gameplay: size based on combo int targetRadius; int combo = data.getComboStreak(); if (combo < 100) - targetRadius = height * 2 / 3; + targetRadius = displayContainer.height * 2 / 3; else if (combo < 200) - targetRadius = height / 2; + targetRadius = displayContainer.height / 2; else - targetRadius = height / 3; + targetRadius = displayContainer.height / 3; if (beatmap.breaks != null && breakIndex < beatmap.breaks.size() && breakTime > 0) { // breaks: expand at beginning, shrink at end flashlightRadius = targetRadius; @@ -2226,11 +2256,11 @@ public class Game extends BasicGameState { progress = (float) (trackPosition - breakTime) / approachTime; else if (endTime - trackPosition < approachTime) progress = (float) (endTime - trackPosition) / approachTime; - flashlightRadius += (width - flashlightRadius) * progress; + flashlightRadius += (displayContainer.width - flashlightRadius) * progress; } } else if (flashlightRadius != targetRadius) { // radius size change - float radiusDiff = height * delta / 2000f; + float radiusDiff = displayContainer.height * delta / 2000f; if (flashlightRadius > targetRadius) { flashlightRadius -= radiusDiff; if (flashlightRadius < targetRadius) diff --git a/src/itdelatrisu/opsu/states/OptionsMenu.java b/src/itdelatrisu/opsu/states/OptionsMenu.java index 03e458b5..4f2c22eb 100644 --- a/src/itdelatrisu/opsu/states/OptionsMenu.java +++ b/src/itdelatrisu/opsu/states/OptionsMenu.java @@ -133,4 +133,63 @@ public class OptionsMenu { }) }; + public static final OptionTab[] storyboardOptions = new OptionsOverlay.OptionTab[]{ + new OptionTab("Gameplay", new GameOption[] { + GameOption.BACKGROUND_DIM, + GameOption.DANCE_REMOVE_BG, + GameOption.SNAKING_SLIDERS, + GameOption.SHRINKING_SLIDERS, + GameOption.SHOW_HIT_LIGHTING, + GameOption.SHOW_HIT_ANIMATIONS, + GameOption.SHOW_COMBO_BURSTS, + GameOption.SHOW_PERFECT_HIT, + GameOption.SHOW_FOLLOW_POINTS, + }), + new OptionTab("Input", new GameOption[] { + GameOption.CURSOR_SIZE, + GameOption.NEW_CURSOR, + GameOption.DISABLE_CURSOR + }), + new OptionTab("Dance", new GameOption[] { + GameOption.DANCE_MOVER, + GameOption.DANCE_EXGON_DELAY, + GameOption.DANCE_QUAD_BEZ_AGGRESSIVENESS, + GameOption.DANCE_QUAD_BEZ_SLIDER_AGGRESSIVENESS_FACTOR, + GameOption.DANCE_QUAD_BEZ_USE_CUBIC_ON_SLIDERS, + GameOption.DANCE_QUAD_BEZ_CUBIC_AGGRESSIVENESS_FACTOR, + GameOption.DANCE_MOVER_DIRECTION, + GameOption.DANCE_SLIDER_MOVER_TYPE, + GameOption.DANCE_SPINNER, + GameOption.DANCE_SPINNER_DELAY, + GameOption.DANCE_LAZY_SLIDERS, + GameOption.DANCE_CIRCLE_STREAMS, + GameOption.DANCE_ONLY_CIRCLE_STACKS, + GameOption.DANCE_CIRLCE_IN_SLOW_SLIDERS, + GameOption.DANCE_CIRLCE_IN_LAZY_SLIDERS, + GameOption.DANCE_MIRROR, + }), + new OptionTab("Dance display", new GameOption[] { + GameOption.DANCE_DRAW_APPROACH, + GameOption.DANCE_OBJECT_COLOR_OVERRIDE, + GameOption.DANCE_OBJECT_COLOR_OVERRIDE_MIRRORED, + GameOption.DANCE_RGB_OBJECT_INC, + GameOption.DANCE_CURSOR_COLOR_OVERRIDE, + GameOption.DANCE_CURSOR_MIRROR_COLOR_OVERRIDE, + GameOption.DANCE_CURSOR_ONLY_COLOR_TRAIL, + GameOption.DANCE_RGB_CURSOR_INC, + GameOption.DANCE_CURSOR_TRAIL_OVERRIDE, + GameOption.DANCE_HIDE_OBJECTS, + GameOption.DANCE_HIDE_UI, + GameOption.DANCE_HIDE_WATERMARK, + }), + new OptionTab ("Pippi", new GameOption[] { + GameOption.PIPPI_ENABLE, + GameOption.PIPPI_RADIUS_PERCENT, + GameOption.PIPPI_ANGLE_INC_MUL, + GameOption.PIPPI_ANGLE_INC_MUL_SLIDER, + GameOption.PIPPI_SLIDER_FOLLOW_EXPAND, + GameOption.PIPPI_PREVENT_WOBBLY_STREAMS, + }) + }; + } diff --git a/src/itdelatrisu/opsu/states/SongMenu.java b/src/itdelatrisu/opsu/states/SongMenu.java index aeef2f1e..ee06bb49 100644 --- a/src/itdelatrisu/opsu/states/SongMenu.java +++ b/src/itdelatrisu/opsu/states/SongMenu.java @@ -326,7 +326,7 @@ public class SongMenu extends ComplexOpsuState { public SongMenu(final DisplayContainer displayContainer, InstanceContainer instanceContainer) { super(displayContainer); this.instanceContainer = instanceContainer; - optionsOverlay = new OptionsOverlay(this, displayContainer, OptionsMenu.normalOptions, 0); + optionsOverlay = new OptionsOverlay(displayContainer, OptionsMenu.normalOptions, 0); overlays.add(optionsOverlay); } @@ -1794,6 +1794,6 @@ public class SongMenu extends ComplexOpsuState { gameState.loadBeatmap(beatmap); gameState.setRestart(Game.Restart.NEW); gameState.setReplay(null); - // TODO d displayContainer.switchState(Game.class); + displayContainer.switchState(Game.class); } } diff --git a/src/yugecin/opsudance/core/DisplayContainer.java b/src/yugecin/opsudance/core/DisplayContainer.java index c827a2e0..fac7d085 100644 --- a/src/yugecin/opsudance/core/DisplayContainer.java +++ b/src/yugecin/opsudance/core/DisplayContainer.java @@ -334,7 +334,13 @@ public class DisplayContainer implements ErrorDumpable, KeyListener, MouseListen } public void switchStateNow(Class newState) { - switchState(newState, EmptyTransitionState.class, 0, EmptyTransitionState.class, 0); + switchState(newState, EmptyTransitionState.class, 0, FadeInTransitionState.class, 300); + } + + public void switchStateInstantly(Class newState) { + state.leave(); + state = instanceContainer.provide(newState); + state.enter(); } public void switchState(Class newState, Class outTransition, int outTime, Class inTransition, int inTime) { diff --git a/src/yugecin/opsudance/core/inject/OpsuDanceInjector.java b/src/yugecin/opsudance/core/inject/OpsuDanceInjector.java index df63f5a9..98ab2278 100644 --- a/src/yugecin/opsudance/core/inject/OpsuDanceInjector.java +++ b/src/yugecin/opsudance/core/inject/OpsuDanceInjector.java @@ -57,6 +57,8 @@ public class OpsuDanceInjector extends Injector { bind(ButtonMenu.class).asEagerSingleton(); bind(SongMenu.class).asEagerSingleton(); bind(DownloadsMenu.class).asEagerSingleton(); + bind(GameRanking.class).asEagerSingleton(); + bind(Game.class).asEagerSingleton(); } } diff --git a/src/yugecin/opsudance/core/state/OverlayOpsuState.java b/src/yugecin/opsudance/core/state/OverlayOpsuState.java index f5df8b46..849b4567 100644 --- a/src/yugecin/opsudance/core/state/OverlayOpsuState.java +++ b/src/yugecin/opsudance/core/state/OverlayOpsuState.java @@ -26,8 +26,13 @@ public abstract class OverlayOpsuState implements OpsuState { protected boolean active; protected boolean acceptInput; - public abstract void hide(); - public abstract void show(); + public void hide() { + acceptInput = active = false; + } + + public void show() { + acceptInput = active = true; + } @Override public final void update() { diff --git a/src/yugecin/opsudance/sbv2/MoveStoryboard.java b/src/yugecin/opsudance/sbv2/MoveStoryboard.java index b6119d86..aa4e95c8 100644 --- a/src/yugecin/opsudance/sbv2/MoveStoryboard.java +++ b/src/yugecin/opsudance/sbv2/MoveStoryboard.java @@ -25,6 +25,8 @@ import itdelatrisu.opsu.ui.animations.AnimationEquation; import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; +import yugecin.opsudance.core.DisplayContainer; +import yugecin.opsudance.core.state.OverlayOpsuState; import yugecin.opsudance.sbv2.movers.CubicStoryboardMover; import yugecin.opsudance.sbv2.movers.LinearStoryboardMover; import yugecin.opsudance.sbv2.movers.QuadraticStoryboardMover; @@ -34,20 +36,20 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; -public class MoveStoryboard { +public class MoveStoryboard extends OverlayOpsuState{ - private final SimpleButton btnAddLinear; - private final SimpleButton btnAddQuadratic; - private final SimpleButton btnAddCubic; + private final DisplayContainer displayContainer; - private final SimpleButton btnAnimLin; - private final SimpleButton btnAnimMid; - private final SimpleButton btnAnimCub; + private SimpleButton btnAddLinear; + private SimpleButton btnAddQuadratic; + private SimpleButton btnAddCubic; + + private SimpleButton btnAnimLin; + private SimpleButton btnAnimMid; + private SimpleButton btnAnimCub; private final StoryboardMove dummyMove; - private int width; - private StoryboardMove[] moves; private GameObject[] gameObjects; @@ -55,14 +57,8 @@ public class MoveStoryboard { private int trackPosition; - public MoveStoryboard(GameContainer container) { - this.width = container.getWidth(); - btnAddLinear = new SimpleButton(width - 205, 50, 200, 25, Fonts.SMALL, "add linear", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); - btnAddQuadratic = new SimpleButton(width - 205, 80, 200, 25, Fonts.SMALL, "add quadratic", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); - btnAddCubic = new SimpleButton(width - 205, 110, 200, 25, Fonts.SMALL, "add cubic", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); - btnAnimLin = new SimpleButton(width - 250, 50, 40, 25, Fonts.SMALL, "lin", Color.blue, Color.white, Color.white, Color.orange); - btnAnimMid = new SimpleButton(width - 250, 80, 40, 25, Fonts.SMALL, "mid", Color.blue, Color.white, Color.white, Color.orange); - btnAnimCub = new SimpleButton(width - 250, 110, 40, 25, Fonts.SMALL, "cub", Color.blue, Color.white, Color.white, Color.orange); + public MoveStoryboard(DisplayContainer displayContainer) { + this.displayContainer = displayContainer; dummyMove = (StoryboardMove) Proxy.newProxyInstance(StoryboardMove.class.getClassLoader(), new Class[]{StoryboardMove.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { @@ -71,6 +67,16 @@ public class MoveStoryboard { }); } + @Override + public void revalidate() { + btnAddLinear = new SimpleButton(displayContainer.width - 205, 50, 200, 25, Fonts.SMALL, "add linear", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); + btnAddQuadratic = new SimpleButton(displayContainer.width - 205, 80, 200, 25, Fonts.SMALL, "add quadratic", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); + btnAddCubic = new SimpleButton(displayContainer.width - 205, 110, 200, 25, Fonts.SMALL, "add cubic", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); + btnAnimLin = new SimpleButton(displayContainer.width - 250, 50, 40, 25, Fonts.SMALL, "lin", Color.blue, Color.white, Color.white, Color.orange); + btnAnimMid = new SimpleButton(displayContainer.width - 250, 80, 40, 25, Fonts.SMALL, "mid", Color.blue, Color.white, Color.white, Color.orange); + btnAnimCub = new SimpleButton(displayContainer.width - 250, 110, 40, 25, Fonts.SMALL, "cub", Color.blue, Color.white, Color.white, Color.orange); + } + /** * Get the point at the current time * @param trackPosition current time in ms @@ -88,7 +94,33 @@ public class MoveStoryboard { return moves[objectIndex].getPointAt(t); } - public void render(Graphics g) { + @Override + public void hide() { + + } + + @Override + public void show() { + + } + + @Override + protected void onPreRenderUpdate() { + int x = displayContainer.mouseX; + int y = displayContainer.mouseY; + btnAddLinear.update(x, y); + btnAddQuadratic.update(x, y); + btnAddCubic.update(x, y); + btnAnimLin.update(x, y); + btnAnimMid.update(x, y); + btnAnimCub.update(x, y); + if (moves[objectIndex] != null) { + moves[objectIndex].update(displayContainer.renderDelta, x, y); + } + } + + @Override + protected void onRender(Graphics g) { btnAddLinear.render(g); btnAddQuadratic.render(g); btnAddCubic.render(g); @@ -100,13 +132,31 @@ public class MoveStoryboard { } } - public void mousePressed(int x, int y) { + @Override + protected boolean onKeyPressed(int key, char c) { + return false; + } + + @Override + protected boolean onKeyReleased(int key, char c) { + return false; + } + + @Override + protected boolean onMouseWheelMoved(int delta) { + return false; + } + + @Override + protected boolean onMousePressed(int button, int x, int y) { if (moves[objectIndex] != null) { moves[objectIndex].mousePressed(x, y); } + return true; } - public void mouseReleased(int x, int y) { + @Override + protected boolean onMouseReleased(int button, int x, int y) { if (moves[objectIndex] != null) { moves[objectIndex].mouseReleased(x, y); if (moves[objectIndex].getAmountOfMovers() == 0) { @@ -114,7 +164,7 @@ public class MoveStoryboard { } } if (objectIndex == 0) { - return; + return true; } if (btnAddLinear.isHovered()) { getCurrentMoveOrCreateNew().add(new LinearStoryboardMover()); @@ -134,6 +184,12 @@ public class MoveStoryboard { if (btnAnimCub.isHovered()) { getCurrentMoveOrDummy().setAnimationEquation(AnimationEquation.IN_OUT_EASE_MIDDLE); } + return true; + } + + @Override + protected boolean onMouseDragged(int oldx, int oldy, int newx, int newy) { + return false; } private StoryboardMove getCurrentMoveOrCreateNew() { @@ -142,7 +198,7 @@ public class MoveStoryboard { return dummyMove; } if (moves[objectIndex] == null) { - return moves[objectIndex] = new StoryboardMoveImpl(gameObjects[objectIndex - 1].end, gameObjects[objectIndex].start, width); + return moves[objectIndex] = new StoryboardMoveImpl(gameObjects[objectIndex - 1].end, gameObjects[objectIndex].start, displayContainer.width); } return moves[objectIndex]; } @@ -154,18 +210,6 @@ public class MoveStoryboard { return moves[objectIndex]; } - public void update(int delta, int x, int y) { - btnAddLinear.update(x, y); - btnAddQuadratic.update(x, y); - btnAddCubic.update(x, y); - btnAnimLin.update(x, y); - btnAnimMid.update(x, y); - btnAnimCub.update(x, y); - if (moves[objectIndex] != null) { - moves[objectIndex].update(delta, x, y); - } - } - public void setGameObjects(GameObject[] gameObjects) { this.gameObjects = gameObjects; this.moves = new StoryboardMove[gameObjects.length]; diff --git a/src/yugecin/opsudance/ui/OptionsOverlay.java b/src/yugecin/opsudance/ui/OptionsOverlay.java index 447a41b8..70e607ac 100644 --- a/src/yugecin/opsudance/ui/OptionsOverlay.java +++ b/src/yugecin/opsudance/ui/OptionsOverlay.java @@ -35,9 +35,10 @@ import yugecin.opsudance.core.state.OverlayOpsuState; public class OptionsOverlay extends OverlayOpsuState { - private final ComplexOpsuState parent; private final DisplayContainer displayContainer; + private Listener listener; + private Image sliderBallImg; private Image checkOnImg; private Image checkOffImg; @@ -81,8 +82,7 @@ public class OptionsOverlay extends OverlayOpsuState { private int sliderSoundDelay; - public OptionsOverlay(ComplexOpsuState parent, DisplayContainer displayContainer, OptionTab[] tabs, int defaultSelectedTabIndex) { - this.parent = parent; + public OptionsOverlay(DisplayContainer displayContainer, OptionTab[] tabs, int defaultSelectedTabIndex) { this.displayContainer = displayContainer; this.tabs = tabs; @@ -91,6 +91,10 @@ public class OptionsOverlay extends OverlayOpsuState { listHoverIndex = -1; } + public void setListener(Listener listener) { + this.listener = listener; + } + @Override public void revalidate() { super.revalidate(); @@ -399,7 +403,9 @@ public class OptionsOverlay extends OverlayOpsuState { if (isListOptionOpen) { if (y > optionStartY && listStartX <= x && x < listStartX + listWidth && listStartY <= y && y < listStartY + listHeight) { hoverOption.clickListItem(listHoverIndex); - // TODO d parent.onSaveOption(hoverOption); + if (listener != null) { + listener.onSaveOption(hoverOption); + } SoundController.playSound(SoundEffect.MENUCLICK); } isListOptionOpen = false; @@ -431,8 +437,8 @@ public class OptionsOverlay extends OverlayOpsuState { @Override public boolean onMouseReleased(int button, int x, int y) { selectedOption = null; - if (isAdjustingSlider) { - // TODO d parent.onSaveOption(hoverOption); + if (isAdjustingSlider && listener != null) { + listener.onSaveOption(hoverOption); } isAdjustingSlider = false; sliderOptionLength = 0; @@ -445,7 +451,9 @@ public class OptionsOverlay extends OverlayOpsuState { if (hoverOption != null) { if (hoverOption.getType() == OptionType.BOOLEAN) { hoverOption.click(); - // TODO d parent.onSaveOption(hoverOption); + if (listener != null) { + listener.onSaveOption(hoverOption); + } SoundController.playSound(SoundEffect.MENUHIT); return true; } else if (hoverOption == GameOption.KEY_LEFT) { @@ -466,6 +474,11 @@ public class OptionsOverlay extends OverlayOpsuState { tScrollOffset += Fonts.MEDIUM.getLineHeight() * 2; tScrollOffset += tab.options.length * optionHeight; } + + if (UI.getBackButton().contains(x, y) && listener != null) { + listener.onLeaveOptionsMenu(); + } + return true; } @@ -500,16 +513,19 @@ public class OptionsOverlay extends OverlayOpsuState { return true; } - switch (key) { - case Input.KEY_ESCAPE: - if (isListOptionOpen) { - isListOptionOpen = false; - listHoverIndex = -1; - return true; - } - hide(); + if (key == Input.KEY_ESCAPE) { + if (isListOptionOpen) { + isListOptionOpen = false; + listHoverIndex = -1; return true; + } + hide(); + if (listener != null) { + listener.onLeaveOptionsMenu(); + } + return true; } + return false; } @@ -570,9 +586,9 @@ public class OptionsOverlay extends OverlayOpsuState { } - public interface Parent { + public interface Listener { - void onLeave(); + void onLeaveOptionsMenu(); void onSaveOption(GameOption option); } diff --git a/src/yugecin/opsudance/ui/SBOverlay.java b/src/yugecin/opsudance/ui/StoryboardOverlay.java similarity index 59% rename from src/yugecin/opsudance/ui/SBOverlay.java rename to src/yugecin/opsudance/ui/StoryboardOverlay.java index 723c0afb..725dc107 100644 --- a/src/yugecin/opsudance/ui/SBOverlay.java +++ b/src/yugecin/opsudance/ui/StoryboardOverlay.java @@ -22,86 +22,27 @@ import itdelatrisu.opsu.Options.GameOption; import itdelatrisu.opsu.audio.MusicController; import itdelatrisu.opsu.objects.GameObject; import itdelatrisu.opsu.states.Game; +import itdelatrisu.opsu.states.OptionsMenu; import itdelatrisu.opsu.ui.Fonts; import org.newdawn.slick.Color; -import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Input; import yugecin.opsudance.ObjectColorOverrides; +import yugecin.opsudance.core.DisplayContainer; +import yugecin.opsudance.core.state.OverlayOpsuState; import yugecin.opsudance.sbv2.MoveStoryboard; import yugecin.opsudance.ui.OptionsOverlay.OptionTab; import java.util.*; @SuppressWarnings("unchecked") -public class SBOverlay implements OptionsOverlay.Parent { - - private static final OptionTab[] options = new OptionsOverlay.OptionTab[]{ - new OptionTab("Gameplay", new GameOption[] { - GameOption.BACKGROUND_DIM, - GameOption.DANCE_REMOVE_BG, - GameOption.SNAKING_SLIDERS, - GameOption.SHRINKING_SLIDERS, - GameOption.SHOW_HIT_LIGHTING, - GameOption.SHOW_HIT_ANIMATIONS, - GameOption.SHOW_COMBO_BURSTS, - GameOption.SHOW_PERFECT_HIT, - GameOption.SHOW_FOLLOW_POINTS, - }), - new OptionTab("Input", new GameOption[] { - GameOption.CURSOR_SIZE, - GameOption.NEW_CURSOR, - GameOption.DISABLE_CURSOR - }), - new OptionTab("Dance", new GameOption[] { - GameOption.DANCE_MOVER, - GameOption.DANCE_EXGON_DELAY, - GameOption.DANCE_QUAD_BEZ_AGGRESSIVENESS, - GameOption.DANCE_QUAD_BEZ_SLIDER_AGGRESSIVENESS_FACTOR, - GameOption.DANCE_QUAD_BEZ_USE_CUBIC_ON_SLIDERS, - GameOption.DANCE_QUAD_BEZ_CUBIC_AGGRESSIVENESS_FACTOR, - GameOption.DANCE_MOVER_DIRECTION, - GameOption.DANCE_SLIDER_MOVER_TYPE, - GameOption.DANCE_SPINNER, - GameOption.DANCE_SPINNER_DELAY, - GameOption.DANCE_LAZY_SLIDERS, - GameOption.DANCE_CIRCLE_STREAMS, - GameOption.DANCE_ONLY_CIRCLE_STACKS, - GameOption.DANCE_CIRLCE_IN_SLOW_SLIDERS, - GameOption.DANCE_CIRLCE_IN_LAZY_SLIDERS, - GameOption.DANCE_MIRROR, - }), - new OptionTab("Dance display", new GameOption[] { - GameOption.DANCE_DRAW_APPROACH, - GameOption.DANCE_OBJECT_COLOR_OVERRIDE, - GameOption.DANCE_OBJECT_COLOR_OVERRIDE_MIRRORED, - GameOption.DANCE_RGB_OBJECT_INC, - GameOption.DANCE_CURSOR_COLOR_OVERRIDE, - GameOption.DANCE_CURSOR_MIRROR_COLOR_OVERRIDE, - GameOption.DANCE_CURSOR_ONLY_COLOR_TRAIL, - GameOption.DANCE_RGB_CURSOR_INC, - GameOption.DANCE_CURSOR_TRAIL_OVERRIDE, - GameOption.DANCE_HIDE_OBJECTS, - GameOption.DANCE_HIDE_UI, - GameOption.DANCE_HIDE_WATERMARK, - }), - new OptionTab ("Pippi", new GameOption[] { - GameOption.PIPPI_ENABLE, - GameOption.PIPPI_RADIUS_PERCENT, - GameOption.PIPPI_ANGLE_INC_MUL, - GameOption.PIPPI_ANGLE_INC_MUL_SLIDER, - GameOption.PIPPI_SLIDER_FOLLOW_EXPAND, - GameOption.PIPPI_PREVENT_WOBBLY_STREAMS, - }) - }; +public class StoryboardOverlay extends OverlayOpsuState implements OptionsOverlay.Listener { private final static List optionList = new ArrayList<>(); - private boolean hide; - private boolean menu; + private final DisplayContainer displayContainer; - private int width; - private int height; + private boolean hide; private int speed; private GameObject[] gameObjects; @@ -112,43 +53,42 @@ public class SBOverlay implements OptionsOverlay.Parent { private final Game game; private final MoveStoryboard msb; - private OptionsOverlay overlay; + private final OptionsOverlay optionsOverlay; static { - for (OptionTab tab : options) { + for (OptionTab tab : OptionsMenu.storyboardOptions) { optionList.addAll(Arrays.asList(tab.options)); } } - public SBOverlay(Game game, MoveStoryboard msb, GameContainer container) { - this.game = game; + public StoryboardOverlay(DisplayContainer displayContainer, MoveStoryboard msb, OptionsOverlay optionsOverlay, Game game) { + this.displayContainer = displayContainer; this.msb = msb; + this.optionsOverlay = optionsOverlay; + this.game = game; initialOptions = new HashMap<>(); - //overlay = new OptionsOverlay(this, options, 2, container); - this.width = container.getWidth(); - this.height = container.getHeight(); speed = 10; gameObjects = new GameObject[0]; } - public void render(GameContainer container, Graphics g) { + @Override + public void onRender(Graphics g) { if (!Options.isEnableSB() || hide) { return; } - msb.render(g); int lh = Fonts.SMALL.getLineHeight(); - Fonts.SMALL.drawString(10, height - 50 + lh, "save position: ctrl+s, load position: ctrl+l", Color.cyan); - Fonts.SMALL.drawString(10, height - 50, "speed: C " + (speed / 10f) + " V", Color.cyan); - Fonts.SMALL.drawString(10, height - 50 - lh, "Menu: N", Color.cyan); - Fonts.SMALL.drawString(10, height - 50 - lh * 2, "HIDE: H", Color.cyan); - Fonts.SMALL.drawString(10, height - 50 - lh * 3, "obj: J " + index + " K", Color.cyan); + Fonts.SMALL.drawString(10, displayContainer.height - 50 + lh, "save position: ctrl+s, load position: ctrl+l", Color.cyan); + Fonts.SMALL.drawString(10, displayContainer.height - 50, "speed: C " + (speed / 10f) + " V", Color.cyan); + Fonts.SMALL.drawString(10, displayContainer.height - 50 - lh, "Menu: N", Color.cyan); + Fonts.SMALL.drawString(10, displayContainer.height - 50 - lh * 2, "HIDE: H", Color.cyan); + Fonts.SMALL.drawString(10, displayContainer.height - 50 - lh * 3, "obj: J " + index + " K", Color.cyan); g.setColor(Color.red); if (index < optionsMap.length && optionsMap[index] != null) { int i = 0; for (Object o : optionsMap[index].entrySet()) { Map.Entry option = (Map.Entry) o; Fonts.SMALL.drawString(10, 50 + i * lh, option.getKey().getName(), Color.cyan); - Fonts.SMALL.drawString(width / 5, 50 + i * lh, option.getKey().getValueString(), Color.cyan); + Fonts.SMALL.drawString(displayContainer.width / 5, 50 + i * lh, option.getKey().getValueString(), Color.cyan); g.fillRect(0, 50 + i * lh + lh / 4, 10, 10); i++; } @@ -157,27 +97,16 @@ public class SBOverlay implements OptionsOverlay.Parent { int start = gameObjects[0].getTime(); int end = gameObjects[gameObjects.length - 1].getEndTime(); float curtime = (float) (MusicController.getPosition() - start) / (end - start); - g.fillRect(curtime * width, height - 10f, 10f, 10f); - } - if (menu) { - //overlay.render(g, container.getInput().getMouseX(), container.getInput().getMouseY()); + g.fillRect(curtime * displayContainer.width, displayContainer.height - 10f, 10f, 10f); } } - public void update(int delta, int mouseX, int mouseY) { - if (Options.isEnableSB() && menu) { - //overlay.update(delta, mouseX, mouseY); - } - msb.update(delta, mouseX, mouseY); + @Override + public void onPreRenderUpdate() { } - public boolean keyPressed(int key, char c) { - if (!Options.isEnableSB()) { - return false; - } - if (menu && overlay.keyPressed(key, c)) { - return true; - } + @Override + public boolean onKeyPressed(int key, char c) { if (key == Input.KEY_C) { if (speed > 0) { speed -= 1; @@ -196,11 +125,9 @@ public class SBOverlay implements OptionsOverlay.Parent { } else if (key == Input.KEY_H) { hide = !hide; } else if (key == Input.KEY_N) { - menu = !menu; - if (menu && speed != 0) { + optionsOverlay.show(); + if (speed != 0) { MusicController.pause(); - } else if (!menu && speed != 0) { - MusicController.resume(); } } else if (key == Input.KEY_J && index > 0) { index--; @@ -214,6 +141,11 @@ public class SBOverlay implements OptionsOverlay.Parent { return false; } + @Override + protected boolean onKeyReleased(int key, char c) { + return false; + } + private void goBackOneSBIndex() { if (index + 1 < optionsMap.length) { // new options on previous index, so to revert then we have to reload them all to this point.. @@ -252,20 +184,13 @@ public class SBOverlay implements OptionsOverlay.Parent { this.gameObjects = gameObjects; } - public boolean mousePressed(int button, int x, int y) { - msb.mousePressed(x, y); - if (!menu) { - return false; - } - overlay.mousePressed(button, x, y); + @Override + public boolean onMousePressed(int button, int x, int y) { return true; } - public boolean mouseDragged(int oldx, int oldy, int newx, int newy) { - if (!menu) { - return false; - } - overlay.mouseDragged(oldx, oldy, newx, newy); + @Override + public boolean onMouseDragged(int oldx, int oldy, int newx, int newy) { return true; } @@ -293,12 +218,8 @@ public class SBOverlay implements OptionsOverlay.Parent { this.index--; } - public boolean mouseReleased(int button, int x, int y) { - if (menu) { - overlay.mouseReleased(button, x, y); - return true; - } - msb.mouseReleased(x, y); + @Override + public boolean onMouseReleased(int button, int x, int y) { if (x > 10 || index >= optionsMap.length || optionsMap[index] == null) { return false; } @@ -318,15 +239,12 @@ public class SBOverlay implements OptionsOverlay.Parent { return true; } - public boolean mouseWheelMoved(int delta) { - if (!menu) { - return false; - } - overlay.mouseWheelMoved(delta); + @Override + public boolean onMouseWheelMoved(int delta) { return true; } - public void enter() { + public void onEnter() { // enter, save current settings for (Options.GameOption o : optionList) { initialOptions.put(o, o.write()); @@ -334,7 +252,7 @@ public class SBOverlay implements OptionsOverlay.Parent { speed = 10; } - public void leave() { + public void onLeave() { // leave, revert the settings saved before entering for (Options.GameOption o : optionList) { if (initialOptions.containsKey(o)) { @@ -358,13 +276,8 @@ public class SBOverlay implements OptionsOverlay.Parent { } } - public float[] getPoint(int trackPosition) { - return msb.getPoint(trackPosition); - } - @Override - public void onLeave() { - menu = false; + public void onLeaveOptionsMenu() { if (speed != 0) { MusicController.resume(); }