Hit object refactoring.
- Moved the bulk of hit object parsing into the OsuHitObject constructor, and made all fields private. Only combo-related data is still set by OsuParser. - Added 'isCircle()', 'isSlider()', 'isSpinner()', and 'isNewCombo()' methods for convenience. Other changes: - Fixed difficulty overrides are no longer affected by game mods. Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
@@ -32,7 +32,7 @@ public class OsuHitObject {
|
||||
TYPE_SPINNER = 8;
|
||||
|
||||
/**
|
||||
* Hit sound types.
|
||||
* Hit sound types (bits).
|
||||
*/
|
||||
public static final byte
|
||||
SOUND_NORMAL = 0,
|
||||
@@ -53,39 +53,263 @@ public class OsuHitObject {
|
||||
/**
|
||||
* Max hit object coordinates.
|
||||
*/
|
||||
public static final int
|
||||
private static final int
|
||||
MAX_X = 512,
|
||||
MAX_Y = 384;
|
||||
|
||||
// parsed fields (coordinates are scaled)
|
||||
public float x, y; // start coordinates
|
||||
public int time; // start time, in ms
|
||||
public int type; // hit object type
|
||||
public byte hitSound; // hit sound type
|
||||
public char sliderType; // slider curve type (sliders only)
|
||||
public float[] sliderX; // slider x coordinate list (sliders only)
|
||||
public float[] sliderY; // slider y coordinate list (sliders only)
|
||||
public int repeat; // slider repeat count (sliders only)
|
||||
public float pixelLength; // slider pixel length (sliders only)
|
||||
public int endTime; // end time, in ms (spinners only)
|
||||
/**
|
||||
* The x and y multipliers for hit object coordinates.
|
||||
*/
|
||||
private static float xMultiplier, yMultiplier;
|
||||
|
||||
/**
|
||||
* The x and y offsets for hit object coordinates.
|
||||
*/
|
||||
private static int
|
||||
xOffset, // offset right of border
|
||||
yOffset; // offset below health bar
|
||||
|
||||
/**
|
||||
* Starting coordinates (scaled).
|
||||
*/
|
||||
private float x, y;
|
||||
|
||||
/**
|
||||
* Start time (in ms).
|
||||
*/
|
||||
private int time;
|
||||
|
||||
/**
|
||||
* Hit object type (TYPE_* bitmask).
|
||||
*/
|
||||
private int type;
|
||||
|
||||
/**
|
||||
* Hit sound type (SOUND_* bitmask).
|
||||
*/
|
||||
private byte hitSound;
|
||||
|
||||
/**
|
||||
* Slider curve type (SLIDER_* constant).
|
||||
*/
|
||||
private char sliderType;
|
||||
|
||||
/**
|
||||
* Slider coordinate lists (scaled).
|
||||
*/
|
||||
private float[] sliderX, sliderY;
|
||||
|
||||
/**
|
||||
* Slider repeat count.
|
||||
*/
|
||||
private int repeat;
|
||||
|
||||
/**
|
||||
* Slider pixel length.
|
||||
*/
|
||||
private float pixelLength;
|
||||
|
||||
/**
|
||||
* Spinner end time (in ms).
|
||||
*/
|
||||
private int endTime;
|
||||
|
||||
// additional v10+ parameters not implemented...
|
||||
// addition -> sampl:add:cust:vol:hitsound
|
||||
// edge_hitsound, edge_addition (sliders only)
|
||||
|
||||
// extra fields
|
||||
public int comboIndex; // current index in Color array
|
||||
public int comboNumber; // number to display in hit object
|
||||
/**
|
||||
* Current index in combo color array.
|
||||
*/
|
||||
private int comboIndex;
|
||||
|
||||
/**
|
||||
* Constructor with all required fields.
|
||||
* Number to display in hit object.
|
||||
*/
|
||||
public OsuHitObject(float x, float y, int time, int type, byte hitSound) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.time = time;
|
||||
this.type = type;
|
||||
this.hitSound = hitSound;
|
||||
private int comboNumber;
|
||||
|
||||
/**
|
||||
* Initializes the OsuHitObject data type with container dimensions.
|
||||
* @param width the container width
|
||||
* @param height the container height
|
||||
*/
|
||||
public static void init(int width, int height) {
|
||||
xMultiplier = (width * 0.6f) / MAX_X;
|
||||
yMultiplier = (height * 0.6f) / MAX_Y;
|
||||
xOffset = width / 5;
|
||||
yOffset = height / 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param line the line to be parsed
|
||||
*/
|
||||
public OsuHitObject(String line) {
|
||||
/**
|
||||
* [OBJECT FORMATS]
|
||||
* Circles:
|
||||
* x,y,time,type,hitSound,addition
|
||||
* 256,148,9466,1,2,0:0:0:0:
|
||||
*
|
||||
* Sliders:
|
||||
* x,y,time,type,hitSound,sliderType|curveX:curveY|...,repeat,pixelLength,edgeHitsound,edgeAddition,addition
|
||||
* 300,68,4591,2,0,B|372:100|332:172|420:192,2,180,2|2|2,0:0|0:0|0:0,0:0:0:0:
|
||||
*
|
||||
* Spinners:
|
||||
* x,y,time,type,hitSound,endTime,addition
|
||||
* 256,192,654,12,0,4029,0:0:0:0:
|
||||
*
|
||||
* NOTE: 'addition' is optional, and defaults to "0:0:0:0:".
|
||||
*/
|
||||
String tokens[] = line.split(",");
|
||||
|
||||
// common fields
|
||||
this.x = Integer.parseInt(tokens[0]) * xMultiplier + xOffset;
|
||||
this.y = Integer.parseInt(tokens[1]) * yMultiplier + yOffset;
|
||||
this.time = Integer.parseInt(tokens[2]);
|
||||
this.type = Integer.parseInt(tokens[3]);
|
||||
this.hitSound = Byte.parseByte(tokens[4]);
|
||||
|
||||
// type-specific fields
|
||||
if ((type & OsuHitObject.TYPE_CIRCLE) > 0) {
|
||||
/* 'addition' not implemented. */
|
||||
|
||||
} else if ((type & OsuHitObject.TYPE_SLIDER) > 0) {
|
||||
// slider curve type and coordinates
|
||||
String[] sliderTokens = tokens[5].split("\\|");
|
||||
this.sliderType = sliderTokens[0].charAt(0);
|
||||
this.sliderX = new float[sliderTokens.length - 1];
|
||||
this.sliderY = new float[sliderTokens.length - 1];
|
||||
for (int j = 1; j < sliderTokens.length; j++) {
|
||||
String[] sliderXY = sliderTokens[j].split(":");
|
||||
this.sliderX[j - 1] = Integer.parseInt(sliderXY[0]) * xMultiplier + xOffset;
|
||||
this.sliderY[j - 1] = Integer.parseInt(sliderXY[1]) * yMultiplier + yOffset;
|
||||
}
|
||||
this.repeat = Integer.parseInt(tokens[6]);
|
||||
this.pixelLength = Float.parseFloat(tokens[7]);
|
||||
/* edge fields and 'addition' not implemented. */
|
||||
|
||||
} else { //if ((type & OsuHitObject.TYPE_SPINNER) > 0) {
|
||||
// some 'endTime' fields contain a ':' character (?)
|
||||
int index = tokens[5].indexOf(':');
|
||||
if (index != -1)
|
||||
tokens[5] = tokens[5].substring(0, index);
|
||||
this.endTime = Integer.parseInt(tokens[5]);
|
||||
/* 'addition' not implemented. */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the starting x coordinate.
|
||||
* @return the x coordinate
|
||||
*/
|
||||
public float getX() { return x; }
|
||||
|
||||
/**
|
||||
* Returns the starting y coordinate.
|
||||
* @return the y coordinate
|
||||
*/
|
||||
public float getY() { return y; }
|
||||
|
||||
/**
|
||||
* Returns the start time.
|
||||
* @return the start time (in ms)
|
||||
*/
|
||||
public int getTime() { return time; }
|
||||
|
||||
/**
|
||||
* Returns the hit object type.
|
||||
* @return the object type (TYPE_* bitmask)
|
||||
*/
|
||||
public int getType() { return type; }
|
||||
|
||||
/**
|
||||
* Returns the hit sound type.
|
||||
* @return the sound type (SOUND_* bitmask)
|
||||
*/
|
||||
public byte getHitSoundType() { return hitSound; }
|
||||
|
||||
/**
|
||||
* Returns the slider type.
|
||||
* @return the slider type (SLIDER_* constant)
|
||||
*/
|
||||
public char getSliderType() { return sliderType; }
|
||||
|
||||
/**
|
||||
* Returns a list of slider x coordinates.
|
||||
* @return the slider x coordinates
|
||||
*/
|
||||
public float[] getSliderX() { return sliderX; }
|
||||
|
||||
/**
|
||||
* Returns a list of slider y coordinates.
|
||||
* @return the slider y coordinates
|
||||
*/
|
||||
public float[] getSliderY() { return sliderY; }
|
||||
|
||||
/**
|
||||
* Returns the slider repeat count.
|
||||
* @return the repeat count
|
||||
*/
|
||||
public int getRepeatCount() { return repeat; }
|
||||
|
||||
/**
|
||||
* Returns the slider pixel length.
|
||||
* @return the pixel length
|
||||
*/
|
||||
public float getPixelLength() { return pixelLength; }
|
||||
|
||||
/**
|
||||
* Returns the spinner end time.
|
||||
* @return the end time (in ms)
|
||||
*/
|
||||
public int getEndTime() { return endTime; }
|
||||
|
||||
/**
|
||||
* Sets the current index in the combo color array.
|
||||
* @param comboIndex the combo index
|
||||
*/
|
||||
public void setComboIndex(int comboIndex) { this.comboIndex = comboIndex; }
|
||||
|
||||
/**
|
||||
* Returns the current index in the combo color array.
|
||||
* @return the combo index
|
||||
*/
|
||||
public int getComboIndex() { return comboIndex; }
|
||||
|
||||
/**
|
||||
* Sets the number to display in the hit object.
|
||||
* @param comboNumber the combo number
|
||||
*/
|
||||
public void setComboNumber(int comboNumber) { this.comboNumber = comboNumber; }
|
||||
|
||||
/**
|
||||
* Returns the number to display in the hit object.
|
||||
* @return the combo number
|
||||
*/
|
||||
public int getComboNumber() { return comboNumber; }
|
||||
|
||||
/**
|
||||
* Returns whether or not the hit object is a circle.
|
||||
* @return true if circle
|
||||
*/
|
||||
public boolean isCircle() { return (type & TYPE_CIRCLE) > 0; }
|
||||
|
||||
/**
|
||||
* Returns whether or not the hit object is a slider.
|
||||
* @return true if slider
|
||||
*/
|
||||
public boolean isSlider() { return (type & TYPE_SLIDER) > 0; }
|
||||
|
||||
/**
|
||||
* Returns whether or not the hit object is a spinner.
|
||||
* @return true if spinner
|
||||
*/
|
||||
public boolean isSpinner() { return (type & TYPE_SPINNER) > 0; }
|
||||
|
||||
/**
|
||||
* Returns whether or not the hit object starts a new combo.
|
||||
* @return true if new combo
|
||||
*/
|
||||
public boolean isNewCombo() { return (type & TYPE_NEWCOMBO) > 0; }
|
||||
}
|
||||
Reference in New Issue
Block a user