diff --git a/src/itdelatrisu/opsu/OptionGroups.java b/src/itdelatrisu/opsu/OptionGroups.java index 33b328e3..8b3942a0 100644 --- a/src/itdelatrisu/opsu/OptionGroups.java +++ b/src/itdelatrisu/opsu/OptionGroups.java @@ -52,6 +52,10 @@ public class OptionGroups { //GameOption.MERGING_SLIDERS_MIRROR_POOL, GameOption.DRAW_SLIDER_ENDCIRCLES, }), + new OptionTab("DANCING HITCIRCLES", new GameOption[] { + GameOption.DANCING_CIRCLES, + GameOption.DANCING_CIRCLES_MULTIPLIER, + }), new OptionTab("SKIN", null), new OptionTab("SKIN", new GameOption[]{ GameOption.SKIN, diff --git a/src/itdelatrisu/opsu/Options.java b/src/itdelatrisu/opsu/Options.java index ba8e4b08..ec48a37b 100644 --- a/src/itdelatrisu/opsu/Options.java +++ b/src/itdelatrisu/opsu/Options.java @@ -582,6 +582,13 @@ public class Options { } }, DRAW_SLIDER_ENDCIRCLES ("Draw endcircles", "DrawSliderEndCircles", "Old slider style", false), + DANCING_CIRCLES ("Enable", "DancingHitcircles", "Make hitcircles dance to the beat", false), + DANCING_CIRCLES_MULTIPLIER ("Multiplier", "DancingHitcirclesMP", "Multiplier to expand the hitcircles when dancing to the beat", 50, 1, 200) { + @Override + public String getValueString() { + return String.format("%.1f%%", val / 10f); + } + }, SHOW_HIT_LIGHTING ("Show Hit Lighting", "HitLighting", "Adds an effect behind hit explosions.", true), SHOW_HIT_ANIMATIONS ("Show Hit Animations", "HitAnimations", "Fade out circles and curves.", true), SHOW_REVERSEARROW_ANIMATIONS ("Show reverse arrow animations", "ReverseArrowAnimations", "Fade out reverse arrows after passing.", true), @@ -1629,6 +1636,8 @@ public class Options { public static boolean isMergingSliders() { return !isFallbackSliders() && GameOption.MERGING_SLIDERS.getBooleanValue(); } public static int getMergingSlidersMirrorPool() { return GameOption.MERGING_SLIDERS_MIRROR_POOL.getIntegerValue(); } public static boolean isDrawSliderEndCircles() { return GameOption.DRAW_SLIDER_ENDCIRCLES.getBooleanValue(); } + public static boolean isDancingHitCircles() { return GameOption.DANCING_CIRCLES.getBooleanValue(); } + public static float getDancingHitCirclesMultiplier() { return GameOption.DANCING_CIRCLES_MULTIPLIER.getIntegerValue() / 10f; } /** * Returns the fixed circle size override, if any. diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index 6335e558..b73ed03e 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -1759,6 +1759,8 @@ public class Game extends ComplexOpsuState { * @param trackPosition the track position */ private void drawHitObjects(Graphics g, int trackPosition) { + gameObjectRenderer.initForFrame(); + // draw result objects if (!Options.isHideObjects()) { data.drawHitResults(trackPosition); diff --git a/src/yugecin/opsudance/render/GameObjectRenderer.java b/src/yugecin/opsudance/render/GameObjectRenderer.java index 86622f0b..dd3a1e7b 100644 --- a/src/yugecin/opsudance/render/GameObjectRenderer.java +++ b/src/yugecin/opsudance/render/GameObjectRenderer.java @@ -21,8 +21,10 @@ import itdelatrisu.opsu.GameData; import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.GameMod; import itdelatrisu.opsu.Options; +import itdelatrisu.opsu.audio.MusicController; import itdelatrisu.opsu.beatmap.HitObject; import itdelatrisu.opsu.ui.Colors; +import itdelatrisu.opsu.ui.animations.AnimationEquation; import org.newdawn.slick.Color; import org.newdawn.slick.Image; import yugecin.opsudance.core.DisplayContainer; @@ -36,6 +38,7 @@ public class GameObjectRenderer { private GameData gameData; private float circleDiameter; + private int circleDiameterInt; private Image hitcircle; private Image hitcircleOverlay; @@ -51,10 +54,10 @@ public class GameObjectRenderer { public void initForGame(GameData gameData, float circleDiameter) { this.gameData = gameData; this.circleDiameter = circleDiameter * HitObject.getXMultiplier(); // convert from Osupixels (640x480) - int diameterInt = (int) this.circleDiameter; - GameImage.HITCIRCLE.setImage(GameImage.HITCIRCLE.getImage().getScaledCopy(diameterInt, diameterInt)); - GameImage.HITCIRCLE_OVERLAY.setImage(GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(diameterInt, diameterInt)); - GameImage.APPROACHCIRCLE.setImage(GameImage.APPROACHCIRCLE.getImage().getScaledCopy(diameterInt, diameterInt)); + this.circleDiameterInt = (int) this.circleDiameter; + GameImage.HITCIRCLE.setImage(GameImage.HITCIRCLE.getImage().getScaledCopy(circleDiameterInt, circleDiameterInt)); + GameImage.HITCIRCLE_OVERLAY.setImage(GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(circleDiameterInt, circleDiameterInt)); + GameImage.APPROACHCIRCLE.setImage(GameImage.APPROACHCIRCLE.getImage().getScaledCopy(circleDiameterInt, circleDiameterInt)); hitcircle = GameImage.HITCIRCLE.getImage(); hitcircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage(); approachCircle = GameImage.APPROACHCIRCLE.getImage(); @@ -68,6 +71,19 @@ public class GameObjectRenderer { this.gameData = gameData; } + public void initForFrame() { + if (!Options.isDancingHitCircles()) { + return; + } + Float position = MusicController.getBeatProgress(); + if (position == null) { + position = 0f; + } + int size = circleDiameterInt + (int) (circleDiameter * Options.getDancingHitCirclesMultiplier() / 100f * AnimationEquation.IN_OUT_QUAD.calc(position)); + hitcircle = GameImage.HITCIRCLE.getImage().getScaledCopy(size, size); + hitcircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(size, size); + } + public void renderHitCircle(float x, float y, Color color, int comboNumber, float comboNumberAlpha) { renderHitCircleOnly(x, y, color); boolean overlayAboveNumber = Options.getSkin().isHitCircleOverlayAboveNumber();