Replaced native cursors with skinnable ones.

- Added support for both the new (2013+) and old cursor styles.  These can be toggled on/off in the configuration file.
- Added cursor images by XinCrin (old style) and teinecthel (new style).

Other changes:
- Refactoring: Created a "Utils" module, containing methods and constants that didn't belong in the "Options" state and some duplicated drawing methods.
- Mouse is now grabbed during gameplay.
- Removed 'optionsChanged' switch, simplifying adding new options.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han
2014-07-01 19:32:03 -04:00
parent 0604a25822
commit ab487c5e80
20 changed files with 523 additions and 266 deletions

View File

@@ -26,6 +26,7 @@ import itdelatrisu.opsu.OsuFile;
import itdelatrisu.opsu.OsuHitObject;
import itdelatrisu.opsu.OsuTimingPoint;
import itdelatrisu.opsu.SoundController;
import itdelatrisu.opsu.Utils;
import itdelatrisu.opsu.objects.Circle;
import itdelatrisu.opsu.objects.Slider;
import itdelatrisu.opsu.objects.Spinner;
@@ -264,8 +265,6 @@ public class Game extends BasicGameState {
if (!osu.drawBG(width, height, 0.7f))
g.setBackground(Color.black);
Options.drawFPS();
int trackPosition = MusicController.getPosition();
if (pauseTime > -1) // returning from pause screen
trackPosition = pauseTime;
@@ -313,6 +312,9 @@ public class Game extends BasicGameState {
warningArrowL.draw(width * 0.75f, height * 0.75f);
}
}
Utils.drawFPS();
Utils.drawCursor();
return;
}
}
@@ -413,7 +415,7 @@ public class Game extends BasicGameState {
// returning from pause screen
if (pauseTime > -1 && pausedMouseX > -1 && pausedMouseY > -1) {
// darken the screen
g.setColor(Options.COLOR_BLACK_ALPHA);
g.setColor(Utils.COLOR_BLACK_ALPHA);
g.fillRect(0, 0, width, height);
// draw glowing hit select circle and pulse effect
@@ -425,6 +427,9 @@ public class Game extends BasicGameState {
cursorCirclePulse.setAlpha(1f - pausePulse);
cursorCirclePulse.drawCentered(pausedMouseX, pausedMouseY);
}
Utils.drawFPS();
Utils.drawCursor();
}
@Override
@@ -589,7 +594,7 @@ public class Game extends BasicGameState {
mousePressed(Input.MOUSE_RIGHT_BUTTON, input.getMouseX(), input.getMouseY());
break;
case Input.KEY_F12:
Options.takeScreenShot();
Utils.takeScreenShot();
break;
}
}
@@ -647,6 +652,9 @@ public class Game extends BasicGameState {
if (osu == null || osu.objects == null)
throw new RuntimeException("Running game with no OsuFile loaded.");
// grab the mouse
container.setMouseGrabbed(true);
// restart the game
if (restart != RESTART_FALSE) {
// new game
@@ -720,6 +728,12 @@ public class Game extends BasicGameState {
}
}
@Override
public void leave(GameContainer container, StateBasedGame game)
throws SlickException {
container.setMouseGrabbed(false);
}
/**
* Skips the beginning of a track.
* @return true if skipped, false otherwise

View File

@@ -22,6 +22,7 @@ import itdelatrisu.opsu.GUIMenuButton;
import itdelatrisu.opsu.MusicController;
import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.SoundController;
import itdelatrisu.opsu.Utils;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
@@ -117,13 +118,14 @@ public class GamePauseMenu extends BasicGameState {
else
g.setBackground(Color.black);
Options.drawFPS();
// draw buttons
if (Game.getRestart() != Game.RESTART_LOSE)
continueButton.draw();
retryButton.draw();
backButton.draw();
Utils.drawFPS();
Utils.drawCursor();
}
@Override
@@ -149,7 +151,7 @@ public class GamePauseMenu extends BasicGameState {
unPause(Game.RESTART_FALSE);
break;
case Input.KEY_F12:
Options.takeScreenShot();
Utils.takeScreenShot();
break;
}
}

View File

@@ -24,6 +24,7 @@ import itdelatrisu.opsu.MusicController;
import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.OsuFile;
import itdelatrisu.opsu.SoundController;
import itdelatrisu.opsu.Utils;
import org.lwjgl.opengl.Display;
import org.newdawn.slick.Color;
@@ -100,7 +101,7 @@ public class GameRanking extends BasicGameState {
// background
if (!osu.drawBG(width, height, 0.7f))
g.setBackground(Options.COLOR_BLACK_ALPHA);
g.setBackground(Utils.COLOR_BLACK_ALPHA);
// ranking screen elements
score.drawRankingElements(g, width, height);
@@ -118,17 +119,18 @@ public class GameRanking extends BasicGameState {
// header text
g.setColor(Color.white);
Options.FONT_LARGE.drawString(10, 0,
Utils.FONT_LARGE.drawString(10, 0,
String.format("%s - %s [%s]", osu.artist, osu.title, osu.version));
Options.FONT_MEDIUM.drawString(10, Options.FONT_LARGE.getLineHeight() - 6,
Utils.FONT_MEDIUM.drawString(10, Utils.FONT_LARGE.getLineHeight() - 6,
String.format("Beatmap by %s", osu.creator));
// buttons
retryButton.draw();
exitButton.draw();
Options.getBackButton().draw();
Utils.getBackButton().draw();
Options.drawFPS();
Utils.drawFPS();
Utils.drawCursor();
}
@Override
@@ -150,7 +152,7 @@ public class GameRanking extends BasicGameState {
game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
break;
case Input.KEY_F12:
Options.takeScreenShot();
Utils.takeScreenShot();
break;
}
}
@@ -170,7 +172,7 @@ public class GameRanking extends BasicGameState {
} else if (exitButton.contains(x, y)) {
SoundController.playSound(SoundController.SOUND_MENUBACK);
game.enterState(Opsu.STATE_MAINMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
} else if (Options.getBackButton().contains(x, y)) {
} else if (Utils.getBackButton().contains(x, y)) {
MusicController.pause();
MusicController.playAt(Game.getOsuFile().previewTime, true);
SoundController.playSound(SoundController.SOUND_MENUBACK);

View File

@@ -23,6 +23,7 @@ import itdelatrisu.opsu.MusicController;
import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.OsuGroupNode;
import itdelatrisu.opsu.SoundController;
import itdelatrisu.opsu.Utils;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -153,8 +154,8 @@ public class MainMenu extends BasicGameState {
if (backgroundImage != null)
backgroundImage.draw();
else
g.setBackground(Options.COLOR_BLUE_BACKGROUND);
g.setFont(Options.FONT_MEDIUM);
g.setBackground(Utils.COLOR_BLUE_BACKGROUND);
g.setFont(Utils.FONT_MEDIUM);
int width = container.getWidth();
int height = container.getHeight();
@@ -173,7 +174,7 @@ public class MainMenu extends BasicGameState {
musicPlay.draw();
musicNext.draw();
musicPrevious.draw();
g.setColor(Options.COLOR_BLACK_ALPHA);
g.setColor(Utils.COLOR_BLACK_ALPHA);
g.fillRoundRect(width - 168, 54, 148, 5, 4);
g.setColor(Color.white);
if (!MusicController.isConverting())
@@ -181,7 +182,7 @@ public class MainMenu extends BasicGameState {
148f * MusicController.getPosition() / MusicController.getTrackLength(), 5, 4);
// draw text
int lineHeight = Options.FONT_MEDIUM.getLineHeight();
int lineHeight = Utils.FONT_MEDIUM.getLineHeight();
g.drawString(String.format("Loaded %d songs and %d beatmaps.",
Opsu.groups.size(), Opsu.groups.getMapCount()), 25, 25);
if (MusicController.isConverting())
@@ -203,7 +204,8 @@ public class MainMenu extends BasicGameState {
new SimpleDateFormat("h:mm a").format(new Date())),
25, height - 25 - lineHeight);
Options.drawFPS();
Utils.drawFPS();
Utils.drawCursor();
}
@Override
@@ -317,7 +319,7 @@ public class MainMenu extends BasicGameState {
game.enterState(Opsu.STATE_MAINMENUEXIT);
break;
case Input.KEY_F12:
Options.takeScreenShot();
Utils.takeScreenShot();
break;
}

View File

@@ -20,6 +20,7 @@ package itdelatrisu.opsu.states;
import itdelatrisu.opsu.GUIMenuButton;
import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.Utils;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
@@ -90,22 +91,23 @@ public class MainMenuExit extends BasicGameState {
// draw text
float c = container.getWidth() * 0.02f;
Options.FONT_LARGE.drawString(c, c, "Are you sure you want to exit opsu!?");
Utils.FONT_LARGE.drawString(c, c, "Are you sure you want to exit opsu!?");
// draw buttons
yesButton.draw(Color.green);
noButton.draw(Color.red);
g.setFont(Options.FONT_XLARGE);
g.setFont(Utils.FONT_XLARGE);
g.drawString("1. Yes",
yesButton.getX() - (Options.FONT_XLARGE.getWidth("1. Yes") / 2f),
yesButton.getY() - (Options.FONT_XLARGE.getHeight() / 2f)
yesButton.getX() - (Utils.FONT_XLARGE.getWidth("1. Yes") / 2f),
yesButton.getY() - (Utils.FONT_XLARGE.getHeight() / 2f)
);
g.drawString("2. No",
noButton.getX() - (Options.FONT_XLARGE.getWidth("2. No") / 2f),
noButton.getY() - (Options.FONT_XLARGE.getHeight() / 2f)
noButton.getX() - (Utils.FONT_XLARGE.getWidth("2. No") / 2f),
noButton.getY() - (Utils.FONT_XLARGE.getHeight() / 2f)
);
Options.drawFPS();
Utils.drawFPS();
Utils.drawCursor();
}
@Override
@@ -150,7 +152,7 @@ public class MainMenuExit extends BasicGameState {
game.enterState(Opsu.STATE_MAINMENU, new EmptyTransition(), new FadeInTransition(Color.black));
break;
case Input.KEY_F12:
Options.takeScreenShot();
Utils.takeScreenShot();
break;
}
}

View File

@@ -20,9 +20,8 @@ package itdelatrisu.opsu.states;
import itdelatrisu.opsu.GUIMenuButton;
import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.SoundController;
import itdelatrisu.opsu.Utils;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
@@ -39,8 +38,6 @@ import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.TrueTypeFont;
import org.newdawn.slick.imageout.ImageOut;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.state.transition.EmptyTransition;
@@ -85,41 +82,6 @@ public class Options extends BasicGameState {
*/
private static final String OPTIONS_FILE = ".opsu.cfg";
/**
* Whether or not any changes were made to options.
* If false, the options file will not be modified.
*/
private static boolean optionsChanged = false;
/**
* Game colors.
*/
public static final Color
COLOR_BLACK_ALPHA = new Color(0, 0, 0, 0.5f),
COLOR_BLUE_DIVIDER = new Color(49, 94, 237),
COLOR_BLUE_BACKGROUND = new Color(74, 130, 255),
COLOR_BLUE_BUTTON = new Color(50, 189, 237),
COLOR_ORANGE_BUTTON = new Color(230, 151, 87),
COLOR_GREEN_OBJECT = new Color(26, 207, 26),
COLOR_BLUE_OBJECT = new Color(46, 136, 248),
COLOR_RED_OBJECT = new Color(243, 48, 77),
COLOR_ORANGE_OBJECT = new Color(255, 200, 32);
/**
* The default map colors, used when a map does not provide custom colors.
*/
public static final Color[] DEFAULT_COMBO = {
COLOR_GREEN_OBJECT, COLOR_BLUE_OBJECT,
COLOR_RED_OBJECT, COLOR_ORANGE_OBJECT
};
/**
* Game fonts.
*/
public static TrueTypeFont
FONT_DEFAULT, FONT_BOLD,
FONT_XLARGE, FONT_LARGE, FONT_MEDIUM, FONT_SMALL;
/**
* Game mods.
*/
@@ -235,12 +197,12 @@ public class Options extends BasicGameState {
/**
* Port binding.
*/
private static int port = 0;
private static int port = 49250;
/**
* Back button (shared by other states).
* Whether or not to use the new cursor type.
*/
private static GUIMenuButton backButton;
private static boolean newCursor = true;
/**
* Game option coordinate modifiers (for drawing).
@@ -248,8 +210,8 @@ public class Options extends BasicGameState {
private int textY, offsetY;
// game-related variables
private static GameContainer container;
private static StateBasedGame game;
private GameContainer container;
private StateBasedGame game;
private Input input;
private int state;
private boolean init = false;
@@ -261,42 +223,17 @@ public class Options extends BasicGameState {
@Override
public void init(GameContainer container, StateBasedGame game)
throws SlickException {
Options.container = container;
Options.game = game;
this.container = container;
this.game = game;
this.input = container.getInput();
// game settings
container.setTargetFrameRate(targetFPS[targetFPSindex]);
container.setMouseCursor("cursor.png", 16, 16);
container.setMusicVolume(getMusicVolume());
container.setShowFPS(false);
container.getInput().enableKeyRepeat();
container.setAlwaysRender(true);
// create fonts
float fontBase;
if (container.getHeight() <= 600)
fontBase = 9f;
else if (container.getHeight() < 800)
fontBase = 10f;
else if (container.getHeight() <= 900)
fontBase = 12f;
else
fontBase = 14f;
Font font = new Font("Lucida Sans Unicode", Font.PLAIN, (int) (fontBase * 4 / 3));
FONT_DEFAULT = new TrueTypeFont(font, false);
FONT_BOLD = new TrueTypeFont(font.deriveFont(Font.BOLD), false);
FONT_XLARGE = new TrueTypeFont(font.deriveFont(fontBase * 4), false);
FONT_LARGE = new TrueTypeFont(font.deriveFont(fontBase * 2), false);
FONT_MEDIUM = new TrueTypeFont(font.deriveFont(fontBase * 3 / 2), false);
FONT_SMALL = new TrueTypeFont(font.deriveFont(fontBase), false);
Utils.init(container, game);
int width = container.getWidth();
int height = container.getHeight();
// game option coordinate modifiers
textY = 10 + (FONT_XLARGE.getLineHeight() * 3 / 2);
textY = 10 + (Utils.FONT_XLARGE.getLineHeight() * 3 / 2);
offsetY = (int) (((height * 0.8f) - textY) / OPTIONS_MAX);
// game mods
@@ -330,14 +267,6 @@ public class Options extends BasicGameState {
for (int i = 0; i < modButtons.length; i++)
modButtons[i].getImage().setAlpha(0.5f);
// back button
Image back = new Image("menu-back.png");
float scale = (height * 0.1f) / back.getHeight();
back = back.getScaledCopy(scale);
backButton = new GUIMenuButton(back,
back.getWidth() / 2f,
height - (back.getHeight() / 2f));
game.enterState(Opsu.STATE_MAINMENU, new EmptyTransition(), new FadeInTransition(Color.black));
}
@@ -347,25 +276,25 @@ public class Options extends BasicGameState {
if (!init)
return;
g.setBackground(COLOR_BLACK_ALPHA);
g.setBackground(Utils.COLOR_BLACK_ALPHA);
g.setColor(Color.white);
int width = container.getWidth();
int height = container.getHeight();
// title
FONT_XLARGE.drawString(
(width / 2) - (FONT_XLARGE.getWidth("GAME OPTIONS") / 2),
Utils.FONT_XLARGE.drawString(
(width / 2) - (Utils.FONT_XLARGE.getWidth("GAME OPTIONS") / 2),
10, "GAME OPTIONS"
);
FONT_DEFAULT.drawString(
(width / 2) - (FONT_DEFAULT.getWidth("Click or drag an option to change it.") / 2),
10 + FONT_XLARGE.getHeight(), "Click or drag an option to change it."
Utils.FONT_DEFAULT.drawString(
(width / 2) - (Utils.FONT_DEFAULT.getWidth("Click or drag an option to change it.") / 2),
10 + Utils.FONT_XLARGE.getHeight(), "Click or drag an option to change it."
);
// game options
g.setLineWidth(1f);
g.setFont(FONT_LARGE);
g.setFont(Utils.FONT_LARGE);
this.drawOption(g, OPTIONS_SCREEN_RESOLUTION, "Screen Resolution",
String.format("%dx%d", resolutions[resolutionIndex][0], resolutions[resolutionIndex][1]),
"Restart to apply resolution changes."
@@ -375,7 +304,7 @@ public class Options extends BasicGameState {
// "Restart to apply changes."
// );
this.drawOption(g, OPTIONS_TARGET_FPS, "Frame Limiter",
String.format("%dfps", targetFPS[targetFPSindex]),
String.format("%dfps", getTargetFPS()),
"Higher values may cause high CPU usage."
);
this.drawOption(g, OPTIONS_MUSIC_VOLUME, "Music Volume",
@@ -408,13 +337,14 @@ public class Options extends BasicGameState {
);
// game mods
FONT_LARGE.drawString(width * 0.02f, height * 0.8f, "Game Mods:", Color.white);
Utils.FONT_LARGE.drawString(width * 0.02f, height * 0.8f, "Game Mods:", Color.white);
for (int i = 0; i < modButtons.length; i++)
modButtons[i].draw();
backButton.draw();
Utils.getBackButton().draw();
drawFPS();
Utils.drawFPS();
Utils.drawCursor();
}
@Override
@@ -433,7 +363,7 @@ public class Options extends BasicGameState {
return;
// back
if (backButton.contains(x, y)) {
if (Utils.getBackButton().contains(x, y)) {
game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition(Color.black));
return;
}
@@ -472,7 +402,7 @@ public class Options extends BasicGameState {
// }
if (isOptionClicked(OPTIONS_TARGET_FPS, y)) {
targetFPSindex = (targetFPSindex + 1) % targetFPS.length;
container.setTargetFrameRate(targetFPS[targetFPSindex]);
container.setTargetFrameRate(getTargetFPS());
return;
}
if (isOptionClicked(OPTIONS_SCREENSHOT_FORMAT, y)) {
@@ -545,7 +475,7 @@ public class Options extends BasicGameState {
game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition(Color.black));
break;
case Input.KEY_F12:
Options.takeScreenShot();
Utils.takeScreenShot();
break;
}
}
@@ -560,14 +490,14 @@ public class Options extends BasicGameState {
*/
private void drawOption(Graphics g, int pos, String label, String value, String notes) {
int width = container.getWidth();
int textHeight = FONT_LARGE.getHeight();
int textHeight = Utils.FONT_LARGE.getHeight();
float y = textY + (pos * offsetY);
g.drawString(label, width / 50, y);
g.drawString(value, width / 2, y);
g.drawLine(0, y + textHeight, width, y + textHeight);
if (notes != null)
FONT_SMALL.drawString(width / 50, y + textHeight, notes);
Utils.FONT_SMALL.drawString(width / 50, y + textHeight, notes);
}
/**
@@ -577,12 +507,8 @@ public class Options extends BasicGameState {
* @return true if clicked
*/
private boolean isOptionClicked(int pos, int y) {
if (y > textY + (offsetY * pos) - FONT_LARGE.getHeight() &&
y < textY + (offsetY * pos) + FONT_LARGE.getHeight()) {
optionsChanged = true;
return true;
}
return false;
return (y > textY + (offsetY * pos) - Utils.FONT_LARGE.getHeight() &&
y < textY + (offsetY * pos) + Utils.FONT_LARGE.getHeight());
}
/**
@@ -610,9 +536,10 @@ public class Options extends BasicGameState {
public static Image getModImage(int mod) { return modButtons[mod].getImage(); }
/**
* Returns the 'back' GUIMenuButton.
* Returns the target frame rate.
* @return the target FPS
*/
public static GUIMenuButton getBackButton() { return backButton; }
public static int getTargetFPS() { return targetFPS[targetFPSindex]; }
/**
* Returns the default music volume.
@@ -633,53 +560,10 @@ public class Options extends BasicGameState {
public static int getMusicOffset() { return musicOffset; }
/**
* Draws the FPS at the bottom-right corner of the game container.
* If the option is not activated, this will do nothing.
* Returns the screenshot file format.
* @return the file extension ("png", "jpg", "bmp")
*/
public static void drawFPS() {
if (showFPS) {
String fps = String.format("FPS: %d", container.getFPS());
FONT_DEFAULT.drawString(
container.getWidth() - 15 - FONT_DEFAULT.getWidth(fps),
container.getHeight() - 15 - FONT_DEFAULT.getHeight(fps),
fps, Color.white
);
}
}
/**
* Takes a screenshot.
* @return true if successful
*/
public static boolean takeScreenShot() {
// TODO: should this be threaded?
try {
// create the screenshot directory
if (!SCREENSHOT_DIR.isDirectory()) {
if (!SCREENSHOT_DIR.mkdir())
return false;
}
// create file name
SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd_HHmmss");
String file = date.format(new Date());
SoundController.playSound(SoundController.SOUND_SHUTTER);
// copy the screen
Image screen = new Image(container.getWidth(), container.getHeight());
container.getGraphics().copyArea(screen, 0, 0);
ImageOut.write(screen, String.format("%s%sscreenshot_%s.%s",
SCREENSHOT_DIR.getName(), File.separator,
file, screenshotFormat[screenshotFormatIndex]), false
);
screen.destroy();
} catch (SlickException e) {
Log.warn("Failed to take a screenshot.", e);
return false;
}
return true;
}
public static String getScreenshotFormat() { return screenshotFormat[screenshotFormatIndex]; }
/**
* Returns the screen resolution.
@@ -693,6 +577,12 @@ public class Options extends BasicGameState {
// */
// public static boolean isFullscreen() { return fullscreen; }
/**
* Returns whether or not the FPS counter display is enabled.
* @return true if enabled
*/
public static boolean isFPSCounterEnabled() { return showFPS; }
/**
* Returns whether or not hit lighting effects are enabled.
* @return true if enabled
@@ -709,14 +599,13 @@ public class Options extends BasicGameState {
* Returns the port number to bind to.
* @return the port
*/
public static int getPort() {
if (port == 0) {
// choose a random port
port = 49250;
optionsChanged = true; // force file creation
}
return port;
}
public static int getPort() { return port; }
/**
* Returns whether or not the new cursor type is enabled.
* @return true if enabled
*/
public static boolean isNewCursorEnabled() { return newCursor; }
/**
* Returns the current beatmap directory.
@@ -730,15 +619,14 @@ public class Options extends BasicGameState {
// search for directory
for (int i = 0; i < BEATMAP_DIRS.length; i++) {
beatmapDir = new File(BEATMAP_DIRS[i]);
if (beatmapDir.isDirectory()) {
optionsChanged = true; // force config file creation
if (beatmapDir.isDirectory())
return beatmapDir;
}
}
beatmapDir.mkdir(); // none found, create new directory
return beatmapDir;
}
/**
* Reads user options from the options file, if it exists.
*/
@@ -746,9 +634,7 @@ public class Options extends BasicGameState {
// if no config file, use default settings
File file = new File(OPTIONS_FILE);
if (!file.isFile()) {
optionsChanged = true; // force file creation
saveOptions();
optionsChanged = false;
return;
}
@@ -816,6 +702,9 @@ public class Options extends BasicGameState {
if (i > 0 && i <= 65535)
port = i;
break;
case "NewCursor": // custom
newCursor = Boolean.parseBoolean(value);
break;
}
}
} catch (IOException e) {
@@ -830,10 +719,6 @@ public class Options extends BasicGameState {
* (Over)writes user options to a file.
*/
public static void saveOptions() {
// only overwrite when needed
if (!optionsChanged)
return;
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(OPTIONS_FILE), "utf-8"))) {
// header
@@ -873,6 +758,8 @@ public class Options extends BasicGameState {
writer.newLine();
writer.write(String.format("Port = %d", port));
writer.newLine();
writer.write(String.format("NewCursor = %b", newCursor)); // custom
writer.newLine();
writer.close();
} catch (IOException e) {
Log.error(String.format("Failed to write to file '%s'.", OPTIONS_FILE), e);

View File

@@ -26,6 +26,7 @@ import itdelatrisu.opsu.OsuGroupList;
import itdelatrisu.opsu.OsuGroupNode;
import itdelatrisu.opsu.OsuParser;
import itdelatrisu.opsu.SoundController;
import itdelatrisu.opsu.Utils;
import org.lwjgl.opengl.Display;
import org.newdawn.slick.Color;
@@ -170,13 +171,13 @@ public class SongMenu extends BasicGameState {
searchResultString = "Type to search!";
searchIcon = new Image("search.png");
float iconScale = Options.FONT_BOLD.getLineHeight() * 2f / searchIcon.getHeight();
float iconScale = Utils.FONT_BOLD.getLineHeight() * 2f / searchIcon.getHeight();
searchIcon = searchIcon.getScaledCopy(iconScale);
search = new TextField(
container, Options.FONT_DEFAULT,
container, Utils.FONT_DEFAULT,
(int) tabX + searchIcon.getWidth(), (int) ((height * 0.15f) - (tab.getHeight() * 5 / 2f)),
(int) (buttonWidth / 2), Options.FONT_DEFAULT.getHeight()
(int) (buttonWidth / 2), Utils.FONT_DEFAULT.getHeight()
);
search.setBackgroundColor(Color.transparent);
search.setBorderColor(Color.transparent);
@@ -205,9 +206,9 @@ public class SongMenu extends BasicGameState {
// header setup
float lowerBound = height * 0.15f;
g.setColor(Options.COLOR_BLACK_ALPHA);
g.setColor(Utils.COLOR_BLACK_ALPHA);
g.fillRect(0, 0, width, lowerBound);
g.setColor(Options.COLOR_BLUE_DIVIDER);
g.setColor(Utils.COLOR_BLUE_DIVIDER);
g.setLineWidth(2f);
g.drawLine(0, lowerBound, width, lowerBound);
g.resetLineWidth();
@@ -220,17 +221,17 @@ public class SongMenu extends BasicGameState {
String[] info = focusNode.getInfo();
g.setColor(Color.white);
Options.FONT_LARGE.drawString(
Utils.FONT_LARGE.drawString(
musicNoteWidth + 5, -3, info[0]);
float y1 = -3 + Options.FONT_LARGE.getHeight() * 0.75f;
Options.FONT_DEFAULT.drawString(
float y1 = -3 + Utils.FONT_LARGE.getHeight() * 0.75f;
Utils.FONT_DEFAULT.drawString(
musicNoteWidth + 5, y1, info[1]);
Options.FONT_BOLD.drawString(
Utils.FONT_BOLD.drawString(
5, Math.max(y1 + 4, musicNoteHeight - 3), info[2]);
Options.FONT_DEFAULT.drawString(
5, musicNoteHeight + Options.FONT_BOLD.getLineHeight() - 9, info[3]);
Options.FONT_SMALL.drawString(
5, musicNoteHeight + Options.FONT_BOLD.getLineHeight() + Options.FONT_DEFAULT.getLineHeight() - 13, info[4]);
Utils.FONT_DEFAULT.drawString(
5, musicNoteHeight + Utils.FONT_BOLD.getLineHeight() - 9, info[3]);
Utils.FONT_SMALL.drawString(
5, musicNoteHeight + Utils.FONT_BOLD.getLineHeight() + Utils.FONT_DEFAULT.getLineHeight() - 13, info[4]);
}
// song buttons
@@ -248,17 +249,17 @@ public class SongMenu extends BasicGameState {
for (int i = sortTabs.length - 1; i >= 0; i--) {
sortTabs[i].getImage().setAlpha((i == currentSort) ? 1.0f : 0.7f);
sortTabs[i].draw();
float tabTextX = sortTabs[i].getX() - (Options.FONT_MEDIUM.getWidth(OsuGroupList.SORT_NAMES[i]) / 2);
Options.FONT_MEDIUM.drawString(tabTextX, tabTextY, OsuGroupList.SORT_NAMES[i], Color.white);
float tabTextX = sortTabs[i].getX() - (Utils.FONT_MEDIUM.getWidth(OsuGroupList.SORT_NAMES[i]) / 2);
Utils.FONT_MEDIUM.drawString(tabTextX, tabTextY, OsuGroupList.SORT_NAMES[i], Color.white);
}
// search
Options.FONT_BOLD.drawString(
search.getX(), search.getY() - Options.FONT_BOLD.getLineHeight(),
Utils.FONT_BOLD.drawString(
search.getX(), search.getY() - Utils.FONT_BOLD.getLineHeight(),
searchResultString, Color.white
);
searchIcon.draw(search.getX() - searchIcon.getWidth(),
search.getY() - Options.FONT_DEFAULT.getLineHeight());
search.getY() - Utils.FONT_DEFAULT.getLineHeight());
g.setColor(Color.white);
search.render(container, g);
@@ -266,16 +267,17 @@ public class SongMenu extends BasicGameState {
if (focusNode != null) {
float scrollStartY = height * 0.16f;
float scrollEndY = height * 0.82f;
g.setColor(Options.COLOR_BLACK_ALPHA);
g.setColor(Utils.COLOR_BLACK_ALPHA);
g.fillRoundRect(width - 10, scrollStartY, 5, scrollEndY, 4);
g.setColor(Color.white);
g.fillRoundRect(width - 10, scrollStartY + (scrollEndY * startNode.index / Opsu.groups.size()), 5, 20, 4);
}
// back button
Options.getBackButton().draw();
Utils.getBackButton().draw();
Options.drawFPS();
Utils.drawFPS();
Utils.drawCursor();
}
@Override
@@ -343,7 +345,7 @@ public class SongMenu extends BasicGameState {
return;
// back
if (Options.getBackButton().contains(x, y)) {
if (Utils.getBackButton().contains(x, y)) {
SoundController.playSound(SoundController.SOUND_MENUBACK);
game.enterState(Opsu.STATE_MAINMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
return;
@@ -436,7 +438,7 @@ public class SongMenu extends BasicGameState {
setFocus(Opsu.groups.getRandomNode(), -1, true);
break;
case Input.KEY_F12:
Options.takeScreenShot();
Utils.takeScreenShot();
break;
case Input.KEY_ENTER:
if (focusNode != null)