Check for parallel vectors before constructing a CircumscribedCircle.

If the check fails, use a LinearBezier instead. (e.g. in map 45471).

Moved slider time and curve calculations into HitObject so that they can be reused.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2015-09-02 10:51:52 -05:00
parent d360b73bf5
commit c516d93d1e
2 changed files with 36 additions and 11 deletions

View File

@ -19,6 +19,11 @@
package itdelatrisu.opsu.beatmap;
import itdelatrisu.opsu.GameMod;
import itdelatrisu.opsu.objects.curves.CatmullCurve;
import itdelatrisu.opsu.objects.curves.CircumscribedCircle;
import itdelatrisu.opsu.objects.curves.Curve;
import itdelatrisu.opsu.objects.curves.LinearBezier;
import itdelatrisu.opsu.objects.curves.Vec2f;
import java.text.DecimalFormat;
import java.text.NumberFormat;
@ -403,6 +408,35 @@ public class HitObject {
*/
public float getPixelLength() { return pixelLength; }
/**
* Returns the time duration of the slider (excluding repeats), in milliseconds.
* @param sliderMultiplier the beatmap's slider movement speed multiplier
* @param beatLength the beat length
* @return the slider segment length
*/
public float getSliderTime(float sliderMultiplier, float beatLength) {
return beatLength * (pixelLength / sliderMultiplier) / 100f;
}
/**
* Returns the slider curve.
* @param scaled whether to use scaled coordinates
* @return a new Curve instance
*/
public Curve getSliderCurve(boolean scaled) {
if (sliderType == SLIDER_PASSTHROUGH && sliderX.length == 2) {
Vec2f nora = new Vec2f(sliderX[0] - x, sliderY[0] - y).nor();
Vec2f norb = new Vec2f(sliderX[0] - sliderX[1], sliderY[0] - sliderY[1]).nor();
if (Math.abs(norb.x * nora.y - norb.y * nora.x) < 0.00001f)
return new LinearBezier(this, false, scaled); // vectors parallel, use linear bezier instead
else
return new CircumscribedCircle(this, scaled);
} else if (sliderType == SLIDER_CATMULL)
return new CatmullCurve(this, scaled);
else
return new LinearBezier(this, sliderType == SLIDER_LINEAR, scaled);
}
/**
* Returns the spinner end time.
* @return the end time (in ms)

View File

@ -26,10 +26,7 @@ import itdelatrisu.opsu.Options;
import itdelatrisu.opsu.Utils;
import itdelatrisu.opsu.beatmap.Beatmap;
import itdelatrisu.opsu.beatmap.HitObject;
import itdelatrisu.opsu.objects.curves.CatmullCurve;
import itdelatrisu.opsu.objects.curves.CircumscribedCircle;
import itdelatrisu.opsu.objects.curves.Curve;
import itdelatrisu.opsu.objects.curves.LinearBezier;
import itdelatrisu.opsu.states.Game;
import itdelatrisu.opsu.ui.Colors;
@ -157,7 +154,7 @@ public class Slider implements GameObject {
updatePosition();
// slider time calculations
this.sliderTime = game.getBeatLength() * (hitObject.getPixelLength() / sliderMultiplier) / 100f;
this.sliderTime = hitObject.getSliderTime(sliderMultiplier, game.getBeatLength());
this.sliderTimeTotal = sliderTime * hitObject.getRepeatCount();
// ticks
@ -525,13 +522,7 @@ public class Slider implements GameObject {
public void updatePosition() {
this.x = hitObject.getScaledX();
this.y = hitObject.getScaledY();
if (hitObject.getSliderType() == HitObject.SLIDER_PASSTHROUGH && hitObject.getSliderX().length == 2)
this.curve = new CircumscribedCircle(hitObject);
else if (hitObject.getSliderType() == HitObject.SLIDER_CATMULL)
this.curve = new CatmullCurve(hitObject);
else
this.curve = new LinearBezier(hitObject, hitObject.getSliderType() == HitObject.SLIDER_LINEAR);
this.curve = hitObject.getSliderCurve(true);
}
@Override