Enabled application restarts.
- Pressing Ctrl+Shift+F5 in the options menu restarts the game. Beatmaps and sounds are not reloaded. - Use GameContainer.setForceExit(false) to trigger a restart after exiting. Other changes: - Fixed general issues with track pausing/pause states. - Store all background images loaded in OsuFiles in a static hash table, instead of in individual objects. This allows easier access to the allocated memory. - Only delete OSZ files if they were unzipped. (They were previously deleted in all cases.) - Moved more images (mods, playfield, lighting) into GameImage. - Moved OsuHitObject initialization inside Utils. Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
3b13cc794b
commit
f98edf8fc8
|
@ -24,6 +24,7 @@ import itdelatrisu.opsu.states.Options;
|
||||||
import org.newdawn.slick.AppGameContainer;
|
import org.newdawn.slick.AppGameContainer;
|
||||||
import org.newdawn.slick.Game;
|
import org.newdawn.slick.Game;
|
||||||
import org.newdawn.slick.SlickException;
|
import org.newdawn.slick.SlickException;
|
||||||
|
import org.newdawn.slick.opengl.InternalTextureLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AppGameContainer extension that sends critical errors to ErrorHandler.
|
* AppGameContainer extension that sends critical errors to ErrorHandler.
|
||||||
|
@ -65,8 +66,11 @@ public class Container extends AppGameContainer {
|
||||||
while (running())
|
while (running())
|
||||||
gameLoop();
|
gameLoop();
|
||||||
} finally {
|
} finally {
|
||||||
MusicController.reset(); // prevent loading tracks from re-initializing OpenAL
|
// destroy the game container
|
||||||
|
close_sub();
|
||||||
destroy();
|
destroy();
|
||||||
|
|
||||||
|
// report any critical errors
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
ErrorHandler.error(null, e, true);
|
ErrorHandler.error(null, e, true);
|
||||||
e = null;
|
e = null;
|
||||||
|
@ -77,20 +81,34 @@ public class Container extends AppGameContainer {
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions to perform before destroying the game container.
|
||||||
|
*/
|
||||||
|
private void close_sub() {
|
||||||
|
// save user options
|
||||||
|
Options.saveOptions();
|
||||||
|
|
||||||
|
// close server socket
|
||||||
|
Opsu.closeSocket();
|
||||||
|
|
||||||
|
// prevent loading tracks from re-initializing OpenAL
|
||||||
|
MusicController.reset();
|
||||||
|
|
||||||
|
// destroy images
|
||||||
|
InternalTextureLoader.get().clear();
|
||||||
|
|
||||||
|
// reset image references
|
||||||
|
GameImage.clearReferences();
|
||||||
|
OsuFile.resetImageCache();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateAndRender(int delta) throws SlickException {
|
protected void updateAndRender(int delta) throws SlickException {
|
||||||
try {
|
try {
|
||||||
super.updateAndRender(delta);
|
super.updateAndRender(delta);
|
||||||
} catch (SlickException e) {
|
} catch (SlickException e) {
|
||||||
this.e = e;
|
this.e = e; // store exception to display later
|
||||||
throw e;
|
throw e; // re-throw exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exit() {
|
|
||||||
Options.saveOptions();
|
|
||||||
Opsu.closeSocket();
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,13 @@ public enum GameImage {
|
||||||
},
|
},
|
||||||
HITCIRCLE_SELECT ("hitcircleselect", "png"),
|
HITCIRCLE_SELECT ("hitcircleselect", "png"),
|
||||||
UNRANKED ("play-unranked", "png"),
|
UNRANKED ("play-unranked", "png"),
|
||||||
|
PLAYFIELD ("playfield", "png|jpg", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
img.setAlpha(0.7f);
|
||||||
|
return img.getScaledCopy(w, h);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Game Pause/Fail
|
// Game Pause/Fail
|
||||||
PAUSE_CONTINUE ("pause-continue", "png"),
|
PAUSE_CONTINUE ("pause-continue", "png"),
|
||||||
|
@ -206,6 +213,70 @@ public enum GameImage {
|
||||||
SCORE_DOT ("score-dot", "png"),
|
SCORE_DOT ("score-dot", "png"),
|
||||||
SCORE_PERCENT ("score-percent", "png"),
|
SCORE_PERCENT ("score-percent", "png"),
|
||||||
SCORE_X ("score-x", "png"),
|
SCORE_X ("score-x", "png"),
|
||||||
|
LIGHTING ("lighting", "png"),
|
||||||
|
LIGHTING1 ("lighting1", "png"),
|
||||||
|
|
||||||
|
// Game Mods
|
||||||
|
MOD_EASY ("selection-mod-easy", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MOD_NO_FAIL ("selection-mod-nofail", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MOD_HARD_ROCK ("selection-mod-hardrock", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MOD_SUDDEN_DEATH ("selection-mod-suddendeath", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MOD_SPUN_OUT ("selection-mod-spunout", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MOD_AUTO ("selection-mod-autoplay", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MOD_HALF_TIME ("selection-mod-halftime", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MOD_DOUBLE_TIME ("selection-mod-doubletime", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MOD_HIDDEN ("selection-mod-hidden", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MOD_FLASHLIGHT ("selection-mod-flashlight", "png", false, false) {
|
||||||
|
@Override
|
||||||
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
return img.getScaledCopy((h * 0.12f) / img.getHeight());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Non-Game Components
|
// Non-Game Components
|
||||||
VOLUME ("volume-bg", "png", false, false) {
|
VOLUME ("volume-bg", "png", false, false) {
|
||||||
|
@ -291,12 +362,10 @@ public enum GameImage {
|
||||||
},
|
},
|
||||||
MENU_BUTTON_LEFT ("button-left", "png", false, false),
|
MENU_BUTTON_LEFT ("button-left", "png", false, false),
|
||||||
MENU_BUTTON_RIGHT ("button-right", "png", false, false),
|
MENU_BUTTON_RIGHT ("button-right", "png", false, false),
|
||||||
|
|
||||||
MUSIC_PLAY ("music-play", "png", false, false),
|
MUSIC_PLAY ("music-play", "png", false, false),
|
||||||
MUSIC_PAUSE ("music-pause", "png", false, false),
|
MUSIC_PAUSE ("music-pause", "png", false, false),
|
||||||
MUSIC_NEXT ("music-next", "png", false, false),
|
MUSIC_NEXT ("music-next", "png", false, false),
|
||||||
MUSIC_PREVIOUS ("music-previous", "png", false, false),
|
MUSIC_PREVIOUS ("music-previous", "png", false, false),
|
||||||
|
|
||||||
RANKING_RETRY ("ranking-retry", "png", false, false) {
|
RANKING_RETRY ("ranking-retry", "png", false, false) {
|
||||||
@Override
|
@Override
|
||||||
protected Image process_sub(Image img, int w, int h) {
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
@ -309,7 +378,6 @@ public enum GameImage {
|
||||||
return img.getScaledCopy((h * 0.15f) / img.getHeight());
|
return img.getScaledCopy((h * 0.15f) / img.getHeight());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
REPOSITORY ("repo", "png", false, false) {
|
REPOSITORY ("repo", "png", false, false) {
|
||||||
@Override
|
@Override
|
||||||
protected Image process_sub(Image img, int w, int h) {
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
@ -375,6 +443,15 @@ public enum GameImage {
|
||||||
containerHeight = height;
|
containerHeight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all image references.
|
||||||
|
* This does NOT destroy images, so be careful of memory leaks!
|
||||||
|
*/
|
||||||
|
public static void clearReferences() {
|
||||||
|
for (GameImage img : GameImage.values())
|
||||||
|
img.defaultImage = img.skinImage = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys all skin images, if any have been loaded.
|
* Destroys all skin images, if any have been loaded.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -23,22 +23,21 @@ import java.util.Collections;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Game mods.
|
* Game mods.
|
||||||
*/
|
*/
|
||||||
public enum GameMod {
|
public enum GameMod {
|
||||||
EASY (0, "selection-mod-easy.png", Input.KEY_Q, 0.5f),
|
EASY (0, GameImage.MOD_EASY, Input.KEY_Q, 0.5f),
|
||||||
NO_FAIL (1, "selection-mod-nofail.png", Input.KEY_W, 0.5f),
|
NO_FAIL (1, GameImage.MOD_NO_FAIL, Input.KEY_W, 0.5f),
|
||||||
HARD_ROCK (2, "selection-mod-hardrock.png", Input.KEY_A, 1.06f),
|
HARD_ROCK (2, GameImage.MOD_HARD_ROCK, Input.KEY_A, 1.06f),
|
||||||
SUDDEN_DEATH (3, "selection-mod-suddendeath.png", Input.KEY_S),
|
SUDDEN_DEATH (3, GameImage.MOD_SUDDEN_DEATH, Input.KEY_S),
|
||||||
SPUN_OUT (4, "selection-mod-spunout.png", Input.KEY_V, 0.9f),
|
SPUN_OUT (4, GameImage.MOD_SPUN_OUT, Input.KEY_V, 0.9f),
|
||||||
AUTO (5, "selection-mod-autoplay.png", Input.KEY_B);
|
AUTO (5, GameImage.MOD_AUTO, Input.KEY_B);
|
||||||
// HALF_TIME (, "selection-mod-halftime.png", Input.KEY_E, 0.3f),
|
// HALF_TIME (, GameImage.MOD_HALF_TIME, Input.KEY_E, 0.3f),
|
||||||
// DOUBLE_TIME (, "selection-mod-doubletime.png", Input.KEY_D, 1.12f),
|
// DOUBLE_TIME (, GameImage.MOD_DOUBLE_TIME, Input.KEY_D, 1.12f),
|
||||||
// HIDDEN (, "selection-mod-hidden.png", Input.KEY_F, 1.06f),
|
// HIDDEN (, GameImage.MOD_HIDDEN, Input.KEY_F, 1.06f),
|
||||||
// FLASHLIGHT (, "selection-mod-flashlight.png", Input.KEY_G, 1.12f);
|
// FLASHLIGHT (, GameImage.MOD_FLASHLIGHT, Input.KEY_G, 1.12f);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID of the mod (used for positioning).
|
* The ID of the mod (used for positioning).
|
||||||
|
@ -48,7 +47,7 @@ public enum GameMod {
|
||||||
/**
|
/**
|
||||||
* The file name of the mod image.
|
* The file name of the mod image.
|
||||||
*/
|
*/
|
||||||
private String filename;
|
private GameImage image;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shortcut key associated with the mod.
|
* The shortcut key associated with the mod.
|
||||||
|
@ -94,12 +93,12 @@ public enum GameMod {
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param id the ID of the mod (for positioning).
|
* @param id the ID of the mod (for positioning).
|
||||||
* @param filename the image file name
|
* @param image the GameImage
|
||||||
* @param key the shortcut key
|
* @param key the shortcut key
|
||||||
*/
|
*/
|
||||||
GameMod(int id, String filename, int key) {
|
GameMod(int id, GameImage image, int key) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.filename = filename;
|
this.image = image;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.multiplier = 1f;
|
this.multiplier = 1f;
|
||||||
}
|
}
|
||||||
|
@ -107,13 +106,13 @@ public enum GameMod {
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param id the ID of the mod (for positioning).
|
* @param id the ID of the mod (for positioning).
|
||||||
* @param filename the image file name
|
* @param image the GameImage
|
||||||
* @param key the shortcut key
|
* @param key the shortcut key
|
||||||
* @param multiplier the score multiplier
|
* @param multiplier the score multiplier
|
||||||
*/
|
*/
|
||||||
GameMod(int id, String filename, int key, float multiplier) {
|
GameMod(int id, GameImage image, int key, float multiplier) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.filename = filename;
|
this.image = image;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.multiplier = multiplier;
|
this.multiplier = multiplier;
|
||||||
}
|
}
|
||||||
|
@ -124,24 +123,17 @@ public enum GameMod {
|
||||||
* @param height the container height
|
* @param height the container height
|
||||||
*/
|
*/
|
||||||
public void init(int width, int height) {
|
public void init(int width, int height) {
|
||||||
try {
|
Image img = image.getImage();
|
||||||
// create and scale image
|
|
||||||
Image img = new Image(filename);
|
|
||||||
float scale = (height * 0.12f) / img.getHeight();
|
|
||||||
img = img.getScaledCopy(scale);
|
|
||||||
|
|
||||||
// find coordinates
|
// find coordinates
|
||||||
float offsetX = img.getWidth() * 1.5f;
|
float offsetX = img.getWidth() * 1.5f;
|
||||||
float x = (width / 2f) - (offsetX * SIZE / 2.75f);
|
float x = (width / 2f) - (offsetX * SIZE / 2.75f);
|
||||||
float y = (height * 0.8f) + (img.getHeight() / 2);
|
float y = (height * 0.8f) + (img.getHeight() / 2);
|
||||||
|
|
||||||
// create button
|
// create button
|
||||||
img.setAlpha(0.5f);
|
img.setAlpha(0.5f);
|
||||||
this.button = new MenuButton(img, x + (offsetX * id), y);
|
this.button = new MenuButton(img, x + (offsetX * id), y);
|
||||||
this.button.setHoverScale(1.15f);
|
this.button.setHoverScale(1.15f);
|
||||||
} catch (SlickException e) {
|
|
||||||
ErrorHandler.error(String.format("Failed to initialize game mod '%s'.", this), e, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,7 +194,7 @@ public enum GameMod {
|
||||||
* Returns the image associated with the mod.
|
* Returns the image associated with the mod.
|
||||||
* @return the associated image
|
* @return the associated image
|
||||||
*/
|
*/
|
||||||
public Image getImage() { return button.getImage(); }
|
public Image getImage() { return image.getImage(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the mod ID.
|
* Returns the mod ID.
|
||||||
|
|
|
@ -305,8 +305,8 @@ public class GameScore {
|
||||||
}
|
}
|
||||||
} else { // load default image
|
} else { // load default image
|
||||||
try {
|
try {
|
||||||
lighting = new Image("lighting.png");
|
lighting = GameImage.LIGHTING.getImage();
|
||||||
lighting1 = new Image("lighting1.png");
|
lighting1 = GameImage.LIGHTING1.getImage();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// optional
|
// optional
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu;
|
package itdelatrisu.opsu;
|
||||||
|
|
||||||
import itdelatrisu.opsu.audio.MusicController;
|
|
||||||
import itdelatrisu.opsu.states.Game;
|
import itdelatrisu.opsu.states.Game;
|
||||||
import itdelatrisu.opsu.states.GamePauseMenu;
|
import itdelatrisu.opsu.states.GamePauseMenu;
|
||||||
import itdelatrisu.opsu.states.GameRanking;
|
import itdelatrisu.opsu.states.GameRanking;
|
||||||
|
@ -138,16 +137,20 @@ public class Opsu extends StateBasedGame {
|
||||||
Options.TMP_DIR.deleteOnExit();
|
Options.TMP_DIR.deleteOnExit();
|
||||||
|
|
||||||
// start the game
|
// start the game
|
||||||
Opsu opsu = new Opsu("opsu!");
|
|
||||||
try {
|
try {
|
||||||
Container app = new Container(opsu);
|
// loop until force exit
|
||||||
|
while (true) {
|
||||||
|
Opsu opsu = new Opsu("opsu!");
|
||||||
|
Container app = new Container(opsu);
|
||||||
|
|
||||||
// basic game settings
|
// basic game settings
|
||||||
Options.setDisplayMode(app);
|
Options.setDisplayMode(app);
|
||||||
String[] icons = { "icon16.png", "icon32.png" };
|
String[] icons = { "icon16.png", "icon32.png" };
|
||||||
app.setIcons(icons);
|
app.setIcons(icons);
|
||||||
|
app.setForceExit(true);
|
||||||
|
|
||||||
app.start();
|
app.start();
|
||||||
|
}
|
||||||
} catch (SlickException e) {
|
} catch (SlickException e) {
|
||||||
// JARs will not run properly inside directories containing '!'
|
// JARs will not run properly inside directories containing '!'
|
||||||
// http://bugs.java.com/view_bug.do?bug_id=4523159
|
// http://bugs.java.com/view_bug.do?bug_id=4523159
|
||||||
|
@ -172,10 +175,6 @@ public class Opsu extends StateBasedGame {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicController.reset();
|
|
||||||
Options.saveOptions();
|
|
||||||
((Container) this.getContainer()).destroy();
|
|
||||||
closeSocket();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,11 @@ import itdelatrisu.opsu.states.Options;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import org.newdawn.slick.Color;
|
import org.newdawn.slick.Color;
|
||||||
import org.newdawn.slick.Image;
|
import org.newdawn.slick.Image;
|
||||||
|
import org.newdawn.slick.SlickException;
|
||||||
import org.newdawn.slick.util.Log;
|
import org.newdawn.slick.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,7 +82,7 @@ public class OsuFile implements Comparable<OsuFile> {
|
||||||
/* [Events] */
|
/* [Events] */
|
||||||
//Background and Video events (0)
|
//Background and Video events (0)
|
||||||
public String bg; // background image path
|
public String bg; // background image path
|
||||||
private Image bgImage; // background image (created when needed)
|
// private Image bgImage; // background image (created when needed)
|
||||||
// public Video bgVideo; // background video (not implemented)
|
// public Video bgVideo; // background video (not implemented)
|
||||||
//Break Periods (2)
|
//Break Periods (2)
|
||||||
public ArrayList<Integer> breaks; // break periods (start time, end time, ...)
|
public ArrayList<Integer> breaks; // break periods (start time, end time, ...)
|
||||||
|
@ -100,6 +102,35 @@ public class OsuFile implements Comparable<OsuFile> {
|
||||||
public int hitObjectSpinner = 0; // number of spinners
|
public int hitObjectSpinner = 0; // number of spinners
|
||||||
public int endTime = -1; // last object end time (in ms)
|
public int endTime = -1; // last object end time (in ms)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of all loaded background images.
|
||||||
|
*/
|
||||||
|
private static HashMap<OsuFile, Image> bgImageMap = new HashMap<OsuFile, Image>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys all cached background images and resets the cache.
|
||||||
|
*/
|
||||||
|
public static void clearImageCache() {
|
||||||
|
for (Image img : bgImageMap.values()) {
|
||||||
|
if (img != null && !img.isDestroyed()) {
|
||||||
|
try {
|
||||||
|
img.destroy();
|
||||||
|
} catch (SlickException e) {
|
||||||
|
Log.warn(String.format("Failed to destroy image '%s'.", img.getResourceReference()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resetImageCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the image cache.
|
||||||
|
* This does NOT destroy images, so be careful of memory leaks!
|
||||||
|
*/
|
||||||
|
public static void resetImageCache() {
|
||||||
|
bgImageMap = new HashMap<OsuFile, Image>();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param file the file associated with this OsuFile
|
* @param file the file associated with this OsuFile
|
||||||
|
@ -143,8 +174,11 @@ public class OsuFile implements Comparable<OsuFile> {
|
||||||
if (bg == null)
|
if (bg == null)
|
||||||
return false;
|
return false;
|
||||||
try {
|
try {
|
||||||
if (bgImage == null)
|
Image bgImage = bgImageMap.get(this);
|
||||||
|
if (bgImage == null) {
|
||||||
bgImage = new Image(bg).getScaledCopy(width, height);
|
bgImage = new Image(bg).getScaledCopy(width, height);
|
||||||
|
bgImageMap.put(this, bgImage);
|
||||||
|
}
|
||||||
bgImage.setAlpha(alpha);
|
bgImage.setAlpha(alpha);
|
||||||
bgImage.draw();
|
bgImage.draw();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -28,10 +28,6 @@ import org.newdawn.slick.Image;
|
||||||
* Node in an OsuGroupList representing a group of OsuFile objects.
|
* Node in an OsuGroupList representing a group of OsuFile objects.
|
||||||
*/
|
*/
|
||||||
public class OsuGroupNode {
|
public class OsuGroupNode {
|
||||||
/**
|
|
||||||
* Menu background image.
|
|
||||||
*/
|
|
||||||
private static Image bg;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of associated OsuFile objects.
|
* List of associated OsuFile objects.
|
||||||
|
@ -62,11 +58,6 @@ public class OsuGroupNode {
|
||||||
this.osuFiles = osuFiles;
|
this.osuFiles = osuFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a button background image.
|
|
||||||
*/
|
|
||||||
public static void setBackground(Image background) { bg = background; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the button.
|
* Draws the button.
|
||||||
* @param x the x coordinate
|
* @param x the x coordinate
|
||||||
|
@ -78,6 +69,7 @@ public class OsuGroupNode {
|
||||||
float xOffset = 0f;
|
float xOffset = 0f;
|
||||||
OsuFile osu;
|
OsuFile osu;
|
||||||
Color textColor = Color.lightGray;
|
Color textColor = Color.lightGray;
|
||||||
|
Image bg = GameImage.MENU_BUTTON_BG.getImage();
|
||||||
|
|
||||||
if (expanded) { // expanded
|
if (expanded) { // expanded
|
||||||
xOffset = bg.getWidth() / 10f;
|
xOffset = bg.getWidth() / 10f;
|
||||||
|
|
|
@ -67,9 +67,6 @@ public class OsuParser {
|
||||||
* @param height the container height
|
* @param height the container height
|
||||||
*/
|
*/
|
||||||
public static void parseAllFiles(File root, int width, int height) {
|
public static void parseAllFiles(File root, int width, int height) {
|
||||||
// initialize hit objects
|
|
||||||
OsuHitObject.init(width, height);
|
|
||||||
|
|
||||||
// progress tracking
|
// progress tracking
|
||||||
File[] folders = root.listFiles();
|
File[] folders = root.listFiles();
|
||||||
currentDirectoryIndex = 0;
|
currentDirectoryIndex = 0;
|
||||||
|
|
|
@ -65,8 +65,8 @@ public class OszUnpacker {
|
||||||
if (!songDir.isDirectory()) {
|
if (!songDir.isDirectory()) {
|
||||||
songDir.mkdir();
|
songDir.mkdir();
|
||||||
unzip(file, songDir);
|
unzip(file, songDir);
|
||||||
|
file.delete(); // delete the OSZ when finished
|
||||||
}
|
}
|
||||||
file.delete(); // delete the OSZ when finished
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fileIndex = -1;
|
fileIndex = -1;
|
||||||
|
|
|
@ -217,6 +217,9 @@ public class Utils {
|
||||||
for (SongSort sort : SongSort.values())
|
for (SongSort sort : SongSort.values())
|
||||||
sort.init(width, height);
|
sort.init(width, height);
|
||||||
|
|
||||||
|
// initialize hit objects
|
||||||
|
OsuHitObject.init(width, height);
|
||||||
|
|
||||||
// back button
|
// back button
|
||||||
Image back = GameImage.MENU_BACK.getImage();
|
Image back = GameImage.MENU_BACK.getImage();
|
||||||
backButton = new MenuButton(back,
|
backButton = new MenuButton(back,
|
||||||
|
@ -316,11 +319,11 @@ public class Utils {
|
||||||
*/
|
*/
|
||||||
public static void loadCursor() throws SlickException {
|
public static void loadCursor() throws SlickException {
|
||||||
// destroy old cursors, if they exist
|
// destroy old cursors, if they exist
|
||||||
if (cursor != null)
|
if (cursor != null && !cursor.isDestroyed())
|
||||||
cursor.destroy();
|
cursor.destroy();
|
||||||
if (cursorTrail != null)
|
if (cursorTrail != null && !cursorTrail.isDestroyed())
|
||||||
cursorTrail.destroy();
|
cursorTrail.destroy();
|
||||||
if (cursorMiddle != null)
|
if (cursorMiddle != null && !cursorMiddle.isDestroyed())
|
||||||
cursorMiddle.destroy();
|
cursorMiddle.destroy();
|
||||||
cursor = cursorTrail = cursorMiddle = null;
|
cursor = cursorTrail = cursorMiddle = null;
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,7 @@ public class MusicController {
|
||||||
if (trackExists()) {
|
if (trackExists()) {
|
||||||
setVolume(Options.getMusicVolume() * Options.getMasterVolume());
|
setVolume(Options.getMusicVolume() * Options.getMasterVolume());
|
||||||
player.setPosition(position / 1000f);
|
player.setPosition(position / 1000f);
|
||||||
|
pauseTime = 0f;
|
||||||
if (loop)
|
if (loop)
|
||||||
player.loop();
|
player.loop();
|
||||||
else
|
else
|
||||||
|
@ -237,6 +238,8 @@ public class MusicController {
|
||||||
public static void stop() {
|
public static void stop() {
|
||||||
if (isPlaying())
|
if (isPlaying())
|
||||||
player.stop();
|
player.stop();
|
||||||
|
if (trackExists())
|
||||||
|
pauseTime = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -400,7 +403,7 @@ public class MusicController {
|
||||||
|
|
||||||
player = null;
|
player = null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ErrorHandler.error("Failed to destroy OpenAL.", e, false);
|
ErrorHandler.error("Failed to destroy OpenAL.", e, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -165,12 +165,6 @@ public class Game extends BasicGameState {
|
||||||
*/
|
*/
|
||||||
private float pausePulse;
|
private float pausePulse;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default playfield background (optional).
|
|
||||||
* Overridden by song background unless "ForceDefaultPlayfield" option enabled.
|
|
||||||
*/
|
|
||||||
private Image playfield;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether a checkpoint has been loaded during this game.
|
* Whether a checkpoint has been loaded during this game.
|
||||||
*/
|
*/
|
||||||
|
@ -214,13 +208,6 @@ public class Game extends BasicGameState {
|
||||||
// create the associated GameScore object
|
// create the associated GameScore object
|
||||||
score = new GameScore(width, height);
|
score = new GameScore(width, height);
|
||||||
((GameRanking) game.getState(Opsu.STATE_GAMERANKING)).setGameScore(score);
|
((GameRanking) game.getState(Opsu.STATE_GAMERANKING)).setGameScore(score);
|
||||||
|
|
||||||
// playfield background
|
|
||||||
try {
|
|
||||||
playfield = new Image("playfield.png").getScaledCopy(width, height);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// optional
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -232,10 +219,8 @@ public class Game extends BasicGameState {
|
||||||
// background
|
// background
|
||||||
g.setBackground(Color.black);
|
g.setBackground(Color.black);
|
||||||
float dimLevel = Options.getBackgroundDim();
|
float dimLevel = Options.getBackgroundDim();
|
||||||
if (Options.isDefaultPlayfieldForced() && playfield != null) {
|
if (Options.isDefaultPlayfieldForced() || !osu.drawBG(width, height, dimLevel)) {
|
||||||
playfield.setAlpha(dimLevel);
|
Image playfield = GameImage.PLAYFIELD.getImage();
|
||||||
playfield.draw();
|
|
||||||
} else if (!osu.drawBG(width, height, dimLevel) && playfield != null) {
|
|
||||||
playfield.setAlpha(dimLevel);
|
playfield.setAlpha(dimLevel);
|
||||||
playfield.draw();
|
playfield.draw();
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ public class Options extends BasicGameState {
|
||||||
*/
|
*/
|
||||||
private static enum GameOption {
|
private static enum GameOption {
|
||||||
NULL (null, null),
|
NULL (null, null),
|
||||||
SCREEN_RESOLUTION ("Screen Resolution", "Restart to apply resolution changes.") {
|
SCREEN_RESOLUTION ("Screen Resolution", "Restart (Ctrl+Shift+F5) to apply resolution changes.") {
|
||||||
@Override
|
@Override
|
||||||
public String getValueString() { return resolution.toString(); }
|
public String getValueString() { return resolution.toString(); }
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ public class Options extends BasicGameState {
|
||||||
@Override
|
@Override
|
||||||
public void click(GameContainer container) { loadVerbose = !loadVerbose; }
|
public void click(GameContainer container) { loadVerbose = !loadVerbose; }
|
||||||
},
|
},
|
||||||
CHECKPOINT ("Track Checkpoint", "Press CTRL+L while playing to load a checkpoint, and CTRL+S to set one.") {
|
CHECKPOINT ("Track Checkpoint", "Press Ctrl+L while playing to load a checkpoint, and Ctrl+S to set one.") {
|
||||||
@Override
|
@Override
|
||||||
public String getValueString() {
|
public String getValueString() {
|
||||||
return (checkpoint == 0) ? "Disabled" : String.format("%02d:%02d",
|
return (checkpoint == 0) ? "Disabled" : String.format("%02d:%02d",
|
||||||
|
@ -975,10 +975,19 @@ public class Options extends BasicGameState {
|
||||||
SoundController.playSound(SoundEffect.MENUBACK);
|
SoundController.playSound(SoundEffect.MENUBACK);
|
||||||
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_F5:
|
||||||
|
// restart application
|
||||||
|
if ((input.isKeyDown(Input.KEY_RCONTROL) || input.isKeyDown(Input.KEY_LCONTROL)) &&
|
||||||
|
(input.isKeyDown(Input.KEY_RSHIFT) || input.isKeyDown(Input.KEY_LSHIFT))) {
|
||||||
|
container.setForceExit(false);
|
||||||
|
container.exit();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Input.KEY_F12:
|
case Input.KEY_F12:
|
||||||
Utils.takeScreenShot();
|
Utils.takeScreenShot();
|
||||||
break;
|
break;
|
||||||
case Input.KEY_TAB:
|
case Input.KEY_TAB:
|
||||||
|
// change tabs
|
||||||
int i = 1;
|
int i = 1;
|
||||||
if (input.isKeyDown(Input.KEY_LSHIFT) || input.isKeyDown(Input.KEY_RSHIFT))
|
if (input.isKeyDown(Input.KEY_LSHIFT) || input.isKeyDown(Input.KEY_RSHIFT))
|
||||||
i = TAB_MAX - 1;
|
i = TAB_MAX - 1;
|
||||||
|
@ -1130,8 +1139,8 @@ public class Options extends BasicGameState {
|
||||||
app.setDisplayMode(resolution.getWidth(), resolution.getHeight(), false);
|
app.setDisplayMode(resolution.getWidth(), resolution.getHeight(), false);
|
||||||
|
|
||||||
// set borderless window if dimensions match screen size
|
// set borderless window if dimensions match screen size
|
||||||
if (screenWidth == resolution.getWidth() && screenHeight == resolution.getHeight())
|
boolean borderless = (screenWidth == resolution.getWidth() && screenHeight == resolution.getHeight());
|
||||||
System.setProperty("org.lwjgl.opengl.Window.undecorated", "true");
|
System.setProperty("org.lwjgl.opengl.Window.undecorated", Boolean.toString(borderless));
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
|
|
|
@ -209,7 +209,6 @@ public class SongMenu extends BasicGameState {
|
||||||
|
|
||||||
// song button background & graphics context
|
// song button background & graphics context
|
||||||
Image menuBackground = GameImage.MENU_BUTTON_BG.getImage();
|
Image menuBackground = GameImage.MENU_BUTTON_BG.getImage();
|
||||||
OsuGroupNode.setBackground(menuBackground);
|
|
||||||
|
|
||||||
// song button coordinates
|
// song button coordinates
|
||||||
buttonX = width * 0.6f;
|
buttonX = width * 0.6f;
|
||||||
|
@ -651,6 +650,13 @@ public class SongMenu extends BasicGameState {
|
||||||
if (MusicController.isThemePlaying() && focusNode != null)
|
if (MusicController.isThemePlaying() && focusNode != null)
|
||||||
MusicController.play(focusNode.osuFiles.get(focusNode.osuFileIndex), true);
|
MusicController.play(focusNode.osuFiles.get(focusNode.osuFileIndex), true);
|
||||||
|
|
||||||
|
// reset music track
|
||||||
|
else if (resetTrack) {
|
||||||
|
MusicController.pause();
|
||||||
|
MusicController.playAt(MusicController.getOsuFile().previewTime, true);
|
||||||
|
resetTrack = false;
|
||||||
|
}
|
||||||
|
|
||||||
// unpause track
|
// unpause track
|
||||||
else if (MusicController.isPaused())
|
else if (MusicController.isPaused())
|
||||||
MusicController.resume();
|
MusicController.resume();
|
||||||
|
@ -664,13 +670,6 @@ public class SongMenu extends BasicGameState {
|
||||||
GameImage.destroySkinImages(); // destroy skin images, if any
|
GameImage.destroySkinImages(); // destroy skin images, if any
|
||||||
resetGame = false;
|
resetGame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset music track
|
|
||||||
if (resetTrack) {
|
|
||||||
MusicController.pause();
|
|
||||||
MusicController.playAt(MusicController.getOsuFile().previewTime, true);
|
|
||||||
resetTrack = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -119,16 +119,19 @@ public class Splash extends BasicGameState {
|
||||||
thread = new Thread() {
|
thread = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
File beatmapDir = Options.getBeatmapDir();
|
// application restart: everything already loaded
|
||||||
|
if (OsuGroupList.get().size() < 1) {
|
||||||
|
File beatmapDir = Options.getBeatmapDir();
|
||||||
|
|
||||||
// unpack all OSZ archives
|
// unpack all OSZ archives
|
||||||
OszUnpacker.unpackAllFiles(Options.getOSZDir(), beatmapDir);
|
OszUnpacker.unpackAllFiles(Options.getOSZDir(), beatmapDir);
|
||||||
|
|
||||||
// parse song directory
|
// parse song directory
|
||||||
OsuParser.parseAllFiles(beatmapDir, width, height);
|
OsuParser.parseAllFiles(beatmapDir, width, height);
|
||||||
|
|
||||||
// load sounds
|
// load sounds
|
||||||
SoundController.init();
|
SoundController.init();
|
||||||
|
}
|
||||||
|
|
||||||
finished = true;
|
finished = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user