Implemented "relax" mod.

Also added a few checks for related "autopilot" mod (probably incomplete).

Fixed the wrong default background being shown in the ranking screen.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2015-03-06 00:25:48 -05:00
parent b80764f3eb
commit 0a1b10fbdb
7 changed files with 75 additions and 53 deletions

View File

@ -522,22 +522,25 @@ public class GameData {
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public void drawGameElements(Graphics g, boolean breakPeriod, boolean firstObject) { public void drawGameElements(Graphics g, boolean breakPeriod, boolean firstObject) {
boolean relaxAutoPilot = (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive());
int margin = (int) (width * 0.008f); int margin = (int) (width * 0.008f);
// score // score
drawFixedSizeSymbolString((scoreDisplay < 100000000) ? String.format("%08d", scoreDisplay) : Long.toString(scoreDisplay), if (!relaxAutoPilot)
width - margin, 0, 1.0f, getScoreSymbolImage('0').getWidth() - 2, true); drawFixedSizeSymbolString((scoreDisplay < 100000000) ? String.format("%08d", scoreDisplay) : Long.toString(scoreDisplay),
width - margin, 0, 1.0f, getScoreSymbolImage('0').getWidth() - 2, true);
// score percentage // score percentage
int symbolHeight = getScoreSymbolImage('0').getHeight(); int symbolHeight = getScoreSymbolImage('0').getHeight();
drawSymbolString( if (!relaxAutoPilot)
String.format((scorePercentDisplay < 10f) ? "0%.2f%%" : "%.2f%%", scorePercentDisplay), drawSymbolString(
width - margin, symbolHeight, 0.60f, 1f, true); String.format((scorePercentDisplay < 10f) ? "0%.2f%%" : "%.2f%%", scorePercentDisplay),
width - margin, symbolHeight, 0.60f, 1f, true);
// map progress circle // map progress circle
g.setAntiAlias(true); OsuFile osu = MusicController.getOsuFile();
g.setLineWidth(2f); int firstObjectTime = osu.objects[0].getTime();
g.setColor(Color.white); int trackPosition = MusicController.getPosition();
float circleDiameter = symbolHeight * 0.60f; float circleDiameter = symbolHeight * 0.60f;
int circleX = (int) (width - margin - ( // max width: "100.00%" int circleX = (int) (width - margin - ( // max width: "100.00%"
getScoreSymbolImage('1').getWidth() + getScoreSymbolImage('1').getWidth() +
@ -545,22 +548,23 @@ public class GameData {
getScoreSymbolImage('.').getWidth() + getScoreSymbolImage('.').getWidth() +
getScoreSymbolImage('%').getWidth() getScoreSymbolImage('%').getWidth()
) * 0.60f - circleDiameter); ) * 0.60f - circleDiameter);
g.drawOval(circleX, symbolHeight, circleDiameter, circleDiameter); if (!relaxAutoPilot) {
g.setAntiAlias(true);
OsuFile osu = MusicController.getOsuFile(); g.setLineWidth(2f);
int firstObjectTime = osu.objects[0].getTime(); g.setColor(Color.white);
int trackPosition = MusicController.getPosition(); g.drawOval(circleX, symbolHeight, circleDiameter, circleDiameter);
if (trackPosition > firstObjectTime) { if (trackPosition > firstObjectTime) {
// map progress (white) // map progress (white)
g.fillArc(circleX, symbolHeight, circleDiameter, circleDiameter, g.fillArc(circleX, symbolHeight, circleDiameter, circleDiameter,
-90, -90 + (int) (360f * (trackPosition - firstObjectTime) / (osu.endTime - firstObjectTime)) -90, -90 + (int) (360f * (trackPosition - firstObjectTime) / (osu.endTime - firstObjectTime))
); );
} else { } else {
// lead-in time (yellow) // lead-in time (yellow)
g.setColor(Utils.COLOR_YELLOW_ALPHA); g.setColor(Utils.COLOR_YELLOW_ALPHA);
g.fillArc(circleX, symbolHeight, circleDiameter, circleDiameter, g.fillArc(circleX, symbolHeight, circleDiameter, circleDiameter,
-90 + (int) (360f * trackPosition / firstObjectTime), -90 -90 + (int) (360f * trackPosition / firstObjectTime), -90
); );
}
} }
// mod icons // mod icons
@ -624,7 +628,7 @@ public class GameData {
} }
} }
if (!breakPeriod) { if (!breakPeriod && !relaxAutoPilot) {
// scorebar // scorebar
float healthRatio = healthDisplay / 100f; float healthRatio = healthDisplay / 100f;
if (firstObject) { // gradually move ki before map begins if (firstObject) { // gradually move ki before map begins
@ -671,7 +675,7 @@ public class GameData {
drawSymbolString(comboString, margin, height - margin - (symbolHeight * comboPopBack), comboPopBack, 0.5f, false); drawSymbolString(comboString, margin, height - margin - (symbolHeight * comboPopBack), comboPopBack, 0.5f, false);
drawSymbolString(comboString, margin, height - margin - (symbolHeight * comboPopFront), comboPopFront, 1f, false); drawSymbolString(comboString, margin, height - margin - (symbolHeight * comboPopFront), comboPopFront, 1f, false);
} }
} else { } else if (!relaxAutoPilot) {
// grade // grade
Grade grade = getGrade(); Grade grade = getGrade();
if (grade != Grade.NULL) { if (grade != Grade.NULL) {
@ -860,7 +864,8 @@ public class GameData {
* If "No Fail" or "Auto" mods are active, this will always return true. * If "No Fail" or "Auto" mods are active, this will always return true.
*/ */
public boolean isAlive() { public boolean isAlive() {
return (health > 0f || GameMod.NO_FAIL.isActive() || GameMod.AUTO.isActive()); return (health > 0f || GameMod.NO_FAIL.isActive() || GameMod.AUTO.isActive() ||
GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive());
} }
/** /**
@ -1043,7 +1048,7 @@ public class GameData {
* Resets the combo streak to zero. * Resets the combo streak to zero.
*/ */
private void resetComboStreak() { private void resetComboStreak() {
if (combo >= 20) if (combo >= 20 && !(GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive()))
SoundController.playSound(SoundEffect.COMBOBREAK); SoundController.playSound(SoundEffect.COMBOBREAK);
combo = 0; combo = 0;
if (GameMod.SUDDEN_DEATH.isActive()) if (GameMod.SUDDEN_DEATH.isActive())
@ -1173,6 +1178,8 @@ public class GameData {
if (perfectHit && !Options.isPerfectHitBurstEnabled()) if (perfectHit && !Options.isPerfectHitBurstEnabled())
; // hide perfect hit results ; // hide perfect hit results
else if (result == HIT_MISS && (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive()))
; // "relax" and "autopilot" mods: hide misses
else else
hitResultList.add(new OsuHitObjectResult(time, result, x, y, color, hitObject.isSpinner())); hitResultList.add(new OsuHitObjectResult(time, result, x, y, color, hitObject.isSpinner()));
} }

View File

@ -49,7 +49,7 @@ public enum GameMod {
"Play with no approach circles and fading notes for a slight score advantage."), "Play with no approach circles and fading notes for a slight score advantage."),
FLASHLIGHT (Category.HARD, 4, GameImage.MOD_FLASHLIGHT, "FL", 1024, Input.KEY_G, 1.12f, false, FLASHLIGHT (Category.HARD, 4, GameImage.MOD_FLASHLIGHT, "FL", 1024, Input.KEY_G, 1.12f, false,
"Restricted view area."), "Restricted view area."),
RELAX (Category.SPECIAL, 0, GameImage.MOD_RELAX, "RL", 128, Input.KEY_Z, 0f, false, RELAX (Category.SPECIAL, 0, GameImage.MOD_RELAX, "RL", 128, Input.KEY_Z, 0f,
"You don't need to click.\nGive your clicking/tapping finger a break from the heat of things.\n**UNRANKED**"), "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, false,
"Automatic cursor movement - just follow the rhythm.\n**UNRANKED**"), "Automatic cursor movement - just follow the rhythm.\n**UNRANKED**"),
@ -303,28 +303,34 @@ public enum GameMod {
scoreMultiplier = -1f; scoreMultiplier = -1f;
if (checkInverse) { if (checkInverse) {
boolean b = (this == SUDDEN_DEATH || this == NO_FAIL || this == RELAX || this == AUTOPILOT);
if (AUTO.isActive()) { if (AUTO.isActive()) {
if (this == AUTO) { if (this == AUTO) {
if (SPUN_OUT.isActive()) SPUN_OUT.active = false;
SPUN_OUT.toggle(false); SUDDEN_DEATH.active = false;
if (SUDDEN_DEATH.isActive()) RELAX.active = false;
SUDDEN_DEATH.toggle(false); AUTOPILOT.active = false;
} else if (this == SPUN_OUT || this == SUDDEN_DEATH) { } else if (b)
if (active) this.active = false;
toggle(false);
}
} }
if (SUDDEN_DEATH.isActive() && NO_FAIL.isActive()) { if (active && b) {
if (this == SUDDEN_DEATH) SUDDEN_DEATH.active = false;
NO_FAIL.toggle(false); NO_FAIL.active = false;
RELAX.active = false;
AUTOPILOT.active = false;
active = true;
}
if (AUTOPILOT.isActive() && SPUN_OUT.isActive()) {
if (this == AUTOPILOT)
SPUN_OUT.active = false;
else else
SUDDEN_DEATH.toggle(false); AUTOPILOT.active = false;
} }
if (EASY.isActive() && HARD_ROCK.isActive()) { if (EASY.isActive() && HARD_ROCK.isActive()) {
if (this == EASY) if (this == EASY)
HARD_ROCK.toggle(false); HARD_ROCK.active = false;
else else
EASY.toggle(false); EASY.active = false;
} }
} }
} }

View File

@ -175,6 +175,10 @@ public class Circle implements HitObject {
} }
} }
// "relax" mod: click automatically
else if (GameMod.RELAX.isActive() && trackPosition >= time)
return mousePressed(mouseX, mouseY);
return false; return false;
} }
} }

