Created a splash screen state for loading resources.

- Game now boots to splash screen, which displays parser progress.
- Added option "LoadVerbose" to disable rendering the progress text.
- Main Menu backgrounds now fade in regardless of DynamicBackground setting (as a transition from the splash screen).

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han
2014-07-05 21:00:52 -04:00
parent 0dbfd18c5f
commit dea7e942a3
7 changed files with 230 additions and 43 deletions

View File

@@ -96,9 +96,9 @@ public class MainMenu extends BasicGameState {
private Image backgroundImage;
/**
* Alpha level for fade-in effect for dynamic backgrounds.
* Background alpha level (for fade-in effect).
*/
private float dynamicBackgroundAlpha = 0f;
private float bgAlpha = 0f;
// game-related variables
private StateBasedGame game;
@@ -111,8 +111,6 @@ public class MainMenu extends BasicGameState {
@Override
public void init(GameContainer container, StateBasedGame game)
throws SlickException {
Utils.init(container, game);
this.game = game;
osuStartTime = System.currentTimeMillis();
@@ -165,11 +163,12 @@ public class MainMenu extends BasicGameState {
// draw background
OsuFile osu = MusicController.getOsuFile();
if (Options.isDynamicBackgroundEnabled() &&
osu != null && osu.drawBG(width, height, dynamicBackgroundAlpha))
osu != null && osu.drawBG(width, height, bgAlpha))
;
else if (backgroundImage != null)
else if (backgroundImage != null) {
backgroundImage.setAlpha(bgAlpha);
backgroundImage.draw();
else
} else
g.setBackground(Utils.COLOR_BLUE_BACKGROUND);
// draw buttons
@@ -224,11 +223,11 @@ public class MainMenu extends BasicGameState {
@Override
public void update(GameContainer container, StateBasedGame game, int delta)
throws SlickException {
// dynamic backgrounds
if (Options.isDynamicBackgroundEnabled() && dynamicBackgroundAlpha < 0.9f) {
dynamicBackgroundAlpha += delta / 1000f;
if (dynamicBackgroundAlpha > 0.9f)
dynamicBackgroundAlpha = 0.9f;
// fade in background
if (bgAlpha < 0.9f) {
bgAlpha += delta / 1000f;
if (bgAlpha > 0.9f)
bgAlpha = 0.9f;
}
// buttons
@@ -296,12 +295,14 @@ public class MainMenu extends BasicGameState {
OsuGroupNode node = menu.setFocus(Opsu.groups.getRandomNode(), -1, true);
if (node != null)
previous.add(node.index);
dynamicBackgroundAlpha = 0f;
if (Options.isDynamicBackgroundEnabled())
bgAlpha = 0f;
} else if (musicPrevious.contains(x, y)) {
if (!previous.isEmpty()) {
SongMenu menu = (SongMenu) game.getState(Opsu.STATE_SONGMENU);
menu.setFocus(Opsu.groups.getBaseNode(previous.pop()), -1, true);
dynamicBackgroundAlpha = 0f;
if (Options.isDynamicBackgroundEnabled())
bgAlpha = 0f;
} else
MusicController.setPosition(0);
}

View File

@@ -134,7 +134,8 @@ public class Options extends BasicGameState {
FIXED_CS,
FIXED_HP,
FIXED_AR,
FIXED_OD;
FIXED_OD,
LOAD_VERBOSE;
};
/**
@@ -177,7 +178,8 @@ public class Options extends BasicGameState {
GameOption.SHOW_FPS,
GameOption.SCREENSHOT_FORMAT,
GameOption.NEW_CURSOR,
GameOption.DYNAMIC_BACKGROUND
GameOption.DYNAMIC_BACKGROUND,
GameOption.LOAD_VERBOSE
};
/**
@@ -341,6 +343,11 @@ public class Options extends BasicGameState {
fixedCS = 0f, fixedHP = 0f,
fixedAR = 0f, fixedOD = 0f;
/**
* Whether or not to render loading text in the splash screen.
*/
private static boolean loadVerbose = true;
/**
* Game option coordinate modifiers (for drawing).
*/
@@ -584,6 +591,9 @@ public class Options extends BasicGameState {
case IGNORE_BEATMAP_SKINS:
ignoreBeatmapSkins = !ignoreBeatmapSkins;
break;
case LOAD_VERBOSE:
loadVerbose = !loadVerbose;
break;
default:
break;
}
@@ -750,6 +760,12 @@ public class Options extends BasicGameState {
"The song background will be used as the main menu background."
);
break;
case LOAD_VERBOSE:
drawOption(pos, "Display Loading Text",
loadVerbose ? "Yes" : "No",
"Display loading progress in the splash screen."
);
break;
case MUSIC_VOLUME:
drawOption(pos, "Music Volume",
String.format("%d%%", musicVolume),
@@ -1048,6 +1064,12 @@ public class Options extends BasicGameState {
*/
public static float getFixedOD() { return fixedOD; }
/**
* Returns whether or not to render loading text in the splash screen.
* @return true if enabled
*/
public static boolean isLoadVerbose() { return loadVerbose; }
/**
* Returns the current beatmap directory.
* If invalid, this will attempt to search for the directory,
@@ -1144,6 +1166,9 @@ public class Options extends BasicGameState {
case "DynamicBackground":
dynamicBackground = Boolean.parseBoolean(value);
break;
case "LoadVerbose":
loadVerbose = Boolean.parseBoolean(value);
break;
case "VolumeMusic":
i = Integer.parseInt(value);
if (i >= 0 && i <= 100)
@@ -1243,6 +1268,8 @@ public class Options extends BasicGameState {
writer.newLine();
writer.write(String.format("DynamicBackground = %b", dynamicBackground));
writer.newLine();
writer.write(String.format("LoadVerbose = %b", loadVerbose));
writer.newLine();
writer.write(String.format("VolumeMusic = %d", musicVolume));
writer.newLine();
writer.write(String.format("VolumeEffect = %d", effectVolume));

View File

@@ -85,7 +85,7 @@ public class SongMenu extends BasicGameState {
/**
* The current sort order (SORT_* constant).
*/
private byte currentSort;
private byte currentSort = OsuGroupList.SORT_TITLE;
/**
* The options button (to enter the "Game Options" menu).
@@ -135,11 +135,6 @@ public class SongMenu extends BasicGameState {
this.game = game;
this.input = container.getInput();
// initialize song list
currentSort = OsuGroupList.SORT_TITLE;
Opsu.groups.init(currentSort);
setFocus(Opsu.groups.getRandomNode(), -1, true);
int width = container.getWidth();
int height = container.getHeight();
@@ -414,7 +409,7 @@ public class SongMenu extends BasicGameState {
startNode = Opsu.groups.getBaseNode(startNode.index);
}
setFocus(node, -1, false);
break;
}
}

View File

@@ -0,0 +1,125 @@
/*
* 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.states;
import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.OsuGroupList;
import itdelatrisu.opsu.OsuParser;
import itdelatrisu.opsu.SoundController;
import itdelatrisu.opsu.Utils;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
public class Splash extends BasicGameState {
/**
* Logo image.
*/
private Image logo;
/**
* Whether or not loading has completed.
*/
private boolean finished = false;
// game-related variables
private int state;
public Splash(int state) {
this.state = state;
}
@Override
public void init(GameContainer container, StateBasedGame game)
throws SlickException {
final int width = container.getWidth();
final int height = container.getHeight();
logo = new Image("logo.png");
logo = logo.getScaledCopy((height / 1.2f) / logo.getHeight());
logo.setAlpha(0f);
// load Utils class first (needed in other 'init' methods)
Utils.init(container, game);
// load other resources in a new thread
final SongMenu menu = (SongMenu) game.getState(Opsu.STATE_SONGMENU);
new Thread() {
@Override
public void run() {
// parse song directory
OsuParser.parseAllFiles(Options.getBeatmapDir(), width, height);
// initialize song list
Opsu.groups.init(OsuGroupList.SORT_TITLE);
menu.setFocus(Opsu.groups.getRandomNode(), -1, true);
// load sounds
SoundController.init();
finished = true;
}
}.start();
}
@Override
public void render(GameContainer container, StateBasedGame game, Graphics g)
throws SlickException {
g.setBackground(Color.black);
int width = container.getWidth();
int height = container.getHeight();
logo.drawCentered(width / 2, height / 2);
// progress tracking
String currentFile = OsuParser.getCurrentFileName();
if (currentFile != null && Options.isLoadVerbose()) {
g.setColor(Color.white);
g.setFont(Utils.FONT_MEDIUM);
int lineHeight = Utils.FONT_MEDIUM.getLineHeight();
g.drawString(
String.format("Loading... (%s%%)", OsuParser.getParserProgress()),
25, height - 25 - (lineHeight * 2)
);
g.drawString(currentFile, 25, height - 25 - lineHeight);
}
}
@Override
public void update(GameContainer container, StateBasedGame game, int delta)
throws SlickException {
// fade in logo
float alpha = logo.getAlpha();
if (alpha < 1f)
logo.setAlpha(alpha + (delta / 400f));
// change states when loading complete
if (finished && alpha >= 1f)
game.enterState(Opsu.STATE_MAINMENU);
}
@Override
public int getID() { return state; }
}