diff --git a/src/itdelatrisu/opsu/Options.java b/src/itdelatrisu/opsu/Options.java index eefa7ada..37f6efb9 100644 --- a/src/itdelatrisu/opsu/Options.java +++ b/src/itdelatrisu/opsu/Options.java @@ -56,7 +56,11 @@ import com.sun.jna.platform.win32.Advapi32Util; import com.sun.jna.platform.win32.Win32Exception; import com.sun.jna.platform.win32.WinReg; import yugecin.opsudance.*; +import yugecin.opsudance.movers.CubicBezierMover; +import yugecin.opsudance.movers.QuadraticBezierMover; import yugecin.opsudance.movers.factories.AutoMoverFactory; +import yugecin.opsudance.movers.factories.QuadraticBezierMoverFactory; +import yugecin.opsudance.movers.slidermovers.DefaultSliderMoverController; import yugecin.opsudance.spinners.Spinner; import yugecin.opsudance.ui.SBOverlay; @@ -623,6 +627,99 @@ public class Options { } }, + DANCE_QUAD_BEZ_AGGRESSIVENESS ("Quadratic Bezier aggressiveness", "QuadBezAgr", "AKA initial D factor", 50, 0, 200) { + @Override + public String getValueString() { + return val + ""; + } + + @Override + public void drag(GameContainer container, int d) { + super.drag(container, d); + QuadraticBezierMover.aggressiveness = val; + } + + @Override + public boolean showCondition() { + return Dancer.moverFactories[Dancer.instance.getMoverFactoryIndex()] instanceof QuadraticBezierMoverFactory; + } + + @Override + public void read(String s) { + super.read(s); + QuadraticBezierMover.aggressiveness = val; + } + }, + + DANCE_QUAD_BEZ_SLIDER_AGGRESSIVENESS_FACTOR ("Slider exit aggressiveness factor", "CubBezSliderExitAgr", "AKA initial D factor for sliderexits", 40, 10, 60) { + @Override + public String getValueString() { + return val / 10 + ""; + } + + @Override + public void drag(GameContainer container, int d) { + super.drag(container, d); + QuadraticBezierMover.sliderExitAggressivenessfactor = val / 10; + } + + @Override + public boolean showCondition() { + return DANCE_QUAD_BEZ_AGGRESSIVENESS.showCondition() + && Dancer.sliderMoverController instanceof DefaultSliderMoverController; + } + + @Override + public void read(String s) { + super.read(s); + QuadraticBezierMover.sliderExitAggressivenessfactor = val / 10; + } + }, + + DANCE_QUAD_BEZ_USE_CUBIC_ON_SLIDERS ("Use cubic bezier before sliders", "QuadBezCubicSliders", "Slider entry looks better using this", true) { + @Override + public void click(GameContainer container) { + super.click(container); + QuadraticBezierMoverFactory.cubicForSliderEntries = bool; + } + + @Override + public boolean showCondition() { + return DANCE_QUAD_BEZ_SLIDER_AGGRESSIVENESS_FACTOR.showCondition(); + } + + @Override + public void read(String s) { + super.read(s); + QuadraticBezierMoverFactory.cubicForSliderEntries = bool; + } + }, + + DANCE_QUAD_BEZ_CUBIC_AGGRESSIVENESS_FACTOR ("Slider entry aggressiveness factor", "CubBezSliderEntryAgr", "AKA initial D factor for sliderentries", 40, 10, 60) { + @Override + public String getValueString() { + return val / 10 + ""; + } + + @Override + public void drag(GameContainer container, int d) { + super.drag(container, d); + CubicBezierMover.aggressivenessfactor = val / 10; + } + + @Override + public boolean showCondition() { + return DANCE_QUAD_BEZ_USE_CUBIC_ON_SLIDERS.showCondition() + && DANCE_QUAD_BEZ_USE_CUBIC_ON_SLIDERS.getBooleanValue(); + } + + @Override + public void read(String s) { + super.read(s); + CubicBezierMover.aggressivenessfactor = val / 10; + } + }, + DANCE_MOVER_DIRECTION ("Mover direction", "MoverDirection", "The direction the mover goes" ) { @Override public String getValueString() { @@ -1252,6 +1349,13 @@ public class Options { this.type = OptionType.NUMERIC; } + /** + * should the option be shown + * @return true if the option should be shown + */ + public boolean showCondition() { + return true; + } /** * Returns the option name. * @return the name string diff --git a/src/itdelatrisu/opsu/states/OptionsMenu.java b/src/itdelatrisu/opsu/states/OptionsMenu.java index 847c129b..a41cb1a5 100644 --- a/src/itdelatrisu/opsu/states/OptionsMenu.java +++ b/src/itdelatrisu/opsu/states/OptionsMenu.java @@ -113,6 +113,10 @@ public class OptionsMenu extends BasicGameState { }), DANCE ("Dance", new GameOption[] { GameOption.DANCE_MOVER, + GameOption.DANCE_QUAD_BEZ_AGGRESSIVENESS, + GameOption.DANCE_QUAD_BEZ_SLIDER_AGGRESSIVENESS_FACTOR, + GameOption.DANCE_QUAD_BEZ_USE_CUBIC_ON_SLIDERS, + GameOption.DANCE_QUAD_BEZ_CUBIC_AGGRESSIVENESS_FACTOR, GameOption.DANCE_MOVER_DIRECTION, GameOption.DANCE_SLIDER_MOVER_TYPE, GameOption.DANCE_SPINNER, @@ -277,9 +281,12 @@ public class OptionsMenu extends BasicGameState { if (selectedOption != null) { hoverOption = selectedOption; } - for (int i = 0; i < currentTab.options.length; i++) { + for (int i = 0, j = 0; i < currentTab.options.length; i++) { GameOption option = currentTab.options[i]; - drawOption(option, i, hoverOption == option); + if (!option.showCondition()) { + continue; + } + drawOption(option, j++, hoverOption == option); } // option tabs @@ -602,6 +609,14 @@ public class OptionsMenu extends BasicGameState { if (index >= currentTab.options.length) return null; - return currentTab.options[index]; + for (GameOption option : currentTab.options) { + if (option.showCondition()) { + index--; + } + if (index < 0) { + return option; + } + } + return null; } } diff --git a/src/yugecin/opsudance/Dancer.java b/src/yugecin/opsudance/Dancer.java index fe56baac..25be5acf 100644 --- a/src/yugecin/opsudance/Dancer.java +++ b/src/yugecin/opsudance/Dancer.java @@ -33,12 +33,15 @@ import itdelatrisu.opsu.objects.Slider; import itdelatrisu.opsu.objects.curves.Vec2f; import yugecin.opsudance.movers.LinearMover; import yugecin.opsudance.movers.Mover; +import yugecin.opsudance.movers.QuadraticBezierMover; import yugecin.opsudance.movers.factories.*; import yugecin.opsudance.movers.slidermovers.DefaultSliderMoverController; import yugecin.opsudance.movers.slidermovers.InheritedSliderMoverController; import yugecin.opsudance.movers.slidermovers.SliderMoverController; import yugecin.opsudance.spinners.*; +import java.awt.*; + public class Dancer { public static MoverFactory[] moverFactories = new MoverFactory[] { @@ -55,6 +58,7 @@ public class Dancer { new CenterSpiralMoverFactory(), //new LinearFactory(), new ArcFactory(), + new QuadraticBezierMoverFactory(), }; public static Spinner[] spinners = new Spinner[] { @@ -131,6 +135,7 @@ public class Dancer { for (Spinner s : spinners) { s.init(); } + QuadraticBezierMover.reset(); } public int getSpinnerIndex() { @@ -216,6 +221,16 @@ public class Dancer { c.start = new Vec2f((float) spinnerStartPoint[0], (float) spinnerStartPoint[1]); } + // specific mover stuff + if (p.isSlider() && sliderMoverController instanceof DefaultSliderMoverController) { + Vec2f st = p.getPointAt(p.getEndTime() - 10); + Vec2f en = p.getPointAt(p.getEndTime()); + //double atan = Math.atan2(en.y - st.y, en.x - st.x); + double distance = Utils.distance(st.x, st.y, en.x, en.y); + QuadraticBezierMover.p = new Point((int) st.x, (int) st.y); + QuadraticBezierMover.setPrevspeed(distance, 10); + } + createNewMover(); } diff --git a/src/yugecin/opsudance/movers/CubicBezierMover.java b/src/yugecin/opsudance/movers/CubicBezierMover.java new file mode 100644 index 00000000..3b73764e --- /dev/null +++ b/src/yugecin/opsudance/movers/CubicBezierMover.java @@ -0,0 +1,73 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.movers; + +import itdelatrisu.opsu.Utils; +import itdelatrisu.opsu.objects.GameObject; +import itdelatrisu.opsu.objects.Slider; +import itdelatrisu.opsu.objects.curves.Vec2f; + +import java.awt.*; + +public class CubicBezierMover extends Mover { + + public static int aggressivenessfactor = 4; + + private static Point p2 = new Point(0, 0); + private static Point p1 = new Point(0, 0); + + private int startTime; + private int totalTime; + + public CubicBezierMover(GameObject start, GameObject end, int dir) { + super(start, end, dir); + + if (end instanceof Slider) { + Slider s = (Slider) end; + double ang = s.getCurve().getStartAngle() * Math.PI / 180d + Math.PI; + Vec2f nextpos = s.getPointAt(s.getTime() + 10); + double dist = Utils.distance(end.start.x, end.start.y, nextpos.x, nextpos.y); + double speed = dist * QuadraticBezierMover.aggressiveness * aggressivenessfactor / 10; + p2.x = (int) (end.start.x + Math.cos(ang) * speed); + p2.y = (int) (end.start.y + Math.sin(ang) * speed); + } + + this.startTime = start.getEndTime(); + this.totalTime = end.getTime() - startTime; + + double startAngle = Math.atan2(startY - QuadraticBezierMover.p.y, startX - QuadraticBezierMover.p.x); + p1.x = (int) (startX + Math.cos(startAngle) * QuadraticBezierMover.getPrevspeed()); + p1.y = (int) (startY + Math.sin(startAngle) * QuadraticBezierMover.getPrevspeed()); + } + + @Override + public double[] getPointAt(int time) { + double t = (double) (time - startTime) / totalTime; + double ct = (1 - t); + return new double[] { + ct * ct * ct * startX + 3 * ct * ct * t * p1.x + 3 * ct * t * t * p2.x + t * t * t * endX, + ct * ct * ct * startY + 3 * ct * ct * t * p1.y + 3 * ct * t * t * p2.y + t * t * t * endY, + }; + } + + @Override + public String getName() { + return "Quadratic Bezier"; + } + +} diff --git a/src/yugecin/opsudance/movers/QuadraticBezierMover.java b/src/yugecin/opsudance/movers/QuadraticBezierMover.java new file mode 100644 index 00000000..0df78422 --- /dev/null +++ b/src/yugecin/opsudance/movers/QuadraticBezierMover.java @@ -0,0 +1,75 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.movers; + +import itdelatrisu.opsu.Utils; +import itdelatrisu.opsu.objects.GameObject; + +import java.awt.*; + +public class QuadraticBezierMover extends Mover { + + public static int sliderExitAggressivenessfactor = 4; + public static int aggressiveness = 50; + public static Point p; + private static double prevspeed; + + public static void reset() { + p = new Point(0, 0); + prevspeed = 0; + } + + public static void setPrevspeed(double distance, int timedelta) { + prevspeed = distance * aggressiveness * sliderExitAggressivenessfactor / timedelta; + } + + public static double getPrevspeed() { + return prevspeed; + } + + private int startTime; + private int totalTime; + + public QuadraticBezierMover(GameObject start, GameObject end, int dir) { + super(start, end, dir); + this.startTime = start.getEndTime(); + this.totalTime = end.getTime() - startTime; + + double startAngle = Math.atan2(startY - p.y, startX - p.x); + double dist = Utils.distance(startX, startY, endX, endY); + p.x = (int) (startX + Math.cos(startAngle) * prevspeed); + p.y = (int) (startY + Math.sin(startAngle) * prevspeed); + prevspeed = (dist / totalTime) * aggressiveness; + } + + @Override + public double[] getPointAt(int time) { + double t = (double) (time - startTime) / totalTime; + double ct = (1 - t); + return new double[] { + ct * ct * startX + ct * 2 * t * p.x + t * t * endX, + ct * ct * startY + ct * 2 * t * p.y + t * t * endY, + }; + } + + @Override + public String getName() { + return "Quadratic Bezier"; + } + +} diff --git a/src/yugecin/opsudance/movers/factories/QuadraticBezierMoverFactory.java b/src/yugecin/opsudance/movers/factories/QuadraticBezierMoverFactory.java new file mode 100644 index 00000000..2b3ac083 --- /dev/null +++ b/src/yugecin/opsudance/movers/factories/QuadraticBezierMoverFactory.java @@ -0,0 +1,42 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.movers.factories; + +import itdelatrisu.opsu.objects.GameObject; +import yugecin.opsudance.movers.CubicBezierMover; +import yugecin.opsudance.movers.Mover; +import yugecin.opsudance.movers.QuadraticBezierMover; + +public class QuadraticBezierMoverFactory implements MoverFactory { + + public static boolean cubicForSliderEntries = true; + + @Override + public Mover create(GameObject start, GameObject end, int dir) { + if (cubicForSliderEntries && end.isSlider()) { + return new CubicBezierMover(start, end, dir); + } + return new QuadraticBezierMover(start, end, dir); + } + + @Override + public String toString() { + return "Quadratic bezier"; + } + +} diff --git a/src/yugecin/opsudance/ui/OptionsOverlay.java b/src/yugecin/opsudance/ui/OptionsOverlay.java index 33c500f9..e366da4d 100644 --- a/src/yugecin/opsudance/ui/OptionsOverlay.java +++ b/src/yugecin/opsudance/ui/OptionsOverlay.java @@ -36,6 +36,10 @@ public class OptionsOverlay { private static Options.GameOption[] options = new Options.GameOption[] { Options.GameOption.DANCE_MOVER, + Options.GameOption.DANCE_QUAD_BEZ_AGGRESSIVENESS, + Options.GameOption.DANCE_QUAD_BEZ_SLIDER_AGGRESSIVENESS_FACTOR, + Options.GameOption.DANCE_QUAD_BEZ_USE_CUBIC_ON_SLIDERS, + Options.GameOption.DANCE_QUAD_BEZ_CUBIC_AGGRESSIVENESS_FACTOR, Options.GameOption.DANCE_MOVER_DIRECTION, Options.GameOption.DANCE_SLIDER_MOVER_TYPE, Options.GameOption.DANCE_SPINNER, @@ -99,8 +103,11 @@ public class OptionsOverlay { g.setColor(Color.black); g.fillRect(0, 0, width, height); Color.black.a = a; - for (int i = 0; i < options.length; i++) { - drawOption(g, options[i], i, selectedOption == null ? hoverIdx == i : selectedOption == options[i]); + for (int i = 0, j = 0; i < options.length; i++) { + if (!options[i].showCondition()) { + continue; + } + drawOption(g, options[i], j++, selectedOption == null ? hoverIdx == i : selectedOption == options[i]); } if (list.isVisible()) { list.render(container, game, g); @@ -123,7 +130,15 @@ public class OptionsOverlay { if (index >= options.length) { return -1; } - return index; + for (int i = 0; i < options.length; i++) { + if (options[i].showCondition()) { + index--; + } + if (index < 0) { + return i; + } + } + return -1; } public void update(int mouseX, int mouseY) {