diff --git a/res/failsound.wav b/res/failsound.wav index ed2ceba2..a94a3e0e 100644 Binary files a/res/failsound.wav and b/res/failsound.wav differ diff --git a/src/itdelatrisu/opsu/Utils.java b/src/itdelatrisu/opsu/Utils.java index a5713b4d..e1f6c968 100644 --- a/src/itdelatrisu/opsu/Utils.java +++ b/src/itdelatrisu/opsu/Utils.java @@ -18,7 +18,6 @@ package itdelatrisu.opsu; -import itdelatrisu.opsu.states.Game; import itdelatrisu.opsu.states.Options; import java.awt.Font; @@ -322,12 +321,10 @@ public class Utils { cursorTrail.drawCentered(x, y); // increase the cursor size if pressed + int state = game.getCurrentStateID(); float scale = 1f; - if (game.getCurrentStateID() == Opsu.STATE_GAME && - ((Game) game.getState(Opsu.STATE_GAME)).isInputKeyPressed()) - scale = 1.25f; - else if (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) || - input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON)) + if (((state == Opsu.STATE_GAME || state == Opsu.STATE_GAMEPAUSEMENU) && isGameKeyPressed()) || + (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) || input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))) scale = 1.25f; // draw the other components @@ -404,6 +401,17 @@ public class Utils { cursor.rotate(delta / 40f); } + /** + * Returns true if a game input key is pressed (mouse/keyboard left/right). + * @return true if pressed + */ + public static boolean isGameKeyPressed() { + return (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) || + input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON) || + input.isKeyDown(Options.getGameKeyLeft()) || + input.isKeyDown(Options.getGameKeyRight())); + } + /** * Draws the FPS at the bottom-right corner of the game container. * If the option is not activated, this will do nothing. diff --git a/src/itdelatrisu/opsu/objects/Slider.java b/src/itdelatrisu/opsu/objects/Slider.java index 3bd92b7d..7ff5e78f 100644 --- a/src/itdelatrisu/opsu/objects/Slider.java +++ b/src/itdelatrisu/opsu/objects/Slider.java @@ -532,7 +532,7 @@ public class Slider { ticksHit++; // check if cursor pressed and within end circle - else if (game.isInputKeyPressed()) { + else if (Utils.isGameKeyPressed()) { double distance = Math.hypot(hitObject.sliderX[lastIndex] - mouseX, hitObject.sliderY[lastIndex] - mouseY); int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2; if (distance < followCircleRadius) @@ -572,7 +572,7 @@ public class Slider { float[] c = bezier.pointAt(getT(trackPosition, false)); double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY); int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2; - if ((game.isInputKeyPressed() && distance < followCircleRadius) || isAutoMod) { + if ((Utils.isGameKeyPressed() && distance < followCircleRadius) || isAutoMod) { // mouse pressed and within follow circle followCircleActive = true; score.changeHealth(delta * GameScore.HP_DRAIN_MULTIPLIER); diff --git a/src/itdelatrisu/opsu/objects/Spinner.java b/src/itdelatrisu/opsu/objects/Spinner.java index e4aa1756..83eacd33 100644 --- a/src/itdelatrisu/opsu/objects/Spinner.java +++ b/src/itdelatrisu/opsu/objects/Spinner.java @@ -47,11 +47,6 @@ public class Spinner { */ private OsuHitObject hitObject; - /** - * The associated Game object. - */ - private Game game; - /** * The associated GameScore object. */ @@ -95,7 +90,6 @@ public class Spinner { */ public Spinner(OsuHitObject hitObject, Game game, GameScore score) { this.hitObject = hitObject; - this.game = game; this.score = score; // calculate rotations needed @@ -202,7 +196,7 @@ public class Spinner { } // not spinning: nothing to do - if (!game.isInputKeyPressed()) { + if (!Utils.isGameKeyPressed()) { lastAngle = -1f; return false; } diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index e3dad7eb..276bc1e5 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -573,6 +573,14 @@ public class Game extends BasicGameState { @Override public void keyPressed(int key, char c) { + // game keys + if (!Keyboard.isRepeatEvent()) { + if (key == Options.getGameKeyLeft()) + mousePressed(Input.MOUSE_LEFT_BUTTON, input.getMouseX(), input.getMouseY()); + else if (key == Options.getGameKeyRight()) + mousePressed(Input.MOUSE_RIGHT_BUTTON, input.getMouseX(), input.getMouseY()); + } + switch (key) { case Input.KEY_ESCAPE: // pause game @@ -642,16 +650,6 @@ public class Game extends BasicGameState { } } break; - case Input.KEY_Z: - // left-click - if (!Keyboard.isRepeatEvent()) - mousePressed(Input.MOUSE_LEFT_BUTTON, input.getMouseX(), input.getMouseY()); - break; - case Input.KEY_X: - // right-click - if (!Keyboard.isRepeatEvent()) - mousePressed(Input.MOUSE_RIGHT_BUTTON, input.getMouseX(), input.getMouseY()); - break; case Input.KEY_F12: Utils.takeScreenShot(); break; @@ -811,15 +809,6 @@ public class Game extends BasicGameState { return false; } - /** - * Returns true if an input key is pressed (mouse left/right, keyboard Z/X). - */ - public boolean isInputKeyPressed() { - return (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) || - input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON) || - input.isKeyDown(Input.KEY_Z) || input.isKeyDown(Input.KEY_X)); - } - /** * Loads all game images. * @throws SlickException diff --git a/src/itdelatrisu/opsu/states/GamePauseMenu.java b/src/itdelatrisu/opsu/states/GamePauseMenu.java index 7f3e807b..ad77292c 100644 --- a/src/itdelatrisu/opsu/states/GamePauseMenu.java +++ b/src/itdelatrisu/opsu/states/GamePauseMenu.java @@ -25,6 +25,7 @@ import itdelatrisu.opsu.Opsu; import itdelatrisu.opsu.SoundController; import itdelatrisu.opsu.Utils; +import org.lwjgl.input.Keyboard; import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; @@ -60,8 +61,9 @@ public class GamePauseMenu extends BasicGameState { private GUIMenuButton continueButton, retryButton, backButton; // game-related variables - private StateBasedGame game; private GameContainer container; + private StateBasedGame game; + private Input input; private int state; public GamePauseMenu(int state) { @@ -73,6 +75,7 @@ public class GamePauseMenu extends BasicGameState { throws SlickException { this.container = container; this.game = game; + input = container.getInput(); } @Override @@ -105,6 +108,14 @@ public class GamePauseMenu extends BasicGameState { @Override public void keyPressed(int key, char c) { + // game keys + if (!Keyboard.isRepeatEvent()) { + if (key == Options.getGameKeyLeft()) + mousePressed(Input.MOUSE_LEFT_BUTTON, input.getMouseX(), input.getMouseY()); + else if (key == Options.getGameKeyRight()) + mousePressed(Input.MOUSE_RIGHT_BUTTON, input.getMouseX(), input.getMouseY()); + } + switch (key) { case Input.KEY_ESCAPE: // 'esc' will normally unpause, but will return to song menu if health is zero @@ -124,8 +135,7 @@ public class GamePauseMenu extends BasicGameState { @Override public void mousePressed(int button, int x, int y) { - // check mouse button - if (button != Input.MOUSE_LEFT_BUTTON) + if (button == Input.MOUSE_MIDDLE_BUTTON) return; boolean loseState = (Game.getRestart() == Game.RESTART_LOSE); diff --git a/src/itdelatrisu/opsu/states/Options.java b/src/itdelatrisu/opsu/states/Options.java index 3a7da4ad..bdffbba0 100644 --- a/src/itdelatrisu/opsu/states/Options.java +++ b/src/itdelatrisu/opsu/states/Options.java @@ -35,6 +35,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.TimeUnit; +import org.lwjgl.input.Keyboard; import org.newdawn.slick.AppGameContainer; import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; @@ -124,7 +125,9 @@ public class Options extends BasicGameState { FIXED_OD, LOAD_VERBOSE, CHECKPOINT, - DISABLE_SOUNDS; + DISABLE_SOUNDS, + KEY_LEFT, + KEY_RIGHT; }; /** @@ -186,6 +189,8 @@ public class Options extends BasicGameState { * Gameplay options. */ private static final GameOption[] gameplayOptions = { + GameOption.KEY_LEFT, + GameOption.KEY_RIGHT, GameOption.BACKGROUND_DIM, GameOption.FORCE_DEFAULT_PLAYFIELD, GameOption.IGNORE_BEATMAP_SKINS, @@ -355,7 +360,19 @@ public class Options extends BasicGameState { * By default, sound is disabled on Linux due to possible driver issues. */ private static boolean disableSound = - (System.getProperty("os.name").toLowerCase().indexOf("linux") > -1); + (System.getProperty("os.name").toLowerCase().indexOf("linux") > -1); + + /** + * Left and right game keys. + */ + private static int + keyLeft = Keyboard.KEY_NONE, + keyRight = Keyboard.KEY_NONE; + + /** + * Key entry states. + */ + private boolean keyEntryLeft = false, keyEntryRight = false; /** * Game option coordinate modifiers (for drawing). @@ -462,6 +479,17 @@ public class Options extends BasicGameState { Utils.getBackButton().draw(); + // key entry state + if (keyEntryLeft || keyEntryRight) { + g.setColor(Utils.COLOR_BLACK_ALPHA); + g.fillRect(0, 0, width, height); + g.setColor(Color.white); + Utils.FONT_LARGE.drawString( + (width / 2) - (Utils.FONT_LARGE.getWidth("Please enter a letter or digit.") / 2), + (height / 2) - Utils.FONT_LARGE.getHeight(), "Please enter a letter or digit." + ); + } + Utils.drawFPS(); Utils.drawCursor(); } @@ -477,6 +505,12 @@ public class Options extends BasicGameState { @Override public void mousePressed(int button, int x, int y) { + // key entry state + if (keyEntryLeft || keyEntryRight) { + keyEntryLeft = keyEntryRight = false; + return; + } + // check mouse button if (button == Input.MOUSE_MIDDLE_BUTTON) return; @@ -564,6 +598,14 @@ public class Options extends BasicGameState { case DISABLE_SOUNDS: disableSound = !disableSound; break; + case KEY_LEFT: + keyEntryLeft = true; + keyEntryRight = false; + break; + case KEY_RIGHT: + keyEntryLeft = false; + keyEntryRight = true; + break; default: break; } @@ -571,6 +613,10 @@ public class Options extends BasicGameState { @Override public void mouseDragged(int oldx, int oldy, int newx, int newy) { + // key entry state + if (keyEntryLeft || keyEntryRight) + return; + // check mouse button (right click scrolls faster) int multiplier; if (input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON)) @@ -660,6 +706,18 @@ public class Options extends BasicGameState { @Override public void keyPressed(int key, char c) { + // key entry state + if (keyEntryLeft || keyEntryRight) { + if (Character.isLetterOrDigit(c)) { + if (keyEntryLeft && keyRight != key) + keyLeft = key; + else if (keyEntryRight && keyLeft != key) + keyRight = key; + } + keyEntryLeft = keyEntryRight = false; + return; + } + switch (key) { case Input.KEY_ESCAPE: SoundController.playSound(SoundController.SOUND_MENUBACK); @@ -769,6 +827,18 @@ public class Options extends BasicGameState { "May resolve Linux sound driver issues. Requires a restart." ); break; + case KEY_LEFT: + drawOption(pos, "Left Game Key", + Keyboard.getKeyName(getGameKeyLeft()), + "Select this option to input a key." + ); + break; + case KEY_RIGHT: + drawOption(pos, "Right Game Key", + Keyboard.getKeyName(getGameKeyRight()), + "Select this option to input a key." + ); + break; case BACKGROUND_DIM: drawOption(pos, "Background Dim", String.format("%d%%", backgroundDim), @@ -1074,6 +1144,26 @@ public class Options extends BasicGameState { return false; } + /** + * Returns the left game key. + * @return the left key code + */ + public static int getGameKeyLeft() { + if (keyLeft == Keyboard.KEY_NONE) + keyLeft = Input.KEY_Z; + return keyLeft; + } + + /** + * Returns the right game key. + * @return the right key code + */ + public static int getGameKeyRight() { + if (keyRight == Keyboard.KEY_NONE) + keyRight = Input.KEY_X; + return keyRight; + } + /** * Returns the beatmap directory. * If invalid, this will attempt to search for the directory, @@ -1213,6 +1303,22 @@ public class Options extends BasicGameState { case "DisableSound": disableSound = Boolean.parseBoolean(value); break; + case "keyOsuLeft": + if ((value.length() == 1 && Character.isLetterOrDigit(value.charAt(0))) || + (value.length() == 7 && value.startsWith("NUMPAD"))) { + i = Keyboard.getKeyIndex(value); + if (keyRight != i) + keyLeft = i; + } + break; + case "keyOsuRight": + if ((value.length() == 1 && Character.isLetterOrDigit(value.charAt(0))) || + (value.length() == 7 && value.startsWith("NUMPAD"))) { + i = Keyboard.getKeyIndex(value); + if (keyLeft != i) + keyRight = i; + } + break; case "DimLevel": i = Integer.parseInt(value); if (i >= 0 && i <= 100) @@ -1309,6 +1415,10 @@ public class Options extends BasicGameState { writer.newLine(); writer.write(String.format("DisableSound = %b", disableSound)); writer.newLine(); + writer.write(String.format("keyOsuLeft = %s", Keyboard.getKeyName(keyLeft))); + writer.newLine(); + writer.write(String.format("keyOsuRight = %s", Keyboard.getKeyName(keyRight))); + writer.newLine(); writer.write(String.format("DimLevel = %d", backgroundDim)); writer.newLine(); writer.write(String.format("ForceDefaultPlayfield = %b", forceDefaultPlayfield));