Skip to content

Commit

Permalink
More accurate slider ticks and repeats.
Browse files Browse the repository at this point in the history
- Fixed an issue where some ticks were being counted twice.
- Try to catch skipped ticks and repeats from delta updates. This still isn't matching osu! combo counts for fast beatmaps, but is much closer than before.

Signed-off-by: Jeffrey Han <[email protected]>
  • Loading branch information
itdelatrisu committed Jan 6, 2017
1 parent b61eaf1 commit ceb4e5d
Showing 1 changed file with 56 additions and 44 deletions.
100 changes: 56 additions & 44 deletions src/itdelatrisu/opsu/objects/Slider.java
Original file line number Diff line number Diff line change
Expand Up @@ -556,64 +556,42 @@ else if (GameMod.RELAX.isActive() && trackPosition >= time)
mousePressed(mouseX, mouseY, trackPosition);
}

// end of slider
if (trackPosition > hitObject.getTime() + sliderTimeTotal) {
tickIntervals++;
tickExpandTime = TICK_EXPAND_TIME;

// check if cursor pressed and within end circle
if (keyPressed || GameMod.RELAX.isActive()) {
Vec2f c = curve.pointAt(getT(trackPosition, false));
double distance = Math.hypot(c.x - mouseX, c.y - mouseY);
if (distance < followRadius)
sliderHeldToEnd = true;
}

// final circle hit
if (sliderHeldToEnd)
ticksHit++;

// "auto" mod: always send a perfect hit result
if (isAutoMod)
ticksHit = tickIntervals;

// calculate and send slider result
hitResult();

return true;
}

// update tick expand time
if (tickExpandTime > 0) {
tickExpandTime -= delta;
if (tickExpandTime < 0)
tickExpandTime = 0;
}

// TODO: Some ticks/repeats get missed if delta updates skip past them.
// The code tries to catch this, but doesn't completely work...

// repeats
boolean isNewRepeat = false;
if (repeatCount - 1 > currentRepeats) {
int newRepeats = 0;
while (repeatCount - 1 > currentRepeats) {
float t = getT(trackPosition, true);
if (Math.floor(t) > currentRepeats) {
currentRepeats++;
tickIndex = 0;
isNewRepeat = true;
newRepeats++;
tickExpandTime = TICK_EXPAND_TIME;
}
} else
break;
}

// ticks
boolean isNewTick = false;
if (ticksT != null &&
tickIntervals < (ticksT.length * (currentRepeats + 1)) + repeatCount &&
tickIntervals < (ticksT.length * repeatCount) + repeatCount) {
int newTicks = 0;
while (ticksT != null &&
tickIntervals < (ticksT.length * (currentRepeats + 1)) + 1 &&
tickIntervals < (ticksT.length * repeatCount) + repeatCount) {
float t = getT(trackPosition, true);
if (t - Math.floor(t) >= ticksT[tickIndex]) {
if (t - Math.floor(t) >= ticksT[tickIndex] || tickIntervals < (ticksT.length * currentRepeats) + 1) {
tickIntervals++;
tickIndex = (tickIndex + 1) % ticksT.length;
isNewTick = true;
newTicks++;
tickExpandTime = TICK_EXPAND_TIME;
}
} else
break;
}

// holding slider...
Expand All @@ -624,12 +602,13 @@ else if (GameMod.RELAX.isActive() && trackPosition >= time)
followCircleActive = true;

// held during new repeat
if (isNewRepeat) {
int newRepeatCount = 0;
while (newRepeats-- > 0) {
ticksHit++;

HitObjectType type;
float posX, posY;
if (currentRepeats % 2 > 0) {
if ((currentRepeats + newRepeatCount) % 2 > 0) {
// last circle
type = HitObjectType.SLIDER_LAST;
Vec2f endPos = curve.pointAt(1f);
Expand All @@ -648,13 +627,19 @@ else if (GameMod.RELAX.isActive() && trackPosition >= time)
float colorLuminance = Utils.getLuminance(color);
Color arrowColor = colorLuminance < 0.8f ? Color.white : Color.black;
data.sendSliderRepeatResult(trackPosition, posX, posY, arrowColor, curve, type);

newRepeatCount++;
}

// held during new tick
if (isNewTick) {
int tickIdx = tickIndex;
while (newTicks-- > 0) {
ticksHit++;

tickIdx = (tickIdx + (ticksT.length - 1)) % ticksT.length;
Vec2f tickPos = curve.pointAt(ticksT[tickIdx]);
data.sendSliderTickResult(trackPosition, GameData.HIT_SLIDER10,
c.x, c.y, hitObject, currentRepeats);
tickPos.x, tickPos.y, hitObject, currentRepeats);
}

// held near end of slider
Expand All @@ -663,12 +648,39 @@ else if (GameMod.RELAX.isActive() && trackPosition >= time)
} else {
followCircleActive = false;

if (isNewRepeat)
while (newRepeats-- > 0)
data.sendSliderTickResult(trackPosition, GameData.HIT_MISS, 0, 0, hitObject, currentRepeats);
if (isNewTick)
while (newTicks-- > 0)
data.sendSliderTickResult(trackPosition, GameData.HIT_MISS, 0, 0, hitObject, currentRepeats);
}

// end of slider
if (trackPosition > hitObject.getTime() + sliderTimeTotal) {
tickIntervals++;
tickExpandTime = TICK_EXPAND_TIME;

// check if cursor pressed and within end circle
if (keyPressed || GameMod.RELAX.isActive()) {
Vec2f pos = curve.pointAt(getT(trackPosition, false));
double dist = Math.hypot(pos.x - mouseX, pos.y - mouseY);
if (dist < followRadius)
sliderHeldToEnd = true;
}

// final circle hit
if (sliderHeldToEnd)
ticksHit++;

// "auto" mod: always send a perfect hit result
if (isAutoMod)
ticksHit = tickIntervals;

// calculate and send slider result
hitResult();

return true;
}

return false;
}

Expand Down

0 comments on commit ceb4e5d

Please sign in to comment.