Added configurable game key bindings.

- Game keys (default Z/X) can be changed to any letter or digit in the options screen.

Other changes:
- Mouse/keyboard input in the "Game Paused Menu" state is now the same as in the game state (i.e. all game keys available).
- Moved 'isInputKeyPressed()' into "Utils" class ("Game" state didn't even call it).
- Trimmed 'failsound.wav'.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2014-07-17 23:58:37 -04:00
parent b0c0b44ef1
commit edf40e11fd
7 changed files with 150 additions and 39 deletions

Binary file not shown.

View File

@ -18,7 +18,6 @@
package itdelatrisu.opsu; package itdelatrisu.opsu;
import itdelatrisu.opsu.states.Game;
import itdelatrisu.opsu.states.Options; import itdelatrisu.opsu.states.Options;
import java.awt.Font; import java.awt.Font;
@ -322,12 +321,10 @@ public class Utils {
cursorTrail.drawCentered(x, y); cursorTrail.drawCentered(x, y);
// increase the cursor size if pressed // increase the cursor size if pressed
int state = game.getCurrentStateID();
float scale = 1f; float scale = 1f;
if (game.getCurrentStateID() == Opsu.STATE_GAME && if (((state == Opsu.STATE_GAME || state == Opsu.STATE_GAMEPAUSEMENU) && isGameKeyPressed()) ||
((Game) game.getState(Opsu.STATE_GAME)).isInputKeyPressed()) (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) || input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON)))
scale = 1.25f;
else if (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) ||
input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))
scale = 1.25f; scale = 1.25f;
// draw the other components // draw the other components
@ -404,6 +401,17 @@ public class Utils {
cursor.rotate(delta / 40f); 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. * Draws the FPS at the bottom-right corner of the game container.
* If the option is not activated, this will do nothing. * If the option is not activated, this will do nothing.

View File

@ -532,7 +532,7 @@ public class Slider {
ticksHit++; ticksHit++;
// check if cursor pressed and within end circle // 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); double distance = Math.hypot(hitObject.sliderX[lastIndex] - mouseX, hitObject.sliderY[lastIndex] - mouseY);
int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2; int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2;
if (distance < followCircleRadius) if (distance < followCircleRadius)
@ -572,7 +572,7 @@ public class Slider {
float[] c = bezier.pointAt(getT(trackPosition, false)); float[] c = bezier.pointAt(getT(trackPosition, false));
double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY); double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY);
int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2; 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 // mouse pressed and within follow circle
followCircleActive = true; followCircleActive = true;
score.changeHealth(delta * GameScore.HP_DRAIN_MULTIPLIER); score.changeHealth(delta * GameScore.HP_DRAIN_MULTIPLIER);

View File

@ -47,11 +47,6 @@ public class Spinner {
*/ */
private OsuHitObject hitObject; private OsuHitObject hitObject;
/**
* The associated Game object.
*/
private Game game;
/** /**
* The associated GameScore object. * The associated GameScore object.
*/ */
@ -95,7 +90,6 @@ public class Spinner {
*/ */
public Spinner(OsuHitObject hitObject, Game game, GameScore score) { public Spinner(OsuHitObject hitObject, Game game, GameScore score) {
this.hitObject = hitObject; this.hitObject = hitObject;
this.game = game;
this.score = score; this.score = score;
// calculate rotations needed // calculate rotations needed
@ -202,7 +196,7 @@ public class Spinner {
} }
// not spinning: nothing to do // not spinning: nothing to do
if (!game.isInputKeyPressed()) { if (!Utils.isGameKeyPressed()) {
lastAngle = -1f; lastAngle = -1f;
return false; return false;
} }

View File

@ -573,6 +573,14 @@ public class Game extends BasicGameState {
@Override @Override
public void keyPressed(int key, char c) { 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) { switch (key) {
case Input.KEY_ESCAPE: case Input.KEY_ESCAPE:
// pause game // pause game
@ -642,16 +650,6 @@ public class Game extends BasicGameState {
} }
} }
break; 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: case Input.KEY_F12:
Utils.takeScreenShot(); Utils.takeScreenShot();
break; break;
@ -811,15 +809,6 @@ public class Game extends BasicGameState {
return false; 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. * Loads all game images.
* @throws SlickException * @throws SlickException

View File

@ -25,6 +25,7 @@ import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.SoundController; import itdelatrisu.opsu.SoundController;
import itdelatrisu.opsu.Utils; import itdelatrisu.opsu.Utils;
import org.lwjgl.input.Keyboard;
import org.newdawn.slick.Color; import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer; import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics; import org.newdawn.slick.Graphics;
@ -60,8 +61,9 @@ public class GamePauseMenu extends BasicGameState {
private GUIMenuButton continueButton, retryButton, backButton; private GUIMenuButton continueButton, retryButton, backButton;
// game-related variables // game-related variables
private StateBasedGame game;
private GameContainer container; private GameContainer container;
private StateBasedGame game;
private Input input;
private int state; private int state;
public GamePauseMenu(int state) { public GamePauseMenu(int state) {
@ -73,6 +75,7 @@ public class GamePauseMenu extends BasicGameState {
throws SlickException { throws SlickException {
this.container = container; this.container = container;
this.game = game; this.game = game;
input = container.getInput();
} }
@Override @Override
@ -105,6 +108,14 @@ public class GamePauseMenu extends BasicGameState {
@Override @Override
public void keyPressed(int key, char c) { 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) { switch (key) {
case Input.KEY_ESCAPE: case Input.KEY_ESCAPE:
// 'esc' will normally unpause, but will return to song menu if health is zero // 'esc' will normally unpause, but will return to song menu if health is zero
@ -124,8 +135,7 @@ public class GamePauseMenu extends BasicGameState {
@Override @Override
public void mousePressed(int button, int x, int y) { public void mousePressed(int button, int x, int y) {
// check mouse button if (button == Input.MOUSE_MIDDLE_BUTTON)
if (button != Input.MOUSE_LEFT_BUTTON)
return; return;
boolean loseState = (Game.getRestart() == Game.RESTART_LOSE); boolean loseState = (Game.getRestart() == Game.RESTART_LOSE);

View File

@ -35,6 +35,7 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.lwjgl.input.Keyboard;
import org.newdawn.slick.AppGameContainer; import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.Color; import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer; import org.newdawn.slick.GameContainer;
@ -124,7 +125,9 @@ public class Options extends BasicGameState {
FIXED_OD, FIXED_OD,
LOAD_VERBOSE, LOAD_VERBOSE,
CHECKPOINT, CHECKPOINT,
DISABLE_SOUNDS; DISABLE_SOUNDS,
KEY_LEFT,
KEY_RIGHT;
}; };
/** /**
@ -186,6 +189,8 @@ public class Options extends BasicGameState {
* Gameplay options. * Gameplay options.
*/ */
private static final GameOption[] gameplayOptions = { private static final GameOption[] gameplayOptions = {
GameOption.KEY_LEFT,
GameOption.KEY_RIGHT,
GameOption.BACKGROUND_DIM, GameOption.BACKGROUND_DIM,
GameOption.FORCE_DEFAULT_PLAYFIELD, GameOption.FORCE_DEFAULT_PLAYFIELD,
GameOption.IGNORE_BEATMAP_SKINS, 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. * By default, sound is disabled on Linux due to possible driver issues.
*/ */
private static boolean disableSound = 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). * Game option coordinate modifiers (for drawing).
@ -462,6 +479,17 @@ public class Options extends BasicGameState {
Utils.getBackButton().draw(); 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.drawFPS();
Utils.drawCursor(); Utils.drawCursor();
} }
@ -477,6 +505,12 @@ public class Options extends BasicGameState {
@Override @Override
public void mousePressed(int button, int x, int y) { public void mousePressed(int button, int x, int y) {
// key entry state
if (keyEntryLeft || keyEntryRight) {
keyEntryLeft = keyEntryRight = false;
return;
}
// check mouse button // check mouse button
if (button == Input.MOUSE_MIDDLE_BUTTON) if (button == Input.MOUSE_MIDDLE_BUTTON)
return; return;
@ -564,6 +598,14 @@ public class Options extends BasicGameState {
case DISABLE_SOUNDS: case DISABLE_SOUNDS:
disableSound = !disableSound; disableSound = !disableSound;
break; break;
case KEY_LEFT:
keyEntryLeft = true;
keyEntryRight = false;
break;
case KEY_RIGHT:
keyEntryLeft = false;
keyEntryRight = true;
break;
default: default:
break; break;
} }
@ -571,6 +613,10 @@ public class Options extends BasicGameState {
@Override @Override
public void mouseDragged(int oldx, int oldy, int newx, int newy) { 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) // check mouse button (right click scrolls faster)
int multiplier; int multiplier;
if (input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON)) if (input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))
@ -660,6 +706,18 @@ public class Options extends BasicGameState {
@Override @Override
public void keyPressed(int key, char c) { 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) { switch (key) {
case Input.KEY_ESCAPE: case Input.KEY_ESCAPE:
SoundController.playSound(SoundController.SOUND_MENUBACK); SoundController.playSound(SoundController.SOUND_MENUBACK);
@ -769,6 +827,18 @@ public class Options extends BasicGameState {
"May resolve Linux sound driver issues. Requires a restart." "May resolve Linux sound driver issues. Requires a restart."
); );
break; 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: case BACKGROUND_DIM:
drawOption(pos, "Background Dim", drawOption(pos, "Background Dim",
String.format("%d%%", backgroundDim), String.format("%d%%", backgroundDim),
@ -1074,6 +1144,26 @@ public class Options extends BasicGameState {
return false; 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. * Returns the beatmap directory.
* If invalid, this will attempt to search for the directory, * If invalid, this will attempt to search for the directory,
@ -1213,6 +1303,22 @@ public class Options extends BasicGameState {
case "DisableSound": case "DisableSound":
disableSound = Boolean.parseBoolean(value); disableSound = Boolean.parseBoolean(value);
break; 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": case "DimLevel":
i = Integer.parseInt(value); i = Integer.parseInt(value);
if (i >= 0 && i <= 100) if (i >= 0 && i <= 100)
@ -1309,6 +1415,10 @@ public class Options extends BasicGameState {
writer.newLine(); writer.newLine();
writer.write(String.format("DisableSound = %b", disableSound)); writer.write(String.format("DisableSound = %b", disableSound));
writer.newLine(); 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.write(String.format("DimLevel = %d", backgroundDim));
writer.newLine(); writer.newLine();
writer.write(String.format("ForceDefaultPlayfield = %b", forceDefaultPlayfield)); writer.write(String.format("ForceDefaultPlayfield = %b", forceDefaultPlayfield));