Implemented in-game beatmap reloading.
- Press F5 to reload beatmaps in the song menu (resets OsuGroupList, then invokes OSZ unpacker and OsuFile parser). - Many components reused from Splash screen (progress display, 'Esc' interrupt). Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
19476993f9
commit
a48f8bd54d
|
@ -63,7 +63,7 @@ public class Opsu extends StateBasedGame {
|
|||
STATE_GAME = 4,
|
||||
STATE_GAMEPAUSEMENU = 5,
|
||||
STATE_GAMERANKING = 6,
|
||||
STATE_OPTIONS = 7;
|
||||
STATE_OPTIONSMENU = 7;
|
||||
|
||||
/**
|
||||
* Used to restrict the program to a single instance.
|
||||
|
@ -83,7 +83,7 @@ public class Opsu extends StateBasedGame {
|
|||
addState(new Game(STATE_GAME));
|
||||
addState(new GamePauseMenu(STATE_GAMEPAUSEMENU));
|
||||
addState(new GameRanking(STATE_GAMERANKING));
|
||||
addState(new OptionsMenu(STATE_OPTIONS));
|
||||
addState(new OptionsMenu(STATE_OPTIONSMENU));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -587,6 +587,47 @@ public class Utils {
|
|||
volumeDisplay = VOLUME_DISPLAY_TIME / 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws loading progress (OSZ unpacking, OsuFile parsing, sound loading)
|
||||
* at the bottom of the screen.
|
||||
*/
|
||||
public static void drawLoadingProgress(Graphics g) {
|
||||
String text, file;
|
||||
int progress;
|
||||
|
||||
// determine current action
|
||||
if ((file = OszUnpacker.getCurrentFileName()) != null) {
|
||||
text = "Unpacking new beatmaps...";
|
||||
progress = OszUnpacker.getUnpackerProgress();
|
||||
} else if ((file = OsuParser.getCurrentFileName()) != null) {
|
||||
text = "Loading beatmaps...";
|
||||
progress = OsuParser.getParserProgress();
|
||||
} else if ((file = SoundController.getCurrentFileName()) != null) {
|
||||
text = "Loading sounds...";
|
||||
progress = SoundController.getLoadingProgress();
|
||||
} else
|
||||
return;
|
||||
|
||||
// draw loading info
|
||||
float marginX = container.getWidth() * 0.02f, marginY = container.getHeight() * 0.02f;
|
||||
float lineY = container.getHeight() - marginY;
|
||||
int lineOffsetY = Utils.FONT_MEDIUM.getLineHeight();
|
||||
if (Options.isLoadVerbose()) {
|
||||
// verbose: display percentages and file names
|
||||
Utils.FONT_MEDIUM.drawString(
|
||||
marginX, lineY - (lineOffsetY * 2),
|
||||
String.format("%s (%d%%)", text, progress), Color.white);
|
||||
Utils.FONT_MEDIUM.drawString(marginX, lineY - lineOffsetY, file, Color.white);
|
||||
} else {
|
||||
// draw loading bar
|
||||
Utils.FONT_MEDIUM.drawString(marginX, lineY - (lineOffsetY * 2), text, Color.white);
|
||||
g.setColor(Color.white);
|
||||
g.fillRoundRect(marginX, lineY - (lineOffsetY / 2f),
|
||||
(container.getWidth() - (marginX * 2f)) * progress / 100f, lineOffsetY / 4f, 4
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a screenshot.
|
||||
* @author http://wiki.lwjgl.org/index.php?title=Taking_Screen_Shots
|
||||
|
|
|
@ -43,7 +43,7 @@ import org.newdawn.slick.state.transition.EmptyTransition;
|
|||
import org.newdawn.slick.state.transition.FadeInTransition;
|
||||
|
||||
/**
|
||||
* "Game OptionsMenu" state.
|
||||
* "Game Options" state.
|
||||
*/
|
||||
public class OptionsMenu extends BasicGameState {
|
||||
/**
|
||||
|
|
|
@ -22,10 +22,12 @@ import itdelatrisu.opsu.GameImage;
|
|||
import itdelatrisu.opsu.GameMod;
|
||||
import itdelatrisu.opsu.MenuButton;
|
||||
import itdelatrisu.opsu.Opsu;
|
||||
import itdelatrisu.opsu.Options;
|
||||
import itdelatrisu.opsu.OsuFile;
|
||||
import itdelatrisu.opsu.OsuGroupList;
|
||||
import itdelatrisu.opsu.OsuGroupNode;
|
||||
import itdelatrisu.opsu.OsuParser;
|
||||
import itdelatrisu.opsu.OszUnpacker;
|
||||
import itdelatrisu.opsu.SongSort;
|
||||
import itdelatrisu.opsu.Utils;
|
||||
import itdelatrisu.opsu.audio.HitSound;
|
||||
|
@ -33,6 +35,7 @@ import itdelatrisu.opsu.audio.MusicController;
|
|||
import itdelatrisu.opsu.audio.SoundController;
|
||||
import itdelatrisu.opsu.audio.SoundEffect;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
@ -187,6 +190,11 @@ public class SongMenu extends BasicGameState {
|
|||
*/
|
||||
private boolean resetTrack = false;
|
||||
|
||||
/**
|
||||
* Beatmap reloading thread.
|
||||
*/
|
||||
private Thread reloadThread;
|
||||
|
||||
// game-related variables
|
||||
private GameContainer container;
|
||||
private StateBasedGame game;
|
||||
|
@ -339,8 +347,18 @@ public class SongMenu extends BasicGameState {
|
|||
g.fillRoundRect(width - 10, scrollStartY + (scrollEndY * startNode.index / OsuGroupList.get().size()), 5, 20, 4);
|
||||
}
|
||||
|
||||
// reloading beatmaps
|
||||
if (reloadThread != null) {
|
||||
// darken the screen
|
||||
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||
g.fillRect(0, 0, width, height);
|
||||
|
||||
Utils.drawLoadingProgress(g);
|
||||
}
|
||||
|
||||
// back button
|
||||
Utils.getBackButton().draw();
|
||||
else
|
||||
Utils.getBackButton().draw();
|
||||
|
||||
Utils.drawVolume(g);
|
||||
Utils.drawFPS();
|
||||
|
@ -445,6 +463,10 @@ public class SongMenu extends BasicGameState {
|
|||
if (button != Input.MOUSE_LEFT_BUTTON)
|
||||
return;
|
||||
|
||||
// block input during beatmap reloading
|
||||
if (reloadThread != null)
|
||||
return;
|
||||
|
||||
// back
|
||||
if (Utils.getBackButton().contains(x, y)) {
|
||||
SoundController.playSound(SoundEffect.MENUBACK);
|
||||
|
@ -456,7 +478,7 @@ public class SongMenu extends BasicGameState {
|
|||
// options
|
||||
if (optionsButton.contains(x, y)) {
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
game.enterState(Opsu.STATE_OPTIONS, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||
game.enterState(Opsu.STATE_OPTIONSMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -520,19 +542,30 @@ public class SongMenu extends BasicGameState {
|
|||
|
||||
@Override
|
||||
public void keyPressed(int key, char c) {
|
||||
// block input during beatmap reloading
|
||||
if (reloadThread != null && !(key == Input.KEY_ESCAPE || key == Input.KEY_F12))
|
||||
return;
|
||||
|
||||
switch (key) {
|
||||
case Input.KEY_ESCAPE:
|
||||
if (!search.getText().isEmpty()) {
|
||||
if (reloadThread != null) {
|
||||
// beatmap reloading: stop parsing OsuFiles by sending interrupt to OsuParser
|
||||
if (reloadThread != null)
|
||||
reloadThread.interrupt();
|
||||
} else if (!search.getText().isEmpty()) {
|
||||
// clear search text
|
||||
search.setText("");
|
||||
searchTimer = SEARCH_DELAY;
|
||||
} else {
|
||||
// return to main menu
|
||||
SoundController.playSound(SoundEffect.MENUBACK);
|
||||
((MainMenu) game.getState(Opsu.STATE_MAINMENU)).reset();
|
||||
game.enterState(Opsu.STATE_MAINMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
}
|
||||
break;
|
||||
case Input.KEY_F1:
|
||||
game.enterState(Opsu.STATE_OPTIONS, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||
SoundController.playSound(SoundEffect.MENUHIT);
|
||||
game.enterState(Opsu.STATE_OPTIONSMENU, new EmptyTransition(), new FadeInTransition(Color.black));
|
||||
break;
|
||||
case Input.KEY_F2:
|
||||
if (focusNode == null)
|
||||
|
@ -549,6 +582,42 @@ public class SongMenu extends BasicGameState {
|
|||
setFocus(OsuGroupList.get().getRandomNode(), -1, true);
|
||||
}
|
||||
break;
|
||||
case Input.KEY_F5:
|
||||
// TODO: osu! has a confirmation menu
|
||||
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||
|
||||
// reset state and node references
|
||||
MusicController.reset();
|
||||
startNode = focusNode = null;
|
||||
oldFocusNode = null;
|
||||
randomStack = new Stack<SongNode>();
|
||||
songInfo = null;
|
||||
hoverOffset = 0f;
|
||||
hoverIndex = -1;
|
||||
search.setText("");
|
||||
searchTimer = SEARCH_DELAY;
|
||||
|
||||
// reload songs in new thread
|
||||
reloadThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
// invoke unpacker and parser
|
||||
File beatmapDir = Options.getBeatmapDir();
|
||||
OszUnpacker.unpackAllFiles(Options.getOSZDir(), beatmapDir);
|
||||
OsuParser.parseAllFiles(beatmapDir, container.getWidth(), container.getHeight());
|
||||
|
||||
// initialize song list
|
||||
if (OsuGroupList.get().size() > 0) {
|
||||
OsuGroupList.get().init();
|
||||
setFocus(OsuGroupList.get().getRandomNode(), -1, true);
|
||||
} else if (Options.isThemSongEnabled())
|
||||
MusicController.playThemeSong();
|
||||
|
||||
reloadThread = null;
|
||||
}
|
||||
};
|
||||
reloadThread.start();
|
||||
break;
|
||||
case Input.KEY_F12:
|
||||
Utils.takeScreenShot();
|
||||
break;
|
||||
|
@ -616,6 +685,10 @@ public class SongMenu extends BasicGameState {
|
|||
|
||||
@Override
|
||||
public void mouseDragged(int oldx, int oldy, int newx, int newy) {
|
||||
// block input during beatmap reloading
|
||||
if (reloadThread != null)
|
||||
return;
|
||||
|
||||
// check mouse button (right click scrolls faster)
|
||||
int multiplier;
|
||||
if (input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))
|
||||
|
@ -634,6 +707,10 @@ public class SongMenu extends BasicGameState {
|
|||
|
||||
@Override
|
||||
public void mouseWheelMoved(int newValue) {
|
||||
// block input during beatmap reloading
|
||||
if (reloadThread != null)
|
||||
return;
|
||||
|
||||
changeIndex((newValue < 0) ? 1 : -1);
|
||||
}
|
||||
|
||||
|
|
|
@ -85,27 +85,7 @@ public class Splash extends BasicGameState {
|
|||
throws SlickException {
|
||||
g.setBackground(Color.black);
|
||||
GameImage.MENU_LOGO.getImage().drawCentered(container.getWidth() / 2, container.getHeight() / 2);
|
||||
|
||||
// display progress
|
||||
String unpackedFile = OszUnpacker.getCurrentFileName();
|
||||
String parsedFile = OsuParser.getCurrentFileName();
|
||||
String soundFile = SoundController.getCurrentFileName();
|
||||
if (unpackedFile != null) {
|
||||
drawLoadProgress(
|
||||
g, OszUnpacker.getUnpackerProgress(),
|
||||
"Unpacking new beatmaps...", unpackedFile
|
||||
);
|
||||
} else if (parsedFile != null) {
|
||||
drawLoadProgress(
|
||||
g, OsuParser.getParserProgress(),
|
||||
"Loading beatmaps...", parsedFile
|
||||
);
|
||||
} else if (soundFile != null) {
|
||||
drawLoadProgress(
|
||||
g, SoundController.getLoadingProgress(),
|
||||
"Loading sounds...", soundFile
|
||||
);
|
||||
}
|
||||
Utils.drawLoadingProgress(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,6 +116,7 @@ public class Splash extends BasicGameState {
|
|||
SoundController.init();
|
||||
|
||||
finished = true;
|
||||
thread = null;
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
|
@ -151,8 +132,10 @@ public class Splash extends BasicGameState {
|
|||
// change states when loading complete
|
||||
if (finished && alpha >= 1f) {
|
||||
// initialize song list
|
||||
OsuGroupList.get().init();
|
||||
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).setFocus(OsuGroupList.get().getRandomNode(), -1, true);
|
||||
if (OsuGroupList.get().size() > 0) {
|
||||
OsuGroupList.get().init();
|
||||
((SongMenu) game.getState(Opsu.STATE_SONGMENU)).setFocus(OsuGroupList.get().getRandomNode(), -1, true);
|
||||
}
|
||||
|
||||
// play the theme song
|
||||
if (Options.isThemSongEnabled())
|
||||
|
@ -175,29 +158,4 @@ public class Splash extends BasicGameState {
|
|||
else if (key == Input.KEY_ESCAPE && thread != null)
|
||||
thread.interrupt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws loading progress.
|
||||
* @param g the graphics context
|
||||
* @param progress the completion percentage
|
||||
* @param text the progress text
|
||||
* @param file the file being loaded
|
||||
*/
|
||||
private void drawLoadProgress(Graphics g, int progress, String text, String file) {
|
||||
float marginX = container.getWidth() * 0.02f, marginY = container.getHeight() * 0.02f;
|
||||
float lineY = container.getHeight() - marginY;
|
||||
int lineOffsetY = Utils.FONT_MEDIUM.getLineHeight();
|
||||
if (Options.isLoadVerbose()) {
|
||||
Utils.FONT_MEDIUM.drawString(
|
||||
marginX, lineY - (lineOffsetY * 2),
|
||||
String.format("%s (%d%%)", text, progress), Color.white);
|
||||
Utils.FONT_MEDIUM.drawString(marginX, lineY - lineOffsetY, file, Color.white);
|
||||
} else {
|
||||
Utils.FONT_MEDIUM.drawString(marginX, lineY - (lineOffsetY * 2), text, Color.white);
|
||||
g.setColor(Color.white);
|
||||
g.fillRoundRect(marginX, lineY - (lineOffsetY / 2f),
|
||||
(container.getWidth() - (marginX * 2f)) * progress / 100f, lineOffsetY / 4f, 4
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user