Merge pull request #211 from yugecin/slider-improvements
Slider improvements (fade in ticks, fade out reversearrow, animations)
This commit is contained in:
commit
d111fc0efe
|
@ -26,7 +26,6 @@ import itdelatrisu.opsu.beatmap.Beatmap;
|
||||||
import itdelatrisu.opsu.beatmap.HitObject;
|
import itdelatrisu.opsu.beatmap.HitObject;
|
||||||
import itdelatrisu.opsu.downloads.Updater;
|
import itdelatrisu.opsu.downloads.Updater;
|
||||||
import itdelatrisu.opsu.objects.curves.Curve;
|
import itdelatrisu.opsu.objects.curves.Curve;
|
||||||
import itdelatrisu.opsu.objects.curves.Vec2f;
|
|
||||||
import itdelatrisu.opsu.replay.Replay;
|
import itdelatrisu.opsu.replay.Replay;
|
||||||
import itdelatrisu.opsu.replay.ReplayFrame;
|
import itdelatrisu.opsu.replay.ReplayFrame;
|
||||||
import itdelatrisu.opsu.ui.Colors;
|
import itdelatrisu.opsu.ui.Colors;
|
||||||
|
@ -150,7 +149,9 @@ public class GameData {
|
||||||
HIT_300G = 6, // Geki
|
HIT_300G = 6, // Geki
|
||||||
HIT_SLIDER10 = 7,
|
HIT_SLIDER10 = 7,
|
||||||
HIT_SLIDER30 = 8,
|
HIT_SLIDER30 = 8,
|
||||||
HIT_MAX = 9; // not a hit result
|
HIT_MAX = 9, // not a hit result
|
||||||
|
HIT_SLIDER_REPEAT = 10, // not a hit result
|
||||||
|
HIT_ANIMATION_RESULT = 11; // not a hit result
|
||||||
|
|
||||||
/** Hit result-related images (indexed by HIT_* constants). */
|
/** Hit result-related images (indexed by HIT_* constants). */
|
||||||
private Image[] hitResults;
|
private Image[] hitResults;
|
||||||
|
@ -231,7 +232,7 @@ public class GameData {
|
||||||
private LinkedBlockingDeque<HitErrorInfo> hitErrorList;
|
private LinkedBlockingDeque<HitErrorInfo> hitErrorList;
|
||||||
|
|
||||||
/** Hit object types, used for drawing results. */
|
/** Hit object types, used for drawing results. */
|
||||||
public enum HitObjectType { CIRCLE, SLIDERTICK, SLIDER_FIRST, SLIDER_LAST, SPINNER }
|
public enum HitObjectType { CIRCLE, SLIDERTICK, SLIDER_FIRST, SLIDER_CURVE, SLIDER_LAST, SPINNER }
|
||||||
|
|
||||||
/** Hit result helper class. */
|
/** Hit result helper class. */
|
||||||
private class HitObjectResult {
|
private class HitObjectResult {
|
||||||
|
@ -891,37 +892,9 @@ public class GameData {
|
||||||
lighting.drawCentered(hitResult.x, hitResult.y, hitResult.color);
|
lighting.drawCentered(hitResult.x, hitResult.y, hitResult.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hit animation
|
// hit animations, only draw when the 'hidden' mod is not enabled
|
||||||
if (hitResult.result != HIT_MISS && (
|
|
||||||
hitResult.hitResultType == HitObjectType.CIRCLE ||
|
|
||||||
hitResult.hitResultType == HitObjectType.SLIDER_FIRST ||
|
|
||||||
hitResult.hitResultType == HitObjectType.SLIDER_LAST)) {
|
|
||||||
float progress = AnimationEquation.OUT_CUBIC.calc(
|
|
||||||
(float) Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_FADE_TIME) / HITCIRCLE_FADE_TIME);
|
|
||||||
float scale = (!hitResult.expand) ? 1f : 1f + (HITCIRCLE_ANIM_SCALE - 1f) * progress;
|
|
||||||
float alpha = 1f - progress;
|
|
||||||
|
|
||||||
// "hidden" mod: circle and slider animations not drawn
|
|
||||||
if (!GameMod.HIDDEN.isActive()) {
|
if (!GameMod.HIDDEN.isActive()) {
|
||||||
// slider curve
|
drawHitAnimations(hitResult, trackPosition);
|
||||||
if (hitResult.curve != null) {
|
|
||||||
float oldWhiteAlpha = Colors.WHITE_FADE.a;
|
|
||||||
float oldColorAlpha = hitResult.color.a;
|
|
||||||
Colors.WHITE_FADE.a = alpha;
|
|
||||||
hitResult.color.a = alpha;
|
|
||||||
hitResult.curve.draw(hitResult.color);
|
|
||||||
Colors.WHITE_FADE.a = oldWhiteAlpha;
|
|
||||||
hitResult.color.a = oldColorAlpha;
|
|
||||||
}
|
|
||||||
|
|
||||||
// hit circles
|
|
||||||
Image scaledHitCircle = GameImage.HITCIRCLE.getImage().getScaledCopy(scale);
|
|
||||||
Image scaledHitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(scale);
|
|
||||||
scaledHitCircle.setAlpha(alpha);
|
|
||||||
scaledHitCircleOverlay.setAlpha(alpha);
|
|
||||||
scaledHitCircle.drawCentered(hitResult.x, hitResult.y, hitResult.color);
|
|
||||||
scaledHitCircleOverlay.drawCentered(hitResult.x, hitResult.y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hit result
|
// hit result
|
||||||
|
@ -949,6 +922,66 @@ public class GameData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the hit animations: circles, reversearrows, slider curves fading out and/or expanding
|
||||||
|
* @param hitResult the hitresult which holds information about the kind of animation to draw
|
||||||
|
* @param trackPosition the current track position (in ms)
|
||||||
|
*/
|
||||||
|
private void drawHitAnimations(HitObjectResult hitResult, int trackPosition) {
|
||||||
|
if (hitResult.hitResultType == HitObjectType.SLIDER_CURVE && hitResult.curve != null) {
|
||||||
|
float progress = AnimationEquation.OUT_CUBIC.calc(
|
||||||
|
(float) Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_FADE_TIME) / HITCIRCLE_FADE_TIME);
|
||||||
|
float alpha = 1f - progress;
|
||||||
|
|
||||||
|
// slider curve
|
||||||
|
float oldWhiteAlpha = Colors.WHITE_FADE.a;
|
||||||
|
float oldColorAlpha = hitResult.color.a;
|
||||||
|
Colors.WHITE_FADE.a = alpha;
|
||||||
|
hitResult.color.a = alpha;
|
||||||
|
hitResult.curve.draw(hitResult.color);
|
||||||
|
Colors.WHITE_FADE.a = oldWhiteAlpha;
|
||||||
|
hitResult.color.a = oldColorAlpha;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitResult.result == HIT_MISS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitResult.hitResultType != HitObjectType.CIRCLE
|
||||||
|
&& hitResult.hitResultType != HitObjectType.SLIDER_FIRST
|
||||||
|
&& hitResult.hitResultType != HitObjectType.SLIDER_LAST) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// circles
|
||||||
|
float progress = AnimationEquation.OUT_CUBIC.calc(
|
||||||
|
(float) Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_FADE_TIME) / HITCIRCLE_FADE_TIME);
|
||||||
|
float scale = (!hitResult.expand) ? 1f : 1f + (HITCIRCLE_ANIM_SCALE - 1f) * progress;
|
||||||
|
float alpha = 1f - progress;
|
||||||
|
|
||||||
|
if (hitResult.result == HIT_SLIDER_REPEAT) {
|
||||||
|
// repeats
|
||||||
|
Image scaledRepeat = GameImage.REVERSEARROW.getImage().getScaledCopy(scale);
|
||||||
|
scaledRepeat.setAlpha(alpha);
|
||||||
|
float ang;
|
||||||
|
if (hitResult.hitResultType == HitObjectType.SLIDER_FIRST) {
|
||||||
|
ang = hitResult.curve.getStartAngle();
|
||||||
|
} else {
|
||||||
|
ang = hitResult.curve.getEndAngle();
|
||||||
|
}
|
||||||
|
scaledRepeat.rotate(ang);
|
||||||
|
scaledRepeat.drawCentered(hitResult.x, hitResult.y, hitResult.color);
|
||||||
|
}
|
||||||
|
// hit circles
|
||||||
|
Image scaledHitCircle = GameImage.HITCIRCLE.getImage().getScaledCopy(scale);
|
||||||
|
Image scaledHitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(scale);
|
||||||
|
scaledHitCircle.setAlpha(alpha);
|
||||||
|
scaledHitCircleOverlay.setAlpha(alpha);
|
||||||
|
scaledHitCircle.drawCentered(hitResult.x, hitResult.y, hitResult.color);
|
||||||
|
scaledHitCircleOverlay.drawCentered(hitResult.x, hitResult.y);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes health by a given percentage, modified by drainRate.
|
* Changes health by a given percentage, modified by drainRate.
|
||||||
* @param percent the health percentage
|
* @param percent the health percentage
|
||||||
|
@ -1177,6 +1210,18 @@ public class GameData {
|
||||||
health = 0f;
|
health = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendRepeatSliderResult(int time, float x, float y, Color color, Curve curve, HitObjectType type) {
|
||||||
|
hitResultList.add(new HitObjectResult(time, HIT_SLIDER_REPEAT, x, y, color, type, curve, true, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendSliderCurveResult(int time, Color color, Curve curve) {
|
||||||
|
hitResultList.add(new HitObjectResult(time, HIT_SLIDER_REPEAT, 0f, 0f, color, HitObjectType.SLIDER_CURVE, curve, true, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendAnimationResult(int time, float x, float y, Color color, boolean expand) {
|
||||||
|
hitResultList.add(new HitObjectResult(time, HIT_ANIMATION_RESULT, x, y, color, HitObjectType.CIRCLE, null, expand, true));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a slider tick result.
|
* Handles a slider tick result.
|
||||||
* @param time the tick start time
|
* @param time the tick start time
|
||||||
|
@ -1378,14 +1423,6 @@ public class GameData {
|
||||||
|
|
||||||
boolean hideResult = (hitResult == HIT_300 || hitResult == HIT_300G || hitResult == HIT_300K) && !Options.isPerfectHitBurstEnabled();
|
boolean hideResult = (hitResult == HIT_300 || hitResult == HIT_300G || hitResult == HIT_300K) && !Options.isPerfectHitBurstEnabled();
|
||||||
hitResultList.add(new HitObjectResult(time, hitResult, x, y, color, hitResultType, curve, expand, hideResult));
|
hitResultList.add(new HitObjectResult(time, hitResult, x, y, color, hitResultType, curve, expand, hideResult));
|
||||||
|
|
||||||
// sliders: add the other curve endpoint for the hit animation
|
|
||||||
if (curve != null) {
|
|
||||||
boolean isFirst = (hitResultType == HitObjectType.SLIDER_FIRST);
|
|
||||||
Vec2f p = curve.pointAt((isFirst) ? 1f : 0f);
|
|
||||||
HitObjectType type = (isFirst) ? HitObjectType.SLIDER_LAST : HitObjectType.SLIDER_FIRST;
|
|
||||||
hitResultList.add(new HitObjectResult(time, hitResult, p.x, p.y, color, type, null, expand, hideResult));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -180,6 +180,7 @@ public class Slider implements GameObject {
|
||||||
@Override
|
@Override
|
||||||
public void draw(Graphics g, int trackPosition) {
|
public void draw(Graphics g, int trackPosition) {
|
||||||
int timeDiff = hitObject.getTime() - trackPosition;
|
int timeDiff = hitObject.getTime() - trackPosition;
|
||||||
|
final int repeats = hitObject.getRepeatCount();
|
||||||
final int approachTime = game.getApproachTime();
|
final int approachTime = game.getApproachTime();
|
||||||
final int fadeInTime = game.getFadeInTime();
|
final int fadeInTime = game.getFadeInTime();
|
||||||
float scale = timeDiff / (float) approachTime;
|
float scale = timeDiff / (float) approachTime;
|
||||||
|
@ -205,21 +206,44 @@ public class Slider implements GameObject {
|
||||||
float curveInterval = Options.isSliderSnaking() ? alpha : 1f;
|
float curveInterval = Options.isSliderSnaking() ? alpha : 1f;
|
||||||
curve.draw(color,curveInterval);
|
curve.draw(color,curveInterval);
|
||||||
|
|
||||||
// end circle
|
// end circle, only draw if ball still has to go there
|
||||||
|
if (curveInterval == 1f && currentRepeats < repeats - (repeats % 2 == 0 ? 1 : 0)) {
|
||||||
|
Color circleColor = new Color(color);
|
||||||
|
Color overlayColor = new Color(Colors.WHITE_FADE);
|
||||||
|
if (currentRepeats == 0) {
|
||||||
|
if (Options.isSliderSnaking()) {
|
||||||
|
// fade in end circle using decorationsAlpha when snaking sliders are enabled
|
||||||
|
circleColor.a = overlayColor.a = sliderAlpha * decorationsAlpha;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// fade in end circle after repeats
|
||||||
|
circleColor.a = overlayColor.a = sliderAlpha * getCircleAlphaAfterRepeat(trackPosition, true);
|
||||||
|
}
|
||||||
Vec2f endCircPos = curve.pointAt(curveInterval);
|
Vec2f endCircPos = curve.pointAt(curveInterval);
|
||||||
hitCircle.drawCentered(endCircPos.x, endCircPos.y, color);
|
hitCircle.drawCentered(endCircPos.x, endCircPos.y, circleColor);
|
||||||
hitCircleOverlay.drawCentered(endCircPos.x, endCircPos.y, Colors.WHITE_FADE);
|
hitCircleOverlay.drawCentered(endCircPos.x, endCircPos.y, overlayColor);
|
||||||
|
}
|
||||||
|
|
||||||
// start circle
|
// set first circle colors to fade in after repeats
|
||||||
hitCircle.drawCentered(x, y, color);
|
Color firstCircleColor = new Color(color);
|
||||||
if (!overlayAboveNumber)
|
Color startCircleOverlayColor = new Color(Colors.WHITE_FADE);
|
||||||
hitCircleOverlay.drawCentered(x, y, Colors.WHITE_FADE);
|
if (sliderClickedInitial) {
|
||||||
|
// fade in first circle after repeats
|
||||||
|
firstCircleColor.a = startCircleOverlayColor.a = sliderAlpha * getCircleAlphaAfterRepeat(trackPosition, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start circle, only draw if ball still has to go there
|
||||||
|
if (!sliderClickedInitial || currentRepeats < repeats - (repeats % 2 == 1 ? 1 : 0)) {
|
||||||
|
hitCircle.drawCentered(x, y, firstCircleColor);
|
||||||
|
if (!overlayAboveNumber || sliderClickedInitial)
|
||||||
|
hitCircleOverlay.drawCentered(x, y, startCircleOverlayColor);
|
||||||
|
}
|
||||||
|
|
||||||
color.a = alpha;
|
color.a = alpha;
|
||||||
|
|
||||||
// ticks
|
// ticks
|
||||||
if (ticksT != null) {
|
if (ticksT != null) {
|
||||||
drawSliderTicks(g, trackPosition, sliderAlpha, decorationsAlpha);
|
drawSliderTicks(trackPosition, sliderAlpha, decorationsAlpha);
|
||||||
Colors.WHITE_FADE.a = oldWhiteFadeAlpha;
|
Colors.WHITE_FADE.a = oldWhiteFadeAlpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,35 +255,34 @@ public class Slider implements GameObject {
|
||||||
alpha = Math.min(alpha, hiddenAlpha);
|
alpha = Math.min(alpha, hiddenAlpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sliderClickedInitial)
|
|
||||||
; // don't draw current combo number if already clicked
|
// draw combonumber and overlay if not initially clicked
|
||||||
else
|
if (!sliderClickedInitial) {
|
||||||
data.drawSymbolNumber(hitObject.getComboNumber(), x, y,
|
data.drawSymbolNumber(hitObject.getComboNumber(), x, y,
|
||||||
hitCircle.getWidth() * 0.40f / data.getDefaultSymbolImage(0).getHeight(), alpha);
|
hitCircle.getWidth() * 0.40f / data.getDefaultSymbolImage(0).getHeight(), alpha);
|
||||||
|
|
||||||
if (overlayAboveNumber) {
|
if (overlayAboveNumber) {
|
||||||
oldWhiteFadeAlpha = Colors.WHITE_FADE.a;
|
startCircleOverlayColor.a = sliderAlpha;
|
||||||
Colors.WHITE_FADE.a = sliderAlpha;
|
hitCircleOverlay.drawCentered(x, y, startCircleOverlayColor);
|
||||||
hitCircleOverlay.drawCentered(x, y, Colors.WHITE_FADE);
|
}
|
||||||
Colors.WHITE_FADE.a = oldWhiteFadeAlpha;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeats
|
// repeats
|
||||||
if (curveInterval == 1.0f) {
|
if (curveInterval == 1.0f) {
|
||||||
for (int tcurRepeat = currentRepeats; tcurRepeat <= currentRepeats + 1; tcurRepeat++) {
|
for (int tcurRepeat = currentRepeats; tcurRepeat <= currentRepeats + 1 && tcurRepeat < repeats - 1; tcurRepeat++) {
|
||||||
if (hitObject.getRepeatCount() - 1 > tcurRepeat) {
|
|
||||||
Image arrow = GameImage.REVERSEARROW.getImage();
|
Image arrow = GameImage.REVERSEARROW.getImage();
|
||||||
// bouncing animation
|
// bouncing animation
|
||||||
//arrow = arrow.getScaledCopy((float) (1 + 0.2d * ((trackPosition + sliderTime * tcurRepeat) % 292) / 292));
|
//arrow = arrow.getScaledCopy((float) (1 + 0.2d * ((trackPosition + sliderTime * tcurRepeat) % 292) / 292));
|
||||||
float colorLuminance = 0.299f*color.r + 0.587f*color.g + 0.114f*color.b;
|
float colorLuminance = 0.299f*color.r + 0.587f*color.g + 0.114f*color.b;
|
||||||
Color arrowColor = colorLuminance < 0.8f ? Color.white : Color.black;
|
Color arrowColor = colorLuminance < 0.8f ? Color.white : Color.black;
|
||||||
if (tcurRepeat != currentRepeats) {
|
if (tcurRepeat == 0) {
|
||||||
if (sliderTime == 0)
|
|
||||||
continue;
|
|
||||||
float t = Math.max(getT(trackPosition, true), 0);
|
|
||||||
arrow.setAlpha((float) (t - Math.floor(t)));
|
|
||||||
} else
|
|
||||||
arrow.setAlpha(Options.isSliderSnaking() ? decorationsAlpha : 1f);
|
arrow.setAlpha(Options.isSliderSnaking() ? decorationsAlpha : 1f);
|
||||||
|
} else {
|
||||||
|
if (!sliderClickedInitial) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
arrow.setAlpha(getCircleAlphaAfterRepeat(trackPosition, tcurRepeat % 2 == 0));
|
||||||
|
}
|
||||||
if (tcurRepeat % 2 == 0) {
|
if (tcurRepeat % 2 == 0) {
|
||||||
// last circle
|
// last circle
|
||||||
arrow.setRotation(curve.getEndAngle());
|
arrow.setRotation(curve.getEndAngle());
|
||||||
|
@ -271,7 +294,6 @@ public class Slider implements GameObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (timeDiff >= 0) {
|
if (timeDiff >= 0) {
|
||||||
// approach circle
|
// approach circle
|
||||||
|
@ -319,12 +341,11 @@ public class Slider implements GameObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws slider ticks.
|
* Draws slider ticks.
|
||||||
* @param g the graphics context
|
|
||||||
* @param trackPosition the track position
|
* @param trackPosition the track position
|
||||||
* @param curveAlpha the curve alpha level
|
* @param curveAlpha the curve alpha level
|
||||||
* @param decorationsAlpha the decorations alpha level
|
* @param decorationsAlpha the decorations alpha level
|
||||||
*/
|
*/
|
||||||
private void drawSliderTicks(Graphics g, int trackPosition, float curveAlpha, float decorationsAlpha) {
|
private void drawSliderTicks(int trackPosition, float curveAlpha, float decorationsAlpha) {
|
||||||
float tickScale = 0.5f + 0.5f * AnimationEquation.OUT_BACK.calc(decorationsAlpha);
|
float tickScale = 0.5f + 0.5f * AnimationEquation.OUT_BACK.calc(decorationsAlpha);
|
||||||
Image tick = GameImage.SLIDER_TICK.getImage().getScaledCopy(tickScale);
|
Image tick = GameImage.SLIDER_TICK.getImage().getScaledCopy(tickScale);
|
||||||
|
|
||||||
|
@ -344,14 +365,44 @@ public class Slider implements GameObject {
|
||||||
min = 0;
|
min = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculate the tick alpha level
|
||||||
|
float sliderTickAlpha;
|
||||||
|
if (currentRepeats == 0) {
|
||||||
|
sliderTickAlpha = decorationsAlpha;
|
||||||
|
} else {
|
||||||
|
float t = getT(trackPosition, false);
|
||||||
|
if (currentRepeats % 2 == 1) {
|
||||||
|
t = 1f - t;
|
||||||
|
}
|
||||||
|
sliderTickAlpha = Utils.clamp(t * ticksT.length * 2, 0f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
// draw ticks
|
// draw ticks
|
||||||
|
Colors.WHITE_FADE.a = Math.min(curveAlpha, sliderTickAlpha);
|
||||||
for (int i = min; i < max; i++) {
|
for (int i = min; i < max; i++) {
|
||||||
Vec2f c = curve.pointAt(ticksT[i]);
|
Vec2f c = curve.pointAt(ticksT[i]);
|
||||||
Colors.WHITE_FADE.a = Math.min(curveAlpha, decorationsAlpha);
|
|
||||||
tick.drawCentered(c.x, c.y, Colors.WHITE_FADE);
|
tick.drawCentered(c.x, c.y, Colors.WHITE_FADE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the alpha level used to fade in circles & reversearrows after repeat
|
||||||
|
* @param trackPosition current trackposition, in ms
|
||||||
|
* @param endCircle request alpha for end circle (true) or start circle (false)?
|
||||||
|
* @return alpha level as float in interval [0, 1]
|
||||||
|
*/
|
||||||
|
private float getCircleAlphaAfterRepeat(int trackPosition, boolean endCircle) {
|
||||||
|
int ticksN = ticksT == null ? 0 : ticksT.length;
|
||||||
|
float t = getT(trackPosition, false);
|
||||||
|
if (endCircle) {
|
||||||
|
t = 1f - t;
|
||||||
|
}
|
||||||
|
if (currentRepeats % 2 == (endCircle ? 0 : 1)) {
|
||||||
|
t = 1f;
|
||||||
|
}
|
||||||
|
return Utils.clamp(t * (ticksN + 1), 0f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the slider hit result.
|
* Calculates the slider hit result.
|
||||||
* @return the hit result (GameData.HIT_* constants)
|
* @return the hit result (GameData.HIT_* constants)
|
||||||
|
@ -430,7 +481,7 @@ public class Slider implements GameObject {
|
||||||
}
|
}
|
||||||
data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result,
|
data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result,
|
||||||
cx, cy, color, comboEnd, hitObject, type, sliderHeldToEnd,
|
cx, cy, color, comboEnd, hitObject, type, sliderHeldToEnd,
|
||||||
currentRepeats + 1, curve, sliderHeldToEnd);
|
currentRepeats + 1, null, sliderHeldToEnd);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -449,8 +500,11 @@ public class Slider implements GameObject {
|
||||||
if (timeDiff < hitResultOffset[GameData.HIT_50]) {
|
if (timeDiff < hitResultOffset[GameData.HIT_50]) {
|
||||||
result = GameData.HIT_SLIDER30;
|
result = GameData.HIT_SLIDER30;
|
||||||
ticksHit++;
|
ticksHit++;
|
||||||
} else if (timeDiff < hitResultOffset[GameData.HIT_MISS])
|
data.sendAnimationResult(trackPosition, this.x, this.y, color, true);
|
||||||
|
} else if (timeDiff < hitResultOffset[GameData.HIT_MISS]) {
|
||||||
result = GameData.HIT_MISS;
|
result = GameData.HIT_MISS;
|
||||||
|
data.sendAnimationResult(trackPosition, this.x, this.y, color, false);
|
||||||
|
}
|
||||||
//else not a hit
|
//else not a hit
|
||||||
|
|
||||||
if (result > -1) {
|
if (result > -1) {
|
||||||
|
@ -478,8 +532,11 @@ public class Slider implements GameObject {
|
||||||
if (isAutoMod) { // "auto" mod: catch any missed notes due to lag
|
if (isAutoMod) { // "auto" mod: catch any missed notes due to lag
|
||||||
ticksHit++;
|
ticksHit++;
|
||||||
data.sliderTickResult(time, GameData.HIT_SLIDER30, x, y, hitObject, currentRepeats);
|
data.sliderTickResult(time, GameData.HIT_SLIDER30, x, y, hitObject, currentRepeats);
|
||||||
} else
|
data.sendAnimationResult(time, x, y, color, true);
|
||||||
|
} else {
|
||||||
data.sliderTickResult(time, GameData.HIT_MISS, x, y, hitObject, currentRepeats);
|
data.sliderTickResult(time, GameData.HIT_MISS, x, y, hitObject, currentRepeats);
|
||||||
|
data.sendAnimationResult(trackPosition, x, y, color, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "auto" mod: send a perfect hit result
|
// "auto" mod: send a perfect hit result
|
||||||
|
@ -488,6 +545,7 @@ public class Slider implements GameObject {
|
||||||
ticksHit++;
|
ticksHit++;
|
||||||
sliderClickedInitial = true;
|
sliderClickedInitial = true;
|
||||||
data.sliderTickResult(time, GameData.HIT_SLIDER30, x, y, hitObject, currentRepeats);
|
data.sliderTickResult(time, GameData.HIT_SLIDER30, x, y, hitObject, currentRepeats);
|
||||||
|
data.sendAnimationResult(time, x, y, color, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,6 +577,9 @@ public class Slider implements GameObject {
|
||||||
|
|
||||||
// calculate and send slider result
|
// calculate and send slider result
|
||||||
hitResult();
|
hitResult();
|
||||||
|
|
||||||
|
// send 'curve fade out' hit result
|
||||||
|
data.sendSliderCurveResult(getEndTime(), color, curve);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,13 +626,26 @@ public class Slider implements GameObject {
|
||||||
// held during new repeat
|
// held during new repeat
|
||||||
if (isNewRepeat) {
|
if (isNewRepeat) {
|
||||||
ticksHit++;
|
ticksHit++;
|
||||||
|
|
||||||
|
HitObjectType type;
|
||||||
|
float posX, posY;
|
||||||
if (currentRepeats % 2 > 0) { // last circle
|
if (currentRepeats % 2 > 0) { // last circle
|
||||||
int lastIndex = hitObject.getSliderX().length;
|
type = HitObjectType.SLIDER_LAST;
|
||||||
|
Vec2f endPos = curve.pointAt(1f);
|
||||||
|
posX = endPos.x;
|
||||||
|
posY = endPos.y;
|
||||||
|
} else { // first circle
|
||||||
|
type = HitObjectType.SLIDER_FIRST;
|
||||||
|
posX = this.x;
|
||||||
|
posY = this.y;
|
||||||
|
}
|
||||||
data.sliderTickResult(trackPosition, GameData.HIT_SLIDER30,
|
data.sliderTickResult(trackPosition, GameData.HIT_SLIDER30,
|
||||||
curve.getX(lastIndex), curve.getY(lastIndex), hitObject, currentRepeats);
|
posX, posY, hitObject, currentRepeats);
|
||||||
} else // first circle
|
|
||||||
data.sliderTickResult(trackPosition, GameData.HIT_SLIDER30,
|
// send hit result, to fade out reversearrow
|
||||||
c.x, c.y, hitObject, currentRepeats);
|
float colorLuminance = 0.299f*color.r + 0.587f*color.g + 0.114f*color.b;
|
||||||
|
Color arrowColor = colorLuminance < 0.8f ? Color.white : Color.black;
|
||||||
|
data.sendRepeatSliderResult(trackPosition, posX, posY, arrowColor, curve, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// held during new tick
|
// held during new tick
|
||||||
|
|
Loading…
Reference in New Issue
Block a user