Follow-up to #71.

- Fixed a major bug where two hit result calculations were being performed for each slider.
- Fixed a bug where hit circles/sliders were being drawn for a miss.
- Sliders now only expand when held to the end (as in osu!).
- Use the track position as the hit result start time for circles (instead of the object time).
- Added a 'color' parameter to Curve.draw(), rather than keeping an extra reference to the slider Color object.
- Renamed HitResultType enum to HitObjectType, and moved it into GameData.
- Removed some overloaded methods (not really necessary...).
- Other style changes.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2015-04-08 02:05:12 -04:00
parent dda9081149
commit 4eaf0b6a54
9 changed files with 88 additions and 128 deletions

View File

@ -23,7 +23,6 @@ import itdelatrisu.opsu.audio.MusicController;
import itdelatrisu.opsu.audio.SoundController; import itdelatrisu.opsu.audio.SoundController;
import itdelatrisu.opsu.audio.SoundEffect; import itdelatrisu.opsu.audio.SoundEffect;
import itdelatrisu.opsu.downloads.Updater; import itdelatrisu.opsu.downloads.Updater;
import itdelatrisu.opsu.objects.HitResultType;
import itdelatrisu.opsu.objects.curves.Curve; import itdelatrisu.opsu.objects.curves.Curve;
import itdelatrisu.opsu.replay.Replay; import itdelatrisu.opsu.replay.Replay;
import itdelatrisu.opsu.replay.ReplayFrame; import itdelatrisu.opsu.replay.ReplayFrame;
@ -225,9 +224,10 @@ public class GameData {
/** List containing recent hit error information. */ /** List containing recent hit error information. */
private LinkedBlockingDeque<HitErrorInfo> hitErrorList; private LinkedBlockingDeque<HitErrorInfo> hitErrorList;
/** /** Hit object types, used for drawing results. */
* Hit result helper class. public enum HitObjectType { CIRCLE, SLIDERTICK, SLIDER_FIRST, SLIDER_LAST, SPINNER }
*/
/** Hit result helper class. */
private class OsuHitObjectResult { private class OsuHitObjectResult {
/** Object start time. */ /** Object start time. */
public int time; public int time;
@ -242,7 +242,7 @@ public class GameData {
public Color color; public Color color;
/** The type of the hit object. */ /** The type of the hit object. */
public HitResultType hitResultType; public HitObjectType hitResultType;
/** Alpha level (for fading out). */ /** Alpha level (for fading out). */
public float alpha = 1f; public float alpha = 1f;
@ -250,23 +250,8 @@ public class GameData {
/** Slider curve. */ /** Slider curve. */
public Curve curve; public Curve curve;
/** /** Whether or not to expand when animating. */
* Constructor. public boolean expand;
* @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 hitResultType the type of the hit object
*/
public OsuHitObjectResult(int time, int result, float x, float y, Color color, HitResultType hitResultType) {
this.time = time;
this.result = result;
this.x = x;
this.y = y;
this.color = color;
this.hitResultType = hitResultType;
}
/** /**
* Constructor. * Constructor.
@ -275,9 +260,11 @@ public class GameData {
* @param x the center x coordinate * @param x the center x coordinate
* @param y the center y coordinate * @param y the center y coordinate
* @param color the color of the hit object * @param color the color of the hit object
* @param curve the slider curve * @param curve the slider curve (or null if not applicable)
* @param expand whether or not the hit result animation should expand (if applicable)
*/ */
public OsuHitObjectResult(int time, int result, float x, float y, Color color, HitResultType hitResultType, Curve curve) { public OsuHitObjectResult(int time, int result, float x, float y, Color color,
HitObjectType hitResultType, Curve curve, boolean expand) {
this.time = time; this.time = time;
this.result = result; this.result = result;
this.x = x; this.x = x;
@ -285,6 +272,7 @@ public class GameData {
this.color = color; this.color = color;
this.hitResultType = hitResultType; this.hitResultType = hitResultType;
this.curve = curve; this.curve = curve;
this.expand = expand;
} }
} }
@ -866,7 +854,7 @@ public class GameData {
OsuHitObjectResult hitResult = iter.next(); OsuHitObjectResult hitResult = iter.next();
if (hitResult.time + HITRESULT_TIME > trackPosition) { if (hitResult.time + HITRESULT_TIME > trackPosition) {
// spinner // spinner
if (hitResult.hitResultType == HitResultType.SPINNER && hitResult.result != HIT_MISS) { if (hitResult.hitResultType == HitObjectType.SPINNER && hitResult.result != HIT_MISS) {
Image spinnerOsu = GameImage.SPINNER_OSU.getImage(); Image spinnerOsu = GameImage.SPINNER_OSU.getImage();
spinnerOsu.setAlpha(hitResult.alpha); spinnerOsu.setAlpha(hitResult.alpha);
spinnerOsu.drawCentered(width / 2, height / 4); spinnerOsu.drawCentered(width / 2, height / 4);
@ -876,68 +864,58 @@ public class GameData {
// hit lighting // hit lighting
else if (Options.isHitLightingEnabled() && hitResult.result != HIT_MISS && else if (Options.isHitLightingEnabled() && hitResult.result != HIT_MISS &&
hitResult.result != HIT_SLIDER30 && hitResult.result != HIT_SLIDER10) { hitResult.result != HIT_SLIDER30 && hitResult.result != HIT_SLIDER10) {
// soon add particle system to reflect original game // TODO: add particle system
Image lighting = GameImage.LIGHTING.getImage(); Image lighting = GameImage.LIGHTING.getImage();
lighting.setAlpha(hitResult.alpha); lighting.setAlpha(hitResult.alpha);
lighting.drawCentered(hitResult.x, hitResult.y, hitResult.color); lighting.drawCentered(hitResult.x, hitResult.y, hitResult.color);
} }
// hit animation // hit animation
if (hitResult.hitResultType == HitResultType.CIRCLE if (hitResult.result != HIT_MISS && (
|| hitResult.hitResultType == HitResultType.SLIDEREND hitResult.hitResultType == HitObjectType.CIRCLE ||
|| hitResult.hitResultType == HitResultType.SLIDEREND_FIRSTOBJECT) { hitResult.hitResultType == HitObjectType.SLIDER_FIRST ||
float scale = Utils.easeOut( hitResult.hitResultType == HitObjectType.SLIDER_LAST)) {
float scale = (!hitResult.expand) ? 1f : Utils.easeOut(
Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_FADE_TIME), Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_FADE_TIME),
1f, 1f, HITCIRCLE_ANIM_SCALE - 1f, HITCIRCLE_FADE_TIME
HITCIRCLE_ANIM_SCALE-1f,
HITCIRCLE_FADE_TIME
); );
float alpha = Utils.easeOut( float alpha = Utils.easeOut(
Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_FADE_TIME), Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_FADE_TIME),
1f, 1f, -1f, HITCIRCLE_FADE_TIME
-1f,
HITCIRCLE_FADE_TIME
); );
// slider curve
if (hitResult.curve != null) { if (hitResult.curve != null) {
float oldAlpha = Utils.COLOR_WHITE_FADE.a; float oldWhiteAlpha = Utils.COLOR_WHITE_FADE.a;
float oldColorAlpha = hitResult.color.a;
Curve curve = hitResult.curve;
Utils.COLOR_WHITE_FADE.a = alpha; Utils.COLOR_WHITE_FADE.a = alpha;
curve.color.a = alpha; hitResult.color.a = alpha;
curve.draw(); hitResult.curve.draw(hitResult.color);
Utils.COLOR_WHITE_FADE.a = oldWhiteAlpha;
Utils.COLOR_WHITE_FADE.a = oldAlpha; hitResult.color.a = oldColorAlpha;
} }
// hit circles
Image scaledHitCircle = GameImage.HITCIRCLE.getImage().getScaledCopy(scale); Image scaledHitCircle = GameImage.HITCIRCLE.getImage().getScaledCopy(scale);
scaledHitCircle.setAlpha(alpha);
Image scaledHitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(scale); Image scaledHitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(scale);
scaledHitCircle.setAlpha(alpha);
scaledHitCircleOverlay.setAlpha(alpha); scaledHitCircleOverlay.setAlpha(alpha);
scaledHitCircle.drawCentered(hitResult.x, hitResult.y, hitResult.color); scaledHitCircle.drawCentered(hitResult.x, hitResult.y, hitResult.color);
scaledHitCircleOverlay.drawCentered(hitResult.x, hitResult.y); scaledHitCircleOverlay.drawCentered(hitResult.x, hitResult.y);
} }
// hit result // hit result
if (hitResult.hitResultType == HitResultType.CIRCLE if (hitResult.hitResultType == HitObjectType.CIRCLE ||
|| hitResult.hitResultType == HitResultType.SLIDEREND hitResult.hitResultType == HitObjectType.SPINNER ||
|| hitResult.hitResultType == HitResultType.SPINNER) { hitResult.curve != null) {
float scale = Utils.easeBounce( float scale = Utils.easeBounce(
Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_TEXT_BOUNCE_TIME), Utils.clamp(trackPosition - hitResult.time, 0, HITCIRCLE_TEXT_BOUNCE_TIME),
1f, 1f, HITCIRCLE_TEXT_ANIM_SCALE - 1f, HITCIRCLE_TEXT_BOUNCE_TIME
HITCIRCLE_TEXT_ANIM_SCALE - 1f,
HITCIRCLE_TEXT_BOUNCE_TIME
); );
float alpha = Utils.easeOut( float alpha = Utils.easeOut(
Utils.clamp((trackPosition - hitResult.time) - HITCIRCLE_FADE_TIME, 0, HITCIRCLE_TEXT_FADE_TIME), Utils.clamp((trackPosition - hitResult.time) - HITCIRCLE_FADE_TIME, 0, HITCIRCLE_TEXT_FADE_TIME),
1f, 1f, -1f, HITCIRCLE_TEXT_FADE_TIME
-1f,
HITCIRCLE_TEXT_FADE_TIME
); );
Image scaledHitResult = hitResults[hitResult.result].getScaledCopy(scale); Image scaledHitResult = hitResults[hitResult.result].getScaledCopy(scale);
scaledHitResult.setAlpha(alpha); scaledHitResult.setAlpha(alpha);
scaledHitResult.drawCentered(hitResult.x, hitResult.y); scaledHitResult.drawCentered(hitResult.x, hitResult.y);
@ -1207,14 +1185,14 @@ public class GameData {
if (!Options.isPerfectHitBurstEnabled()) if (!Options.isPerfectHitBurstEnabled())
; // hide perfect hit results ; // hide perfect hit results
else else
hitResultList.add(new OsuHitObjectResult(time, result, x, y, null, HitResultType.SLIDERTICK)); hitResultList.add(new OsuHitObjectResult(time, result, x, y, null, HitObjectType.SLIDERTICK, null, false));
} }
} }
/** /**
* Handles a hit result. * Handles a hit result and performs all associated calculations.
* @param time the object start time * @param time the object start time
* @param result the hit result (HIT_* constants) * @param result the base hit result (HIT_* constants)
* @param x the x coordinate * @param x the x coordinate
* @param y the y coordinate * @param y the y coordinate
* @param color the combo color * @param color the combo color
@ -1222,10 +1200,10 @@ public class GameData {
* @param hitObject the hit object * @param hitObject the hit object
* @param repeat the current repeat number (for sliders, or 0 otherwise) * @param repeat the current repeat number (for sliders, or 0 otherwise)
* @param hitResultType the type of hit object for the result * @param hitResultType the type of hit object for the result
* @return the hit result (HIT_* constants) * @return the actual hit result (HIT_* constants)
*/ */
private int hitRes(int time, int result, float x, float y, Color color, private int handleHitResult(int time, int result, float x, float y, Color color,
boolean end, OsuHitObject hitObject, int repeat, HitResultType hitResultType) { boolean end, OsuHitObject hitObject, int repeat, HitObjectType hitResultType) {
int hitValue = 0; int hitValue = 0;
switch (result) { switch (result) {
case HIT_300: case HIT_300:
@ -1292,31 +1270,6 @@ public class GameData {
return result; return result;
} }
/**
* 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) {
result = hitRes(time, result, x, y, color, end, hitObject, repeat, hitResultType);
if ((result == HIT_300 || result == HIT_300G || result == HIT_300K)
&& !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));
}
/** /**
* Handles a slider hit result. * Handles a slider hit result.
* @param time the object start time * @param time the object start time
@ -1328,19 +1281,29 @@ public class GameData {
* @param hitObject the hit object * @param hitObject the hit object
* @param repeat the current repeat number (for sliders, or 0 otherwise) * @param repeat the current repeat number (for sliders, or 0 otherwise)
* @param hitResultType the type of hit object for the result * @param hitResultType the type of hit object for the result
* @param curve the slider curve * @param curve the slider curve (or null if not applicable)
* @param expand whether or not the hit result animation should expand (if applicable)
*/ */
public void hitResult(int time, int result, float x, float y, Color color, public void hitResult(int time, int result, float x, float y, Color color,
boolean end, OsuHitObject hitObject, int repeat, HitResultType hitResultType, Curve curve) { boolean end, OsuHitObject hitObject, int repeat,
result = hitRes(time, result, x, y, color, end, hitObject, repeat, hitResultType); HitObjectType hitResultType, Curve curve, boolean expand) {
result = handleHitResult(time, result, x, y, color, end, hitObject, repeat, hitResultType);
if ((result == HIT_300 || result == HIT_300G || result == HIT_300K) if ((result == HIT_300 || result == HIT_300G || result == HIT_300K) && !Options.isPerfectHitBurstEnabled())
&& !Options.isPerfectHitBurstEnabled())
; // hide perfect hit results ; // hide perfect hit results
else if (result == HIT_MISS && (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive())) else if (result == HIT_MISS && (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive()))
; // "relax" and "autopilot" mods: hide misses ; // "relax" and "autopilot" mods: hide misses
else else {
hitResultList.add(new OsuHitObjectResult(time, result, x, y, color, hitResultType, curve)); hitResultList.add(new OsuHitObjectResult(time, result, x, y, color, hitResultType, curve, expand));
// sliders: add the other curve endpoint for the hit animation
if (curve != null) {
boolean isFirst = (hitResultType == HitObjectType.SLIDER_FIRST);
float[] p = curve.pointAt((isFirst) ? 1f : 0f);
HitObjectType type = (isFirst) ? HitObjectType.SLIDER_LAST : HitObjectType.SLIDER_FIRST;
hitResultList.add(new OsuHitObjectResult(time, result, p[0], p[1], color, type, null, expand));
}
}
} }
/** /**

View File

@ -609,7 +609,7 @@ public class Utils {
} }
/** /**
* Cubic ease out function * Cubic ease out function.
* @param t the current time * @param t the current time
* @param a the starting position * @param a the starting position
* @param b the finishing position * @param b the finishing position
@ -621,7 +621,7 @@ public class Utils {
} }
/** /**
* Fake bounce ease function * Fake bounce ease function.
* @param t the current time * @param t the current time
* @param a the starting position * @param a the starting position
* @param b the finishing position * @param b the finishing position
@ -631,6 +631,6 @@ public class Utils {
public static float easeBounce(float t, float a, float b, float d) { public static float easeBounce(float t, float a, float b, float d) {
if (t < d / 2) if (t < d / 2)
return easeOut(t, a, b, d); return easeOut(t, a, b, d);
return easeOut(d-t, a, b, d); return easeOut(d - t, a, b, d);
} }
} }

View File

@ -19,6 +19,7 @@
package itdelatrisu.opsu.objects; package itdelatrisu.opsu.objects;
import itdelatrisu.opsu.GameData; import itdelatrisu.opsu.GameData;
import itdelatrisu.opsu.GameData.HitObjectType;
import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.GameImage;
import itdelatrisu.opsu.GameMod; import itdelatrisu.opsu.GameMod;
import itdelatrisu.opsu.OsuHitObject; import itdelatrisu.opsu.OsuHitObject;
@ -138,7 +139,7 @@ public class Circle implements HitObject {
if (result > -1) { if (result > -1) {
data.addHitError(hitObject.getTime(), x, y, timeDiff); data.addHitError(hitObject.getTime(), x, y, timeDiff);
data.hitResult(hitObject.getTime(), result, this.x, this.y, color, comboEnd, hitObject, 0, HitResultType.CIRCLE); data.hitResult(trackPosition, result, this.x, this.y, color, comboEnd, hitObject, 0, HitObjectType.CIRCLE, null, true);
return true; return true;
} }
} }
@ -154,17 +155,17 @@ public class Circle implements HitObject {
if (overlap || trackPosition > time + hitResultOffset[GameData.HIT_50]) { if (overlap || trackPosition > time + hitResultOffset[GameData.HIT_50]) {
if (isAutoMod) // "auto" mod: catch any missed notes due to lag if (isAutoMod) // "auto" mod: catch any missed notes due to lag
data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitObject, 0, HitResultType.CIRCLE); data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitObject, 0, HitObjectType.CIRCLE, null, true);
else // no more points can be scored, so send a miss else // no more points can be scored, so send a miss
data.hitResult(time, GameData.HIT_MISS, x, y, null, comboEnd, hitObject, 0, HitResultType.CIRCLE); data.hitResult(trackPosition, GameData.HIT_MISS, x, y, null, comboEnd, hitObject, 0, HitObjectType.CIRCLE, null, true);
return true; return true;
} }
// "auto" mod: send a perfect hit result // "auto" mod: send a perfect hit result
else if (isAutoMod) { else if (isAutoMod) {
if (Math.abs(trackPosition - time) < hitResultOffset[GameData.HIT_300]) { if (Math.abs(trackPosition - time) < hitResultOffset[GameData.HIT_300]) {
data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitObject, 0, HitResultType.CIRCLE); data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitObject, 0, HitObjectType.CIRCLE, null, true);
return true; return true;
} }
} }

View File

@ -1,10 +0,0 @@
package itdelatrisu.opsu.objects;
public enum HitResultType {
CIRCLE,
//SLIDERSTART,
SLIDERTICK,
SLIDEREND,
SLIDEREND_FIRSTOBJECT,
SPINNER
}

View File

@ -19,6 +19,7 @@
package itdelatrisu.opsu.objects; package itdelatrisu.opsu.objects;
import itdelatrisu.opsu.GameData; import itdelatrisu.opsu.GameData;
import itdelatrisu.opsu.GameData.HitObjectType;
import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.GameImage;
import itdelatrisu.opsu.GameMod; import itdelatrisu.opsu.GameMod;
import itdelatrisu.opsu.OsuFile; import itdelatrisu.opsu.OsuFile;
@ -172,7 +173,7 @@ public class Slider implements HitObject {
Utils.COLOR_WHITE_FADE.a = color.a = alpha; Utils.COLOR_WHITE_FADE.a = color.a = alpha;
// curve // curve
curve.draw(); curve.draw(color);
// ticks // ticks
if (ticksT != null) { if (ticksT != null) {
@ -278,13 +279,20 @@ public class Slider implements HitObject {
else else
result = GameData.HIT_MISS; result = GameData.HIT_MISS;
float cx, cy;
HitObjectType type;
if (currentRepeats % 2 == 0) { // last circle
float[] lastPos = curve.pointAt(1); float[] lastPos = curve.pointAt(1);
cx = lastPos[0];
cy = lastPos[1];
type = HitObjectType.SLIDER_LAST;
} else { // first circle
cx = x;
cy = y;
type = HitObjectType.SLIDER_FIRST;
}
data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result, data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result,
x, y, color, comboEnd, hitObject, currentRepeats + 1, cx, cy, color, comboEnd, hitObject, currentRepeats + 1, type, curve, sliderClickedFinal);
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);
return result; return result;
} }

View File

@ -19,6 +19,7 @@
package itdelatrisu.opsu.objects; package itdelatrisu.opsu.objects;
import itdelatrisu.opsu.GameData; import itdelatrisu.opsu.GameData;
import itdelatrisu.opsu.GameData.HitObjectType;
import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.GameImage;
import itdelatrisu.opsu.GameMod; import itdelatrisu.opsu.GameMod;
import itdelatrisu.opsu.OsuHitObject; import itdelatrisu.opsu.OsuHitObject;
@ -191,7 +192,7 @@ public class Spinner implements HitObject {
result = GameData.HIT_MISS; result = GameData.HIT_MISS;
data.hitResult(hitObject.getEndTime(), result, width / 2, height / 2, data.hitResult(hitObject.getEndTime(), result, width / 2, height / 2,
Color.transparent, true, hitObject, 0, HitResultType.SPINNER); Color.transparent, true, hitObject, 0, HitObjectType.SPINNER, null, true);
return result; return result;
} }

View File

@ -179,7 +179,7 @@ public class CircumscribedCircle extends Curve {
} }
@Override @Override
public void draw() { public void draw(Color color) {
Image hitCircle = GameImage.HITCIRCLE.getImage(); Image hitCircle = GameImage.HITCIRCLE.getImage();
Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage(); Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage();
for (int i = 0; i < step; i++) for (int i = 0; i < step; i++)

View File

@ -28,9 +28,6 @@ import org.newdawn.slick.Color;
* @author fluddokt (https://github.com/fluddokt) * @author fluddokt (https://github.com/fluddokt)
*/ */
public abstract class Curve { public abstract class Curve {
/** The color of this curve. */
public Color color;
/** The associated OsuHitObject. */ /** The associated OsuHitObject. */
protected OsuHitObject hitObject; protected OsuHitObject hitObject;
@ -51,7 +48,6 @@ public abstract class Curve {
this.y = hitObject.getScaledY(); this.y = hitObject.getScaledY();
this.sliderX = hitObject.getScaledSliderX(); this.sliderX = hitObject.getScaledSliderX();
this.sliderY = hitObject.getScaledSliderY(); this.sliderY = hitObject.getScaledSliderY();
this.color = color;
} }
/** /**
@ -63,8 +59,9 @@ public abstract class Curve {
/** /**
* Draws the full curve to the graphics context. * Draws the full curve to the graphics context.
* @param color the color filter
*/ */
public abstract void draw(); public abstract void draw(Color color);
/** /**
* Returns the angle of the first control point. * Returns the angle of the first control point.

View File

@ -164,7 +164,7 @@ public class LinearBezier extends Curve {
} }
@Override @Override
public void draw() { public void draw(Color color) {
Image hitCircle = GameImage.HITCIRCLE.getImage(); Image hitCircle = GameImage.HITCIRCLE.getImage();
Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage(); Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage();
for (int i = curve.length - 2; i >= 0; i--) for (int i = curve.length - 2; i >= 0; i--)