Some code cleanup.

- Overhauled OsuTimingPoint class: parsing is done in the constructor, and fields are no longer public.
- Improved consistency of static/non-static fields in a couple of classes.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2014-07-09 13:36:42 -04:00
parent 50fb71e353
commit 5a1972a2bd
7 changed files with 172 additions and 64 deletions

View File

@ -336,35 +336,20 @@ public class OsuParser {
continue;
if (line.charAt(0) == '[')
break;
tokens = line.split(",");
OsuTimingPoint timingPoint = new OsuTimingPoint();
try { // newer file versions have many new fields
timingPoint.time = (int) Float.parseFloat(tokens[0]); //rare float
timingPoint.meter = Integer.parseInt(tokens[2]);
timingPoint.sampleType = Byte.parseByte(tokens[3]);
timingPoint.sampleTypeCustom = Byte.parseByte(tokens[4]);
timingPoint.sampleVolume = Integer.parseInt(tokens[5]);
timingPoint.inherited = (Integer.parseInt(tokens[6]) == 1);
timingPoint.kiai = (Integer.parseInt(tokens[7]) == 1);
} catch (ArrayIndexOutOfBoundsException e) {
// TODO: better support for old formats
// Log.error(String.format("Error while parsing TimingPoints, line: '%s'.", line), e);
}
// parse timing point
OsuTimingPoint timingPoint = new OsuTimingPoint(line);
// tokens[1] is either beatLength (positive) or velocity (negative)
float beatLength = Float.parseFloat(tokens[1]);
if (beatLength > 0) {
timingPoint.beatLength = beatLength;
int bpm = Math.round(60000 / beatLength);
// calculate BPM
if (!timingPoint.isInherited()) {
int bpm = Math.round(60000 / timingPoint.getBeatLength());
if (osu.bpmMin == 0)
osu.bpmMin = osu.bpmMax = bpm;
else if (bpm < osu.bpmMin)
osu.bpmMin = bpm;
else if (bpm > osu.bpmMax)
osu.bpmMax = bpm;
} else
timingPoint.velocity = (int) beatLength;
}
osu.timingPoints.add(timingPoint);
}

View File

@ -18,22 +18,145 @@
package itdelatrisu.opsu;
import org.newdawn.slick.util.Log;
/**
* Data type representing a timing point.
*/
public class OsuTimingPoint {
public int time; // start time/offset (in ms)
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, 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?
/**
* Timing point start time/offset (in ms).
*/
private int time = 0;
/**
* Time per beat (in ms). [NON-INHERITED]
*/
private float beatLength = 0f;
/**
* Slider multiplier. [INHERITED]
*/
private int velocity = 0;
/**
* Beats per measure.
*/
private int meter = 4;
/**
* Sound sample type.
*/
private byte sampleType = 1;
/**
* Custom sound sample type.
*/
private byte sampleTypeCustom = 0;
/**
* Volume of samples. [0, 100]
*/
private int sampleVolume = 100;
/**
* Whether or not this timing point is inherited.
*/
private boolean inherited = false;
/**
* Whether or not Kiai Mode is active.
*/
private boolean kiai = false;
/**
* Constructor.
* @param line the line to be parsed
*/
public OsuTimingPoint() {}
public OsuTimingPoint(String line) {
// TODO: better support for old formats
String[] tokens = line.split(",");
try {
this.time = (int) Float.parseFloat(tokens[0]); // rare float
this.meter = Integer.parseInt(tokens[2]);
this.sampleType = Byte.parseByte(tokens[3]);
this.sampleTypeCustom = Byte.parseByte(tokens[4]);
this.sampleVolume = Integer.parseInt(tokens[5]);
// this.inherited = (Integer.parseInt(tokens[6]) == 1);
this.kiai = (Integer.parseInt(tokens[7]) == 1);
} catch (ArrayIndexOutOfBoundsException e) {
Log.debug(String.format("Error parsing timing point: '%s'", line));
}
// tokens[1] is either beatLength (positive) or velocity (negative)
float beatLength = Float.parseFloat(tokens[1]);
if (beatLength > 0)
this.beatLength = beatLength;
else {
this.velocity = (int) beatLength;
this.inherited = true;
}
}
/**
* Returns the timing point start time/offset.
* @return the start time (in ms)
*/
public int getTime() { return time; }
/**
* Returns the beat length. [NON-INHERITED]
* @return the time per beat (in ms)
*/
public float getBeatLength() { return beatLength; }
/**
* Returns the slider multiplier. [INHERITED]
*/
public float getSliderMultiplier() { return velocity / -100f; }
/**
* Returns the meter.
* @return the number of beats per measure
*/
public int getMeter() { return meter; }
/**
* Returns the sample type.
* <ul>
* <li>0: none
* <li>1: normal
* <li>2: soft
* <li>3: drum
* </ul>
*/
public byte getSampleType() { return sampleType; }
/**
* Returns the custom sample type.
* <ul>
* <li>0: default
* <li>1: custom 1
* <li>2: custom 2
* </ul>
*/
public byte getSampleTypeCustom() { return sampleTypeCustom; }
/**
* Returns the sample volume.
* @return the sample volume [0, 1]
*/
public float getSampleVolume() { return sampleVolume / 100f; }
/**
* Returns whether or not this timing point is inherited.
* @return the inherited
*/
public boolean isInherited() { return inherited; }
/**
* Returns whether or not Kiai Time is active.
* @return true if active
*/
public boolean isKiaiTimeActive() { return kiai; }
}

