Added initial sound effect support.
- Added SoundController module, which uses Java Sound since OpenAL has a slight delay on playing sounds. - Uploaded all effect WAVs. (credits: WWWskin, AL's IA, Fantasy's Skin, Minimalist Miku) - Added a missing entry in credits. Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
@@ -23,4 +23,5 @@ Projects
|
||||
The following projects were referenced in creating opsu!:
|
||||
|
||||
* "Wojtkosu" - Wojtek Kowaluk (https://osu.ppy.sh/forum/t/97260)
|
||||
* "osu-parser" - nojhamster (https://github.com/nojhamster/osu-parser)
|
||||
* "osu! web" - pictuga (https://github.com/pictuga/osu-web)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -717,29 +717,41 @@ public class GameScore {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the combo streak to zero.
|
||||
*/
|
||||
private void resetComboStreak() {
|
||||
if (combo >= 20)
|
||||
SoundController.playSound(SoundController.SOUND_COMBOBREAK);
|
||||
combo = 0;
|
||||
if (Options.isModActive(Options.MOD_SUDDEN_DEATH))
|
||||
health = 0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a slider tick result.
|
||||
* @param time the tick start time
|
||||
* @param result the hit result (HIT_* constants)
|
||||
* @param x the x coordinate
|
||||
* @param y the y coordinate
|
||||
* @param hitSound the object's hit sound
|
||||
*/
|
||||
public void sliderTickResult(int time, int result, float x, float y) {
|
||||
public void sliderTickResult(int time, int result, float x, float y, byte hitSound) {
|
||||
int hitValue = 0;
|
||||
switch (result) {
|
||||
case HIT_SLIDER30:
|
||||
hitValue = 30;
|
||||
incrementComboStreak();
|
||||
changeHealth(1f);
|
||||
SoundController.playHitSound(hitSound);
|
||||
break;
|
||||
case HIT_SLIDER10:
|
||||
hitValue = 10;
|
||||
incrementComboStreak();
|
||||
SoundController.playHitSound(SoundController.HIT_SLIDERTICK);
|
||||
break;
|
||||
case HIT_MISS:
|
||||
combo = 0;
|
||||
if (Options.isModActive(Options.MOD_SUDDEN_DEATH))
|
||||
health = 0f;
|
||||
resetComboStreak();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -760,8 +772,10 @@ public class GameScore {
|
||||
* @param y the y coordinate
|
||||
* @param color the combo color
|
||||
* @param end true if this is the last hit object in the combo
|
||||
* @param hitSound the object's hit sound
|
||||
*/
|
||||
public void hitResult(int time, int result, float x, float y, Color color, boolean end) {
|
||||
public void hitResult(int time, int result, float x, float y, Color color,
|
||||
boolean end, byte hitSound) {
|
||||
int hitValue = 0;
|
||||
switch (result) {
|
||||
case HIT_300:
|
||||
@@ -784,15 +798,15 @@ public class GameScore {
|
||||
hitValue = 0;
|
||||
changeHealth(-10f);
|
||||
comboEnd |= 2;
|
||||
combo = 0;
|
||||
if (Options.isModActive(Options.MOD_SUDDEN_DEATH))
|
||||
health = 0f;
|
||||
resetComboStreak();
|
||||
objectCount++;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (hitValue > 0) {
|
||||
SoundController.playHitSound(hitSound);
|
||||
|
||||
// game mod score multipliers
|
||||
float modMultiplier = 1f;
|
||||
if (Options.isModActive(Options.MOD_NO_FAIL))
|
||||
|
||||
@@ -143,6 +143,9 @@ public class Opsu extends StateBasedGame {
|
||||
}
|
||||
Options.TMP_DIR.deleteOnExit();
|
||||
|
||||
// load sounds
|
||||
SoundController.init();
|
||||
|
||||
app.start();
|
||||
} catch (SlickException e) {
|
||||
Log.error("Error while creating game container.", e);
|
||||
|
||||
@@ -40,7 +40,7 @@ public class OsuFile implements Comparable<OsuFile> {
|
||||
// public String audioHash = ""; // audio hash (deprecated)
|
||||
public int previewTime = -1; // start position of music preview (in ms)
|
||||
public byte countdown = 0; // countdown type (0:disabled, 1:normal, 2:half, 3:double)
|
||||
public String sampleSet = ""; // ? ("Normal", "Soft")
|
||||
public String sampleSet = ""; // sound samples ("None", "Normal", "Soft")
|
||||
public float stackLeniency = 0.7f; // how often closely placed hit objects will be stacked together
|
||||
public byte mode = 0; // game mode (0:osu!, 1:taiko, 2:catch the beat, 3:osu!mania)
|
||||
public boolean letterboxInBreaks = false; // whether the letterbox (top/bottom black bars) appears during breaks
|
||||
|
||||
@@ -38,7 +38,6 @@ public class OsuHitObject {
|
||||
SOUND_NORMAL = 0,
|
||||
SOUND_WHISTLE = 2,
|
||||
SOUND_FINISH = 4,
|
||||
SOUND_WHISTLEFINISH = 6,
|
||||
SOUND_CLAP = 8;
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,8 +26,8 @@ public class OsuTimingPoint {
|
||||
public float beatLength; // (non-inherited) ms per beat
|
||||
public int velocity = 0; // (inherited) slider multiplier = -100 / value
|
||||
public int meter; // beats per measure
|
||||
public byte sampleType; // sound samples (0:none, 1:normal, 2:soft)
|
||||
public byte sampleTypeCustom; // custom samples (0:default, 1:custom1, 2:custom2
|
||||
public byte sampleType; // sound samples (0:none, 1:normal, 2:soft, 3:drum)
|
||||
public byte sampleTypeCustom; // custom samples (0:default, 1:custom1, 2:custom2)
|
||||
public int sampleVolume; // volume of samples (0~100)
|
||||
public boolean inherited; // is this timing point inherited?
|
||||
public boolean kiai; // is Kiai Mode active?
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.Clip;
|
||||
import javax.sound.sampled.FloatControl;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
|
||||
import org.newdawn.slick.util.Log;
|
||||
import org.newdawn.slick.util.ResourceLoader;
|
||||
|
||||
/**
|
||||
* Controller for all sound effects.
|
||||
* Note: Uses Java Sound because OpenAL lags too much for accurate hit sounds.
|
||||
*/
|
||||
public class SoundController {
|
||||
/**
|
||||
* Sound effect constants.
|
||||
*/
|
||||
public static final int
|
||||
SOUND_APPLAUSE = 0,
|
||||
SOUND_COMBOBREAK = 1,
|
||||
// SOUND_COUNT = , // ?
|
||||
SOUND_COUNT1 = 2,
|
||||
SOUND_COUNT2 = 3,
|
||||
SOUND_COUNT3 = 4,
|
||||
SOUND_FAIL = 5,
|
||||
SOUND_GO = 6,
|
||||
SOUND_MENUBACK = 7,
|
||||
SOUND_MENUCLICK = 8,
|
||||
SOUND_MENUHIT = 9,
|
||||
SOUND_READY = 10,
|
||||
SOUND_SECTIONFAIL = 11,
|
||||
SOUND_SECTIONPASS = 12,
|
||||
SOUND_SHUTTER = 13,
|
||||
SOUND_SPINNERBONUS = 14,
|
||||
SOUND_SPINNEROSU = 15,
|
||||
SOUND_SPINNERSPIN = 16,
|
||||
SOUND_MAX = 17; // not a sound
|
||||
|
||||
/**
|
||||
* Sound effect names (indexed by SOUND_* constants).
|
||||
*/
|
||||
private static final String[] soundNames = {
|
||||
"applause",
|
||||
"combobreak",
|
||||
// "count", // ?
|
||||
"count1s",
|
||||
"count2s",
|
||||
"count3s",
|
||||
"failsound",
|
||||
"gos",
|
||||
"menuback",
|
||||
"menuclick",
|
||||
"menuhit",
|
||||
"readys",
|
||||
"sectionfail",
|
||||
"sectionpass",
|
||||
"shutter",
|
||||
"spinnerbonus",
|
||||
"spinner-osu",
|
||||
"spinnerspin",
|
||||
};
|
||||
|
||||
/**
|
||||
* Sound effects (indexed by SOUND_* constants).
|
||||
*/
|
||||
private static Clip[] sounds = new Clip[SOUND_MAX];
|
||||
|
||||
/**
|
||||
* Sound sample sets.
|
||||
*/
|
||||
private static final String[] sampleSets = {
|
||||
"normal",
|
||||
"soft",
|
||||
"drum",
|
||||
// "taiko"
|
||||
};
|
||||
|
||||
/**
|
||||
* Current sample set (index in sampleSet[] array).
|
||||
*/
|
||||
private static int sampleSetIndex = -1;
|
||||
|
||||
/**
|
||||
* Hit sound effects.
|
||||
*/
|
||||
public static final int
|
||||
HIT_CLAP = 0,
|
||||
HIT_FINISH = 1,
|
||||
HIT_NORMAL = 2,
|
||||
HIT_WHISTLE = 3,
|
||||
HIT_SLIDERSLIDE = 4,
|
||||
HIT_SLIDERTICK = 5,
|
||||
HIT_SLIDERWHISTLE = 6,
|
||||
HIT_MAX = 7; // not a sound
|
||||
|
||||
/**
|
||||
* Hit sound effect names (indexed by HIT_* constants).
|
||||
*/
|
||||
private static final String[] hitSoundNames = {
|
||||
"hitclap",
|
||||
"hitfinish",
|
||||
"hitnormal",
|
||||
"hitwhistle",
|
||||
"sliderslide",
|
||||
"slidertick",
|
||||
"sliderwhistle"
|
||||
};
|
||||
|
||||
/**
|
||||
* Hit sound effects (indexed by sampleSets[], HIT_* constants).
|
||||
*/
|
||||
private static Clip[][] hitSounds = new Clip[sampleSets.length][HIT_MAX];
|
||||
|
||||
/**
|
||||
* Sample volume multiplier, from timing points [0, 1].
|
||||
*/
|
||||
private static float sampleVolumeMultiplier = 1f;
|
||||
|
||||
// This class should not be instantiated.
|
||||
private SoundController() {}
|
||||
|
||||
/**
|
||||
* Loads and returns a Clip from a resource.
|
||||
* @param ref the resource name
|
||||
* @return the loaded and opened clip
|
||||
*/
|
||||
private static Clip loadClip(String ref) {
|
||||
try {
|
||||
URL url = ResourceLoader.getResource(ref);
|
||||
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
|
||||
Clip clip = AudioSystem.getClip();
|
||||
clip.open(audioIn);
|
||||
return clip;
|
||||
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
|
||||
Log.error(String.format("Failed to load file '%s'.", ref), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all sound files.
|
||||
*/
|
||||
public static void init() {
|
||||
// TODO: support MP3 sounds?
|
||||
|
||||
// menu and game sounds
|
||||
for (int i = 0; i < SOUND_MAX; i++)
|
||||
sounds[i] = loadClip(String.format("%s.wav", soundNames[i]));
|
||||
|
||||
// hit sounds
|
||||
for (int i = 0; i < sampleSets.length; i++) {
|
||||
for (int j = 0; j < HIT_MAX; j++)
|
||||
hitSounds[i][j] = loadClip(String.format("%s-%s.wav", sampleSets[i], hitSoundNames[j]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample set to use when playing hit sounds.
|
||||
* @param sampleSet the sample set ("None", "Normal", "Soft", "Drum")
|
||||
*/
|
||||
public static void setSampleSet(String sampleSet) {
|
||||
sampleSetIndex = -1;
|
||||
for (int i = 0; i < sampleSets.length; i++) {
|
||||
if (sampleSet.equalsIgnoreCase(sampleSets[i])) {
|
||||
sampleSetIndex = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample set to use when playing hit sounds.
|
||||
* @param sampleType the sample set (0:none, 1:normal, 2:soft, 3:drum)
|
||||
*/
|
||||
public static void setSampleSet(byte sampleType) {
|
||||
if (sampleType >= 0 && sampleType <= 3)
|
||||
sampleSetIndex = sampleType - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample volume (modifies the global sample volume).
|
||||
* @param volume the sample volume [0, 100]
|
||||
*/
|
||||
public static void setSampleVolume(int volume) {
|
||||
if (volume >= 0 && volume <= 100)
|
||||
sampleVolumeMultiplier = volume / 100f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays a sound clip.
|
||||
* @param clip the Clip to play
|
||||
* @param volume the volume [0, 1]
|
||||
*/
|
||||
private static void playClip(Clip clip, float volume) {
|
||||
if (volume > 0f) {
|
||||
// stop clip if running
|
||||
if (clip.isRunning()) {
|
||||
clip.stop();
|
||||
clip.flush();
|
||||
}
|
||||
|
||||
// set volume
|
||||
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
|
||||
float dB = (float) (Math.log(volume) / Math.log(10.0) * 20.0);
|
||||
gainControl.setValue(dB * sampleVolumeMultiplier);
|
||||
|
||||
// play clip
|
||||
clip.setFramePosition(0);
|
||||
clip.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays a sound.
|
||||
* @param sound the sound (SOUND_* constant)
|
||||
*/
|
||||
public static void playSound(int sound) {
|
||||
if (sound < 0 || sound >= SOUND_MAX)
|
||||
return;
|
||||
|
||||
playClip(sounds[sound], Options.getEffectVolume());
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays hit sound(s) using an OsuHitObject bitmask.
|
||||
* @param hitSound the sound (bitmask)
|
||||
*/
|
||||
public static void playHitSound(byte hitSound) {
|
||||
if (sampleSetIndex < 0 || hitSound < 0)
|
||||
return;
|
||||
|
||||
float volume = Options.getEffectVolume();
|
||||
if (volume == 0f)
|
||||
return;
|
||||
|
||||
// play all sounds
|
||||
if (hitSound == OsuHitObject.SOUND_NORMAL)
|
||||
playClip(hitSounds[sampleSetIndex][HIT_NORMAL], volume);
|
||||
else {
|
||||
if ((hitSound & OsuHitObject.SOUND_WHISTLE) > 0)
|
||||
playClip(hitSounds[sampleSetIndex][HIT_WHISTLE], volume);
|
||||
if ((hitSound & OsuHitObject.SOUND_FINISH) > 0)
|
||||
playClip(hitSounds[sampleSetIndex][HIT_FINISH], volume);
|
||||
if ((hitSound & OsuHitObject.SOUND_CLAP) > 0)
|
||||
playClip(hitSounds[sampleSetIndex][HIT_CLAP], volume);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays a hit sound.
|
||||
* @param sound (HIT_* constant)
|
||||
*/
|
||||
public static void playHitSound(int sound) {
|
||||
if (sampleSetIndex < 0 || sound < 0 || sound > HIT_MAX)
|
||||
return;
|
||||
|
||||
playClip(hitSounds[sampleSetIndex][sound], Options.getEffectVolume());
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,9 @@ public class Circle {
|
||||
if (distance < circleRadius) {
|
||||
int result = hitResult(hitObject.time);
|
||||
if (result > -1) {
|
||||
score.hitResult(hitObject.time, result, hitObject.x, hitObject.y, color, comboEnd);
|
||||
score.hitResult(hitObject.time, result, hitObject.x, hitObject.y,
|
||||
color, comboEnd, hitObject.hitSound
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -192,11 +194,11 @@ public class Circle {
|
||||
if (overlap || trackPosition > hitObject.time + hitResultOffset[GameScore.HIT_50]) {
|
||||
if (isAutoMod) // "auto" mod: catch any missed notes due to lag
|
||||
score.hitResult(hitObject.time, GameScore.HIT_300,
|
||||
hitObject.x, hitObject.y, color, comboEnd);
|
||||
hitObject.x, hitObject.y, color, comboEnd, hitObject.hitSound);
|
||||
|
||||
else // no more points can be scored, so send a miss
|
||||
score.hitResult(hitObject.time, GameScore.HIT_MISS,
|
||||
hitObject.x, hitObject.y, null, comboEnd);
|
||||
hitObject.x, hitObject.y, null, comboEnd, hitObject.hitSound);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -204,7 +206,7 @@ public class Circle {
|
||||
else if (isAutoMod) {
|
||||
if (Math.abs(trackPosition - hitObject.time) < hitResultOffset[GameScore.HIT_300]) {
|
||||
score.hitResult(hitObject.time, GameScore.HIT_300,
|
||||
hitObject.x, hitObject.y, color, comboEnd);
|
||||
hitObject.x, hitObject.y, color, comboEnd, hitObject.hitSound);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,10 +384,11 @@ public class Slider {
|
||||
|
||||
if (currentRepeats % 2 == 0) // last circle
|
||||
score.hitResult(hitObject.time + (int) sliderTimeTotal, result,
|
||||
hitObject.sliderX[lastIndex], hitObject.sliderY[lastIndex], color, comboEnd);
|
||||
hitObject.sliderX[lastIndex], hitObject.sliderY[lastIndex],
|
||||
color, comboEnd, hitObject.hitSound);
|
||||
else // first circle
|
||||
score.hitResult(hitObject.time + (int) sliderTimeTotal, result,
|
||||
hitObject.x, hitObject.y, color, comboEnd);
|
||||
hitObject.x, hitObject.y, color, comboEnd, hitObject.hitSound);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -420,7 +421,8 @@ public class Slider {
|
||||
|
||||
if (result > -1) {
|
||||
sliderClicked = true;
|
||||
score.sliderTickResult(hitObject.time, result, hitObject.x, hitObject.y);
|
||||
score.sliderTickResult(hitObject.time, result,
|
||||
hitObject.x, hitObject.y, hitObject.hitSound);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -465,9 +467,11 @@ public class Slider {
|
||||
sliderClicked = true;
|
||||
if (isAutoMod) { // "auto" mod: catch any missed notes due to lag
|
||||
ticksHit++;
|
||||
score.sliderTickResult(hitObject.time, GameScore.HIT_SLIDER30, hitObject.x, hitObject.y);
|
||||
score.sliderTickResult(hitObject.time, GameScore.HIT_SLIDER30,
|
||||
hitObject.x, hitObject.y, hitObject.hitSound);
|
||||
} else
|
||||
score.sliderTickResult(hitObject.time, GameScore.HIT_MISS, hitObject.x, hitObject.y);
|
||||
score.sliderTickResult(hitObject.time, GameScore.HIT_MISS,
|
||||
hitObject.x, hitObject.y, hitObject.hitSound);
|
||||
}
|
||||
|
||||
// "auto" mod: send a perfect hit result
|
||||
@@ -475,7 +479,8 @@ public class Slider {
|
||||
if (Math.abs(trackPosition - hitObject.time) < hitResultOffset[GameScore.HIT_300]) {
|
||||
ticksHit++;
|
||||
sliderClicked = true;
|
||||
score.sliderTickResult(hitObject.time, GameScore.HIT_SLIDER30, hitObject.x, hitObject.y);
|
||||
score.sliderTickResult(hitObject.time, GameScore.HIT_SLIDER30,
|
||||
hitObject.x, hitObject.y, hitObject.hitSound);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -540,24 +545,26 @@ public class Slider {
|
||||
ticksHit++;
|
||||
if (currentRepeats % 2 > 0) // last circle
|
||||
score.sliderTickResult(trackPosition, GameScore.HIT_SLIDER30,
|
||||
hitObject.sliderX[lastIndex], hitObject.sliderY[lastIndex]);
|
||||
hitObject.sliderX[lastIndex], hitObject.sliderY[lastIndex],
|
||||
hitObject.hitSound);
|
||||
else // first circle
|
||||
score.sliderTickResult(trackPosition, GameScore.HIT_SLIDER30,
|
||||
c[0], c[1]);
|
||||
c[0], c[1], hitObject.hitSound);
|
||||
}
|
||||
|
||||
// held during new tick
|
||||
if (isNewTick) {
|
||||
ticksHit++;
|
||||
score.sliderTickResult(trackPosition, GameScore.HIT_SLIDER10, c[0], c[1]);
|
||||
score.sliderTickResult(trackPosition, GameScore.HIT_SLIDER10,
|
||||
c[0], c[1], (byte) -1);
|
||||
}
|
||||
} else {
|
||||
followCircleActive = false;
|
||||
|
||||
if (isNewRepeat)
|
||||
score.sliderTickResult(trackPosition, GameScore.HIT_MISS, 0, 0);
|
||||
score.sliderTickResult(trackPosition, GameScore.HIT_MISS, 0, 0, hitObject.hitSound);
|
||||
if (isNewTick)
|
||||
score.sliderTickResult(trackPosition, GameScore.HIT_MISS, 0, 0);
|
||||
score.sliderTickResult(trackPosition, GameScore.HIT_MISS, 0, 0, (byte) -1);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -21,6 +21,7 @@ package itdelatrisu.opsu.objects;
|
||||
import itdelatrisu.opsu.GameScore;
|
||||
import itdelatrisu.opsu.MusicController;
|
||||
import itdelatrisu.opsu.OsuHitObject;
|
||||
import itdelatrisu.opsu.SoundController;
|
||||
import itdelatrisu.opsu.states.Game;
|
||||
import itdelatrisu.opsu.states.Options;
|
||||
|
||||
@@ -163,16 +164,19 @@ public class Spinner {
|
||||
int result;
|
||||
float ratio = rotations / rotationsNeeded;
|
||||
if (ratio >= 1.0f ||
|
||||
Options.isModActive(Options.MOD_AUTO) || Options.isModActive(Options.MOD_SPUN_OUT))
|
||||
Options.isModActive(Options.MOD_AUTO) ||
|
||||
Options.isModActive(Options.MOD_SPUN_OUT)) {
|
||||
result = GameScore.HIT_300;
|
||||
else if (ratio >= 0.8f)
|
||||
SoundController.playSound(SoundController.SOUND_SPINNEROSU);
|
||||
} else if (ratio >= 0.8f)
|
||||
result = GameScore.HIT_100;
|
||||
else if (ratio >= 0.5f)
|
||||
result = GameScore.HIT_50;
|
||||
else
|
||||
result = GameScore.HIT_MISS;
|
||||
|
||||
score.hitResult(hitObject.endTime, result, width / 2, height / 2, Color.transparent, true);
|
||||
score.hitResult(hitObject.endTime, result, width / 2, height / 2,
|
||||
Color.transparent, true, (byte) -1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -240,10 +244,13 @@ public class Spinner {
|
||||
|
||||
// added one whole rotation...
|
||||
if (Math.floor(newRotations) > rotations) {
|
||||
if (newRotations > rotationsNeeded) // extra rotations
|
||||
if (newRotations > rotationsNeeded) { // extra rotations
|
||||
score.changeScore(1000);
|
||||
else
|
||||
SoundController.playSound(SoundController.SOUND_SPINNERBONUS);
|
||||
} else {
|
||||
score.changeScore(100);
|
||||
SoundController.playSound(SoundController.SOUND_SPINNERSPIN);
|
||||
}
|
||||
}
|
||||
|
||||
rotations = newRotations;
|
||||
|
||||
@@ -25,6 +25,7 @@ import itdelatrisu.opsu.Opsu;
|
||||
import itdelatrisu.opsu.OsuFile;
|
||||
import itdelatrisu.opsu.OsuHitObject;
|
||||
import itdelatrisu.opsu.OsuTimingPoint;
|
||||
import itdelatrisu.opsu.SoundController;
|
||||
import itdelatrisu.opsu.objects.Circle;
|
||||
import itdelatrisu.opsu.objects.Slider;
|
||||
import itdelatrisu.opsu.objects.Spinner;
|
||||
@@ -134,6 +135,11 @@ public class Game extends BasicGameState {
|
||||
*/
|
||||
private int breakTime = 0;
|
||||
|
||||
/**
|
||||
* Whether the break sound has been played.
|
||||
*/
|
||||
private boolean breakSound;
|
||||
|
||||
/**
|
||||
* Skip button (displayed at song start, when necessary).
|
||||
*/
|
||||
@@ -164,6 +170,13 @@ public class Game extends BasicGameState {
|
||||
countdown2, // "1" text
|
||||
countdownGo; // "GO!" text
|
||||
|
||||
/**
|
||||
* Whether the countdown sound has been played.
|
||||
*/
|
||||
private boolean
|
||||
countdownReadySound, countdown3Sound, countdown1Sound,
|
||||
countdown2Sound, countdownGoSound;
|
||||
|
||||
/**
|
||||
* Glowing hit circle outline which must be clicked when returning from pause menu.
|
||||
*/
|
||||
@@ -276,10 +289,19 @@ public class Game extends BasicGameState {
|
||||
trackPosition - breakTime > 2000 &&
|
||||
trackPosition - breakTime < 5000) {
|
||||
// show break start
|
||||
if (score.getHealth() >= 50)
|
||||
if (score.getHealth() >= 50) {
|
||||
breakStartPass.drawCentered(width / 2f, height / 2f);
|
||||
else
|
||||
if (!breakSound) {
|
||||
SoundController.playSound(SoundController.SOUND_SECTIONPASS);
|
||||
breakSound = true;
|
||||
}
|
||||
} else {
|
||||
breakStartFail.drawCentered(width / 2f, height / 2f);
|
||||
if (!breakSound) {
|
||||
SoundController.playSound(SoundController.SOUND_SECTIONFAIL);
|
||||
breakSound = true;
|
||||
}
|
||||
}
|
||||
} else if (breakLength >= 4000) {
|
||||
// show break end (flash twice for 500ms)
|
||||
int endTimeDiff = endTime - trackPosition;
|
||||
@@ -326,18 +348,41 @@ public class Game extends BasicGameState {
|
||||
if (osu.countdown > 0) { // TODO: implement half/double rate settings
|
||||
int timeDiff = osu.objects[0].time - trackPosition;
|
||||
if (timeDiff >= 500 && timeDiff < 3000) {
|
||||
if (timeDiff >= 1500)
|
||||
if (timeDiff >= 1500) {
|
||||
countdownReady.drawCentered(width / 2, height / 2);
|
||||
|
||||
if (timeDiff < 2000)
|
||||
if (!countdownReadySound) {
|
||||
SoundController.playSound(SoundController.SOUND_READY);
|
||||
countdownReadySound = true;
|
||||
}
|
||||
}
|
||||
if (timeDiff < 2000) {
|
||||
countdown3.draw(0, 0);
|
||||
if (timeDiff < 1500)
|
||||
if (!countdown3Sound) {
|
||||
SoundController.playSound(SoundController.SOUND_COUNT3);
|
||||
countdown3Sound = true;
|
||||
}
|
||||
}
|
||||
if (timeDiff < 1500) {
|
||||
countdown2.draw(width - countdown2.getWidth(), 0);
|
||||
if (timeDiff < 1000)
|
||||
if (!countdown2Sound) {
|
||||
SoundController.playSound(SoundController.SOUND_COUNT2);
|
||||
countdown2Sound = true;
|
||||
}
|
||||
}
|
||||
if (timeDiff < 1000) {
|
||||
countdown1.drawCentered(width / 2, height / 2);
|
||||
if (!countdown1Sound) {
|
||||
SoundController.playSound(SoundController.SOUND_COUNT1);
|
||||
countdown1Sound = true;
|
||||
}
|
||||
}
|
||||
} else if (timeDiff >= -500 && timeDiff < 500) {
|
||||
countdownGo.setAlpha((timeDiff < 0) ? 1 - (timeDiff / -1000f) : 1);
|
||||
countdownGo.drawCentered(width / 2, height / 2);
|
||||
if (!countdownGoSound) {
|
||||
SoundController.playSound(SoundController.SOUND_GO);
|
||||
countdownGoSound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,6 +477,8 @@ public class Game extends BasicGameState {
|
||||
beatLengthBase = beatLength = timingPoint.beatLength;
|
||||
else
|
||||
beatLength = beatLengthBase * (timingPoint.velocity / -100f);
|
||||
SoundController.setSampleSet(timingPoint.sampleType);
|
||||
SoundController.setSampleVolume(timingPoint.sampleVolume);
|
||||
timingPointIndex++;
|
||||
}
|
||||
}
|
||||
@@ -456,6 +503,7 @@ public class Game extends BasicGameState {
|
||||
} else if (trackPosition >= breakValue) {
|
||||
// start a break
|
||||
breakTime = breakValue;
|
||||
breakSound = false;
|
||||
breakIndex++;
|
||||
return;
|
||||
}
|
||||
@@ -638,22 +686,33 @@ public class Game extends BasicGameState {
|
||||
}
|
||||
}
|
||||
|
||||
// reset indexes
|
||||
// reset data
|
||||
MusicController.setPosition(0);
|
||||
MusicController.pause();
|
||||
score.clear();
|
||||
objectIndex = 0;
|
||||
breakIndex = 0;
|
||||
breakTime = 0;
|
||||
breakSound = false;
|
||||
timingPointIndex = 0;
|
||||
pauseTime = -1;
|
||||
pausedMouseX = -1;
|
||||
pausedMouseY = -1;
|
||||
countdownReadySound = false;
|
||||
countdown3Sound = false;
|
||||
countdown1Sound = false;
|
||||
countdown2Sound = false;
|
||||
countdownGoSound = false;
|
||||
|
||||
// load the first timingPoint
|
||||
if (!osu.timingPoints.isEmpty() && osu.timingPoints.get(0).velocity >= 0) {
|
||||
beatLengthBase = beatLength = osu.timingPoints.get(0).beatLength;
|
||||
timingPointIndex++;
|
||||
if (!osu.timingPoints.isEmpty()) {
|
||||
OsuTimingPoint timingPoint = osu.timingPoints.get(0);
|
||||
if (timingPoint.velocity >= 0) {
|
||||
beatLengthBase = beatLength = timingPoint.beatLength;
|
||||
SoundController.setSampleSet(timingPoint.sampleType);
|
||||
SoundController.setSampleVolume(timingPoint.sampleVolume);
|
||||
timingPointIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
leadInTime = osu.audioLeadIn + approachTime;
|
||||
@@ -675,6 +734,7 @@ public class Game extends BasicGameState {
|
||||
MusicController.resume();
|
||||
}
|
||||
MusicController.setPosition(osu.objects[0].time - skipOffsetTime);
|
||||
SoundController.playSound(SoundController.SOUND_MENUHIT);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -21,6 +21,7 @@ package itdelatrisu.opsu.states;
|
||||
import itdelatrisu.opsu.GUIMenuButton;
|
||||
import itdelatrisu.opsu.MusicController;
|
||||
import itdelatrisu.opsu.Opsu;
|
||||
import itdelatrisu.opsu.SoundController;
|
||||
|
||||
import org.newdawn.slick.Color;
|
||||
import org.newdawn.slick.GameContainer;
|
||||
@@ -142,6 +143,7 @@ public class GamePauseMenu extends BasicGameState {
|
||||
if (Game.getRestart() == Game.RESTART_LOSE) {
|
||||
MusicController.stop();
|
||||
MusicController.playAt(Game.getOsuFile().previewTime, true);
|
||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||
game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
} else
|
||||
unPause(Game.RESTART_FALSE);
|
||||
@@ -171,6 +173,7 @@ public class GamePauseMenu extends BasicGameState {
|
||||
} else if (backButton.contains(x, y)) {
|
||||
MusicController.pause(); // lose state
|
||||
MusicController.playAt(Game.getOsuFile().previewTime, true);
|
||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||
game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
}
|
||||
}
|
||||
@@ -179,9 +182,10 @@ public class GamePauseMenu extends BasicGameState {
|
||||
public void enter(GameContainer container, StateBasedGame game)
|
||||
throws SlickException {
|
||||
pauseStartTime = System.currentTimeMillis();
|
||||
if (Game.getRestart() == Game.RESTART_LOSE)
|
||||
if (Game.getRestart() == Game.RESTART_LOSE) {
|
||||
MusicController.fadeOut(FADEOUT_TIME);
|
||||
else
|
||||
SoundController.playSound(SoundController.SOUND_FAIL);
|
||||
} else
|
||||
MusicController.pause();
|
||||
}
|
||||
|
||||
@@ -189,6 +193,10 @@ public class GamePauseMenu extends BasicGameState {
|
||||
* Unpause and return to the Game state.
|
||||
*/
|
||||
private void unPause(byte restart) {
|
||||
if (restart == Game.RESTART_MANUAL)
|
||||
SoundController.playSound(SoundController.SOUND_MENUHIT);
|
||||
else
|
||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||
Game.setRestart(restart);
|
||||
game.enterState(Opsu.STATE_GAME);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import itdelatrisu.opsu.GameScore;
|
||||
import itdelatrisu.opsu.MusicController;
|
||||
import itdelatrisu.opsu.Opsu;
|
||||
import itdelatrisu.opsu.OsuFile;
|
||||
import itdelatrisu.opsu.SoundController;
|
||||
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.newdawn.slick.Color;
|
||||
@@ -143,7 +144,9 @@ public class GameRanking extends BasicGameState {
|
||||
public void keyPressed(int key, char c) {
|
||||
switch (key) {
|
||||
case Input.KEY_ESCAPE:
|
||||
MusicController.pause();
|
||||
MusicController.playAt(Game.getOsuFile().previewTime, true);
|
||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||
game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
break;
|
||||
case Input.KEY_F12:
|
||||
@@ -162,12 +165,15 @@ public class GameRanking extends BasicGameState {
|
||||
OsuFile osu = Game.getOsuFile();
|
||||
Display.setTitle(String.format("%s - %s", game.getTitle(), osu.toString()));
|
||||
Game.setRestart(Game.RESTART_MANUAL);
|
||||
SoundController.playSound(SoundController.SOUND_MENUHIT);
|
||||
game.enterState(Opsu.STATE_GAME, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
} else if (exitButton.contains(x, y))
|
||||
} else if (exitButton.contains(x, y)) {
|
||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||
game.enterState(Opsu.STATE_MAINMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
else if (Options.getBackButton().contains(x, y)) {
|
||||
MusicController.stop();
|
||||
} else if (Options.getBackButton().contains(x, y)) {
|
||||
MusicController.pause();
|
||||
MusicController.playAt(Game.getOsuFile().previewTime, true);
|
||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||
game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
}
|
||||
}
|
||||
@@ -176,5 +182,6 @@ public class GameRanking extends BasicGameState {
|
||||
public void enter(GameContainer container, StateBasedGame game)
|
||||
throws SlickException {
|
||||
Display.setTitle(game.getTitle());
|
||||
SoundController.playSound(SoundController.SOUND_APPLAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import itdelatrisu.opsu.GUIMenuButton;
|
||||
import itdelatrisu.opsu.MusicController;
|
||||
import itdelatrisu.opsu.Opsu;
|
||||
import itdelatrisu.opsu.OsuGroupNode;
|
||||
import itdelatrisu.opsu.SoundController;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
@@ -287,17 +288,22 @@ public class MainMenu extends BasicGameState {
|
||||
logoTimer = 0;
|
||||
playButton.getImage().setAlpha(0f);
|
||||
exitButton.getImage().setAlpha(0f);
|
||||
SoundController.playSound(SoundController.SOUND_MENUHIT);
|
||||
}
|
||||
}
|
||||
|
||||
// other button actions (if visible)
|
||||
else if (logoClicked) {
|
||||
if (logo.contains(x, y))
|
||||
if (logo.contains(x, y)) {
|
||||
SoundController.playSound(SoundController.SOUND_MENUHIT);
|
||||
logoTimer = MOVE_DELAY;
|
||||
else if (playButton.contains(x, y))
|
||||
} else if (playButton.contains(x, y)) {
|
||||
SoundController.playSound(SoundController.SOUND_MENUHIT);
|
||||
game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
else if (exitButton.contains(x, y))
|
||||
} else if (exitButton.contains(x, y)) {
|
||||
SoundController.playSound(SoundController.SOUND_MENUHIT);
|
||||
game.enterState(Opsu.STATE_MAINMENUEXIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ package itdelatrisu.opsu.states;
|
||||
|
||||
import itdelatrisu.opsu.GUIMenuButton;
|
||||
import itdelatrisu.opsu.Opsu;
|
||||
import itdelatrisu.opsu.SoundController;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.io.BufferedReader;
|
||||
@@ -148,12 +149,13 @@ public class Options extends BasicGameState {
|
||||
// OPTIONS_FULLSCREEN = ,
|
||||
OPTIONS_TARGET_FPS = 1,
|
||||
OPTIONS_MUSIC_VOLUME = 2,
|
||||
OPTIONS_MUSIC_OFFSET = 3,
|
||||
OPTIONS_SCREENSHOT_FORMAT = 4,
|
||||
OPTIONS_DISPLAY_FPS = 5,
|
||||
OPTIONS_HIT_LIGHTING = 6,
|
||||
OPTIONS_COMBO_BURSTS = 7,
|
||||
OPTIONS_MAX = 8; // not an option
|
||||
OPTIONS_EFFECT_VOLUME = 3,
|
||||
OPTIONS_MUSIC_OFFSET = 4,
|
||||
OPTIONS_SCREENSHOT_FORMAT = 5,
|
||||
OPTIONS_DISPLAY_FPS = 6,
|
||||
OPTIONS_HIT_LIGHTING = 7,
|
||||
OPTIONS_COMBO_BURSTS = 8,
|
||||
OPTIONS_MAX = 9; // not an option
|
||||
|
||||
/**
|
||||
* Screen resolutions.
|
||||
@@ -208,7 +210,12 @@ public class Options extends BasicGameState {
|
||||
/**
|
||||
* Default music volume.
|
||||
*/
|
||||
private static int musicVolume = 20;
|
||||
private static int musicVolume = 30;
|
||||
|
||||
/**
|
||||
* Default sound effect volume.
|
||||
*/
|
||||
private static int effectVolume = 20;
|
||||
|
||||
/**
|
||||
* Offset time, in milliseconds, for music position-related elements.
|
||||
@@ -258,8 +265,8 @@ public class Options extends BasicGameState {
|
||||
Options.game = game;
|
||||
this.input = container.getInput();
|
||||
|
||||
// game settings;
|
||||
container.setTargetFrameRate(60);
|
||||
// game settings
|
||||
container.setTargetFrameRate(targetFPS[targetFPSindex]);
|
||||
container.setMouseCursor("cursor.png", 16, 16);
|
||||
container.setMusicVolume(getMusicVolume());
|
||||
container.setShowFPS(false);
|
||||
@@ -375,6 +382,10 @@ public class Options extends BasicGameState {
|
||||
String.format("%d%%", musicVolume),
|
||||
"Global music volume."
|
||||
);
|
||||
this.drawOption(g, OPTIONS_EFFECT_VOLUME, "Effect Volume",
|
||||
String.format("%d%%", effectVolume),
|
||||
"Sound effect volume."
|
||||
);
|
||||
this.drawOption(g, OPTIONS_MUSIC_OFFSET, "Music Offset",
|
||||
String.format("%dms", musicOffset),
|
||||
"Adjust this value if hit objects are out of sync."
|
||||
@@ -509,6 +520,14 @@ public class Options extends BasicGameState {
|
||||
container.setMusicVolume(getMusicVolume());
|
||||
return;
|
||||
}
|
||||
if (isOptionClicked(OPTIONS_EFFECT_VOLUME, oldy)) {
|
||||
effectVolume += diff;
|
||||
if (effectVolume < 0)
|
||||
effectVolume = 0;
|
||||
else if (effectVolume > 100)
|
||||
effectVolume = 100;
|
||||
return;
|
||||
}
|
||||
if (isOptionClicked(OPTIONS_MUSIC_OFFSET, oldy)) {
|
||||
musicOffset += diff;
|
||||
if (musicOffset < -500)
|
||||
@@ -601,6 +620,12 @@ public class Options extends BasicGameState {
|
||||
*/
|
||||
public static float getMusicVolume() { return musicVolume / 100f; }
|
||||
|
||||
/**
|
||||
* Returns the default sound effect volume.
|
||||
* @return the sound volume [0, 1]
|
||||
*/
|
||||
public static float getEffectVolume() { return effectVolume / 100f; }
|
||||
|
||||
/**
|
||||
* Returns the music offset time.
|
||||
* @return the offset (in milliseconds)
|
||||
@@ -639,6 +664,8 @@ public class Options extends BasicGameState {
|
||||
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);
|
||||
@@ -760,6 +787,11 @@ public class Options extends BasicGameState {
|
||||
if (i >= 0 && i <= 100)
|
||||
musicVolume = i;
|
||||
break;
|
||||
case "VolumeEffect":
|
||||
i = Integer.parseInt(value);
|
||||
if (i >= 0 && i <= 100)
|
||||
effectVolume = i;
|
||||
break;
|
||||
case "Offset":
|
||||
i = Integer.parseInt(value);
|
||||
if (i >= -500 && i <= 500)
|
||||
@@ -827,6 +859,8 @@ public class Options extends BasicGameState {
|
||||
writer.newLine();
|
||||
writer.write(String.format("VolumeMusic = %d", musicVolume));
|
||||
writer.newLine();
|
||||
writer.write(String.format("VolumeEffect = %d", effectVolume));
|
||||
writer.newLine();
|
||||
writer.write(String.format("Offset = %d", musicOffset));
|
||||
writer.newLine();
|
||||
writer.write(String.format("ScreenshotFormat = %d", screenshotFormatIndex));
|
||||
|
||||
@@ -25,6 +25,7 @@ import itdelatrisu.opsu.OsuFile;
|
||||
import itdelatrisu.opsu.OsuGroupList;
|
||||
import itdelatrisu.opsu.OsuGroupNode;
|
||||
import itdelatrisu.opsu.OsuParser;
|
||||
import itdelatrisu.opsu.SoundController;
|
||||
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.newdawn.slick.Color;
|
||||
@@ -343,6 +344,7 @@ public class SongMenu extends BasicGameState {
|
||||
|
||||
// back
|
||||
if (Options.getBackButton().contains(x, y)) {
|
||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||
game.enterState(Opsu.STATE_MAINMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
return;
|
||||
}
|
||||
@@ -422,8 +424,10 @@ public class SongMenu extends BasicGameState {
|
||||
if (!search.getText().isEmpty()) {
|
||||
search.setText("");
|
||||
searchTimer = SEARCH_DELAY;
|
||||
} else
|
||||
} else {
|
||||
SoundController.playSound(SoundController.SOUND_MENUBACK);
|
||||
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));
|
||||
@@ -592,8 +596,10 @@ public class SongMenu extends BasicGameState {
|
||||
if (MusicController.isConverting())
|
||||
return;
|
||||
|
||||
SoundController.playSound(SoundController.SOUND_MENUHIT);
|
||||
Display.setTitle(String.format("%s - %s", game.getTitle(), osu.toString()));
|
||||
OsuParser.parseHitObjects(osu);
|
||||
SoundController.setSampleSet(osu.sampleSet);
|
||||
Game.setOsuFile(osu);
|
||||
Game.setRestart(Game.RESTART_NEW);
|
||||
game.enterState(Opsu.STATE_GAME, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||
|
||||
Reference in New Issue
Block a user