Implemented "autopilot" mod.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2015-03-17 19:03:50 -04:00
parent e362232d5f
commit c14b4b4822
3 changed files with 54 additions and 21 deletions

View File

@ -51,7 +51,7 @@ public enum GameMod {
"Flashlight", "Restricted view area."),
RELAX (Category.SPECIAL, 0, GameImage.MOD_RELAX, "RL", 128, Input.KEY_Z, 0f,
"Relax", "You don't need to click.\nGive your clicking/tapping finger a break from the heat of things.\n**UNRANKED**"),
AUTOPILOT (Category.SPECIAL, 1, GameImage.MOD_AUTOPILOT, "AP", 8192, Input.KEY_X, 0f, false,
AUTOPILOT (Category.SPECIAL, 1, GameImage.MOD_AUTOPILOT, "AP", 8192, Input.KEY_X, 0f,
"Relax2", "Automatic cursor movement - just follow the rhythm.\n**UNRANKED**"),
SPUN_OUT (Category.SPECIAL, 2, GameImage.MOD_SPUN_OUT, "SO", 4096, Input.KEY_V, 0.9f,
"SpunOut", "Spinners will be automatically completed."),

View File

@ -50,6 +50,11 @@ public class Spinner implements HitObject {
/** The amount of time, in milliseconds, to fade in the spinner. */
private static final int FADE_IN_TIME = 500;
/** Angle mod multipliers: "auto" (477rpm), "spun out" (287rpm) */
private static final float
AUTO_MULTIPLIER = 1 / 20f, // angle = 477/60f * delta/1000f * TWO_PI;
SPUN_OUT_MULTIPLIER = 1 / 33.25f; // angle = 287/60f * delta/1000f * TWO_PI;
/** PI constants. */
private static final float
TWO_PI = (float) (Math.PI * 2),
@ -176,8 +181,7 @@ public class Spinner implements HitObject {
// TODO: verify ratios
int result;
float ratio = rotations / rotationsNeeded;
if (ratio >= 1.0f ||
GameMod.AUTO.isActive() || GameMod.SPUN_OUT.isActive()) {
if (ratio >= 1.0f || GameMod.AUTO.isActive() || GameMod.AUTOPILOT.isActive() || GameMod.SPUN_OUT.isActive()) {
result = GameData.HIT_300;
SoundController.playSound(SoundEffect.SPINNEROSU);
} else if (ratio >= 0.9f)
@ -213,14 +217,12 @@ public class Spinner implements HitObject {
// http://osu.ppy.sh/wiki/FAQ#Spinners
float angle;
if (GameMod.AUTO.isActive()) {
// "auto" mod (fast: 477rpm)
lastAngle = 0;
angle = delta / 20f; // angle = 477/60f * delta/1000f * TWO_PI;
angle = delta * AUTO_MULTIPLIER;
isSpinning = true;
} else if (GameMod.SPUN_OUT.isActive()) {
// "spun out" mod (slow: 287rpm)
} else if (GameMod.SPUN_OUT.isActive() || GameMod.AUTOPILOT.isActive()) {
lastAngle = 0;
angle = delta / 33.25f; // angle = 287/60f * delta/1000f * TWO_PI;
angle = delta * SPUN_OUT_MULTIPLIER;
isSpinning = true;
} else {
angle = (float) Math.atan2(mouseY - (height / 2), mouseX - (width / 2));
@ -276,7 +278,8 @@ public class Spinner implements HitObject {
timeDiff = trackPosition - hitObject.getTime();
// calculate point
float angle = timeDiff / 20f - HALF_PI;
float multiplier = (GameMod.AUTO.isActive()) ? AUTO_MULTIPLIER : SPUN_OUT_MULTIPLIER;
float angle = (timeDiff * multiplier) - HALF_PI;
final float r = height / 10f;
return new float[] {
(float) (x + r * Math.cos(angle)),

View File

@ -201,6 +201,12 @@ public class Game extends BasicGameState {
/** The current flashlight area radius. */
private int flashlightRadius;
/** The cursor coordinates using the "auto" or "relax" mods. */
private int autoMouseX = 0, autoMouseY = 0;
/** Whether or not the cursor should be pressed using the "auto" mod. */
private boolean autoMousePressed;
// game-related variables
private GameContainer container;
private StateBasedGame game;
@ -263,10 +269,12 @@ public class Game extends BasicGameState {
int firstObjectTime = osu.objects[0].getTime();
int timeDiff = firstObjectTime - trackPosition;
// "auto" mod: move cursor automatically
int autoMouseX = width / 2, autoMouseY = height / 2;
boolean autoMousePress = false;
if (GameMod.AUTO.isActive()) {
// "auto" and "autopilot" mods: move cursor automatically
// TODO: this should really be in update(), not render()
autoMouseX = width / 2;
autoMouseY = height / 2;
autoMousePressed = false;
if (GameMod.AUTO.isActive() || GameMod.AUTOPILOT.isActive()) {
float[] autoXY = null;
if (isLeadIn()) {
// lead-in
@ -306,11 +314,11 @@ public class Game extends BasicGameState {
int offset300 = hitResultOffset[GameData.HIT_300];
if ((osu.objects[objectIndex].isCircle() && objectTime - trackPosition < offset300) ||
(osu.objects[objectIndex - 1].isCircle() && trackPosition - osu.objects[objectIndex - 1].getTime() < offset300))
autoMousePress = true;
autoMousePressed = true;
}
} else {
autoXY = hitObjects[objectIndex].getPointAt(trackPosition);
autoMousePress = true;
autoMousePressed = true;
}
} else {
// last object
@ -342,7 +350,7 @@ public class Game extends BasicGameState {
if (pauseTime > -1 && pausedMouseX > -1 && pausedMouseY > -1) {
mouseX = pausedMouseX;
mouseY = pausedMouseY;
} else if (GameMod.AUTO.isActive()) {
} else if (GameMod.AUTO.isActive() || GameMod.AUTOPILOT.isActive()) {
mouseX = autoMouseX;
mouseY = autoMouseY;
} else if (isReplay) {
@ -510,7 +518,9 @@ public class Game extends BasicGameState {
}
if (GameMod.AUTO.isActive())
UI.draw(g, autoMouseX, autoMouseY, autoMousePress);
UI.draw(g, autoMouseX, autoMouseY, autoMousePressed);
else if (GameMod.AUTOPILOT.isActive())
UI.draw(g, autoMouseX, autoMouseY, Utils.isGameKeyPressed());
else if (!isReplay)
UI.draw(g);
else
@ -522,7 +532,10 @@ public class Game extends BasicGameState {
throws SlickException {
UI.update(delta);
int mouseX, mouseY;
if (!isReplay) {
if (GameMod.AUTO.isActive() || GameMod.AUTOPILOT.isActive()) {
mouseX = autoMouseX;
mouseY = autoMouseY;
} else if (!isReplay) {
mouseX = input.getMouseX();
mouseY = input.getMouseY();
} else {
@ -940,16 +953,26 @@ public class Game extends BasicGameState {
if (GameMod.AUTO.isActive() || GameMod.RELAX.isActive())
return;
// "autopilot" mod: ignore actual cursor coordinates
int cx, cy;
if (GameMod.AUTOPILOT.isActive()) {
cx = autoMouseX;
cy = autoMouseY;
} else {
cx = x;
cy = y;
}
if (!isReplay)
addReplayFrame(x, y, lastKeysPressed | keys);
addReplayFrame(cx, cy, lastKeysPressed | keys);
// circles
if (hitObject.isCircle() && hitObjects[objectIndex].mousePressed(x, y))
if (hitObject.isCircle() && hitObjects[objectIndex].mousePressed(cx, cy))
objectIndex++; // circle hit
// sliders
else if (hitObject.isSlider())
hitObjects[objectIndex].mousePressed(x, y);
hitObjects[objectIndex].mousePressed(cx, cy);
}
@Override
@ -1209,6 +1232,9 @@ public class Game extends BasicGameState {
deaths = 0;
deathTime = -1;
replayFrames = null;
autoMouseX = 0;
autoMouseY = 0;
autoMousePressed = false;
System.gc();
}
@ -1415,6 +1441,10 @@ public class Game extends BasicGameState {
* @return the [x,y] coordinates
*/
private float[] 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);
float[] xy = new float[2];
xy[0] = startX + (endX - startX) * t;
xy[1] = startY + (endY - startY) * t;