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:
parent
0604a25822
commit
ab487c5e80
|
@ -17,6 +17,7 @@ The images included in opsu! belong to their respective authors.
|
||||||
* pictuga - "osu! web"
|
* pictuga - "osu! web"
|
||||||
* sherrie__fay
|
* sherrie__fay
|
||||||
* kouyang
|
* kouyang
|
||||||
|
* teinecthel
|
||||||
|
|
||||||
Projects
|
Projects
|
||||||
--------
|
--------
|
||||||
|
|
BIN
res/cursor.png
BIN
res/cursor.png
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 5.7 KiB |
BIN
res/cursor2.png
Normal file
BIN
res/cursor2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
BIN
res/cursormiddle.png
Normal file
BIN
res/cursormiddle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 565 B |
BIN
res/cursortrail.png
Normal file
BIN
res/cursortrail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
BIN
res/cursortrail2.png
Normal file
BIN
res/cursortrail2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
|
@ -509,7 +509,7 @@ public class GameScore {
|
||||||
|
|
||||||
// header & "Ranking" text
|
// header & "Ranking" text
|
||||||
float rankingHeight = (rankingImage.getHeight() * 0.75f) + 3;
|
float rankingHeight = (rankingImage.getHeight() * 0.75f) + 3;
|
||||||
g.setColor(Options.COLOR_BLACK_ALPHA);
|
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||||
g.fillRect(0, 0, width, rankingHeight);
|
g.fillRect(0, 0, width, rankingHeight);
|
||||||
rankingImage.draw((width * 0.97f) - rankingImage.getWidth(), 0);
|
rankingImage.draw((width * 0.97f) - rankingImage.getWidth(), 0);
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu;
|
package itdelatrisu.opsu;
|
||||||
|
|
||||||
import itdelatrisu.opsu.states.Options;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
@ -128,21 +126,21 @@ public class OsuGroupNode implements Comparable<OsuGroupNode> {
|
||||||
textColor = Color.white;
|
textColor = Color.white;
|
||||||
} else {
|
} else {
|
||||||
xOffset = bg.getWidth() * 0.05f;
|
xOffset = bg.getWidth() * 0.05f;
|
||||||
bg.draw(x + xOffset, y, Options.COLOR_BLUE_BUTTON);
|
bg.draw(x + xOffset, y, Utils.COLOR_BLUE_BUTTON);
|
||||||
}
|
}
|
||||||
osu = osuFiles.get(osuFileIndex);
|
osu = osuFiles.get(osuFileIndex);
|
||||||
} else {
|
} else {
|
||||||
bg.draw(x, y, Options.COLOR_ORANGE_BUTTON);
|
bg.draw(x, y, Utils.COLOR_ORANGE_BUTTON);
|
||||||
osu = osuFiles.get(0);
|
osu = osuFiles.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float cx = x + (bg.getWidth() * 0.05f) + xOffset;
|
float cx = x + (bg.getWidth() * 0.05f) + xOffset;
|
||||||
float cy = y + (bg.getHeight() * 0.2f) - 3;
|
float cy = y + (bg.getHeight() * 0.2f) - 3;
|
||||||
|
|
||||||
Options.FONT_MEDIUM.drawString(cx, cy, osu.title, textColor);
|
Utils.FONT_MEDIUM.drawString(cx, cy, osu.title, textColor);
|
||||||
Options.FONT_DEFAULT.drawString(cx, cy + Options.FONT_MEDIUM.getLineHeight() - 4, String.format("%s // %s", osu.artist, osu.creator), textColor);
|
Utils.FONT_DEFAULT.drawString(cx, cy + Utils.FONT_MEDIUM.getLineHeight() - 4, String.format("%s // %s", osu.artist, osu.creator), textColor);
|
||||||
if (expanded)
|
if (expanded)
|
||||||
Options.FONT_BOLD.drawString(cx, cy + Options.FONT_MEDIUM.getLineHeight() + Options.FONT_DEFAULT.getLineHeight() - 8, osu.version, textColor);
|
Utils.FONT_BOLD.drawString(cx, cy + Utils.FONT_MEDIUM.getLineHeight() + Utils.FONT_DEFAULT.getLineHeight() - 8, osu.version, textColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,15 +18,12 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu;
|
package itdelatrisu.opsu;
|
||||||
|
|
||||||
import itdelatrisu.opsu.states.Options;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
@ -104,8 +101,6 @@ public class OsuParser {
|
||||||
|
|
||||||
try (BufferedReader in = new BufferedReader(new FileReader(file))) {
|
try (BufferedReader in = new BufferedReader(new FileReader(file))) {
|
||||||
|
|
||||||
// copy the default combo colors
|
|
||||||
osu.combo = Arrays.copyOf(Options.DEFAULT_COMBO, Options.DEFAULT_COMBO.length);
|
|
||||||
// initialize timing point list
|
// initialize timing point list
|
||||||
osu.timingPoints = new ArrayList<OsuTimingPoint>();
|
osu.timingPoints = new ArrayList<OsuTimingPoint>();
|
||||||
|
|
||||||
|
@ -403,7 +398,7 @@ public class OsuParser {
|
||||||
|
|
||||||
// if no custom colors, use the default color scheme
|
// if no custom colors, use the default color scheme
|
||||||
if (osu.combo == null)
|
if (osu.combo == null)
|
||||||
osu.combo = Options.DEFAULT_COMBO;
|
osu.combo = Utils.DEFAULT_COMBO;
|
||||||
|
|
||||||
// add tags
|
// add tags
|
||||||
if (!tags.isEmpty()) {
|
if (!tags.isEmpty()) {
|
||||||
|
|
369
src/itdelatrisu/opsu/Utils.java
Normal file
369
src/itdelatrisu/opsu/Utils.java
Normal file
|
@ -0,0 +1,369 @@
|
||||||
|
/*
|
||||||
|
* opsu! - an open-source osu! client
|
||||||
|
* Copyright (C) 2014 Jeffrey Han
|
||||||
|
*
|
||||||
|
* opsu! is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* opsu! is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with opsu!. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package itdelatrisu.opsu;
|
||||||
|
|
||||||
|
import itdelatrisu.opsu.states.Options;
|
||||||
|
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.io.File;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.LWJGLException;
|
||||||
|
import org.lwjgl.input.Cursor;
|
||||||
|
import org.newdawn.slick.Animation;
|
||||||
|
import org.newdawn.slick.Color;
|
||||||
|
import org.newdawn.slick.GameContainer;
|
||||||
|
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.StateBasedGame;
|
||||||
|
import org.newdawn.slick.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains miscellaneous utilities.
|
||||||
|
*/
|
||||||
|
public class Utils {
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Back button (shared by other states).
|
||||||
|
*/
|
||||||
|
private static GUIMenuButton backButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cursor image and trail.
|
||||||
|
*/
|
||||||
|
private static Image cursor, cursorTrail, cursorMiddle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last cursor coordinates.
|
||||||
|
*/
|
||||||
|
private static int lastX = -1, lastY = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores all previous cursor locations to display a trail.
|
||||||
|
*/
|
||||||
|
private static LinkedList<Integer>
|
||||||
|
cursorX = new LinkedList<Integer>(),
|
||||||
|
cursorY = new LinkedList<Integer>();
|
||||||
|
|
||||||
|
// game-related variables
|
||||||
|
private static GameContainer container;
|
||||||
|
// private static StateBasedGame game;
|
||||||
|
private static Input input;
|
||||||
|
|
||||||
|
// This class should not be instantiated.
|
||||||
|
private Utils() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes game settings and class data.
|
||||||
|
* @param container the game container
|
||||||
|
* @param game the game object
|
||||||
|
* @throws SlickException
|
||||||
|
*/
|
||||||
|
public static void init(GameContainer container, StateBasedGame game)
|
||||||
|
throws SlickException {
|
||||||
|
Utils.container = container;
|
||||||
|
// Utils.game = game;
|
||||||
|
Utils.input = container.getInput();
|
||||||
|
|
||||||
|
// game settings
|
||||||
|
container.setTargetFrameRate(Options.getTargetFPS());
|
||||||
|
container.setMusicVolume(Options.getMusicVolume());
|
||||||
|
container.setShowFPS(false);
|
||||||
|
container.getInput().enableKeyRepeat();
|
||||||
|
container.setAlwaysRender(true);
|
||||||
|
|
||||||
|
// hide the cursor
|
||||||
|
try {
|
||||||
|
Cursor emptyCursor = new Cursor(1, 1, 0, 0, 1, BufferUtils.createIntBuffer(1), null);
|
||||||
|
container.setMouseCursor(emptyCursor, 0, 0);
|
||||||
|
} catch (LWJGLException e) {
|
||||||
|
Log.error("Failed to set the cursor.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load cursor images
|
||||||
|
if (Options.isNewCursorEnabled()) {
|
||||||
|
// load new cursor type
|
||||||
|
try {
|
||||||
|
cursorMiddle = new Image("cursormiddle.png");
|
||||||
|
cursor = new Image("cursor.png");
|
||||||
|
cursorTrail = new Image("cursortrail.png");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// optional
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cursorMiddle == null) {
|
||||||
|
// load old cursor type
|
||||||
|
cursor = new Image("cursor2.png");
|
||||||
|
cursorTrail = new Image("cursortrail2.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create fonts
|
||||||
|
int height = container.getHeight();
|
||||||
|
float fontBase;
|
||||||
|
if (height <= 600)
|
||||||
|
fontBase = 9f;
|
||||||
|
else if (height < 800)
|
||||||
|
fontBase = 10f;
|
||||||
|
else if (height <= 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);
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the 'back' GUIMenuButton.
|
||||||
|
*/
|
||||||
|
public static GUIMenuButton getBackButton() { return backButton; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws an image based on its center with a color filter.
|
||||||
|
* @param img the image to draw
|
||||||
|
* @param x the center x coordinate
|
||||||
|
* @param y the center y coordinate
|
||||||
|
* @param color the color filter to apply
|
||||||
|
*/
|
||||||
|
public static void drawCentered(Image img, float x, float y, Color color) {
|
||||||
|
img.draw(x - (img.getWidth() / 2f), y - (img.getHeight() / 2f), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws an animation based on its center.
|
||||||
|
* @param anim the animation to draw
|
||||||
|
* @param x the center x coordinate
|
||||||
|
* @param y the center y coordinate
|
||||||
|
*/
|
||||||
|
public static void drawCentered(Animation anim, float x, float y) {
|
||||||
|
anim.draw(x - (anim.getWidth() / 2f), y - (anim.getHeight() / 2f));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the cursor.
|
||||||
|
*/
|
||||||
|
public static void drawCursor() {
|
||||||
|
// TODO: use an image buffer
|
||||||
|
|
||||||
|
int x = input.getMouseX();
|
||||||
|
int y = input.getMouseY();
|
||||||
|
|
||||||
|
int removeCount = 0;
|
||||||
|
int FPSmod = (Options.getTargetFPS() / 60);
|
||||||
|
|
||||||
|
// if middle exists, add all points between cursor movements
|
||||||
|
if (cursorMiddle != null) {
|
||||||
|
if (lastX < 0) {
|
||||||
|
lastX = x;
|
||||||
|
lastY = y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addCursorPoints(lastX, lastY, x, y);
|
||||||
|
lastX = x;
|
||||||
|
lastY = y;
|
||||||
|
|
||||||
|
removeCount = (cursorX.size() / (6 * FPSmod)) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// else, sample one point at a time
|
||||||
|
else {
|
||||||
|
cursorX.add(x);
|
||||||
|
cursorY.add(y);
|
||||||
|
|
||||||
|
int max = 10 * FPSmod;
|
||||||
|
if (cursorX.size() > max)
|
||||||
|
removeCount = cursorX.size() - max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove points from the lists
|
||||||
|
for (int i = 0; i < removeCount && !cursorX.isEmpty(); i++) {
|
||||||
|
cursorX.remove();
|
||||||
|
cursorY.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw a fading trail
|
||||||
|
float alpha = 0f;
|
||||||
|
float t = 2f / cursorX.size();
|
||||||
|
Iterator<Integer> iterX = cursorX.iterator();
|
||||||
|
Iterator<Integer> iterY = cursorY.iterator();
|
||||||
|
while (iterX.hasNext()) {
|
||||||
|
int cx = iterX.next();
|
||||||
|
int cy = iterY.next();
|
||||||
|
alpha += t;
|
||||||
|
cursorTrail.setAlpha(alpha);
|
||||||
|
// if (cx != x || cy != y)
|
||||||
|
cursorTrail.drawCentered(cx, cy);
|
||||||
|
}
|
||||||
|
cursorTrail.drawCentered(x, y);
|
||||||
|
|
||||||
|
// draw the other components
|
||||||
|
cursor.drawCentered(x, y);
|
||||||
|
if (cursorMiddle != null)
|
||||||
|
cursorMiddle.drawCentered(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all points between (x1, y1) and (x2, y2) to the cursor point lists.
|
||||||
|
* @author http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#Java
|
||||||
|
*/
|
||||||
|
private static void addCursorPoints(int x1, int y1, int x2, int y2) {
|
||||||
|
// delta of exact value and rounded value of the dependent variable
|
||||||
|
int d = 0;
|
||||||
|
int dy = Math.abs(y2 - y1);
|
||||||
|
int dx = Math.abs(x2 - x1);
|
||||||
|
|
||||||
|
int dy2 = (dy << 1); // slope scaling factors to avoid floating
|
||||||
|
int dx2 = (dx << 1); // point
|
||||||
|
int ix = x1 < x2 ? 1 : -1; // increment direction
|
||||||
|
int iy = y1 < y2 ? 1 : -1;
|
||||||
|
|
||||||
|
int k = 5; // sample size
|
||||||
|
if (dy <= dx) {
|
||||||
|
for (int i = 0; ; i++) {
|
||||||
|
if (i == k) {
|
||||||
|
cursorX.add(x1);
|
||||||
|
cursorY.add(y1);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
if (x1 == x2)
|
||||||
|
break;
|
||||||
|
x1 += ix;
|
||||||
|
d += dy2;
|
||||||
|
if (d > dx) {
|
||||||
|
y1 += iy;
|
||||||
|
d -= dx2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; ; i++) {
|
||||||
|
if (i == k) {
|
||||||
|
cursorX.add(x1);
|
||||||
|
cursorY.add(y1);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
if (y1 == y2)
|
||||||
|
break;
|
||||||
|
y1 += iy;
|
||||||
|
d += dx2;
|
||||||
|
if (d > dy) {
|
||||||
|
x1 += ix;
|
||||||
|
d -= dy2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the FPS at the bottom-right corner of the game container.
|
||||||
|
* If the option is not activated, this will do nothing.
|
||||||
|
*/
|
||||||
|
public static void drawFPS() {
|
||||||
|
if (!Options.isFPSCounterEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
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 (!Options.SCREENSHOT_DIR.isDirectory()) {
|
||||||
|
if (!Options.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",
|
||||||
|
Options.SCREENSHOT_DIR.getName(), File.separator,
|
||||||
|
file, Options.getScreenshotFormat()), false
|
||||||
|
);
|
||||||
|
screen.destroy();
|
||||||
|
} catch (SlickException e) {
|
||||||
|
Log.warn("Failed to take a screenshot.", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ package itdelatrisu.opsu.objects;
|
||||||
import itdelatrisu.opsu.GameScore;
|
import itdelatrisu.opsu.GameScore;
|
||||||
import itdelatrisu.opsu.MusicController;
|
import itdelatrisu.opsu.MusicController;
|
||||||
import itdelatrisu.opsu.OsuHitObject;
|
import itdelatrisu.opsu.OsuHitObject;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
import itdelatrisu.opsu.states.Game;
|
import itdelatrisu.opsu.states.Game;
|
||||||
import itdelatrisu.opsu.states.Options;
|
import itdelatrisu.opsu.states.Options;
|
||||||
|
|
||||||
|
@ -120,21 +121,14 @@ public class Circle {
|
||||||
|
|
||||||
if (timeDiff >= 0) {
|
if (timeDiff >= 0) {
|
||||||
float approachScale = 1 + (timeDiff * 2f / game.getApproachTime());
|
float approachScale = 1 + (timeDiff * 2f / game.getApproachTime());
|
||||||
drawCentered(approachCircle.getScaledCopy(approachScale), hitObject.x, hitObject.y, color);
|
Utils.drawCentered(approachCircle.getScaledCopy(approachScale), hitObject.x, hitObject.y, color);
|
||||||
drawCentered(hitCircleOverlay, hitObject.x, hitObject.y, Color.white);
|
Utils.drawCentered(hitCircleOverlay, hitObject.x, hitObject.y, Color.white);
|
||||||
drawCentered(hitCircle, hitObject.x, hitObject.y, color);
|
Utils.drawCentered(hitCircle, hitObject.x, hitObject.y, color);
|
||||||
score.drawSymbolNumber(hitObject.comboNumber, hitObject.x, hitObject.y,
|
score.drawSymbolNumber(hitObject.comboNumber, hitObject.x, hitObject.y,
|
||||||
hitCircle.getWidth() * 0.40f / score.getDefaultSymbolImage(0).getHeight());
|
hitCircle.getWidth() * 0.40f / score.getDefaultSymbolImage(0).getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws an image based on its center with a color filter.
|
|
||||||
*/
|
|
||||||
private void drawCentered(Image img, float x, float y, Color color) {
|
|
||||||
img.draw(x - (img.getWidth() / 2f), y - (img.getHeight() / 2f), color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the circle hit result.
|
* Calculates the circle hit result.
|
||||||
* @param time the hit object time (difference between track time)
|
* @param time the hit object time (difference between track time)
|
||||||
|
|
|
@ -22,6 +22,7 @@ import itdelatrisu.opsu.GameScore;
|
||||||
import itdelatrisu.opsu.MusicController;
|
import itdelatrisu.opsu.MusicController;
|
||||||
import itdelatrisu.opsu.OsuFile;
|
import itdelatrisu.opsu.OsuFile;
|
||||||
import itdelatrisu.opsu.OsuHitObject;
|
import itdelatrisu.opsu.OsuHitObject;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
import itdelatrisu.opsu.states.Game;
|
import itdelatrisu.opsu.states.Game;
|
||||||
import itdelatrisu.opsu.states.Options;
|
import itdelatrisu.opsu.states.Options;
|
||||||
|
|
||||||
|
@ -240,9 +241,9 @@ public class Slider {
|
||||||
|
|
||||||
// draw overlay and hit circle
|
// draw overlay and hit circle
|
||||||
for (int i = curveX.length - 1; i >= 0; i--)
|
for (int i = curveX.length - 1; i >= 0; i--)
|
||||||
drawCentered(hitCircleOverlay, curveX[i], curveY[i], Color.white);
|
Utils.drawCentered(hitCircleOverlay, curveX[i], curveY[i], Color.white);
|
||||||
for (int i = curveX.length - 1; i >= 0; i--)
|
for (int i = curveX.length - 1; i >= 0; i--)
|
||||||
drawCentered(hitCircle, curveX[i], curveY[i], color);
|
Utils.drawCentered(hitCircle, curveX[i], curveY[i], color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,12 +313,12 @@ public class Slider {
|
||||||
|
|
||||||
// end circle
|
// end circle
|
||||||
int lastIndex = hitObject.sliderX.length - 1;
|
int lastIndex = hitObject.sliderX.length - 1;
|
||||||
drawCentered(hitCircleOverlay, hitObject.sliderX[lastIndex], hitObject.sliderY[lastIndex], Color.white);
|
Utils.drawCentered(hitCircleOverlay, hitObject.sliderX[lastIndex], hitObject.sliderY[lastIndex], Color.white);
|
||||||
drawCentered(hitCircle, hitObject.sliderX[lastIndex], hitObject.sliderY[lastIndex], color);
|
Utils.drawCentered(hitCircle, hitObject.sliderX[lastIndex], hitObject.sliderY[lastIndex], color);
|
||||||
|
|
||||||
// start circle
|
// start circle
|
||||||
drawCentered(hitCircleOverlay, hitObject.x, hitObject.y, Color.white);
|
Utils.drawCentered(hitCircleOverlay, hitObject.x, hitObject.y, Color.white);
|
||||||
drawCentered(hitCircle, hitObject.x, hitObject.y, color);
|
Utils.drawCentered(hitCircle, hitObject.x, hitObject.y, color);
|
||||||
if (sliderClicked)
|
if (sliderClicked)
|
||||||
; // don't draw current combo number if already clicked
|
; // don't draw current combo number if already clicked
|
||||||
else
|
else
|
||||||
|
@ -335,12 +336,13 @@ public class Slider {
|
||||||
if (timeDiff >= 0) {
|
if (timeDiff >= 0) {
|
||||||
// approach circle
|
// approach circle
|
||||||
float approachScale = 1 + (timeDiff * 2f / game.getApproachTime());
|
float approachScale = 1 + (timeDiff * 2f / game.getApproachTime());
|
||||||
drawCentered(Circle.getApproachCircle().getScaledCopy(approachScale), hitObject.x, hitObject.y, color);
|
Utils.drawCentered(Circle.getApproachCircle().getScaledCopy(approachScale),
|
||||||
|
hitObject.x, hitObject.y, color);
|
||||||
} else {
|
} else {
|
||||||
float[] c = bezier.pointAt(getT(trackPosition, false));
|
float[] c = bezier.pointAt(getT(trackPosition, false));
|
||||||
|
|
||||||
// slider ball
|
// slider ball
|
||||||
drawCentered(sliderBall, c[0], c[1]);
|
Utils.drawCentered(sliderBall, c[0], c[1]);
|
||||||
|
|
||||||
// follow circle
|
// follow circle
|
||||||
if (followCircleActive)
|
if (followCircleActive)
|
||||||
|
@ -348,20 +350,6 @@ public class Slider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws an image based on its center with a color filter.
|
|
||||||
*/
|
|
||||||
private void drawCentered(Image img, float x, float y, Color color) {
|
|
||||||
img.draw(x - (img.getWidth() / 2f), y - (img.getHeight() / 2f), color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws an animation based on its center with a color filter.
|
|
||||||
*/
|
|
||||||
private static void drawCentered(Animation anim, float x, float y) {
|
|
||||||
anim.draw(x - (anim.getWidth() / 2f), y - (anim.getHeight() / 2f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the slider hit result.
|
* Calculates the slider hit result.
|
||||||
* @param time the hit object time (difference between track time)
|
* @param time the hit object time (difference between track time)
|
||||||
|
|
|
@ -22,6 +22,7 @@ import itdelatrisu.opsu.GameScore;
|
||||||
import itdelatrisu.opsu.MusicController;
|
import itdelatrisu.opsu.MusicController;
|
||||||
import itdelatrisu.opsu.OsuHitObject;
|
import itdelatrisu.opsu.OsuHitObject;
|
||||||
import itdelatrisu.opsu.SoundController;
|
import itdelatrisu.opsu.SoundController;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
import itdelatrisu.opsu.states.Game;
|
import itdelatrisu.opsu.states.Game;
|
||||||
import itdelatrisu.opsu.states.Options;
|
import itdelatrisu.opsu.states.Options;
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ public class Spinner {
|
||||||
//spinnerOsuImage.drawCentered(width / 2, height / 4);
|
//spinnerOsuImage.drawCentered(width / 2, height / 4);
|
||||||
|
|
||||||
// darken screen
|
// darken screen
|
||||||
g.setColor(Options.COLOR_BLACK_ALPHA);
|
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||||
g.fillRect(0, 0, width, height);
|
g.fillRect(0, 0, width, height);
|
||||||
|
|
||||||
if (timeDiff > 0)
|
if (timeDiff > 0)
|
||||||
|
|
|
@ -26,6 +26,7 @@ import itdelatrisu.opsu.OsuFile;
|
||||||
import itdelatrisu.opsu.OsuHitObject;
|
import itdelatrisu.opsu.OsuHitObject;
|
||||||
import itdelatrisu.opsu.OsuTimingPoint;
|
import itdelatrisu.opsu.OsuTimingPoint;
|
||||||
import itdelatrisu.opsu.SoundController;
|
import itdelatrisu.opsu.SoundController;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
import itdelatrisu.opsu.objects.Circle;
|
import itdelatrisu.opsu.objects.Circle;
|
||||||
import itdelatrisu.opsu.objects.Slider;
|
import itdelatrisu.opsu.objects.Slider;
|
||||||
import itdelatrisu.opsu.objects.Spinner;
|
import itdelatrisu.opsu.objects.Spinner;
|
||||||
|
@ -264,8 +265,6 @@ public class Game extends BasicGameState {
|
||||||
if (!osu.drawBG(width, height, 0.7f))
|
if (!osu.drawBG(width, height, 0.7f))
|
||||||
g.setBackground(Color.black);
|
g.setBackground(Color.black);
|
||||||
|
|
||||||
Options.drawFPS();
|
|
||||||
|
|
||||||
int trackPosition = MusicController.getPosition();
|
int trackPosition = MusicController.getPosition();
|
||||||
if (pauseTime > -1) // returning from pause screen
|
if (pauseTime > -1) // returning from pause screen
|
||||||
trackPosition = pauseTime;
|
trackPosition = pauseTime;
|
||||||
|
@ -313,6 +312,9 @@ public class Game extends BasicGameState {
|
||||||
warningArrowL.draw(width * 0.75f, height * 0.75f);
|
warningArrowL.draw(width * 0.75f, height * 0.75f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils.drawFPS();
|
||||||
|
Utils.drawCursor();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,7 +415,7 @@ public class Game extends BasicGameState {
|
||||||
// returning from pause screen
|
// returning from pause screen
|
||||||
if (pauseTime > -1 && pausedMouseX > -1 && pausedMouseY > -1) {
|
if (pauseTime > -1 && pausedMouseX > -1 && pausedMouseY > -1) {
|
||||||
// darken the screen
|
// darken the screen
|
||||||
g.setColor(Options.COLOR_BLACK_ALPHA);
|
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||||
g.fillRect(0, 0, width, height);
|
g.fillRect(0, 0, width, height);
|
||||||
|
|
||||||
// draw glowing hit select circle and pulse effect
|
// draw glowing hit select circle and pulse effect
|
||||||
|
@ -425,6 +427,9 @@ public class Game extends BasicGameState {
|
||||||
cursorCirclePulse.setAlpha(1f - pausePulse);
|
cursorCirclePulse.setAlpha(1f - pausePulse);
|
||||||
cursorCirclePulse.drawCentered(pausedMouseX, pausedMouseY);
|
cursorCirclePulse.drawCentered(pausedMouseX, pausedMouseY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils.drawFPS();
|
||||||
|
Utils.drawCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -589,7 +594,7 @@ public class Game extends BasicGameState {
|
||||||
mousePressed(Input.MOUSE_RIGHT_BUTTON, input.getMouseX(), input.getMouseY());
|
mousePressed(Input.MOUSE_RIGHT_BUTTON, input.getMouseX(), input.getMouseY());
|
||||||
break;
|
break;
|
||||||
case Input.KEY_F12:
|
case Input.KEY_F12:
|
||||||
Options.takeScreenShot();
|
Utils.takeScreenShot();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,6 +652,9 @@ public class Game extends BasicGameState {
|
||||||
if (osu == null || osu.objects == null)
|
if (osu == null || osu.objects == null)
|
||||||
throw new RuntimeException("Running game with no OsuFile loaded.");
|
throw new RuntimeException("Running game with no OsuFile loaded.");
|
||||||
|
|
||||||
|
// grab the mouse
|
||||||
|
container.setMouseGrabbed(true);
|
||||||
|
|
||||||
// restart the game
|
// restart the game
|
||||||
if (restart != RESTART_FALSE) {
|
if (restart != RESTART_FALSE) {
|
||||||
// new game
|
// 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.
|
* Skips the beginning of a track.
|
||||||
* @return true if skipped, false otherwise
|
* @return true if skipped, false otherwise
|
||||||
|
|
|
@ -22,6 +22,7 @@ import itdelatrisu.opsu.GUIMenuButton;
|
||||||
import itdelatrisu.opsu.MusicController;
|
import itdelatrisu.opsu.MusicController;
|
||||||
import itdelatrisu.opsu.Opsu;
|
import itdelatrisu.opsu.Opsu;
|
||||||
import itdelatrisu.opsu.SoundController;
|
import itdelatrisu.opsu.SoundController;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
|
|
||||||
import org.newdawn.slick.Color;
|
import org.newdawn.slick.Color;
|
||||||
import org.newdawn.slick.GameContainer;
|
import org.newdawn.slick.GameContainer;
|
||||||
|
@ -117,13 +118,14 @@ public class GamePauseMenu extends BasicGameState {
|
||||||
else
|
else
|
||||||
g.setBackground(Color.black);
|
g.setBackground(Color.black);
|
||||||
|
|
||||||
Options.drawFPS();
|
|
||||||
|
|
||||||
// draw buttons
|
// draw buttons
|
||||||
if (Game.getRestart() != Game.RESTART_LOSE)
|
if (Game.getRestart() != Game.RESTART_LOSE)
|
||||||
continueButton.draw();
|
continueButton.draw();
|
||||||
retryButton.draw();
|
retryButton.draw();
|
||||||
backButton.draw();
|
backButton.draw();
|
||||||
|
|
||||||
|
Utils.drawFPS();
|
||||||
|
Utils.drawCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -149,7 +151,7 @@ public class GamePauseMenu extends BasicGameState {
|
||||||
unPause(Game.RESTART_FALSE);
|
unPause(Game.RESTART_FALSE);
|
||||||
break;
|
break;
|
||||||
case Input.KEY_F12:
|
case Input.KEY_F12:
|
||||||
Options.takeScreenShot();
|
Utils.takeScreenShot();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import itdelatrisu.opsu.MusicController;
|
||||||
import itdelatrisu.opsu.Opsu;
|
import itdelatrisu.opsu.Opsu;
|
||||||
import itdelatrisu.opsu.OsuFile;
|
import itdelatrisu.opsu.OsuFile;
|
||||||
import itdelatrisu.opsu.SoundController;
|
import itdelatrisu.opsu.SoundController;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
|
|
||||||
import org.lwjgl.opengl.Display;
|
import org.lwjgl.opengl.Display;
|
||||||
import org.newdawn.slick.Color;
|
import org.newdawn.slick.Color;
|
||||||
|
@ -100,7 +101,7 @@ public class GameRanking extends BasicGameState {
|
||||||
|
|
||||||
// background
|
// background
|
||||||
if (!osu.drawBG(width, height, 0.7f))
|
if (!osu.drawBG(width, height, 0.7f))
|
||||||
g.setBackground(Options.COLOR_BLACK_ALPHA);
|
g.setBackground(Utils.COLOR_BLACK_ALPHA);
|
||||||
|
|
||||||
// ranking screen elements
|
// ranking screen elements
|
||||||
score.drawRankingElements(g, width, height);
|
score.drawRankingElements(g, width, height);
|
||||||
|
@ -118,17 +119,18 @@ public class GameRanking extends BasicGameState {
|
||||||
|
|
||||||
// header text
|
// header text
|
||||||
g.setColor(Color.white);
|
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));
|
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));
|
String.format("Beatmap by %s", osu.creator));
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
retryButton.draw();
|
retryButton.draw();
|
||||||
exitButton.draw();
|
exitButton.draw();
|
||||||
Options.getBackButton().draw();
|
Utils.getBackButton().draw();
|
||||||
|
|
||||||
Options.drawFPS();
|
Utils.drawFPS();
|
||||||
|
Utils.drawCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -150,7 +152,7 @@ public class GameRanking extends BasicGameState {
|
||||||
game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||||
break;
|
break;
|
||||||
case Input.KEY_F12:
|
case Input.KEY_F12:
|
||||||
Options.takeScreenShot();
|
Utils.takeScreenShot();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +172,7 @@ public class GameRanking extends BasicGameState {
|
||||||
} else if (exitButton.contains(x, y)) {
|
} else if (exitButton.contains(x, y)) {
|
||||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||||
game.enterState(Opsu.STATE_MAINMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
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.pause();
|
||||||
MusicController.playAt(Game.getOsuFile().previewTime, true);
|
MusicController.playAt(Game.getOsuFile().previewTime, true);
|
||||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||||
|
|
|
@ -23,6 +23,7 @@ import itdelatrisu.opsu.MusicController;
|
||||||
import itdelatrisu.opsu.Opsu;
|
import itdelatrisu.opsu.Opsu;
|
||||||
import itdelatrisu.opsu.OsuGroupNode;
|
import itdelatrisu.opsu.OsuGroupNode;
|
||||||
import itdelatrisu.opsu.SoundController;
|
import itdelatrisu.opsu.SoundController;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -153,8 +154,8 @@ public class MainMenu extends BasicGameState {
|
||||||
if (backgroundImage != null)
|
if (backgroundImage != null)
|
||||||
backgroundImage.draw();
|
backgroundImage.draw();
|
||||||
else
|
else
|
||||||
g.setBackground(Options.COLOR_BLUE_BACKGROUND);
|
g.setBackground(Utils.COLOR_BLUE_BACKGROUND);
|
||||||
g.setFont(Options.FONT_MEDIUM);
|
g.setFont(Utils.FONT_MEDIUM);
|
||||||
|
|
||||||
int width = container.getWidth();
|
int width = container.getWidth();
|
||||||
int height = container.getHeight();
|
int height = container.getHeight();
|
||||||
|
@ -173,7 +174,7 @@ public class MainMenu extends BasicGameState {
|
||||||
musicPlay.draw();
|
musicPlay.draw();
|
||||||
musicNext.draw();
|
musicNext.draw();
|
||||||
musicPrevious.draw();
|
musicPrevious.draw();
|
||||||
g.setColor(Options.COLOR_BLACK_ALPHA);
|
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||||
g.fillRoundRect(width - 168, 54, 148, 5, 4);
|
g.fillRoundRect(width - 168, 54, 148, 5, 4);
|
||||||
g.setColor(Color.white);
|
g.setColor(Color.white);
|
||||||
if (!MusicController.isConverting())
|
if (!MusicController.isConverting())
|
||||||
|
@ -181,7 +182,7 @@ public class MainMenu extends BasicGameState {
|
||||||
148f * MusicController.getPosition() / MusicController.getTrackLength(), 5, 4);
|
148f * MusicController.getPosition() / MusicController.getTrackLength(), 5, 4);
|
||||||
|
|
||||||
// draw text
|
// draw text
|
||||||
int lineHeight = Options.FONT_MEDIUM.getLineHeight();
|
int lineHeight = Utils.FONT_MEDIUM.getLineHeight();
|
||||||
g.drawString(String.format("Loaded %d songs and %d beatmaps.",
|
g.drawString(String.format("Loaded %d songs and %d beatmaps.",
|
||||||
Opsu.groups.size(), Opsu.groups.getMapCount()), 25, 25);
|
Opsu.groups.size(), Opsu.groups.getMapCount()), 25, 25);
|
||||||
if (MusicController.isConverting())
|
if (MusicController.isConverting())
|
||||||
|
@ -203,7 +204,8 @@ public class MainMenu extends BasicGameState {
|
||||||
new SimpleDateFormat("h:mm a").format(new Date())),
|
new SimpleDateFormat("h:mm a").format(new Date())),
|
||||||
25, height - 25 - lineHeight);
|
25, height - 25 - lineHeight);
|
||||||
|
|
||||||
Options.drawFPS();
|
Utils.drawFPS();
|
||||||
|
Utils.drawCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -317,7 +319,7 @@ public class MainMenu extends BasicGameState {
|
||||||
game.enterState(Opsu.STATE_MAINMENUEXIT);
|
game.enterState(Opsu.STATE_MAINMENUEXIT);
|
||||||
break;
|
break;
|
||||||
case Input.KEY_F12:
|
case Input.KEY_F12:
|
||||||
Options.takeScreenShot();
|
Utils.takeScreenShot();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ package itdelatrisu.opsu.states;
|
||||||
|
|
||||||
import itdelatrisu.opsu.GUIMenuButton;
|
import itdelatrisu.opsu.GUIMenuButton;
|
||||||
import itdelatrisu.opsu.Opsu;
|
import itdelatrisu.opsu.Opsu;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
|
|
||||||
import org.newdawn.slick.Color;
|
import org.newdawn.slick.Color;
|
||||||
import org.newdawn.slick.GameContainer;
|
import org.newdawn.slick.GameContainer;
|
||||||
|
@ -90,22 +91,23 @@ public class MainMenuExit extends BasicGameState {
|
||||||
|
|
||||||
// draw text
|
// draw text
|
||||||
float c = container.getWidth() * 0.02f;
|
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
|
// draw buttons
|
||||||
yesButton.draw(Color.green);
|
yesButton.draw(Color.green);
|
||||||
noButton.draw(Color.red);
|
noButton.draw(Color.red);
|
||||||
g.setFont(Options.FONT_XLARGE);
|
g.setFont(Utils.FONT_XLARGE);
|
||||||
g.drawString("1. Yes",
|
g.drawString("1. Yes",
|
||||||
yesButton.getX() - (Options.FONT_XLARGE.getWidth("1. Yes") / 2f),
|
yesButton.getX() - (Utils.FONT_XLARGE.getWidth("1. Yes") / 2f),
|
||||||
yesButton.getY() - (Options.FONT_XLARGE.getHeight() / 2f)
|
yesButton.getY() - (Utils.FONT_XLARGE.getHeight() / 2f)
|
||||||
);
|
);
|
||||||
g.drawString("2. No",
|
g.drawString("2. No",
|
||||||
noButton.getX() - (Options.FONT_XLARGE.getWidth("2. No") / 2f),
|
noButton.getX() - (Utils.FONT_XLARGE.getWidth("2. No") / 2f),
|
||||||
noButton.getY() - (Options.FONT_XLARGE.getHeight() / 2f)
|
noButton.getY() - (Utils.FONT_XLARGE.getHeight() / 2f)
|
||||||
);
|
);
|
||||||
|
|
||||||
Options.drawFPS();
|
Utils.drawFPS();
|
||||||
|
Utils.drawCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -150,7 +152,7 @@ public class MainMenuExit extends BasicGameState {
|
||||||
game.enterState(Opsu.STATE_MAINMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
game.enterState(Opsu.STATE_MAINMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||||
break;
|
break;
|
||||||
case Input.KEY_F12:
|
case Input.KEY_F12:
|
||||||
Options.takeScreenShot();
|
Utils.takeScreenShot();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,8 @@ package itdelatrisu.opsu.states;
|
||||||
|
|
||||||
import itdelatrisu.opsu.GUIMenuButton;
|
import itdelatrisu.opsu.GUIMenuButton;
|
||||||
import itdelatrisu.opsu.Opsu;
|
import itdelatrisu.opsu.Opsu;
|
||||||
import itdelatrisu.opsu.SoundController;
|
import itdelatrisu.opsu.Utils;
|
||||||
|
|
||||||
import java.awt.Font;
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -39,8 +38,6 @@ import org.newdawn.slick.Graphics;
|
||||||
import org.newdawn.slick.Image;
|
import org.newdawn.slick.Image;
|
||||||
import org.newdawn.slick.Input;
|
import org.newdawn.slick.Input;
|
||||||
import org.newdawn.slick.SlickException;
|
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.BasicGameState;
|
||||||
import org.newdawn.slick.state.StateBasedGame;
|
import org.newdawn.slick.state.StateBasedGame;
|
||||||
import org.newdawn.slick.state.transition.EmptyTransition;
|
import org.newdawn.slick.state.transition.EmptyTransition;
|
||||||
|
@ -85,41 +82,6 @@ public class Options extends BasicGameState {
|
||||||
*/
|
*/
|
||||||
private static final String OPTIONS_FILE = ".opsu.cfg";
|
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.
|
* Game mods.
|
||||||
*/
|
*/
|
||||||
|
@ -235,12 +197,12 @@ public class Options extends BasicGameState {
|
||||||
/**
|
/**
|
||||||
* Port binding.
|
* 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).
|
* Game option coordinate modifiers (for drawing).
|
||||||
|
@ -248,8 +210,8 @@ public class Options extends BasicGameState {
|
||||||
private int textY, offsetY;
|
private int textY, offsetY;
|
||||||
|
|
||||||
// game-related variables
|
// game-related variables
|
||||||
private static GameContainer container;
|
private GameContainer container;
|
||||||
private static StateBasedGame game;
|
private StateBasedGame game;
|
||||||
private Input input;
|
private Input input;
|
||||||
private int state;
|
private int state;
|
||||||
private boolean init = false;
|
private boolean init = false;
|
||||||
|
@ -261,42 +223,17 @@ public class Options extends BasicGameState {
|
||||||
@Override
|
@Override
|
||||||
public void init(GameContainer container, StateBasedGame game)
|
public void init(GameContainer container, StateBasedGame game)
|
||||||
throws SlickException {
|
throws SlickException {
|
||||||
Options.container = container;
|
this.container = container;
|
||||||
Options.game = game;
|
this.game = game;
|
||||||
this.input = container.getInput();
|
this.input = container.getInput();
|
||||||
|
|
||||||
// game settings
|
Utils.init(container, game);
|
||||||
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);
|
|
||||||
|
|
||||||
int width = container.getWidth();
|
int width = container.getWidth();
|
||||||
int height = container.getHeight();
|
int height = container.getHeight();
|
||||||
|
|
||||||
// game option coordinate modifiers
|
// 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);
|
offsetY = (int) (((height * 0.8f) - textY) / OPTIONS_MAX);
|
||||||
|
|
||||||
// game mods
|
// game mods
|
||||||
|
@ -330,14 +267,6 @@ public class Options extends BasicGameState {
|
||||||
for (int i = 0; i < modButtons.length; i++)
|
for (int i = 0; i < modButtons.length; i++)
|
||||||
modButtons[i].getImage().setAlpha(0.5f);
|
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));
|
game.enterState(Opsu.STATE_MAINMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,25 +276,25 @@ public class Options extends BasicGameState {
|
||||||
if (!init)
|
if (!init)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g.setBackground(COLOR_BLACK_ALPHA);
|
g.setBackground(Utils.COLOR_BLACK_ALPHA);
|
||||||
g.setColor(Color.white);
|
g.setColor(Color.white);
|
||||||
|
|
||||||
int width = container.getWidth();
|
int width = container.getWidth();
|
||||||
int height = container.getHeight();
|
int height = container.getHeight();
|
||||||
|
|
||||||
// title
|
// title
|
||||||
FONT_XLARGE.drawString(
|
Utils.FONT_XLARGE.drawString(
|
||||||
(width / 2) - (FONT_XLARGE.getWidth("GAME OPTIONS") / 2),
|
(width / 2) - (Utils.FONT_XLARGE.getWidth("GAME OPTIONS") / 2),
|
||||||
10, "GAME OPTIONS"
|
10, "GAME OPTIONS"
|
||||||
);
|
);
|
||||||
FONT_DEFAULT.drawString(
|
Utils.FONT_DEFAULT.drawString(
|
||||||
(width / 2) - (FONT_DEFAULT.getWidth("Click or drag an option to change it.") / 2),
|
(width / 2) - (Utils.FONT_DEFAULT.getWidth("Click or drag an option to change it.") / 2),
|
||||||
10 + FONT_XLARGE.getHeight(), "Click or drag an option to change it."
|
10 + Utils.FONT_XLARGE.getHeight(), "Click or drag an option to change it."
|
||||||
);
|
);
|
||||||
|
|
||||||
// game options
|
// game options
|
||||||
g.setLineWidth(1f);
|
g.setLineWidth(1f);
|
||||||
g.setFont(FONT_LARGE);
|
g.setFont(Utils.FONT_LARGE);
|
||||||
this.drawOption(g, OPTIONS_SCREEN_RESOLUTION, "Screen Resolution",
|
this.drawOption(g, OPTIONS_SCREEN_RESOLUTION, "Screen Resolution",
|
||||||
String.format("%dx%d", resolutions[resolutionIndex][0], resolutions[resolutionIndex][1]),
|
String.format("%dx%d", resolutions[resolutionIndex][0], resolutions[resolutionIndex][1]),
|
||||||
"Restart to apply resolution changes."
|
"Restart to apply resolution changes."
|
||||||
|
@ -375,7 +304,7 @@ public class Options extends BasicGameState {
|
||||||
// "Restart to apply changes."
|
// "Restart to apply changes."
|
||||||
// );
|
// );
|
||||||
this.drawOption(g, OPTIONS_TARGET_FPS, "Frame Limiter",
|
this.drawOption(g, OPTIONS_TARGET_FPS, "Frame Limiter",
|
||||||
String.format("%dfps", targetFPS[targetFPSindex]),
|
String.format("%dfps", getTargetFPS()),
|
||||||
"Higher values may cause high CPU usage."
|
"Higher values may cause high CPU usage."
|
||||||
);
|
);
|
||||||
this.drawOption(g, OPTIONS_MUSIC_VOLUME, "Music Volume",
|
this.drawOption(g, OPTIONS_MUSIC_VOLUME, "Music Volume",
|
||||||
|
@ -408,13 +337,14 @@ public class Options extends BasicGameState {
|
||||||
);
|
);
|
||||||
|
|
||||||
// game mods
|
// 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++)
|
for (int i = 0; i < modButtons.length; i++)
|
||||||
modButtons[i].draw();
|
modButtons[i].draw();
|
||||||
|
|
||||||
backButton.draw();
|
Utils.getBackButton().draw();
|
||||||
|
|
||||||
drawFPS();
|
Utils.drawFPS();
|
||||||
|
Utils.drawCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -433,7 +363,7 @@ public class Options extends BasicGameState {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// back
|
// back
|
||||||
if (backButton.contains(x, y)) {
|
if (Utils.getBackButton().contains(x, y)) {
|
||||||
game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -472,7 +402,7 @@ public class Options extends BasicGameState {
|
||||||
// }
|
// }
|
||||||
if (isOptionClicked(OPTIONS_TARGET_FPS, y)) {
|
if (isOptionClicked(OPTIONS_TARGET_FPS, y)) {
|
||||||
targetFPSindex = (targetFPSindex + 1) % targetFPS.length;
|
targetFPSindex = (targetFPSindex + 1) % targetFPS.length;
|
||||||
container.setTargetFrameRate(targetFPS[targetFPSindex]);
|
container.setTargetFrameRate(getTargetFPS());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isOptionClicked(OPTIONS_SCREENSHOT_FORMAT, y)) {
|
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));
|
game.enterState(Opsu.STATE_SONGMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||||
break;
|
break;
|
||||||
case Input.KEY_F12:
|
case Input.KEY_F12:
|
||||||
Options.takeScreenShot();
|
Utils.takeScreenShot();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,14 +490,14 @@ public class Options extends BasicGameState {
|
||||||
*/
|
*/
|
||||||
private void drawOption(Graphics g, int pos, String label, String value, String notes) {
|
private void drawOption(Graphics g, int pos, String label, String value, String notes) {
|
||||||
int width = container.getWidth();
|
int width = container.getWidth();
|
||||||
int textHeight = FONT_LARGE.getHeight();
|
int textHeight = Utils.FONT_LARGE.getHeight();
|
||||||
float y = textY + (pos * offsetY);
|
float y = textY + (pos * offsetY);
|
||||||
|
|
||||||
g.drawString(label, width / 50, y);
|
g.drawString(label, width / 50, y);
|
||||||
g.drawString(value, width / 2, y);
|
g.drawString(value, width / 2, y);
|
||||||
g.drawLine(0, y + textHeight, width, y + textHeight);
|
g.drawLine(0, y + textHeight, width, y + textHeight);
|
||||||
if (notes != null)
|
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
|
* @return true if clicked
|
||||||
*/
|
*/
|
||||||
private boolean isOptionClicked(int pos, int y) {
|
private boolean isOptionClicked(int pos, int y) {
|
||||||
if (y > textY + (offsetY * pos) - FONT_LARGE.getHeight() &&
|
return (y > textY + (offsetY * pos) - Utils.FONT_LARGE.getHeight() &&
|
||||||
y < textY + (offsetY * pos) + FONT_LARGE.getHeight()) {
|
y < textY + (offsetY * pos) + Utils.FONT_LARGE.getHeight());
|
||||||
optionsChanged = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -610,9 +536,10 @@ public class Options extends BasicGameState {
|
||||||
public static Image getModImage(int mod) { return modButtons[mod].getImage(); }
|
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.
|
* Returns the default music volume.
|
||||||
|
@ -633,53 +560,10 @@ public class Options extends BasicGameState {
|
||||||
public static int getMusicOffset() { return musicOffset; }
|
public static int getMusicOffset() { return musicOffset; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the FPS at the bottom-right corner of the game container.
|
* Returns the screenshot file format.
|
||||||
* If the option is not activated, this will do nothing.
|
* @return the file extension ("png", "jpg", "bmp")
|
||||||
*/
|
*/
|
||||||
public static void drawFPS() {
|
public static String getScreenshotFormat() { return screenshotFormat[screenshotFormatIndex]; }
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the screen resolution.
|
* Returns the screen resolution.
|
||||||
|
@ -693,6 +577,12 @@ public class Options extends BasicGameState {
|
||||||
// */
|
// */
|
||||||
// public static boolean isFullscreen() { return fullscreen; }
|
// 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.
|
* Returns whether or not hit lighting effects are enabled.
|
||||||
* @return true if enabled
|
* @return true if enabled
|
||||||
|
@ -709,14 +599,13 @@ public class Options extends BasicGameState {
|
||||||
* Returns the port number to bind to.
|
* Returns the port number to bind to.
|
||||||
* @return the port
|
* @return the port
|
||||||
*/
|
*/
|
||||||
public static int getPort() {
|
public static int getPort() { return port; }
|
||||||
if (port == 0) {
|
|
||||||
// choose a random port
|
/**
|
||||||
port = 49250;
|
* Returns whether or not the new cursor type is enabled.
|
||||||
optionsChanged = true; // force file creation
|
* @return true if enabled
|
||||||
}
|
*/
|
||||||
return port;
|
public static boolean isNewCursorEnabled() { return newCursor; }
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current beatmap directory.
|
* Returns the current beatmap directory.
|
||||||
|
@ -730,15 +619,14 @@ public class Options extends BasicGameState {
|
||||||
// search for directory
|
// search for directory
|
||||||
for (int i = 0; i < BEATMAP_DIRS.length; i++) {
|
for (int i = 0; i < BEATMAP_DIRS.length; i++) {
|
||||||
beatmapDir = new File(BEATMAP_DIRS[i]);
|
beatmapDir = new File(BEATMAP_DIRS[i]);
|
||||||
if (beatmapDir.isDirectory()) {
|
if (beatmapDir.isDirectory())
|
||||||
optionsChanged = true; // force config file creation
|
|
||||||
return beatmapDir;
|
return beatmapDir;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
beatmapDir.mkdir(); // none found, create new directory
|
beatmapDir.mkdir(); // none found, create new directory
|
||||||
return beatmapDir;
|
return beatmapDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads user options from the options file, if it exists.
|
* 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
|
// if no config file, use default settings
|
||||||
File file = new File(OPTIONS_FILE);
|
File file = new File(OPTIONS_FILE);
|
||||||
if (!file.isFile()) {
|
if (!file.isFile()) {
|
||||||
optionsChanged = true; // force file creation
|
|
||||||
saveOptions();
|
saveOptions();
|
||||||
optionsChanged = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,6 +702,9 @@ public class Options extends BasicGameState {
|
||||||
if (i > 0 && i <= 65535)
|
if (i > 0 && i <= 65535)
|
||||||
port = i;
|
port = i;
|
||||||
break;
|
break;
|
||||||
|
case "NewCursor": // custom
|
||||||
|
newCursor = Boolean.parseBoolean(value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -830,10 +719,6 @@ public class Options extends BasicGameState {
|
||||||
* (Over)writes user options to a file.
|
* (Over)writes user options to a file.
|
||||||
*/
|
*/
|
||||||
public static void saveOptions() {
|
public static void saveOptions() {
|
||||||
// only overwrite when needed
|
|
||||||
if (!optionsChanged)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
|
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
|
||||||
new FileOutputStream(OPTIONS_FILE), "utf-8"))) {
|
new FileOutputStream(OPTIONS_FILE), "utf-8"))) {
|
||||||
// header
|
// header
|
||||||
|
@ -873,6 +758,8 @@ public class Options extends BasicGameState {
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
writer.write(String.format("Port = %d", port));
|
writer.write(String.format("Port = %d", port));
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
|
writer.write(String.format("NewCursor = %b", newCursor)); // custom
|
||||||
|
writer.newLine();
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.error(String.format("Failed to write to file '%s'.", OPTIONS_FILE), e);
|
Log.error(String.format("Failed to write to file '%s'.", OPTIONS_FILE), e);
|
||||||
|
|
|
@ -26,6 +26,7 @@ import itdelatrisu.opsu.OsuGroupList;
|
||||||
import itdelatrisu.opsu.OsuGroupNode;
|
import itdelatrisu.opsu.OsuGroupNode;
|
||||||
import itdelatrisu.opsu.OsuParser;
|
import itdelatrisu.opsu.OsuParser;
|
||||||
import itdelatrisu.opsu.SoundController;
|
import itdelatrisu.opsu.SoundController;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
|
|
||||||
import org.lwjgl.opengl.Display;
|
import org.lwjgl.opengl.Display;
|
||||||
import org.newdawn.slick.Color;
|
import org.newdawn.slick.Color;
|
||||||
|
@ -170,13 +171,13 @@ public class SongMenu extends BasicGameState {
|
||||||
searchResultString = "Type to search!";
|
searchResultString = "Type to search!";
|
||||||
|
|
||||||
searchIcon = new Image("search.png");
|
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);
|
searchIcon = searchIcon.getScaledCopy(iconScale);
|
||||||
|
|
||||||
search = new TextField(
|
search = new TextField(
|
||||||
container, Options.FONT_DEFAULT,
|
container, Utils.FONT_DEFAULT,
|
||||||
(int) tabX + searchIcon.getWidth(), (int) ((height * 0.15f) - (tab.getHeight() * 5 / 2f)),
|
(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.setBackgroundColor(Color.transparent);
|
||||||
search.setBorderColor(Color.transparent);
|
search.setBorderColor(Color.transparent);
|
||||||
|
@ -205,9 +206,9 @@ public class SongMenu extends BasicGameState {
|
||||||
|
|
||||||
// header setup
|
// header setup
|
||||||
float lowerBound = height * 0.15f;
|
float lowerBound = height * 0.15f;
|
||||||
g.setColor(Options.COLOR_BLACK_ALPHA);
|
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||||
g.fillRect(0, 0, width, lowerBound);
|
g.fillRect(0, 0, width, lowerBound);
|
||||||
g.setColor(Options.COLOR_BLUE_DIVIDER);
|
g.setColor(Utils.COLOR_BLUE_DIVIDER);
|
||||||
g.setLineWidth(2f);
|
g.setLineWidth(2f);
|
||||||
g.drawLine(0, lowerBound, width, lowerBound);
|
g.drawLine(0, lowerBound, width, lowerBound);
|
||||||
g.resetLineWidth();
|
g.resetLineWidth();
|
||||||
|
@ -220,17 +221,17 @@ public class SongMenu extends BasicGameState {
|
||||||
|
|
||||||
String[] info = focusNode.getInfo();
|
String[] info = focusNode.getInfo();
|
||||||
g.setColor(Color.white);
|
g.setColor(Color.white);
|
||||||
Options.FONT_LARGE.drawString(
|
Utils.FONT_LARGE.drawString(
|
||||||
musicNoteWidth + 5, -3, info[0]);
|
musicNoteWidth + 5, -3, info[0]);
|
||||||
float y1 = -3 + Options.FONT_LARGE.getHeight() * 0.75f;
|
float y1 = -3 + Utils.FONT_LARGE.getHeight() * 0.75f;
|
||||||
Options.FONT_DEFAULT.drawString(
|
Utils.FONT_DEFAULT.drawString(
|
||||||
musicNoteWidth + 5, y1, info[1]);
|
musicNoteWidth + 5, y1, info[1]);
|
||||||
Options.FONT_BOLD.drawString(
|
Utils.FONT_BOLD.drawString(
|
||||||
5, Math.max(y1 + 4, musicNoteHeight - 3), info[2]);
|
5, Math.max(y1 + 4, musicNoteHeight - 3), info[2]);
|
||||||
Options.FONT_DEFAULT.drawString(
|
Utils.FONT_DEFAULT.drawString(
|
||||||
5, musicNoteHeight + Options.FONT_BOLD.getLineHeight() - 9, info[3]);
|
5, musicNoteHeight + Utils.FONT_BOLD.getLineHeight() - 9, info[3]);
|
||||||
Options.FONT_SMALL.drawString(
|
Utils.FONT_SMALL.drawString(
|
||||||
5, musicNoteHeight + Options.FONT_BOLD.getLineHeight() + Options.FONT_DEFAULT.getLineHeight() - 13, info[4]);
|
5, musicNoteHeight + Utils.FONT_BOLD.getLineHeight() + Utils.FONT_DEFAULT.getLineHeight() - 13, info[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// song buttons
|
// song buttons
|
||||||
|
@ -248,17 +249,17 @@ public class SongMenu extends BasicGameState {
|
||||||
for (int i = sortTabs.length - 1; i >= 0; i--) {
|
for (int i = sortTabs.length - 1; i >= 0; i--) {
|
||||||
sortTabs[i].getImage().setAlpha((i == currentSort) ? 1.0f : 0.7f);
|
sortTabs[i].getImage().setAlpha((i == currentSort) ? 1.0f : 0.7f);
|
||||||
sortTabs[i].draw();
|
sortTabs[i].draw();
|
||||||
float tabTextX = sortTabs[i].getX() - (Options.FONT_MEDIUM.getWidth(OsuGroupList.SORT_NAMES[i]) / 2);
|
float tabTextX = sortTabs[i].getX() - (Utils.FONT_MEDIUM.getWidth(OsuGroupList.SORT_NAMES[i]) / 2);
|
||||||
Options.FONT_MEDIUM.drawString(tabTextX, tabTextY, OsuGroupList.SORT_NAMES[i], Color.white);
|
Utils.FONT_MEDIUM.drawString(tabTextX, tabTextY, OsuGroupList.SORT_NAMES[i], Color.white);
|
||||||
}
|
}
|
||||||
|
|
||||||
// search
|
// search
|
||||||
Options.FONT_BOLD.drawString(
|
Utils.FONT_BOLD.drawString(
|
||||||
search.getX(), search.getY() - Options.FONT_BOLD.getLineHeight(),
|
search.getX(), search.getY() - Utils.FONT_BOLD.getLineHeight(),
|
||||||
searchResultString, Color.white
|
searchResultString, Color.white
|
||||||
);
|
);
|
||||||
searchIcon.draw(search.getX() - searchIcon.getWidth(),
|
searchIcon.draw(search.getX() - searchIcon.getWidth(),
|
||||||
search.getY() - Options.FONT_DEFAULT.getLineHeight());
|
search.getY() - Utils.FONT_DEFAULT.getLineHeight());
|
||||||
g.setColor(Color.white);
|
g.setColor(Color.white);
|
||||||
search.render(container, g);
|
search.render(container, g);
|
||||||
|
|
||||||
|
@ -266,16 +267,17 @@ public class SongMenu extends BasicGameState {
|
||||||
if (focusNode != null) {
|
if (focusNode != null) {
|
||||||
float scrollStartY = height * 0.16f;
|
float scrollStartY = height * 0.16f;
|
||||||
float scrollEndY = height * 0.82f;
|
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.fillRoundRect(width - 10, scrollStartY, 5, scrollEndY, 4);
|
||||||
g.setColor(Color.white);
|
g.setColor(Color.white);
|
||||||
g.fillRoundRect(width - 10, scrollStartY + (scrollEndY * startNode.index / Opsu.groups.size()), 5, 20, 4);
|
g.fillRoundRect(width - 10, scrollStartY + (scrollEndY * startNode.index / Opsu.groups.size()), 5, 20, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// back button
|
// back button
|
||||||
Options.getBackButton().draw();
|
Utils.getBackButton().draw();
|
||||||
|
|
||||||
Options.drawFPS();
|
Utils.drawFPS();
|
||||||
|
Utils.drawCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -343,7 +345,7 @@ public class SongMenu extends BasicGameState {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// back
|
// back
|
||||||
if (Options.getBackButton().contains(x, y)) {
|
if (Utils.getBackButton().contains(x, y)) {
|
||||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||||
game.enterState(Opsu.STATE_MAINMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
game.enterState(Opsu.STATE_MAINMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||||
return;
|
return;
|
||||||
|
@ -436,7 +438,7 @@ public class SongMenu extends BasicGameState {
|
||||||
setFocus(Opsu.groups.getRandomNode(), -1, true);
|
setFocus(Opsu.groups.getRandomNode(), -1, true);
|
||||||
break;
|
break;
|
||||||
case Input.KEY_F12:
|
case Input.KEY_F12:
|
||||||
Options.takeScreenShot();
|
Utils.takeScreenShot();
|
||||||
break;
|
break;
|
||||||
case Input.KEY_ENTER:
|
case Input.KEY_ENTER:
|
||||||
if (focusNode != null)
|
if (focusNode != null)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user