View File

@ -231,11 +231,11 @@ public class SoundController {
/**
* Sets the sample volume (modifies the global sample volume).
* @param volume the sample volume [0, 100]
* @param volume the sample volume [0, 1]
*/
public static void setSampleVolume(int volume) {
if (volume >= 0 && volume <= 100)
sampleVolumeMultiplier = volume / 100f;
public static void setSampleVolume(float volume) {
if (volume >= 0f && volume <= 1f)
sampleVolumeMultiplier = volume;
}
/**

View File

@ -71,7 +71,7 @@ public class Game extends BasicGameState {
/**
* The associated OsuFile object.
*/
private static OsuFile osu;
private OsuFile osu;
/**
* The associated GameScore object (holds all score data).
@ -101,7 +101,7 @@ public class Game extends BasicGameState {
/**
* Delay time, in milliseconds, before song starts.
*/
private static int leadInTime;
private int leadInTime;
/**
* Hit object approach time, in milliseconds.
@ -141,7 +141,7 @@ public class Game extends BasicGameState {
/**
* Minimum time before start of song, in milliseconds, to process skip-related actions.
*/
private final int skipOffsetTime = 2000;
private static final int SKIP_OFFSET = 2000;
/**
* Current timing point index in timingPoints ArrayList.
@ -308,8 +308,8 @@ public class Game extends BasicGameState {
// skip beginning
if (objectIndex == 0 &&
osu.objects[0].time - skipOffsetTime > 5000 &&
trackPosition < osu.objects[0].time - skipOffsetTime)
osu.objects[0].time - SKIP_OFFSET > 5000 &&
trackPosition < osu.objects[0].time - SKIP_OFFSET)
skipButton.draw();
if (isLeadIn())
@ -456,13 +456,13 @@ public class Game extends BasicGameState {
// timing points
if (timingPointIndex < osu.timingPoints.size()) {
OsuTimingPoint timingPoint = osu.timingPoints.get(timingPointIndex);
if (trackPosition >= timingPoint.time) {
if (timingPoint.velocity >= 0)
beatLengthBase = beatLength = timingPoint.beatLength;
if (trackPosition >= timingPoint.getTime()) {
if (!timingPoint.isInherited())
beatLengthBase = beatLength = timingPoint.getBeatLength();
else
beatLength = beatLengthBase * (timingPoint.velocity / -100f);
SoundController.setSampleSet(timingPoint.sampleType);
SoundController.setSampleVolume(timingPoint.sampleVolume);
beatLength = beatLengthBase * timingPoint.getSliderMultiplier();
SoundController.setSampleSet(timingPoint.getSampleType());
SoundController.setSampleVolume(timingPoint.getSampleVolume());
timingPointIndex++;
}
}
@ -644,7 +644,7 @@ public class Game extends BasicGameState {
pauseTime = -1;
pausedMouseX = -1;
pausedMouseY = -1;
if (!Game.isLeadIn())
if (!isLeadIn())
MusicController.resume();
}
return;
@ -751,10 +751,10 @@ public class Game extends BasicGameState {
// load the first timingPoint
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);
if (!timingPoint.isInherited()) {
beatLengthBase = beatLength = timingPoint.getBeatLength();
SoundController.setSampleSet(timingPoint.getSampleType());
SoundController.setSampleVolume(timingPoint.getSampleVolume());
timingPointIndex++;
}
}
@ -777,13 +777,13 @@ public class Game extends BasicGameState {
private boolean skipIntro() {
int trackPosition = MusicController.getPosition();
if (objectIndex == 0 &&
osu.objects[0].time - skipOffsetTime > 4000 &&
trackPosition < osu.objects[0].time - skipOffsetTime) {
osu.objects[0].time - SKIP_OFFSET > 4000 &&
trackPosition < osu.objects[0].time - SKIP_OFFSET) {
if (isLeadIn()) {
leadInTime = 0;
MusicController.resume();
}
MusicController.setPosition(osu.objects[0].time - skipOffsetTime);
MusicController.setPosition(osu.objects[0].time - SKIP_OFFSET);
SoundController.playSound(SoundController.SOUND_MENUHIT);
return true;
}
@ -931,7 +931,7 @@ public class Game extends BasicGameState {
/**
* Returns whether or not the track is in the lead-in time state.
*/
public static boolean isLeadIn() { return leadInTime > 0; }
public boolean isLeadIn() { return leadInTime > 0; }
/**
* Returns the object approach time, in milliseconds.

View File

@ -50,7 +50,7 @@ public class GameRanking extends BasicGameState {
/**
* Associated GameScore object.
*/
private static GameScore score;
private GameScore score;
/**
* "Retry" and "Exit" buttons.

View File

@ -209,9 +209,9 @@ public class MainMenu extends BasicGameState {
long time = System.currentTimeMillis() - osuStartTime;
g.drawString(String.format("opsu! has been running for %d minutes, %d seconds.",
TimeUnit.MILLISECONDS.toMinutes(time),
TimeUnit.MILLISECONDS.toSeconds(time) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(time))),
25, height - 25 - (lineHeight * 2));
TimeUnit.MILLISECONDS.toSeconds(time) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(time))),
25, height - 25 - (lineHeight * 2));
g.drawString(String.format("The current time is %s.",
new SimpleDateFormat("h:mm a").format(new Date())),
25, height - 25 - lineHeight);

View File

@ -118,7 +118,7 @@ public class Options extends BasicGameState {
/**
* Game options.
*/
private enum GameOption {
private static enum GameOption {
NULL,
SCREEN_RESOLUTION,
// FULLSCREEN,
@ -168,7 +168,7 @@ public class Options extends BasicGameState {
/**
* Option tab buttons.
*/
private GUIMenuButton[] optionTabs = new GUIMenuButton[TAB_MAX];
private static GUIMenuButton[] optionTabs = new GUIMenuButton[TAB_MAX];
/**
* Current tab.
@ -870,7 +870,7 @@ public class Options extends BasicGameState {
drawOption(pos, "Track Checkpoint",
(checkpoint == 0) ? "Disabled" : String.format("%02d:%02d",
TimeUnit.SECONDS.toMinutes(checkpoint),
checkpoint - TimeUnit.MINUTES.toSeconds(TimeUnit.SECONDS.toMinutes(checkpoint))),
checkpoint - TimeUnit.MINUTES.toSeconds(TimeUnit.SECONDS.toMinutes(checkpoint))),
"Press CTRL+L while playing to load a checkpoint, and CTRL+S to set one."
);
break;
@ -975,8 +975,8 @@ public class Options extends BasicGameState {
public static float getEffectVolume() { return effectVolume / 100f; }
/**
* Returns the default sound effect volume.
* @return the sound volume [0, 1]
* Returns the default hit sound volume.
* @return the hit sound volume [0, 1]
*/
public static float getHitSoundVolume() { return hitSoundVolume / 100f; }