/** * Initializes the Slider data type with images and dimensions. * * @param container the game container * @param circleSize the map's circleSize value * @param beatmap the associated beatmap */ public static void init(GameContainer container, float circleSize, Beatmap beatmap) { containerWidth = container.getWidth(); containerHeight = container.getHeight(); diameter = (104 - (circleSize * 8)); diameter = (diameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480) int diameterInt = (int) diameter; followRadius = diameter / 2 * 3f; // slider ball if (GameImage.SLIDER_BALL.hasSkinImages() || (!GameImage.SLIDER_BALL.hasSkinImage() && GameImage.SLIDER_BALL.getImages() != null)) sliderBallImages = GameImage.SLIDER_BALL.getImages(); else sliderBallImages = new Image[] {GameImage.SLIDER_BALL.getImage()}; for (int i = 0; i < sliderBallImages.length; i++) sliderBallImages[i] = sliderBallImages[i].getScaledCopy(diameterInt * 118 / 128, diameterInt * 118 / 128); GameImage.SLIDER_FOLLOWCIRCLE.setImage( GameImage.SLIDER_FOLLOWCIRCLE .getImage() .getScaledCopy(diameterInt * 259 / 128, diameterInt * 259 / 128)); GameImage.REVERSEARROW.setImage( GameImage.REVERSEARROW.getImage().getScaledCopy(diameterInt, diameterInt)); GameImage.SLIDER_TICK.setImage( GameImage.SLIDER_TICK.getImage().getScaledCopy(diameterInt / 4, diameterInt / 4)); sliderMultiplier = beatmap.sliderMultiplier; sliderTickRate = beatmap.sliderTickRate; }
@Override public void draw(Graphics g, int trackPosition) { int timeDiff = hitObject.getTime() - trackPosition; float scale = timeDiff / (float) game.getApproachTime(); float fadeinScale = (timeDiff - game.getApproachTime() + FADE_IN_TIME) / (float) FADE_IN_TIME; float approachScale = 1 + scale * 3; float alpha = Utils.clamp(1 - fadeinScale, 0, 1); boolean overlayAboveNumber = Options.getSkin().isHitCircleOverlayAboveNumber(); float oldAlpha = Utils.COLOR_WHITE_FADE.a; Utils.COLOR_WHITE_FADE.a = color.a = alpha; Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage(); Image hitCircle = GameImage.HITCIRCLE.getImage(); float[] endPos = curve.pointAt(1); curve.draw(color); color.a = alpha; // end circle hitCircle.drawCentered(endPos[0], endPos[1], color); hitCircleOverlay.drawCentered(endPos[0], endPos[1], Utils.COLOR_WHITE_FADE); // start circle hitCircle.drawCentered(x, y, color); if (!overlayAboveNumber) hitCircleOverlay.drawCentered(x, y, Utils.COLOR_WHITE_FADE); // ticks if (ticksT != null) { Image tick = GameImage.SLIDER_TICK.getImage(); for (int i = 0; i < ticksT.length; i++) { float[] c = curve.pointAt(ticksT[i]); tick.drawCentered(c[0], c[1], Utils.COLOR_WHITE_FADE); } } if (sliderClickedInitial) ; // don't draw current combo number if already clicked else data.drawSymbolNumber( hitObject.getComboNumber(), x, y, hitCircle.getWidth() * 0.40f / data.getDefaultSymbolImage(0).getHeight(), alpha); if (overlayAboveNumber) hitCircleOverlay.drawCentered(x, y, Utils.COLOR_WHITE_FADE); // repeats for (int tcurRepeat = currentRepeats; tcurRepeat <= currentRepeats + 1; tcurRepeat++) { if (hitObject.getRepeatCount() - 1 > tcurRepeat) { Image arrow = GameImage.REVERSEARROW.getImage(); if (tcurRepeat != currentRepeats) { if (sliderTime == 0) continue; float t = Math.max(getT(trackPosition, true), 0); arrow.setAlpha((float) (t - Math.floor(t))); } else arrow.setAlpha(1f); if (tcurRepeat % 2 == 0) { // last circle arrow.setRotation(curve.getEndAngle()); arrow.drawCentered(endPos[0], endPos[1]); } else { // first circle arrow.setRotation(curve.getStartAngle()); arrow.drawCentered(x, y); } } } if (timeDiff >= 0) { // approach circle GameImage.APPROACHCIRCLE.getImage().getScaledCopy(approachScale).drawCentered(x, y, color); } else { // Since update() might not have run before drawing during a replay, the // slider time may not have been calculated, which causes NAN numbers and flicker. if (sliderTime == 0) return; float[] c = curve.pointAt(getT(trackPosition, false)); float[] c2 = curve.pointAt(getT(trackPosition, false) + 0.01f); float t = getT(trackPosition, false); // float dis = hitObject.getPixelLength() * HitObject.getXMultiplier() * (t - (int) t); // Image sliderBallFrame = sliderBallImages[(int) (dis / (diameter * Math.PI) * 30) % // sliderBallImages.length]; Image sliderBallFrame = sliderBallImages[(int) (t * sliderTime * 60 / 1000) % sliderBallImages.length]; float angle = (float) (Math.atan2(c2[1] - c[1], c2[0] - c[0]) * 180 / Math.PI); sliderBallFrame.setRotation(angle); sliderBallFrame.drawCentered(c[0], c[1]); // follow circle if (followCircleActive) { GameImage.SLIDER_FOLLOWCIRCLE.getImage().drawCentered(c[0], c[1]); // "flashlight" mod: dim the screen if (GameMod.FLASHLIGHT.isActive()) { float oldAlphaBlack = Utils.COLOR_BLACK_ALPHA.a; Utils.COLOR_BLACK_ALPHA.a = 0.75f; g.setColor(Utils.COLOR_BLACK_ALPHA); g.fillRect(0, 0, containerWidth, containerHeight); Utils.COLOR_BLACK_ALPHA.a = oldAlphaBlack; } } } Utils.COLOR_WHITE_FADE.a = oldAlpha; }