View File

@ -344,6 +344,10 @@ public class Slider implements HitObject {
hitObject.getX(), hitObject.getY(), hitObject, currentRepeats); hitObject.getX(), hitObject.getY(), hitObject, currentRepeats);
} }
} }
// "relax" mod: click automatically
else if (GameMod.RELAX.isActive() && trackPosition >= time)
mousePressed(mouseX, mouseY);
} }
// end of slider // end of slider
@ -351,7 +355,7 @@ public class Slider implements HitObject {
tickIntervals++; tickIntervals++;
// check if cursor pressed and within end circle // check if cursor pressed and within end circle
if (Utils.isGameKeyPressed()) { if (Utils.isGameKeyPressed() || GameMod.RELAX.isActive()) {
float[] c = curve.pointAt(getT(trackPosition, false)); float[] c = curve.pointAt(getT(trackPosition, false));
double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY); double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY);
int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2; int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2;
@ -400,7 +404,7 @@ public class Slider implements HitObject {
float[] c = curve.pointAt(getT(trackPosition, false)); float[] c = curve.pointAt(getT(trackPosition, false));
double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY); double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY);
int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2; int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2;
if ((Utils.isGameKeyPressed() && distance < followCircleRadius) || isAutoMod) { if (((Utils.isGameKeyPressed() || GameMod.RELAX.isActive()) && distance < followCircleRadius) || isAutoMod) {
// mouse pressed and within follow circle // mouse pressed and within follow circle
followCircleActive = true; followCircleActive = true;
data.changeHealth(delta * GameData.HP_DRAIN_MULTIPLIER); data.changeHealth(delta * GameData.HP_DRAIN_MULTIPLIER);

View File

@ -195,13 +195,13 @@ public class Spinner implements HitObject {
} }
// game button is released // game button is released
if (isSpinning && !Utils.isGameKeyPressed()) if (isSpinning && !(Utils.isGameKeyPressed() || GameMod.RELAX.isActive()))
isSpinning = false; isSpinning = false;
float angle = (float) Math.atan2(mouseY - (height / 2), mouseX - (width / 2)); float angle = (float) Math.atan2(mouseY - (height / 2), mouseX - (width / 2));
// set initial angle to current mouse position to skip first click // set initial angle to current mouse position to skip first click
if (!isSpinning && Utils.isGameKeyPressed()) { if (!isSpinning && (Utils.isGameKeyPressed() || GameMod.RELAX.isActive())) {
lastAngle = angle; lastAngle = angle;
isSpinning = true; isSpinning = true;
return false; return false;

View File

@ -384,8 +384,9 @@ public class Game extends BasicGameState {
// returning from pause screen: must click previous mouse position // returning from pause screen: must click previous mouse position
if (pauseTime > -1) { if (pauseTime > -1) {
// paused during lead-in or break: continue immediately // paused during lead-in or break, or "relax" or "autopilot": continue immediately
if (pausedMouseX < 0 && pausedMouseY < 0) { if ((pausedMouseX < 0 && pausedMouseY < 0) ||
(GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive())) {
pauseTime = -1; pauseTime = -1;
if (!isLeadIn()) if (!isLeadIn())
MusicController.resume(); MusicController.resume();
@ -429,7 +430,7 @@ public class Game extends BasicGameState {
else { // go to ranking screen else { // go to ranking screen
((GameRanking) game.getState(Opsu.STATE_GAMERANKING)).setGameData(data); ((GameRanking) game.getState(Opsu.STATE_GAMERANKING)).setGameData(data);
ScoreData score = data.getScoreData(osu); ScoreData score = data.getScoreData(osu);
if (!GameMod.AUTO.isActive()) if (!GameMod.AUTO.isActive() && !GameMod.RELAX.isActive() && !GameMod.AUTOPILOT.isActive())
ScoreDB.addScore(score); ScoreDB.addScore(score);
game.enterState(Opsu.STATE_GAMERANKING, new FadeOutTransition(Color.black), new FadeInTransition(Color.black)); game.enterState(Opsu.STATE_GAMERANKING, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
} }
@ -685,8 +686,8 @@ public class Game extends BasicGameState {
return; // successfully skipped return; // successfully skipped
} }
// "auto" mod: ignore user actions // "auto" and "relax" mods: ignore user actions
if (GameMod.AUTO.isActive()) if (GameMod.AUTO.isActive() || GameMod.RELAX.isActive())
return; return;
// circles // circles

View File

@ -102,7 +102,7 @@ public class GameRanking extends BasicGameState {
// background // background
if (!osu.drawBG(width, height, 0.7f, true)) if (!osu.drawBG(width, height, 0.7f, true))
GameImage.MENU_BG.getImage().draw(0,0); GameImage.PLAYFIELD.getImage().draw(0,0);
// ranking screen elements // ranking screen elements
data.drawRankingElements(g, osu); data.drawRankingElements(g, osu);