diff --git a/src/itdelatrisu/opsu/objects/Circle.java b/src/itdelatrisu/opsu/objects/Circle.java index f9b99123..a03d4889 100644 --- a/src/itdelatrisu/opsu/objects/Circle.java +++ b/src/itdelatrisu/opsu/objects/Circle.java @@ -38,7 +38,7 @@ import org.newdawn.slick.Graphics; */ public class Circle extends GameObject { /** The diameter of hit circles. */ - private static float diameter; + public static float diameter; /** The associated HitObject. */ private HitObject hitObject; diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index 72128cb7..921f0a38 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -73,6 +73,7 @@ import org.newdawn.slick.state.transition.DelayedFadeOutTransition; import org.newdawn.slick.state.transition.EasedFadeOutTransition; import org.newdawn.slick.state.transition.EmptyTransition; import org.newdawn.slick.state.transition.FadeInTransition; +import yugecin.opsudance.Dancer; /** * "Game" state. @@ -341,19 +342,17 @@ public class Game extends BasicGameState { autoMousePosition.set(width / 2, height / 2); autoMousePressed = false; if (GameMod.AUTO.isActive() || GameMod.AUTOPILOT.isActive()) { - Vec2f autoPoint = null; - if (isLeadIn()) { - // lead-in - float progress = Math.max((float) (leadInTime - beatmap.audioLeadIn) / approachTime, 0f); - autoMousePosition.y = height / (2f - progress); - } else if (objectIndex == 0 && trackPosition < firstObjectTime) { - // before first object - timeDiff = firstObjectTime - trackPosition; - if (timeDiff < approachTime) { - Vec2f point = gameObjects[0].getPointAt(trackPosition); - autoPoint = getPointAt(autoMousePosition.x, autoMousePosition.y, point.x, point.y, 1f - ((float) timeDiff / approachTime)); + Vec2f autoPoint; + if (objectIndex == 0) { + autoPoint = gameObjects[0].getPointAt(trackPosition); + } else if (objectIndex < beatmap.objects.length - 1) { + Dancer d = Dancer.instance; + d.update(trackPosition, gameObjects[objectIndex - 1], gameObjects[objectIndex]); + autoPoint = new Vec2f(d.x, d.y); + if (trackPosition < gameObjects[objectIndex].getTime()) { + autoMousePressed = true; } - } else if (objectIndex < beatmap.objects.length) { + /* // normal object int objectTime = beatmap.objects[objectIndex].getTime(); if (trackPosition < objectTime) { @@ -386,14 +385,14 @@ public class Game extends BasicGameState { autoPoint = gameObjects[objectIndex].getPointAt(trackPosition); autoMousePressed = true; } + */ } else { // last object autoPoint = gameObjects[objectIndex - 1].getPointAt(trackPosition); } // set mouse coordinates - if (autoPoint != null) - autoMousePosition.set(autoPoint.x, autoPoint.y); + autoMousePosition.set(autoPoint.x, autoPoint.y); } // "flashlight" mod: restricted view of hit objects around cursor @@ -1139,6 +1138,8 @@ public class Game extends BasicGameState { if (beatmap == null || beatmap.objects == null) throw new RuntimeException("Running game with no beatmap loaded."); + Dancer.instance.init(beatmap.getTitle()); + // free all previously cached hitobject to framebuffer mappings if some still exist FrameBufferCache.getInstance().freeMap(); @@ -1217,7 +1218,6 @@ public class Game extends BasicGameState { hitObject.getTypeName(), i, hitObject.toString()), e, true); gameObjects[i] = new DummyObject(hitObject); } - gameObjects[i].updateStartEndPositions(hitObjectTime); } // stack calculations @@ -1267,6 +1267,10 @@ public class Game extends BasicGameState { replayFrames.add(new ReplayFrame(0, 0, input.getMouseX(), input.getMouseY(), 0)); } + for (int i = 0; i < gameObjects.length; i++) { + gameObjects[i].updateStartEndPositions(beatmap.objects[i].getTime()); + } + leadInTime = beatmap.audioLeadIn + approachTime; restart = Restart.FALSE; @@ -1756,22 +1760,6 @@ public class Game extends BasicGameState { return frame; } - /** - * Returns the point at the t value between a start and end point. - * @param startX the starting x coordinate - * @param startY the starting y coordinate - * @param endX the ending x coordinate - * @param endY the ending y coordinate - * @param t the t value [0, 1] - * @return the position vector - */ - private Vec2f getPointAt(float startX, float startY, float endX, float endY, float t) { - // "autopilot" mod: move quicker between objects - if (GameMod.AUTOPILOT.isActive()) - t = Utils.clamp(t * 2f, 0f, 1f); - return new Vec2f(startX + (endX - startX) * t, startY + (endY - startY) * t); - } - /** * Updates the current visible area radius (if the "flashlight" mod is enabled). * @param delta the delta interval diff --git a/src/yugecin/opsudance/Dancer.java b/src/yugecin/opsudance/Dancer.java new file mode 100644 index 00000000..b02a9f2f --- /dev/null +++ b/src/yugecin/opsudance/Dancer.java @@ -0,0 +1,111 @@ +/* + * 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! 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; + +import itdelatrisu.opsu.Options; +import itdelatrisu.opsu.Utils; +import itdelatrisu.opsu.objects.GameObject; +import itdelatrisu.opsu.objects.curves.Vec2f; +import yugecin.opsudance.movers.Mover; +import yugecin.opsudance.movers.factories.*; +import yugecin.opsudance.spinners.RektSpinner; +import yugecin.opsudance.spinners.Spinner; + +import java.util.Random; + +public class Dancer { + + public static MoverFactory[] moverFactories = new MoverFactory[] { + new AutoMoverFactory(), + new AutoEllipseMoverFactory(), + new CircleMoverFactory(), + new HalfCircleMoverFactory(), + new HalfEllipseMoverFactory(), + new HalfLowEllipseMoverFactory(), + new JumpMoverFactory(), + new LinearMoverFactory(), + new QuartCircleMoverFactory() + }; + + public static Spinner[] spinners = new Spinner[] { + new RektSpinner() + }; + + public static Dancer instance = new Dancer(); + + private int dir; + private GameObject p; + private Random rand; + + private MoverFactory moverFactory; + private Mover mover; + private Spinner spinner; + + public float x; + public float y; + + public Dancer() { + moverFactory = moverFactories[0]; + spinner = spinners[0]; + } + + public void init(String mapname) { + p = null; + rand = new Random(mapname.hashCode()); + dir = 1; + for (Spinner s : spinners) { + s.init(); + } + } + + public void update(int time, GameObject p, GameObject c) { + if (this.p != p) { + this.p = p; + if (rand.nextInt(2) == 1) { + dir *= -1; + } + if (c.isSpinner()) { + double[] spinnerStartPoint = spinner.getPoint(); + c.start = new Vec2f((float) spinnerStartPoint[0], (float) spinnerStartPoint[1]); + } + mover = moverFactory.create(p, c, dir); + } + + if (time < c.getTime()) { + if (!p.isSpinner() || !c.isSpinner()) { + double[] point = mover.getPointAt(time); + x = (float) point[0]; + y = (float) point[1]; + } + x = Utils.clamp(x, 10, Options.width - 10); + y = Utils.clamp(y, 10, Options.height - 10); + } else { + if (c.isSpinner()) { + double[] point = spinner.getPoint(); + x = (float) point[0]; + y = (float) point[1]; + c.end = new Vec2f(x, y); + } else { + Vec2f point = c.getPointAt(time); + x = point.x; + y = point.y; + } + } + } + +}