diff --git a/res/reversearrow.png b/res/reversearrow.png index 7ebdec37..f88117ca 100644 Binary files a/res/reversearrow.png and b/res/reversearrow.png differ diff --git a/src/itdelatrisu/opsu/MusicController.java b/src/itdelatrisu/opsu/MusicController.java index 62f8e21a..91b26643 100644 --- a/src/itdelatrisu/opsu/MusicController.java +++ b/src/itdelatrisu/opsu/MusicController.java @@ -68,9 +68,9 @@ public class MusicController { */ @SuppressWarnings("deprecation") public static void play(final OsuFile osu, final boolean loop) { - if (lastOsu == null || !osu.audioFilename.equals(lastOsu.audioFilename)) { - lastOsu = osu; - + boolean play = (lastOsu == null || !osu.audioFilename.equals(lastOsu.audioFilename)); + lastOsu = osu; + if (play) { // TODO: properly interrupt instead of using deprecated conversion.stop(); // interrupt the conversion if (isConverting()) diff --git a/src/itdelatrisu/opsu/Opsu.java b/src/itdelatrisu/opsu/Opsu.java index 32b12e39..0aedf827 100644 --- a/src/itdelatrisu/opsu/Opsu.java +++ b/src/itdelatrisu/opsu/Opsu.java @@ -61,13 +61,13 @@ public class Opsu extends StateBasedGame { * Game states. */ public static final int - STATE_OPTIONS = 1, - STATE_MAINMENU = 2, - STATE_MAINMENUEXIT = 3, - STATE_SONGMENU = 4, - STATE_GAME = 5, - STATE_GAMEPAUSEMENU = 6, - STATE_GAMERANKING = 7; + STATE_MAINMENU = 1, + STATE_MAINMENUEXIT = 2, + STATE_SONGMENU = 3, + STATE_GAME = 4, + STATE_GAMEPAUSEMENU = 5, + STATE_GAMERANKING = 6, + STATE_OPTIONS = 7; /** * Used to restrict the program to a single instance. @@ -80,13 +80,13 @@ public class Opsu extends StateBasedGame { @Override public void initStatesList(GameContainer container) throws SlickException { - addState(new Options(STATE_OPTIONS)); addState(new MainMenu(STATE_MAINMENU)); addState(new MainMenuExit(STATE_MAINMENUEXIT)); addState(new SongMenu(STATE_SONGMENU)); addState(new Game(STATE_GAME)); addState(new GamePauseMenu(STATE_GAMEPAUSEMENU)); addState(new GameRanking(STATE_GAMERANKING)); + addState(new Options(STATE_OPTIONS)); } public static void main(String[] args) { diff --git a/src/itdelatrisu/opsu/objects/Slider.java b/src/itdelatrisu/opsu/objects/Slider.java index 6a110483..5ad9cc2b 100644 --- a/src/itdelatrisu/opsu/objects/Slider.java +++ b/src/itdelatrisu/opsu/objects/Slider.java @@ -151,12 +151,17 @@ public class Slider { */ private float[] curveX, curveY; + /** + * The angles of the first and last control points. + */ + private float startAngle, endAngle; + /** * Constructor. */ - public Bezier(float length) { + public Bezier() { this.order = hitObject.sliderX.length + 1; - this.step = 5 / length; + this.step = 5 / hitObject.pixelLength; // calculate curve points for drawing int N = (int) (1 / step); @@ -168,6 +173,16 @@ public class Slider { curveX[i] = c[0]; curveY[i] = c[1]; } + + // calculate angles (if needed) + if (hitObject.repeat > 1) { + float[] c1 = pointAt(0f); + float[] c2 = pointAt(0.01f); + startAngle = (float) (Math.atan2(c2[1] - c1[1], c2[0] - c1[0]) * 180 / Math.PI); + c1 = pointAt(1f); + c2 = pointAt(0.99f); + endAngle = (float) (Math.atan2(c2[1] - c1[1], c2[0] - c1[0]) * 180 / Math.PI); + } } /** @@ -176,21 +191,31 @@ public class Slider { private float getX(int i) { return (i == 0) ? hitObject.x : hitObject.sliderX[i - 1]; } - + /** * Returns the y coordinate of the control point at index i. */ private float getY(int i) { return (i == 0) ? hitObject.y : hitObject.sliderY[i - 1]; } - + + /** + * Returns the angle of the first control point. + */ + private float getStartAngle() { return startAngle; } + + /** + * Returns the angle of the last control point. + */ + private float getEndAngle() { return endAngle; } + /** * Calculates the factorial of a number. */ private long factorial(int n) { return (n <= 1 || n > 20) ? 1 : n * factorial(n - 1); } - + /** * Calculates the Bernstein polynomial. * @param i the index @@ -201,7 +226,7 @@ public class Slider { return factorial(n) / (factorial(i) * factorial(n-i)) * Math.pow(t, i) * Math.pow(1-t, n-i); } - + /** * Returns the point on the Bezier curve at a value t. * For curves of order greater than 4, points will be generated along @@ -284,7 +309,7 @@ public class Slider { this.color = color; this.comboEnd = comboEnd; - this.bezier = new Bezier(hitObject.pixelLength); + this.bezier = new Bezier(); // calculate slider time and ticks upon first update call } @@ -327,10 +352,13 @@ public class Slider { // repeats if (hitObject.repeat - 1 > currentRepeats) { - if (currentRepeats % 2 == 0) // last circle + if (currentRepeats % 2 == 0) { // last circle + reverseArrow.setRotation(bezier.getEndAngle()); reverseArrow.drawCentered(hitObject.sliderX[lastIndex], hitObject.sliderY[lastIndex]); - else // first circle + } else { // first circle + reverseArrow.setRotation(bezier.getStartAngle()); reverseArrow.drawCentered(hitObject.x, hitObject.y); + } } if (timeDiff >= 0) { diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index 655ff2e2..cc9000c7 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -322,23 +322,22 @@ public class Game extends BasicGameState { // game elements score.drawGameElements(g, mapLength, false, objectIndex == 0); - // first object... - if (objectIndex == 0) { - // skip beginning - if (osu.objects[objectIndex].time - skipOffsetTime > 5000 && - trackPosition < osu.objects[objectIndex].time - skipOffsetTime) - skipButton.draw(); - - // mod icons - if (trackPosition < osu.objects[objectIndex].time) { - for (int i = Options.MOD_MAX - 1; i >= 0; i--) { - if (Options.isModActive(i)) { - Image modImage = Options.getModImage(i); - modImage.draw( - (width * 0.85f) + ((i - (Options.MOD_MAX / 2)) * modImage.getWidth() / 3f), - height / 10f - ); - } + // skip beginning + if (objectIndex == 0 && + osu.objects[0].time - skipOffsetTime > 5000 && + trackPosition < osu.objects[0].time - skipOffsetTime) + skipButton.draw(); + + // mod icons + if ((objectIndex == 0 && trackPosition < osu.objects[0].time) || + Options.isModActive(Options.MOD_AUTO)) { + for (int i = Options.MOD_MAX - 1; i >= 0; i--) { + if (Options.isModActive(i)) { + Image modImage = Options.getModImage(i); + modImage.draw( + (width * 0.85f) + ((i - (Options.MOD_MAX / 2)) * modImage.getWidth() / 3f), + height / 10f + ); } } } @@ -570,7 +569,9 @@ public class Game extends BasicGameState { case Input.KEY_ESCAPE: // pause game int trackPosition = MusicController.getPosition(); - if (pauseTime < 0 && breakTime <= 0 && trackPosition >= osu.objects[0].time) { + if (pauseTime < 0 && breakTime <= 0 && + trackPosition >= osu.objects[0].time && + !Options.isModActive(Options.MOD_AUTO)) { pausedMouseX = input.getMouseX(); pausedMouseY = input.getMouseY(); pausePulse = 0f; diff --git a/src/itdelatrisu/opsu/states/MainMenu.java b/src/itdelatrisu/opsu/states/MainMenu.java index 8eac1291..66375dc4 100644 --- a/src/itdelatrisu/opsu/states/MainMenu.java +++ b/src/itdelatrisu/opsu/states/MainMenu.java @@ -111,6 +111,8 @@ public class MainMenu extends BasicGameState { @Override public void init(GameContainer container, StateBasedGame game) throws SlickException { + Utils.init(container, game); + this.game = game; osuStartTime = System.currentTimeMillis(); diff --git a/src/itdelatrisu/opsu/states/Options.java b/src/itdelatrisu/opsu/states/Options.java index e88b7e4c..3bc9b7c0 100644 --- a/src/itdelatrisu/opsu/states/Options.java +++ b/src/itdelatrisu/opsu/states/Options.java @@ -315,7 +315,6 @@ public class Options extends BasicGameState { private Input input; private Graphics g; private int state; - private boolean init = false; public Options(int state) { this.state = state; @@ -329,8 +328,6 @@ public class Options extends BasicGameState { this.input = container.getInput(); this.g = container.getGraphics(); - Utils.init(container, game); - int width = container.getWidth(); int height = container.getHeight(); @@ -376,16 +373,11 @@ public class Options extends BasicGameState { ); for (int i = 0; i < modButtons.length; i++) modButtons[i].getImage().setAlpha(0.5f); - - game.enterState(Opsu.STATE_MAINMENU, new EmptyTransition(), new FadeInTransition(Color.black)); } @Override public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException { - if (!init) - return; - g.setBackground(Utils.COLOR_BLACK_ALPHA); g.setColor(Color.white); @@ -449,7 +441,7 @@ public class Options extends BasicGameState { @Override public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException { - init = true; + // empty } @Override diff --git a/src/itdelatrisu/opsu/states/SongMenu.java b/src/itdelatrisu/opsu/states/SongMenu.java index c5b855bb..6427cf5e 100644 --- a/src/itdelatrisu/opsu/states/SongMenu.java +++ b/src/itdelatrisu/opsu/states/SongMenu.java @@ -363,6 +363,7 @@ public class SongMenu extends BasicGameState { if (sortTabs[i].contains(x, y)) { if (i != currentSort) { currentSort = i; + SoundController.playSound(SoundController.SOUND_MENUCLICK); OsuGroupNode oldFocusBase = Opsu.groups.getBaseNode(focusNode.index); int oldFocusFileIndex = focusNode.osuFileIndex; focusNode = null; @@ -395,7 +396,7 @@ public class SongMenu extends BasicGameState { } else if (node.osuFileIndex == focusNode.osuFileIndex) { // if already focused, load the beatmap - startGame(focusNode.osuFiles.get(focusNode.osuFileIndex)); + startGame(); } else { // focus the node @@ -443,7 +444,7 @@ public class SongMenu extends BasicGameState { break; case Input.KEY_ENTER: if (focusNode != null) - startGame(focusNode.osuFiles.get(focusNode.osuFileIndex)); + startGame(); break; case Input.KEY_DOWN: changeIndex(1); @@ -595,11 +596,12 @@ public class SongMenu extends BasicGameState { * Starts the game. * @param osu the OsuFile to send to the game */ - private void startGame(OsuFile osu) { + private void startGame() { if (MusicController.isConverting()) return; SoundController.playSound(SoundController.SOUND_MENUHIT); + OsuFile osu = MusicController.getOsuFile(); Display.setTitle(String.format("%s - %s", game.getTitle(), osu.toString())); OsuParser.parseHitObjects(osu); SoundController.setSampleSet(osu.sampleSet);