Cursor updates.
- Supported loading beatmap-skinned cursors. - Moved cursor loading into GameImage. - Removed unnecessary scalings/rotations when drawing.
This commit is contained in:
parent
d2b3249e2c
commit
0c1b86de62
|
@ -29,6 +29,38 @@ import org.newdawn.slick.SlickException;
|
||||||
* Game images.
|
* Game images.
|
||||||
*/
|
*/
|
||||||
public enum GameImage {
|
public enum GameImage {
|
||||||
|
// Cursor
|
||||||
|
CURSOR ("cursor", "png") {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy(1 + ((h - 600) / 1000f));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CURSOR_MIDDLE ("cursormiddle", "png") {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy(1 + ((h - 600) / 1000f));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CURSOR_TRAIL ("cursortrail", "png") {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy(1 + ((h - 600) / 1000f));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CURSOR_OLD ("cursor2", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy(1 + ((h - 600) / 1000f));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CURSOR_TRAIL_OLD ("cursortrail2", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy(1 + ((h - 600) / 1000f));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Game
|
// Game
|
||||||
SECTION_PASS ("section-pass", "png"),
|
SECTION_PASS ("section-pass", "png"),
|
||||||
SECTION_FAIL ("section-fail", "png"),
|
SECTION_FAIL ("section-fail", "png"),
|
||||||
|
@ -438,9 +470,6 @@ public enum GameImage {
|
||||||
/** Container dimensions. */
|
/** Container dimensions. */
|
||||||
private static int containerWidth, containerHeight;
|
private static int containerWidth, containerHeight;
|
||||||
|
|
||||||
/** Whether a skin image has been loaded. */
|
|
||||||
private static boolean skinImageLoaded = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the GameImage class with container dimensions.
|
* Initializes the GameImage class with container dimensions.
|
||||||
* @param width the container width
|
* @param width the container width
|
||||||
|
@ -462,19 +491,6 @@ public enum GameImage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys all skin images, if any have been loaded.
|
|
||||||
*/
|
|
||||||
public static void destroySkinImages() {
|
|
||||||
if (skinImageLoaded) {
|
|
||||||
for (GameImage img : GameImage.values()) {
|
|
||||||
if (img.isSkinnable())
|
|
||||||
img.destroySkinImage();
|
|
||||||
}
|
|
||||||
skinImageLoaded = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bitmask image type from a type string.
|
* Returns the bitmask image type from a type string.
|
||||||
* @param type the type string
|
* @param type the type string
|
||||||
|
@ -698,7 +714,6 @@ public enum GameImage {
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
this.skinImages = list.toArray(new Image[list.size()]);
|
this.skinImages = list.toArray(new Image[list.size()]);
|
||||||
process();
|
process();
|
||||||
skinImageLoaded = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -716,7 +731,6 @@ public enum GameImage {
|
||||||
// image successfully loaded
|
// image successfully loaded
|
||||||
this.skinImage = img;
|
this.skinImage = img;
|
||||||
process();
|
process();
|
||||||
skinImageLoaded = true;
|
|
||||||
return true;
|
return true;
|
||||||
} catch (SlickException | RuntimeException e) {
|
} catch (SlickException | RuntimeException e) {
|
||||||
errorFile = file.getAbsolutePath();
|
errorFile = file.getAbsolutePath();
|
||||||
|
@ -744,7 +758,7 @@ public enum GameImage {
|
||||||
/**
|
/**
|
||||||
* Destroys the associated skin image(s), if any.
|
* Destroys the associated skin image(s), if any.
|
||||||
*/
|
*/
|
||||||
private void destroySkinImage() {
|
public void destroySkinImage() {
|
||||||
if (skinImage == null && skinImages == null)
|
if (skinImage == null && skinImages == null)
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -176,6 +176,7 @@ public class Opsu extends StateBasedGame {
|
||||||
MusicController.resume();
|
MusicController.resume();
|
||||||
} else
|
} else
|
||||||
songMenu.resetTrackOnLoad();
|
songMenu.resetTrackOnLoad();
|
||||||
|
Utils.resetCursor();
|
||||||
this.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
this.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,11 +213,7 @@ public class Options {
|
||||||
@Override
|
@Override
|
||||||
public void click(GameContainer container) {
|
public void click(GameContainer container) {
|
||||||
newCursor = !newCursor;
|
newCursor = !newCursor;
|
||||||
try {
|
Utils.resetCursor();
|
||||||
Utils.loadCursor();
|
|
||||||
} catch (SlickException e) {
|
|
||||||
ErrorHandler.error("Failed to load cursor.", e, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DYNAMIC_BACKGROUND ("Enable Dynamic Backgrounds", "The song background will be used as the main menu background.") {
|
DYNAMIC_BACKGROUND ("Enable Dynamic Backgrounds", "The song background will be used as the main menu background.") {
|
||||||
|
|
|
@ -87,12 +87,12 @@ public class Utils {
|
||||||
/** Back button (shared by other states). */
|
/** Back button (shared by other states). */
|
||||||
private static MenuButton backButton;
|
private static MenuButton backButton;
|
||||||
|
|
||||||
/** Cursor image and trail. */
|
|
||||||
private static Image cursor, cursorTrail, cursorMiddle;
|
|
||||||
|
|
||||||
/** Last cursor coordinates. */
|
/** Last cursor coordinates. */
|
||||||
private static int lastX = -1, lastY = -1;
|
private static int lastX = -1, lastY = -1;
|
||||||
|
|
||||||
|
/** Cursor rotation angle. */
|
||||||
|
private static float cursorAngle = 0f;
|
||||||
|
|
||||||
/** Stores all previous cursor locations to display a trail. */
|
/** Stores all previous cursor locations to display a trail. */
|
||||||
private static LinkedList<Integer>
|
private static LinkedList<Integer>
|
||||||
cursorX = new LinkedList<Integer>(),
|
cursorX = new LinkedList<Integer>(),
|
||||||
|
@ -148,7 +148,6 @@ public class Utils {
|
||||||
} catch (LWJGLException e) {
|
} catch (LWJGLException e) {
|
||||||
ErrorHandler.error("Failed to set the cursor.", e, true);
|
ErrorHandler.error("Failed to set the cursor.", e, true);
|
||||||
}
|
}
|
||||||
loadCursor();
|
|
||||||
|
|
||||||
// create fonts
|
// create fonts
|
||||||
float fontBase;
|
float fontBase;
|
||||||
|
@ -292,84 +291,46 @@ public class Utils {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the cursor images.
|
|
||||||
* @throws SlickException
|
|
||||||
*/
|
|
||||||
public static void loadCursor() throws SlickException {
|
|
||||||
// destroy old cursors, if they exist
|
|
||||||
if (cursor != null && !cursor.isDestroyed())
|
|
||||||
cursor.destroy();
|
|
||||||
if (cursorTrail != null && !cursorTrail.isDestroyed())
|
|
||||||
cursorTrail.destroy();
|
|
||||||
if (cursorMiddle != null && !cursorMiddle.isDestroyed())
|
|
||||||
cursorMiddle.destroy();
|
|
||||||
cursor = cursorTrail = cursorMiddle = null;
|
|
||||||
|
|
||||||
// TODO: cleanup
|
|
||||||
boolean skinCursor = new File(Options.getSkinDir(), "cursor.png").isFile();
|
|
||||||
if (Options.isNewCursorEnabled()) {
|
|
||||||
// load new cursor type
|
|
||||||
// if skin cursor exists but middle part does not, don't load default middle
|
|
||||||
if (skinCursor && !new File(Options.getSkinDir(), "cursormiddle.png").isFile())
|
|
||||||
;
|
|
||||||
else {
|
|
||||||
cursorMiddle = new Image("cursormiddle.png");
|
|
||||||
cursor = new Image("cursor.png");
|
|
||||||
cursorTrail = new Image("cursortrail.png");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cursorMiddle == null) {
|
|
||||||
// load old cursor type
|
|
||||||
// default is stored as *2.png, but load skin cursor if it exists
|
|
||||||
if (skinCursor)
|
|
||||||
cursor = new Image("cursor.png");
|
|
||||||
else
|
|
||||||
cursor = new Image("cursor2.png");
|
|
||||||
if (new File(Options.getSkinDir(), "cursortrail.png").isFile())
|
|
||||||
cursorTrail = new Image("cursortrail.png");
|
|
||||||
else
|
|
||||||
cursorTrail = new Image("cursortrail2.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
// scale the cursor
|
|
||||||
float scale = 1 + ((container.getHeight() - 600) / 1000f);
|
|
||||||
cursor = cursor.getScaledCopy(scale);
|
|
||||||
cursorTrail = cursorTrail.getScaledCopy(scale);
|
|
||||||
if (cursorMiddle != null)
|
|
||||||
cursorMiddle = cursorMiddle.getScaledCopy(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the cursor.
|
* Draws the cursor.
|
||||||
*/
|
*/
|
||||||
public static void drawCursor() {
|
public static void drawCursor() {
|
||||||
// TODO: use an image buffer
|
// determine correct cursor image
|
||||||
|
// TODO: most beatmaps don't skin CURSOR_MIDDLE, so how to determine style?
|
||||||
int x = input.getMouseX();
|
Image cursor = null, cursorMiddle = null, cursorTrail = null;
|
||||||
int y = input.getMouseY();
|
boolean skinned = GameImage.CURSOR.hasSkinImage();
|
||||||
|
boolean newStyle = (skinned) ? true : Options.isNewCursorEnabled();
|
||||||
|
if (skinned || newStyle) {
|
||||||
|
cursor = GameImage.CURSOR.getImage();
|
||||||
|
cursorTrail = GameImage.CURSOR_TRAIL.getImage();
|
||||||
|
} else {
|
||||||
|
cursor = GameImage.CURSOR_OLD.getImage();
|
||||||
|
cursorTrail = GameImage.CURSOR_TRAIL_OLD.getImage();
|
||||||
|
}
|
||||||
|
if (newStyle)
|
||||||
|
cursorMiddle = GameImage.CURSOR_MIDDLE.getImage();
|
||||||
|
|
||||||
|
int mouseX = input.getMouseX(), mouseY = input.getMouseY();
|
||||||
int removeCount = 0;
|
int removeCount = 0;
|
||||||
int FPSmod = (Options.getTargetFPS() / 60);
|
int FPSmod = (Options.getTargetFPS() / 60);
|
||||||
|
|
||||||
// if middle exists, add all points between cursor movements
|
// TODO: use an image buffer
|
||||||
if (cursorMiddle != null) {
|
if (newStyle) {
|
||||||
|
// new style: add all points between cursor movements
|
||||||
if (lastX < 0) {
|
if (lastX < 0) {
|
||||||
lastX = x;
|
lastX = mouseX;
|
||||||
lastY = y;
|
lastY = mouseY;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addCursorPoints(lastX, lastY, x, y);
|
addCursorPoints(lastX, lastY, mouseX, mouseY);
|
||||||
lastX = x;
|
lastX = mouseX;
|
||||||
lastY = y;
|
lastY = mouseY;
|
||||||
|
|
||||||
removeCount = (cursorX.size() / (6 * FPSmod)) + 1;
|
removeCount = (cursorX.size() / (6 * FPSmod)) + 1;
|
||||||
}
|
} else {
|
||||||
|
// old style: sample one point at a time
|
||||||
// else, sample one point at a time
|
cursorX.add(mouseX);
|
||||||
else {
|
cursorY.add(mouseY);
|
||||||
cursorX.add(x);
|
|
||||||
cursorY.add(y);
|
|
||||||
|
|
||||||
int max = 10 * FPSmod;
|
int max = 10 * FPSmod;
|
||||||
if (cursorX.size() > max)
|
if (cursorX.size() > max)
|
||||||
|
@ -395,24 +356,24 @@ public class Utils {
|
||||||
// if (cx != x || cy != y)
|
// if (cx != x || cy != y)
|
||||||
cursorTrail.drawCentered(cx, cy);
|
cursorTrail.drawCentered(cx, cy);
|
||||||
}
|
}
|
||||||
cursorTrail.drawCentered(x, y);
|
cursorTrail.drawCentered(mouseX, mouseY);
|
||||||
|
|
||||||
// increase the cursor size if pressed
|
// increase the cursor size if pressed
|
||||||
|
final float scale = 1.25f;
|
||||||
int state = game.getCurrentStateID();
|
int state = game.getCurrentStateID();
|
||||||
float scale = 1f;
|
|
||||||
if (((state == Opsu.STATE_GAME || state == Opsu.STATE_GAMEPAUSEMENU) && isGameKeyPressed()) ||
|
if (((state == Opsu.STATE_GAME || state == Opsu.STATE_GAMEPAUSEMENU) && isGameKeyPressed()) ||
|
||||||
(input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) || input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON)))
|
(input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) || input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))) {
|
||||||
scale = 1.25f;
|
cursor = cursor.getScaledCopy(scale);
|
||||||
|
if (newStyle)
|
||||||
|
cursorMiddle = cursorMiddle.getScaledCopy(scale);
|
||||||
|
}
|
||||||
|
|
||||||
// draw the other components
|
// draw the other components
|
||||||
Image cursorScaled = cursor.getScaledCopy(scale);
|
if (newStyle)
|
||||||
cursorScaled.setRotation(cursor.getRotation());
|
cursor.setRotation(cursorAngle);
|
||||||
cursorScaled.drawCentered(x, y);
|
cursor.drawCentered(mouseX, mouseY);
|
||||||
if (cursorMiddle != null) {
|
if (newStyle)
|
||||||
Image cursorMiddleScaled = cursorMiddle.getScaledCopy(scale);
|
cursorMiddle.drawCentered(mouseX, mouseY);
|
||||||
cursorMiddleScaled.setRotation(cursorMiddle.getRotation());
|
|
||||||
cursorMiddleScaled.drawCentered(x, y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -472,10 +433,22 @@ public class Utils {
|
||||||
* @param delta the delta interval since the last call
|
* @param delta the delta interval since the last call
|
||||||
*/
|
*/
|
||||||
public static void updateCursor(int delta) {
|
public static void updateCursor(int delta) {
|
||||||
if (cursorMiddle == null)
|
cursorAngle += delta / 40f;
|
||||||
return;
|
cursorAngle %= 360;
|
||||||
|
}
|
||||||
|
|
||||||
cursor.rotate(delta / 40f);
|
/**
|
||||||
|
* Resets all cursor data and skins.
|
||||||
|
*/
|
||||||
|
public static void resetCursor() {
|
||||||
|
GameImage.CURSOR.destroySkinImage();
|
||||||
|
GameImage.CURSOR_MIDDLE.destroySkinImage();
|
||||||
|
GameImage.CURSOR_TRAIL.destroySkinImage();
|
||||||
|
cursorAngle = 0f;
|
||||||
|
lastX = lastY = -1;
|
||||||
|
cursorX.clear();
|
||||||
|
cursorY.clear();
|
||||||
|
GameImage.CURSOR.getImage().setRotation(0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -135,6 +135,7 @@ public class GamePauseMenu extends BasicGameState {
|
||||||
SoundController.playSound(SoundEffect.MENUBACK);
|
SoundController.playSound(SoundEffect.MENUBACK);
|
||||||
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).resetGameDataOnLoad();
|
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).resetGameDataOnLoad();
|
||||||
MusicController.playAt(MusicController.getOsuFile().previewTime, true);
|
MusicController.playAt(MusicController.getOsuFile().previewTime, true);
|
||||||
|
Utils.resetCursor();
|
||||||
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));
|
||||||
} else {
|
} else {
|
||||||
SoundController.playSound(SoundEffect.MENUBACK);
|
SoundController.playSound(SoundEffect.MENUBACK);
|
||||||
|
@ -181,6 +182,7 @@ public class GamePauseMenu extends BasicGameState {
|
||||||
MusicController.playAt(MusicController.getOsuFile().previewTime, true);
|
MusicController.playAt(MusicController.getOsuFile().previewTime, true);
|
||||||
else
|
else
|
||||||
MusicController.resume();
|
MusicController.resume();
|
||||||
|
Utils.resetCursor();
|
||||||
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,6 +150,7 @@ public class GameRanking extends BasicGameState {
|
||||||
SongMenu songMenu = (SongMenu) game.getState(Opsu.STATE_SONGMENU);
|
SongMenu songMenu = (SongMenu) game.getState(Opsu.STATE_SONGMENU);
|
||||||
songMenu.resetGameDataOnLoad();
|
songMenu.resetGameDataOnLoad();
|
||||||
songMenu.resetTrackOnLoad();
|
songMenu.resetTrackOnLoad();
|
||||||
|
Utils.resetCursor();
|
||||||
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:
|
||||||
|
@ -174,12 +175,14 @@ public class GameRanking extends BasicGameState {
|
||||||
SoundController.playSound(SoundEffect.MENUBACK);
|
SoundController.playSound(SoundEffect.MENUBACK);
|
||||||
((MainMenu) game.getState(Opsu.STATE_MAINMENU)).reset();
|
((MainMenu) game.getState(Opsu.STATE_MAINMENU)).reset();
|
||||||
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).resetGameDataOnLoad();
|
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).resetGameDataOnLoad();
|
||||||
|
Utils.resetCursor();
|
||||||
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 (Utils.getBackButton().contains(x, y)) {
|
} else if (Utils.getBackButton().contains(x, y)) {
|
||||||
SoundController.playSound(SoundEffect.MENUBACK);
|
SoundController.playSound(SoundEffect.MENUBACK);
|
||||||
SongMenu songMenu = (SongMenu) game.getState(Opsu.STATE_SONGMENU);
|
SongMenu songMenu = (SongMenu) game.getState(Opsu.STATE_SONGMENU);
|
||||||
songMenu.resetGameDataOnLoad();
|
songMenu.resetGameDataOnLoad();
|
||||||
songMenu.resetTrackOnLoad();
|
songMenu.resetTrackOnLoad();
|
||||||
|
Utils.resetCursor();
|
||||||
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -703,7 +703,11 @@ public class SongMenu extends BasicGameState {
|
||||||
// reset game data
|
// reset game data
|
||||||
if (resetGame) {
|
if (resetGame) {
|
||||||
((Game) game.getState(Opsu.STATE_GAME)).resetGameData();
|
((Game) game.getState(Opsu.STATE_GAME)).resetGameData();
|
||||||
GameImage.destroySkinImages(); // destroy skin images, if any
|
// destroy skin images, if any
|
||||||
|
for (GameImage img : GameImage.values()) {
|
||||||
|
if (img.isSkinnable())
|
||||||
|
img.destroySkinImage();
|
||||||
|
}
|
||||||
resetGame = false;
|
resetGame = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user