diff --git a/src/itdelatrisu/opsu/GameData.java b/src/itdelatrisu/opsu/GameData.java index 4bcf47dc..1e644ec0 100644 --- a/src/itdelatrisu/opsu/GameData.java +++ b/src/itdelatrisu/opsu/GameData.java @@ -24,6 +24,7 @@ import itdelatrisu.opsu.audio.SoundController; import itdelatrisu.opsu.audio.SoundEffect; import itdelatrisu.opsu.downloads.Updater; import itdelatrisu.opsu.objects.HitResultType; +import itdelatrisu.opsu.objects.curves.Curve; import itdelatrisu.opsu.replay.Replay; import itdelatrisu.opsu.replay.ReplayFrame; @@ -45,6 +46,9 @@ public class GameData { /** Delta multiplier for steady HP drain. */ public static final float HP_DRAIN_MULTIPLIER = 1 / 200f; + /** Time, in milliseconds, for a hit result to remain existent. */ + public static final int HITRESULT_TIME = 833; + /** Time, in milliseconds, for a hit result to fade. */ public static final int HITRESULT_FADE_TIME = 500; @@ -243,6 +247,9 @@ public class GameData { /** Alpha level (for fading out). */ public float alpha = 1f; + /** Slider curve. */ + public Curve curve; + /** * Constructor. * @param time the result's starting track position @@ -260,6 +267,25 @@ public class GameData { this.color = color; this.hitResultType = hitResultType; } + + /** + * Constructor. + * @param time the result's starting track position + * @param result the hit result (HIT_* constants) + * @param x the center x coordinate + * @param y the center y coordinate + * @param color the color of the hit object + * @param curve the slider curve + */ + public OsuHitObjectResult(int time, int result, float x, float y, Color color, HitResultType hitResultType, Curve curve) { + this.time = time; + this.result = result; + this.x = x; + this.y = y; + this.color = color; + this.hitResultType = hitResultType; + this.curve = curve; + } } /** Current game score. */ @@ -838,7 +864,7 @@ public class GameData { Iterator iter = hitResultList.iterator(); while (iter.hasNext()) { OsuHitObjectResult hitResult = iter.next(); - if (hitResult.time + HITRESULT_FADE_TIME > trackPosition) { + if (hitResult.time + HITRESULT_TIME > trackPosition) { // spinner if (hitResult.hitResultType == HitResultType.SPINNER && hitResult.result != HIT_MISS) { Image spinnerOsu = GameImage.SPINNER_OSU.getImage(); @@ -874,6 +900,17 @@ public class GameData { HITCIRCLE_FADE_TIME ); + if (hitResult.curve != null) { + float oldAlpha = Utils.COLOR_WHITE_FADE.a; + + Curve curve = hitResult.curve; + Utils.COLOR_WHITE_FADE.a = alpha; + curve.color.a = alpha; + curve.draw(); + + Utils.COLOR_WHITE_FADE.a = oldAlpha; + } + Image scaledHitCircle = GameImage.HITCIRCLE.getImage().getScaledCopy(scale); scaledHitCircle.setAlpha(alpha); Image scaledHitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(scale); @@ -1185,8 +1222,9 @@ public class GameData { * @param hitObject the hit object * @param repeat the current repeat number (for sliders, or 0 otherwise) * @param hitResultType the type of hit object for the result + * @return was this a perfect hit? */ - public void hitResult(int time, int result, float x, float y, Color color, + private boolean hitRes(int time, int result, float x, float y, Color color, boolean end, OsuHitObject hitObject, int repeat, HitResultType hitResultType) { int hitValue = 0; boolean perfectHit = false; @@ -1208,11 +1246,12 @@ public class GameData { case HIT_MISS: hitValue = 0; changeHealth(-10f); + changeHealth(-10f); comboEnd |= 2; resetComboStreak(); break; default: - return; + return false; } if (hitValue > 0) { SoundController.playHitSound( @@ -1253,6 +1292,25 @@ public class GameData { comboEnd = 0; } + return perfectHit; + } + + /** + * Handles a hit result. + * @param time the object start time + * @param result the hit result (HIT_* constants) + * @param x the x coordinate + * @param y the y coordinate + * @param color the combo color + * @param end true if this is the last hit object in the combo + * @param hitObject the hit object + * @param repeat the current repeat number (for sliders, or 0 otherwise) + * @param hitResultType the type of hit object for the result + */ + public void hitResult(int time, int result, float x, float y, Color color, + boolean end, OsuHitObject hitObject, int repeat, HitResultType hitResultType) { + boolean perfectHit = hitRes(time, result, x, y, color, end, hitObject, repeat, hitResultType); + if (perfectHit && !Options.isPerfectHitBurstEnabled()) ; // hide perfect hit results else if (result == HIT_MISS && (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive())) @@ -1261,6 +1319,31 @@ public class GameData { hitResultList.add(new OsuHitObjectResult(time, result, x, y, color, hitResultType)); } + /** + * Handles a slider hit result. + * @param time the object start time + * @param result the hit result (HIT_* constants) + * @param x the x coordinate + * @param y the y coordinate + * @param color the combo color + * @param end true if this is the last hit object in the combo + * @param hitObject the hit object + * @param repeat the current repeat number (for sliders, or 0 otherwise) + * @param hitResultType the type of hit object for the result + * @param curve the slider curve + */ + public void hitResult(int time, int result, float x, float y, Color color, + boolean end, OsuHitObject hitObject, int repeat, HitResultType hitResultType, Curve curve) { + boolean perfectHit = hitRes(time, result, x, y, color, end, hitObject, repeat, hitResultType); + + if (perfectHit && !Options.isPerfectHitBurstEnabled()) + ; // hide perfect hit results + else if (result == HIT_MISS && (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive())) + ; // "relax" and "autopilot" mods: hide misses + else + hitResultList.add(new OsuHitObjectResult(time, result, x, y, color, hitResultType, curve)); + } + /** * Returns a ScoreData object encapsulating all game data. * If score data already exists, the existing object will be returned diff --git a/src/itdelatrisu/opsu/objects/Slider.java b/src/itdelatrisu/opsu/objects/Slider.java index 0d470a08..2dbd40b3 100644 --- a/src/itdelatrisu/opsu/objects/Slider.java +++ b/src/itdelatrisu/opsu/objects/Slider.java @@ -281,7 +281,7 @@ public class Slider implements HitObject { float[] lastPos = curve.pointAt(1); data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result, x, y, color, comboEnd, hitObject, currentRepeats + 1, - currentRepeats % 2 == 0 ? HitResultType.SLIDEREND_FIRSTOBJECT : HitResultType.SLIDEREND); + currentRepeats % 2 == 0 ? HitResultType.SLIDEREND_FIRSTOBJECT : HitResultType.SLIDEREND, curve); data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result, lastPos[0], lastPos[1], color, comboEnd, hitObject, currentRepeats + 1, currentRepeats % 2 == 0 ? HitResultType.SLIDEREND : HitResultType.SLIDEREND_FIRSTOBJECT); diff --git a/src/itdelatrisu/opsu/objects/curves/Curve.java b/src/itdelatrisu/opsu/objects/curves/Curve.java index 028923be..c09de69f 100644 --- a/src/itdelatrisu/opsu/objects/curves/Curve.java +++ b/src/itdelatrisu/opsu/objects/curves/Curve.java @@ -28,12 +28,12 @@ import org.newdawn.slick.Color; * @author fluddokt (https://github.com/fluddokt) */ public abstract class Curve { + /** The color of this curve. */ + public Color color; + /** The associated OsuHitObject. */ protected OsuHitObject hitObject; - /** The color of this curve. */ - protected Color color; - /** The scaled starting x, y coordinates. */ protected float x, y;