Spinner Test2

Improves Score accuracy
(still mostly wrong)

inital replay seek
This commit is contained in:
fd 2015-04-05 11:24:05 -04:00
parent fa9accfc88
commit 40e67cedc9
17 changed files with 348 additions and 92 deletions

View File

@ -267,6 +267,14 @@ public class GameData {
/** Beatmap OverallDifficulty value. (0:easy ~ 10:hard) */ /** Beatmap OverallDifficulty value. (0:easy ~ 10:hard) */
private float difficulty = 5f; private float difficulty = 5f;
/** Beatmap ApproachRate value. (0:easy ~ 10:hard) */
private float approachRate = 5f;
/** Beatmap CircleSize value. (2:big ~ 7:small) */
private float circleSize = 5f;
private int difficultyMultiplier = -1;
/** Default text symbol images. */ /** Default text symbol images. */
private Image[] defaultSymbols; private Image[] defaultSymbols;
@ -432,6 +440,18 @@ public class GameData {
public void setDifficulty(float difficulty) { this.difficulty = difficulty; } public void setDifficulty(float difficulty) { this.difficulty = difficulty; }
public float getDifficulty() { return difficulty; } public float getDifficulty() { return difficulty; }
/**
* Sets or returns the approach rate.
*/
public void setApproachRate(float approachRate) { this.approachRate = approachRate; }
public float getApproachRate() { return approachRate; }
/**
* Sets or returns the approach rate.
*/
public void setCircleSize(float circleSize) { this.circleSize = circleSize; }
public float getCircleSize() { return circleSize; }
/** /**
* Sets the array of hit result offsets. * Sets the array of hit result offsets.
*/ */
@ -1118,6 +1138,10 @@ public class GameData {
hitResultList.add(new OsuHitObjectResult(time, result, x, y, null, false)); hitResultList.add(new OsuHitObjectResult(time, result, x, y, null, false));
} }
} }
public void sliderFinalResult(int time, int hitSlider30, float x, float y,
OsuHitObject hitObject, int currentRepeats) {
score += 30;
}
/** /**
* Handles a hit result. * Handles a hit result.
@ -1141,15 +1165,18 @@ public class GameData {
changeHealth(5f); changeHealth(5f);
break; break;
case HIT_100: case HIT_100:
System.out.println("100! "+hitObject+" "+hitObject.getTime()+" "+hitObject.getTypeName());
hitValue = 100; hitValue = 100;
changeHealth(2f); changeHealth(2f);
comboEnd |= 1; comboEnd |= 1;
break; break;
case HIT_50: case HIT_50:
System.out.println("50! "+hitObject+" "+hitObject.getTime()+" "+hitObject.getTypeName());
hitValue = 50; hitValue = 50;
comboEnd |= 2; comboEnd |= 2;
break; break;
case HIT_MISS: case HIT_MISS:
System.out.println("miss! "+hitObject+" "+hitObject.getTime()+" "+hitObject.getTypeName());
hitValue = 0; hitValue = 0;
changeHealth(-10f); changeHealth(-10f);
comboEnd |= 2; comboEnd |= 2;
@ -1164,6 +1191,7 @@ public class GameData {
hitObject.getSampleSet(repeat), hitObject.getSampleSet(repeat),
hitObject.getAdditionSampleSet(repeat)); hitObject.getAdditionSampleSet(repeat));
/** /**
* https://osu.ppy.sh/wiki/Score
* [SCORE FORMULA] * [SCORE FORMULA]
* Score = Hit Value + Hit Value * (Combo * Difficulty * Mod) / 25 * Score = Hit Value + Hit Value * (Combo * Difficulty * Mod) / 25
* - Hit Value: hit result (50, 100, 300), slider ticks, spinner bonus * - Hit Value: hit result (50, 100, 300), slider ticks, spinner bonus
@ -1171,7 +1199,11 @@ public class GameData {
* - Difficulty: the beatmap difficulty * - Difficulty: the beatmap difficulty
* - Mod: mod multipliers * - Mod: mod multipliers
*/ */
score += (hitValue + (hitValue * (Math.max(combo - 1, 0) * difficulty * GameMod.getScoreMultiplier()) / 25)); int comboMulti = Math.max(combo - 1, 0);
if(hitObject.isSlider()){
comboMulti += 1;
}
score += (hitValue + (hitValue * (comboMulti * getDifficultyMultiplier() * GameMod.getScoreMultiplier()) / 25));
incrementComboStreak(); incrementComboStreak();
} }
hitResultCount[result]++; hitResultCount[result]++;
@ -1205,6 +1237,23 @@ public class GameData {
hitResultList.add(new OsuHitObjectResult(time, result, x, y, color, hitObject.isSpinner())); hitResultList.add(new OsuHitObjectResult(time, result, x, y, color, hitObject.isSpinner()));
} }
private int getDifficultyMultiplier() {
return difficultyMultiplier;
}
public void calculateDifficultyMultiplier() {
//https://osu.ppy.sh/wiki/Score#How_to_calculate_the_Difficulty_multiplier
//TODO THE LIES ( difficultyMultiplier )
/*
924 3x1/4 beat notes 0.14stars
924 3x1beat 0.28stars
912 3x1beat wth 1 extra note 10 sec away 0.29stars
seems to be based on hitobject density? (Total Objects/Time)
*/
difficultyMultiplier = (int)((circleSize + difficulty + drainRate) / 6) + 2;
}
/** /**
* Returns a ScoreData object encapsulating all game data. * Returns a ScoreData object encapsulating all game data.
* If score data already exists, the existing object will be returned * If score data already exists, the existing object will be returned
@ -1235,7 +1284,7 @@ public class GameData {
scoreData.perfect = (comboMax == fullObjectCount); scoreData.perfect = (comboMax == fullObjectCount);
scoreData.mods = GameMod.getModState(); scoreData.mods = GameMod.getModState();
scoreData.replayString = (replay == null) ? null : replay.getReplayFilename(); scoreData.replayString = (replay == null) ? null : replay.getReplayFilename();
scoreData.playerName = "OpsuPlayer"; //TODO? scoreData.playerName = "OpsuPlayer"; //TODO GameDataPlayerName?
return scoreData; return scoreData;
} }

View File

@ -452,7 +452,7 @@ public class Options {
private static Resolution resolution = Resolution.RES_1024_768; private static Resolution resolution = Resolution.RES_1024_768;
/** Frame limiters. */ /** Frame limiters. */
private static final int[] targetFPS = { 60, 120, 240 }; private static final int[] targetFPS = { 60, 120, 240, 30, 20, 15, 12 };
/** Index in targetFPS[] array. */ /** Index in targetFPS[] array. */
private static int targetFPSindex = 0; private static int targetFPSindex = 0;
@ -830,8 +830,8 @@ public class Options {
/** /**
* Returns the replay import directory. * Returns the replay import directory.
* If invalid, this will create and return a "SongPacks" directory. * If invalid, this will create and return a "ReplayImport" directory.
* @return the OSZ archive directory * @return the replay import directory
*/ */
public static File getReplayImportDir() { public static File getReplayImportDir() {
if (replayImportDir != null && replayImportDir.isDirectory()) if (replayImportDir != null && replayImportDir.isDirectory())

View File

@ -180,6 +180,7 @@ public class OsuFile implements Comparable<OsuFile> {
/** Combo colors (max 8). */ /** Combo colors (max 8). */
public Color[] combo; public Color[] combo;
/** md5 hash of this file */
public String md5Hash; public String md5Hash;
/** /**

View File

@ -57,7 +57,7 @@ public class OsuGroupList {
/** Set of all beatmap set IDs for the parsed beatmaps. */ /** Set of all beatmap set IDs for the parsed beatmaps. */
private HashSet<Integer> MSIDdb; private HashSet<Integer> MSIDdb;
/** Set of all beatmap set IDs for the parsed beatmaps. */ /** Map of all hash to OsuFile . */
public HashMap<String, OsuFile> beatmapHashesToFile; public HashMap<String, OsuFile> beatmapHashesToFile;

View File

@ -77,6 +77,7 @@ public class ScoreData implements Comparable<ScoreData> {
/** The tooltip string. */ /** The tooltip string. */
private String tooltip; private String tooltip;
/** The players Name. */
public String playerName; public String playerName;
/** Drawing values. */ /** Drawing values. */

View File

@ -244,6 +244,7 @@ public class UI {
int FPSmod = (Options.getTargetFPS() / 60); int FPSmod = (Options.getTargetFPS() / 60);
// TODO: use an image buffer // TODO: use an image buffer
/*
if (newStyle) { if (newStyle) {
// new style: add all points between cursor movements // new style: add all points between cursor movements
if (lastX < 0) { if (lastX < 0) {
@ -264,7 +265,7 @@ public class UI {
int max = 10 * FPSmod; int max = 10 * FPSmod;
if (cursorX.size() > max) if (cursorX.size() > max)
removeCount = cursorX.size() - max; removeCount = cursorX.size() - max;
} }*/
// remove points from the lists // remove points from the lists
for (int i = 0; i < removeCount && !cursorX.isEmpty(); i++) { for (int i = 0; i < removeCount && !cursorX.isEmpty(); i++) {

View File

@ -97,6 +97,11 @@ public class ScoreDB {
// prepare sql statements // prepare sql statements
try { try {
//TODO timestamp as primary key should prevent importing the same replay multiple times
//but if for some magical reason two different replays has the same time stamp
//it will fail, such as copying replays from another drive? which will reset
//the last modified of the file.
insertStmt = connection.prepareStatement( insertStmt = connection.prepareStatement(
"INSERT OR IGNORE INTO scores VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" "INSERT OR IGNORE INTO scores VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
); );
@ -116,7 +121,8 @@ public class ScoreDB {
"DELETE FROM scores WHERE " + "DELETE FROM scores WHERE " +
"timestamp = ? AND MID = ? AND MSID = ? AND title = ? AND artist = ? AND " + "timestamp = ? AND MID = ? AND MSID = ? AND title = ? AND artist = ? AND " +
"creator = ? AND version = ? AND hit300 = ? AND hit100 = ? AND hit50 = ? AND " + "creator = ? AND version = ? AND hit300 = ? AND hit100 = ? AND hit50 = ? AND " +
"geki = ? AND katu = ? AND miss = ? AND score = ? AND combo = ? AND perfect = ? AND mods = ?" "geki = ? AND katu = ? AND miss = ? AND score = ? AND combo = ? AND perfect = ? AND mods = ? AND " +
"replay = ? AND playerName = ?"
); );
} catch (SQLException e) { } catch (SQLException e) {
ErrorHandler.error("Failed to prepare score statements.", e, true); ErrorHandler.error("Failed to prepare score statements.", e, true);
@ -286,6 +292,7 @@ public class ScoreDB {
stmt.setInt(15, data.combo); stmt.setInt(15, data.combo);
stmt.setBoolean(16, data.perfect); stmt.setBoolean(16, data.perfect);
stmt.setInt(17, data.mods); stmt.setInt(17, data.mods);
stmt.setString(18, data.replayString);
stmt.setString(19, data.playerName); stmt.setString(19, data.playerName);
} }

View File

@ -18,6 +18,7 @@
package itdelatrisu.opsu.io; package itdelatrisu.opsu.io;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -51,7 +52,7 @@ public class OsuWriter {
* @param dest the output stream to write to * @param dest the output stream to write to
*/ */
public OsuWriter(OutputStream dest) { public OsuWriter(OutputStream dest) {
this.writer = new DataOutputStream(dest); this.writer = new DataOutputStream(new BufferedOutputStream(dest));
} }
/** /**

View File

@ -36,6 +36,8 @@ public class Circle implements HitObject {
/** The amount of time, in milliseconds, to fade in the circle. */ /** The amount of time, in milliseconds, to fade in the circle. */
private static final int FADE_IN_TIME = 375; private static final int FADE_IN_TIME = 375;
private static float diameter;
/** The associated OsuHitObject. */ /** The associated OsuHitObject. */
private OsuHitObject hitObject; private OsuHitObject hitObject;
@ -54,17 +56,19 @@ public class Circle implements HitObject {
/** Whether or not the circle result ends the combo streak. */ /** Whether or not the circle result ends the combo streak. */
private boolean comboEnd; private boolean comboEnd;
/** /**
* Initializes the Circle data type with map modifiers, images, and dimensions. * Initializes the Circle data type with map modifiers, images, and dimensions.
* @param container the game container * @param container the game container
* @param circleSize the map's circleSize value * @param circleSize the map's circleSize value
*/ */
public static void init(GameContainer container, float circleSize) { public static void init(GameContainer container, float circleSize) {
int diameter = (int) (104 - (circleSize * 8)); diameter = (108 - (circleSize * 8));
diameter = (int) (diameter * OsuHitObject.getXMultiplier()); // convert from Osupixels (640x480) diameter = (diameter * OsuHitObject.getXMultiplier()); // convert from Osupixels (640x480)
GameImage.HITCIRCLE.setImage(GameImage.HITCIRCLE.getImage().getScaledCopy(diameter, diameter)); int diameterInt = (int)diameter;
GameImage.HITCIRCLE_OVERLAY.setImage(GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(diameter, diameter)); GameImage.HITCIRCLE.setImage(GameImage.HITCIRCLE.getImage().getScaledCopy(diameterInt, diameterInt));
GameImage.APPROACHCIRCLE.setImage(GameImage.APPROACHCIRCLE.getImage().getScaledCopy(diameter, diameter)); GameImage.HITCIRCLE_OVERLAY.setImage(GameImage.HITCIRCLE_OVERLAY.getImage().getScaledCopy(diameterInt, diameterInt));
GameImage.APPROACHCIRCLE.setImage(GameImage.APPROACHCIRCLE.getImage().getScaledCopy(diameterInt, diameterInt));
} }
/** /**
@ -113,16 +117,19 @@ public class Circle implements HitObject {
private int hitResult(int time) { private int hitResult(int time) {
int timeDiff = Math.abs(time); int timeDiff = Math.abs(time);
int[] hitResultOffset = game.getHitResultOffsets(); int[] hitResultOffset = game.getHitResultOffsets();
int result = -1; int result = -1;
if (timeDiff < hitResultOffset[GameData.HIT_300]) if (timeDiff <= hitResultOffset[GameData.HIT_300])
result = GameData.HIT_300; result = GameData.HIT_300;
else if (timeDiff < hitResultOffset[GameData.HIT_100]) else if (timeDiff <= hitResultOffset[GameData.HIT_100])
result = GameData.HIT_100; result = GameData.HIT_100;
else if (timeDiff < hitResultOffset[GameData.HIT_50]) else if (timeDiff <= hitResultOffset[GameData.HIT_50])
result = GameData.HIT_50; result = GameData.HIT_50;
else if (timeDiff < hitResultOffset[GameData.HIT_MISS]) else if (timeDiff <= hitResultOffset[GameData.HIT_MISS]){
result = GameData.HIT_MISS; result = GameData.HIT_MISS;
System.out.println(timeDiff);
}
//else not a hit //else not a hit
return result; return result;
@ -131,8 +138,7 @@ public class Circle implements HitObject {
@Override @Override
public boolean mousePressed(int x, int y, int trackPosition) { public boolean mousePressed(int x, int y, int trackPosition) {
double distance = Math.hypot(this.x - x, this.y - y); double distance = Math.hypot(this.x - x, this.y - y);
int circleRadius = GameImage.HITCIRCLE.getImage().getWidth() / 2; if (distance < diameter/2) {
if (distance < circleRadius) {
int timeDiff = trackPosition - hitObject.getTime(); int timeDiff = trackPosition - hitObject.getTime();
int result = hitResult(timeDiff); int result = hitResult(timeDiff);
@ -152,7 +158,7 @@ public class Circle implements HitObject {
int[] hitResultOffset = game.getHitResultOffsets(); int[] hitResultOffset = game.getHitResultOffsets();
boolean isAutoMod = GameMod.AUTO.isActive(); boolean isAutoMod = GameMod.AUTO.isActive();
if (overlap || trackPosition > time + hitResultOffset[GameData.HIT_50]) { if (trackPosition > time + hitResultOffset[GameData.HIT_50]) {
if (isAutoMod) // "auto" mod: catch any missed notes due to lag if (isAutoMod) // "auto" mod: catch any missed notes due to lag
data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitObject, 0); data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitObject, 0);
@ -187,4 +193,9 @@ public class Circle implements HitObject {
this.x = hitObject.getScaledX(); this.x = hitObject.getScaledX();
this.y = hitObject.getScaledY(); this.y = hitObject.getScaledY();
} }
@Override
public void reset() {
}
} }

View File

@ -63,4 +63,9 @@ public class DummyObject implements HitObject {
this.x = hitObject.getScaledX(); this.x = hitObject.getScaledX();
this.y = hitObject.getScaledY(); this.y = hitObject.getScaledY();
} }
@Override
public void reset() {
}
} }

View File

@ -69,4 +69,9 @@ public interface HitObject {
* Updates the position of the hit object. * Updates the position of the hit object.
*/ */
public void updatePosition(); public void updatePosition();
/**
* Resets the hit object so that it can be reused.
*/
public void reset();
} }

View File

@ -46,6 +46,10 @@ public class Slider implements HitObject {
/** Rate at which slider ticks are placed. */ /** Rate at which slider ticks are placed. */
private static float sliderTickRate = 1.0f; private static float sliderTickRate = 1.0f;
private static float followRadius;
private static float diameter;
/** The amount of time, in milliseconds, to fade in the slider. */ /** The amount of time, in milliseconds, to fade in the slider. */
private static final int FADE_IN_TIME = 375; private static final int FADE_IN_TIME = 375;
@ -97,6 +101,8 @@ public class Slider implements HitObject {
/** Container dimensions. */ /** Container dimensions. */
private static int containerWidth, containerHeight; private static int containerWidth, containerHeight;
/** /**
* Initializes the Slider data type with images and dimensions. * Initializes the Slider data type with images and dimensions.
@ -107,10 +113,13 @@ public class Slider implements HitObject {
public static void init(GameContainer container, float circleSize, OsuFile osu) { public static void init(GameContainer container, float circleSize, OsuFile osu) {
containerWidth = container.getWidth(); containerWidth = container.getWidth();
containerHeight = container.getHeight(); containerHeight = container.getHeight();
int diameter = (int) (104 - (circleSize * 8)); diameter = (108 - (circleSize * 8));
diameter = (int) (diameter * OsuHitObject.getXMultiplier()); // convert from Osupixels (640x480) diameter = (diameter * OsuHitObject.getXMultiplier()); // convert from Osupixels (640x480)
int diameterInt = (int)diameter;
followRadius = diameter / 2 * 3f;
// slider ball // slider ball
if (GameImage.SLIDER_BALL.hasSkinImages() || if (GameImage.SLIDER_BALL.hasSkinImages() ||
(!GameImage.SLIDER_BALL.hasSkinImage() && GameImage.SLIDER_BALL.getImages() != null)) (!GameImage.SLIDER_BALL.hasSkinImage() && GameImage.SLIDER_BALL.getImages() != null))
@ -118,11 +127,11 @@ public class Slider implements HitObject {
else else
sliderBallImages = new Image[]{ GameImage.SLIDER_BALL.getImage() }; sliderBallImages = new Image[]{ GameImage.SLIDER_BALL.getImage() };
for (int i = 0; i < sliderBallImages.length; i++) for (int i = 0; i < sliderBallImages.length; i++)
sliderBallImages[i] = sliderBallImages[i].getScaledCopy(diameter * 118 / 128, diameter * 118 / 128); sliderBallImages[i] = sliderBallImages[i].getScaledCopy(diameterInt * 118 / 128, diameterInt * 118 / 128);
GameImage.SLIDER_FOLLOWCIRCLE.setImage(GameImage.SLIDER_FOLLOWCIRCLE.getImage().getScaledCopy(diameter * 259 / 128, diameter * 259 / 128)); GameImage.SLIDER_FOLLOWCIRCLE.setImage(GameImage.SLIDER_FOLLOWCIRCLE.getImage().getScaledCopy(diameterInt * 259 / 128, diameterInt * 259 / 128));
GameImage.REVERSEARROW.setImage(GameImage.REVERSEARROW.getImage().getScaledCopy(diameter, diameter)); GameImage.REVERSEARROW.setImage(GameImage.REVERSEARROW.getImage().getScaledCopy(diameterInt, diameterInt));
GameImage.SLIDER_TICK.setImage(GameImage.SLIDER_TICK.getImage().getScaledCopy(diameter / 4, diameter / 4)); GameImage.SLIDER_TICK.setImage(GameImage.SLIDER_TICK.getImage().getScaledCopy(diameterInt / 4, diameterInt / 4));
sliderMultiplier = osu.sliderMultiplier; sliderMultiplier = osu.sliderMultiplier;
sliderTickRate = osu.sliderTickRate; sliderTickRate = osu.sliderTickRate;
@ -266,6 +275,55 @@ public class Slider implements HitObject {
* @return the hit result (GameData.HIT_* constants) * @return the hit result (GameData.HIT_* constants)
*/ */
private int hitResult() { private int hitResult() {
/*
time scoredelta score-hit-initial-tick= unaccounted
(1/4 - 1) 396 - 300 - 30 46
(1+1/4 - 2) 442 - 300 - 30 - 10
(2+1/4 - 3) 488 - 300 - 30 - 2*10 896 (408)5x
(3+1/4 - 4) 534 - 300 - 30 - 3*10
(4+1/4 - 5) 580 - 300 - 30 - 4*10
(5+1/4 - 6) 626 - 300 - 30 - 5*10
(6+1/4 - 7) 672 - 300 - 30 - 6*10
difficultyMulti = 3 (+36 per combo)
score =
(t)ticks(10) * nticks +
(h)hitValue
(c)combo (hitValue/25 * difficultyMultiplier*(combo-1))
(i)initialHit (30) +
(f)finalHit(30) +
s t h c i f
626 - 10*5 - 300 - 276(-216 - 30 - 30) (all)(7x)
240 - 10*5 - 100 - 90 (-60 <- 30>) (no final or initial)(6x)
218 - 10*4 - 100 - 78 (-36 - 30) (4 tick no initial)(5x)
196 - 10*3 - 100 - 66 (-24 - 30 ) (3 tick no initial)(4x)
112 - 10*2 - 50 - 42 (-12 - 30 ) (2 tick no initial)(3x)
96 - 10 - 50 - 36 ( -6 - 30 ) (1 tick no initial)(2x)
206 - 10*4 - 100 - 66 (-36 - 30 ) (4 tick no initial)(4x)
184 - 10*3 - 100 - 54 (-24 - 30 ) (3 tick no initial)(3x)
90 - 10 - 50 - 30 ( - 30 ) (1 tick no initial)(0x)
194 - 10*4 - 100 - 54 (-24 - 30 ) (4 tick no initial)(3x)
170 - 10*4 - 100 - 30 ( - 30 ) (4 tick no final)(0x)
160 - 10*3 - 100 - 30 ( - 30 ) (3 tick no final)(0x)
100 - 10*2 - 50 - 30 ( - 30 ) (2 tick no final)(0x)
198 - 10*5 - 100 - 48 (-36 ) (no initial and final)(5x)
110 - 50 - ( - 30 - 30 ) (final and initial no tick)(0x)
80 - 50 - ( <- 30> ) (only final or initial)(0x)
140 - 10*4 - 100 - 0 (4 ticks only)(0x)
80 - 10*3 - 50 - 0 (3 tick only)(0x)
70 - 10*2 - 50 - 0 (2 tick only)(0x)
60 - 10 - 50 - 0 (1 tick only)(0x)
*/
float tickRatio = (float) ticksHit / tickIntervals; float tickRatio = (float) ticksHit / tickIntervals;
int result; int result;
@ -277,7 +335,7 @@ public class Slider implements HitObject {
result = GameData.HIT_50; result = GameData.HIT_50;
else else
result = GameData.HIT_MISS; result = GameData.HIT_MISS;
if (currentRepeats % 2 == 0) { // last circle if (currentRepeats % 2 == 0) { // last circle
float[] lastPos = curve.pointAt(1); float[] lastPos = curve.pointAt(1);
data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result, data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result,
@ -296,8 +354,7 @@ public class Slider implements HitObject {
return false; return false;
double distance = Math.hypot(this.x - x, this.y - y); double distance = Math.hypot(this.x - x, this.y - y);
int circleRadius = GameImage.HITCIRCLE.getImage().getWidth() / 2; if (distance < diameter / 2) {
if (distance < circleRadius) {
int timeDiff = Math.abs(trackPosition - hitObject.getTime()); int timeDiff = Math.abs(trackPosition - hitObject.getTime());
int[] hitResultOffset = game.getHitResultOffsets(); int[] hitResultOffset = game.getHitResultOffsets();
@ -353,26 +410,29 @@ public class Slider implements HitObject {
} }
// end of slider // end of slider
if (overlap || trackPosition > hitObject.getTime() + sliderTimeTotal) { if (trackPosition > hitObject.getTime() + sliderTimeTotal) {
tickIntervals++; tickIntervals++;
// check if cursor pressed and within end circle // check if cursor pressed and within end circle
if (keyPressed || GameMod.RELAX.isActive()) { if (keyPressed || 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; if (distance < followRadius) //TODO IDK Magic numbers
if (distance < followCircleRadius)
sliderClickedFinal = true; sliderClickedFinal = true;
} }
// final circle hit // final circle hit
if (sliderClickedFinal) if (sliderClickedFinal){
ticksHit++; ticksHit++;
data.sliderFinalResult(hitObject.getTime(), GameData.HIT_SLIDER30, this.x, this.y, hitObject, currentRepeats);
}
// "auto" mod: always send a perfect hit result // "auto" mod: always send a perfect hit result
if (isAutoMod) if (isAutoMod)
ticksHit = tickIntervals; ticksHit = tickIntervals;
//TODO missing the final shouldn't increment the combo
// calculate and send slider result // calculate and send slider result
hitResult(); hitResult();
return true; return true;
@ -405,8 +465,7 @@ public class Slider implements HitObject {
// holding slider... // holding slider...
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; if (((keyPressed || GameMod.RELAX.isActive()) && distance < followRadius) || isAutoMod) {
if (((keyPressed || 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);
@ -487,4 +546,16 @@ public class Slider implements HitObject {
return (floor % 2 == 0) ? t - floor : floor + 1 - t; return (floor % 2 == 0) ? t - floor : floor + 1 - t;
} }
} }
@Override
public void reset() {
sliderClickedInitial = false;
sliderClickedFinal = false;
followCircleActive = false;
currentRepeats = 0;
tickIndex = 0;
ticksHit = 0;
tickIntervals = 1;
}
} }

View File

@ -40,12 +40,13 @@ public class Spinner implements HitObject {
private static int width, height; private static int width, height;
/** The number of rotation velocities to store. */ /** The number of rotation velocities to store. */
// note: currently takes about 200ms to spin up (4 * 50) // note: currently takes about 200ms to spin up (1000/60 * 12)
private static final int MAX_ROTATION_VELOCITIES = 50; private static final int MAX_ROTATION_VELOCITIES = 12;
/** The amount of time, in milliseconds, before another velocity is stored. */ /** The amount of time, in milliseconds, before another velocity is stored. */
private static final int DELTA_UPDATE_TIME = 16; private static final float DELTA_UPDATE_TIME = 1000 / 60f;
/** The amount of time, in milliseconds, to fade in the spinner. */ /** The amount of time, in milliseconds, to fade in the spinner. */
private static final int FADE_IN_TIME = 500; private static final int FADE_IN_TIME = 500;
@ -59,6 +60,8 @@ public class Spinner implements HitObject {
TWO_PI = (float) (Math.PI * 2), TWO_PI = (float) (Math.PI * 2),
HALF_PI = (float) (Math.PI / 2); HALF_PI = (float) (Math.PI / 2);
private static final float MAX_ANG_DIFF = DELTA_UPDATE_TIME * 477 / 60 / 1000 * TWO_PI; // ~95.3
/** The associated OsuHitObject. */ /** The associated OsuHitObject. */
private OsuHitObject hitObject; private OsuHitObject hitObject;
@ -78,19 +81,23 @@ public class Spinner implements HitObject {
private float rotationsNeeded; private float rotationsNeeded;
/** The remaining amount of time that was not used. */ /** The remaining amount of time that was not used. */
private int deltaOverflow; private float deltaOverflow;
/** The sum of all the velocities in storedVelocities. */ /** The sum of all the velocities in storedVelocities. */
private float sumVelocity = 0f; private float sumDeltaAngle = 0f;
/** Array holding the most recent rotation velocities. */ /** Array holding the most recent rotation velocities. */
private float[] storedVelocities = new float[MAX_ROTATION_VELOCITIES]; private float[] storedDeltaAngle = new float[MAX_ROTATION_VELOCITIES];
/** True if the mouse cursor is pressed. */ /** True if the mouse cursor is pressed. */
private boolean isSpinning; private boolean isSpinning;
/** Current index of the stored velocities in rotations/second. */ /** Current index of the stored velocities in rotations/second. */
private int velocityIndex = 0; private int deltaAngleIndex = 0;
private float deltaAngleOverflow = 0;
private int drawnRPM = 0;
/** /**
* Initializes the Spinner data type with images and dimensions. * Initializes the Spinner data type with images and dimensions.
@ -112,8 +119,9 @@ public class Spinner implements HitObject {
this.data = data; this.data = data;
// calculate rotations needed // calculate rotations needed
float spinsPerMinute = 100 + (data.getDifficulty() * 15); float spinsPerMinute = 94 + (data.getDifficulty() * 15);
rotationsNeeded = spinsPerMinute * (hitObject.getEndTime() - hitObject.getTime()) / 60000f; rotationsNeeded = spinsPerMinute * (hitObject.getEndTime() - hitObject.getTime()) / 60000f;
System.out.println("rotationsNeeded "+rotationsNeeded);
} }
@Override @Override
@ -135,12 +143,11 @@ public class Spinner implements HitObject {
Utils.COLOR_BLACK_ALPHA.a = oldAlpha; Utils.COLOR_BLACK_ALPHA.a = oldAlpha;
// rpm // rpm
int rpm = Math.abs(Math.round(sumVelocity / storedVelocities.length * 60));
Image rpmImg = GameImage.SPINNER_RPM.getImage(); Image rpmImg = GameImage.SPINNER_RPM.getImage();
rpmImg.setAlpha(alpha); rpmImg.setAlpha(alpha);
rpmImg.drawCentered(width / 2f, height - rpmImg.getHeight() / 2f); rpmImg.drawCentered(width / 2f, height - rpmImg.getHeight() / 2f);
if (timeDiff < 0) if (timeDiff < 0)
data.drawSymbolString(Integer.toString(rpm), (width + rpmImg.getWidth() * 0.95f) / 2f, data.drawSymbolString(Integer.toString(drawnRPM), (width + rpmImg.getWidth() * 0.95f) / 2f,
height - data.getScoreSymbolImage('0').getHeight() * 1.025f, 1f, 1f, true); height - data.getScoreSymbolImage('0').getHeight() * 1.025f, 1f, 1f, true);
// spinner meter (subimage) // spinner meter (subimage)
@ -196,7 +203,11 @@ public class Spinner implements HitObject {
} }
@Override @Override
public boolean mousePressed(int x, int y, int trackPosition) { return false; } // not used public boolean mousePressed(int x, int y, int trackPosition) {
lastAngle = (float) Math.atan2(x - (height / 2), y - (width / 2));
System.out.println("lastAngle:"+lastAngle);
return false;
}
@Override @Override
public boolean update(boolean overlap, int delta, int mouseX, int mouseY, boolean keyPressed, int trackPosition) { public boolean update(boolean overlap, int delta, int mouseX, int mouseY, boolean keyPressed, int trackPosition) {
@ -211,22 +222,25 @@ public class Spinner implements HitObject {
if (isSpinning && !(keyPressed || GameMod.RELAX.isActive())) if (isSpinning && !(keyPressed || GameMod.RELAX.isActive()))
isSpinning = false; isSpinning = false;
System.out.println("Spinner update "+mouseX+" "+mouseY+" "+deltaOverflow);
// spin automatically
// http://osu.ppy.sh/wiki/FAQ#Spinners
deltaOverflow += delta; deltaOverflow += delta;
while (deltaOverflow >= DELTA_UPDATE_TIME) {
// spin automatically float angle = 0;
// http://osu.ppy.sh/wiki/FAQ#Spinners if (deltaOverflow >= DELTA_UPDATE_TIME){
float angle;
if (GameMod.AUTO.isActive()) { if (GameMod.AUTO.isActive()) {
lastAngle = 0; lastAngle = 0;
angle = delta * AUTO_MULTIPLIER; angle = deltaOverflow * AUTO_MULTIPLIER;
isSpinning = true; isSpinning = true;
} else if (GameMod.SPUN_OUT.isActive() || GameMod.AUTOPILOT.isActive()) { } else if (GameMod.SPUN_OUT.isActive() || GameMod.AUTOPILOT.isActive()) {
lastAngle = 0; lastAngle = 0;
angle = delta * SPUN_OUT_MULTIPLIER; angle = deltaOverflow * SPUN_OUT_MULTIPLIER;
isSpinning = true; isSpinning = true;
} else { } else {
angle = (float) Math.atan2(mouseY - (height / 2), mouseX - (width / 2)); 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 && (keyPressed || GameMod.RELAX.isActive())) { if (!isSpinning && (keyPressed || GameMod.RELAX.isActive())) {
lastAngle = angle; lastAngle = angle;
@ -234,33 +248,45 @@ public class Spinner implements HitObject {
return false; return false;
} }
} }
// make angleDiff the smallest angle change possible // make angleDiff the smallest angle change possible
// (i.e. 1/4 rotation instead of 3/4 rotation) // (i.e. 1/4 rotation instead of 3/4 rotation)
float angleDiff = angle - lastAngle; float angleDiff = angle - lastAngle;
lastAngle = angle;
if (angleDiff < -Math.PI) if (angleDiff < -Math.PI)
angleDiff += TWO_PI; angleDiff += TWO_PI;
else if (angleDiff > Math.PI) else if (angleDiff > Math.PI)
angleDiff -= TWO_PI; angleDiff -= TWO_PI;
System.out.println("AngleDiff "+angleDiff);
// spin caused by the cursor
float cursorVelocity = 0;
if (isSpinning) if (isSpinning)
cursorVelocity = Utils.clamp(angleDiff / TWO_PI / delta * 1000, -8f, 8f); deltaAngleOverflow += angleDiff;
}
sumVelocity -= storedVelocities[velocityIndex];
sumVelocity += cursorVelocity; while (deltaOverflow >= DELTA_UPDATE_TIME) {
storedVelocities[velocityIndex++] = cursorVelocity; System.out.println("Spinner update2 "+mouseX+" "+mouseY+" "+deltaAngleOverflow+" "+deltaOverflow);
velocityIndex %= storedVelocities.length;
deltaOverflow -= DELTA_UPDATE_TIME;
float rotationAngle = sumVelocity / storedVelocities.length * TWO_PI * delta / 1000; // spin caused by the cursor
float deltaAngle = 0;
if (isSpinning){
deltaAngle = deltaAngleOverflow * DELTA_UPDATE_TIME / deltaOverflow;
deltaAngleOverflow -= deltaAngle;
deltaAngle = Utils.clamp(deltaAngle, -MAX_ANG_DIFF, MAX_ANG_DIFF);
}
sumDeltaAngle -= storedDeltaAngle[deltaAngleIndex];
sumDeltaAngle += deltaAngle;
storedDeltaAngle[deltaAngleIndex++] = deltaAngle;
deltaAngleIndex %= storedDeltaAngle.length;
deltaOverflow -= DELTA_UPDATE_TIME;
float rotationAngle = sumDeltaAngle / MAX_ROTATION_VELOCITIES;
rotationAngle = Utils.clamp(rotationAngle, -MAX_ANG_DIFF, MAX_ANG_DIFF);//*0.9650f;
float rotationPerSec = rotationAngle * (1000/DELTA_UPDATE_TIME) / TWO_PI;
drawnRPM = (int)(Math.abs(rotationPerSec * 60));
System.out.println("Ang DIFF:"+deltaAngle+" "+rotations+" "+angle+" "+lastAngle+" "+rotationAngle+" "+sumDeltaAngle+" "+MAX_ANG_DIFF);
rotate(rotationAngle); rotate(rotationAngle);
if (Math.abs(rotationAngle) > 0.00001f) if (Math.abs(rotationAngle) > 0.00001f)
data.changeHealth(delta * GameData.HP_DRAIN_MULTIPLIER); data.changeHealth(DELTA_UPDATE_TIME * GameData.HP_DRAIN_MULTIPLIER);
lastAngle = angle;
} }
return false; return false;
} }
@ -304,15 +330,37 @@ public class Spinner implements HitObject {
// added one whole rotation... // added one whole rotation...
if (Math.floor(newRotations) > rotations) { if (Math.floor(newRotations) > rotations) {
//TODO seems to give 1100 points per spin but also an extra 100 for some spinners
if (newRotations > rotationsNeeded) { // extra rotations if (newRotations > rotationsNeeded) { // extra rotations
data.changeScore(1000); data.changeScore(1000);
SoundController.playSound(SoundEffect.SPINNERBONUS); SoundController.playSound(SoundEffect.SPINNERBONUS);
} else { }
data.changeScore(100);
SoundController.playSound(SoundEffect.SPINNERSPIN);
}
//*
if (Math.floor(newRotations + 0.5f) > rotations + 0.5f) {
if (newRotations + 0.5f > rotationsNeeded) { // extra rotations
data.changeScore(100); data.changeScore(100);
SoundController.playSound(SoundEffect.SPINNERSPIN);
} }
} }
//*/
rotations = newRotations; rotations = newRotations;
} }
@Override
public void reset() {
deltaAngleIndex = 0;
sumDeltaAngle = 0;
for(int i=0; i<storedDeltaAngle.length; i++){
storedDeltaAngle[i] = 0;
}
drawRotation = 0;
rotations = 0;
deltaOverflow = 0;
isSpinning = false;
}
} }

View File

@ -138,6 +138,11 @@ public class Replay {
loaded = true; loaded = true;
} }
public void loadHeader() throws IOException {
OsuReader reader = new OsuReader(file);
loadHeader(reader);
reader.close();
}
/** /**
* Returns a ScoreData object encapsulating all game data. * Returns a ScoreData object encapsulating all game data.
* If score data already exists, the existing object will be returned * If score data already exists, the existing object will be returned
@ -181,7 +186,7 @@ public class Replay {
private void loadHeader(OsuReader reader) throws IOException { private void loadHeader(OsuReader reader) throws IOException {
this.mode = reader.readByte(); this.mode = reader.readByte();
this.version = reader.readInt(); this.version = reader.readInt();
System.out.println("Header:"+file.getName()+" "+mode+" "+version); //System.out.println("Header:"+file.getName()+" "+mode+" "+version);
this.beatmapHash = reader.readString(); this.beatmapHash = reader.readString();
this.playerName = reader.readString(); this.playerName = reader.readString();
this.replayHash = reader.readString(); this.replayHash = reader.readString();
@ -203,6 +208,7 @@ public class Replay {
* @throws IOException * @throws IOException
*/ */
private void loadData(OsuReader reader) throws IOException { private void loadData(OsuReader reader) throws IOException {
//System.out.println("Load Data");
// life data // life data
String[] lifeData = reader.readString().split(","); String[] lifeData = reader.readString().split(",");
List<LifeFrame> lifeFrameList = new ArrayList<LifeFrame>(lifeData.length); List<LifeFrame> lifeFrameList = new ArrayList<LifeFrame>(lifeData.length);
@ -369,8 +375,8 @@ public class Replay {
@Override @Override
public String toString() { public String toString() {
final int LINE_SPLIT = 5; final int LINE_SPLIT = 1;
final int MAX_LINES = LINE_SPLIT * 10; final int MAX_LINES = LINE_SPLIT * 99999999;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("File: "); sb.append(file.getName()); sb.append('\n'); sb.append("File: "); sb.append(file.getName()); sb.append('\n');

View File

@ -12,16 +12,22 @@ import java.io.IOException;
public class ReplayImporter { public class ReplayImporter {
public static void importAllReplaysFromDir(File dir) { public static void importAllReplaysFromDir(File dir) {
System.out.println(OsuGroupList.get().beatmapHashesToFile);
for (File replayToImport : dir.listFiles()) { for (File replayToImport : dir.listFiles()) {
try { try {
Replay r = new Replay(replayToImport); Replay r = new Replay(replayToImport);
r.load(); r.loadHeader();
OsuFile oFile = OsuGroupList.get().getFileFromBeatmapHash(r.beatmapHash); OsuFile oFile = OsuGroupList.get().getFileFromBeatmapHash(r.beatmapHash);
if(oFile != null){ if(oFile != null){
File replaydir = Options.getReplayDir();
if (!replaydir.isDirectory()) {
if (!replaydir.mkdir()) {
ErrorHandler.error("Failed to create replay directory.", null, false);
return;
}
}
//ErrorHandler.error("Importing"+replayToImport+" forBeatmap:"+oFile, null, false); //ErrorHandler.error("Importing"+replayToImport+" forBeatmap:"+oFile, null, false);
ScoreData data = r.getScoreData(oFile); ScoreData data = r.getScoreData(oFile);
File moveToFile = new File(Options.getReplayDir(),replayToImport.getName()); File moveToFile = new File(replaydir, replayToImport.getName());
System.out.println("Moving "+replayToImport+" to "+moveToFile); System.out.println("Moving "+replayToImport+" to "+moveToFile);
if( if(
!replayToImport.renameTo(moveToFile) !replayToImport.renameTo(moveToFile)
@ -35,7 +41,6 @@ public class ReplayImporter {
//ErrorHandler.error("Could not find beatmap for replay "+replayToImport, null, false); //ErrorHandler.error("Could not find beatmap for replay "+replayToImport, null, false);
} }
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace(); //e.printStackTrace();
System.out.println(e); System.out.println(e);
} }

View File

@ -217,6 +217,10 @@ public class Game extends BasicGameState {
private Input input; private Input input;
private int state; private int state;
private int width;
private int height;
public Game(int state) { public Game(int state) {
this.state = state; this.state = state;
} }
@ -228,8 +232,8 @@ public class Game extends BasicGameState {
this.game = game; this.game = game;
input = container.getInput(); input = container.getInput();
int width = container.getWidth(); width = container.getWidth();
int height = container.getHeight(); height = container.getHeight();
// create offscreen graphics // create offscreen graphics
offscreen = new Image(width, height); offscreen = new Image(width, height);
@ -597,6 +601,27 @@ public class Game extends BasicGameState {
// out of frames, use previous data // out of frames, use previous data
if (replayIndex >= replay.frames.length) if (replayIndex >= replay.frames.length)
updateGame(replayX, replayY, delta, MusicController.getPosition(), lastKeysPressed); updateGame(replayX, replayY, delta, MusicController.getPosition(), lastKeysPressed);
//TODO probably should to disable sounds then reseek to the new position
if(replayIndex-1 >= 1 && replayIndex < replay.frames.length && trackPosition < replay.frames[replayIndex-1].getTime()){
replayIndex = 0;
while(objectIndex>=0){
hitObjects[objectIndex].reset();
objectIndex--;
}
// load the first timingPoint
if (!osu.timingPoints.isEmpty()) {
OsuTimingPoint timingPoint = osu.timingPoints.get(0);
if (!timingPoint.isInherited()) {
beatLengthBase = beatLength = timingPoint.getBeatLength();
HitSound.setDefaultSampleSet(timingPoint.getSampleType());
SoundController.setSampleVolume(timingPoint.getSampleVolume());
timingPointIndex++;
}
}
resetGameData();
}
// update and run replay frames // update and run replay frames
while (replayIndex < replay.frames.length && trackPosition >= replay.frames[replayIndex].getTime()) { while (replayIndex < replay.frames.length && trackPosition >= replay.frames[replayIndex].getTime()) {
@ -743,7 +768,7 @@ public class Game extends BasicGameState {
while (objectIndex < hitObjects.length && trackPosition > osu.objects[objectIndex].getTime()) { while (objectIndex < hitObjects.length && trackPosition > osu.objects[objectIndex].getTime()) {
// check if we've already passed the next object's start time // check if we've already passed the next object's start time
boolean overlap = (objectIndex + 1 < hitObjects.length && boolean overlap = (objectIndex + 1 < hitObjects.length &&
trackPosition > osu.objects[objectIndex + 1].getTime() - hitResultOffset[GameData.HIT_300]); trackPosition > osu.objects[objectIndex + 1].getTime() - hitResultOffset[GameData.HIT_50]);
// update hit object and check completion status // update hit object and check completion status
if (hitObjects[objectIndex].update(overlap, delta, mouseX, mouseY, keyPressed, trackPosition)) if (hitObjects[objectIndex].update(overlap, delta, mouseX, mouseY, keyPressed, trackPosition))
@ -879,6 +904,11 @@ public class Game extends BasicGameState {
// only allow skip button // only allow skip button
if (button != Input.MOUSE_MIDDLE_BUTTON && skipButton.contains(x, y)) if (button != Input.MOUSE_MIDDLE_BUTTON && skipButton.contains(x, y))
skipIntro(); skipIntro();
if(y < 50){
float pos = (float)x / width * osu.endTime;
System.out.println("Seek to"+pos);
MusicController.setPosition((int)pos);
}
return; return;
} }
@ -1028,13 +1058,21 @@ public class Game extends BasicGameState {
MusicController.setPosition(0); MusicController.setPosition(0);
MusicController.pause(); MusicController.pause();
if (!osu.timingPoints.isEmpty()) {
OsuTimingPoint timingPoint = osu.timingPoints.get(0);
if (!timingPoint.isInherited()) {
beatLengthBase = beatLength = timingPoint.getBeatLength();
}
}
hitObjects = new HitObject[osu.objects.length];
// initialize object maps // initialize object maps
for (int i = 0; i < osu.objects.length; i++) { for (int i = 0; i < osu.objects.length; i++) {
OsuHitObject hitObject = osu.objects[i]; OsuHitObject hitObject = osu.objects[i];
// is this the last note in the combo? // is this the last note in the combo?
boolean comboEnd = false; boolean comboEnd = false;
if (i + 1 < osu.objects.length && osu.objects[i + 1].isNewCombo()) if (i + 1 >= osu.objects.length || osu.objects[i + 1].isNewCombo())
comboEnd = true; comboEnd = true;
Color color = osu.combo[hitObject.getComboIndex()]; Color color = osu.combo[hitObject.getComboIndex()];
@ -1086,6 +1124,7 @@ public class Game extends BasicGameState {
// load replay frames // load replay frames
if (isReplay) { if (isReplay) {
//System.out.println(replay.toString());
// load mods // load mods
previousMods = GameMod.getModState(); previousMods = GameMod.getModState();
GameMod.loadModState(replay.mods); GameMod.loadModState(replay.mods);
@ -1238,7 +1277,6 @@ public class Game extends BasicGameState {
* Resets all game data and structures. * Resets all game data and structures.
*/ */
public void resetGameData() { public void resetGameData() {
hitObjects = new HitObject[osu.objects.length];
data.clear(); data.clear();
objectIndex = 0; objectIndex = 0;
breakIndex = 0; breakIndex = 0;
@ -1376,15 +1414,25 @@ public class Game extends BasicGameState {
// overallDifficulty (hit result time offsets) // overallDifficulty (hit result time offsets)
hitResultOffset = new int[GameData.HIT_MAX]; hitResultOffset = new int[GameData.HIT_MAX];
//*
float mult = 0.608f;
hitResultOffset[GameData.HIT_300] = (int) ((128 - (overallDifficulty * 9.6))*mult);
hitResultOffset[GameData.HIT_100] = (int) ((224 - (overallDifficulty * 12.8))*mult);
hitResultOffset[GameData.HIT_50] = (int) ((320 - (overallDifficulty * 16))*mult);
hitResultOffset[GameData.HIT_MISS] = (int) ((1000 - (overallDifficulty * 10))*mult);
/*/
hitResultOffset[GameData.HIT_300] = (int) (78 - (overallDifficulty * 6)); hitResultOffset[GameData.HIT_300] = (int) (78 - (overallDifficulty * 6));
hitResultOffset[GameData.HIT_100] = (int) (138 - (overallDifficulty * 8)); hitResultOffset[GameData.HIT_100] = (int) (138 - (overallDifficulty * 8));
hitResultOffset[GameData.HIT_50] = (int) (198 - (overallDifficulty * 10)); hitResultOffset[GameData.HIT_50] = (int) (198 - (overallDifficulty * 10));
hitResultOffset[GameData.HIT_MISS] = (int) (500 - (overallDifficulty * 10)); hitResultOffset[GameData.HIT_MISS] = (int) (500 - (overallDifficulty * 10));
//*/
// HPDrainRate (health change), overallDifficulty (scoring) // HPDrainRate (health change), overallDifficulty (scoring)
data.setDrainRate(HPDrainRate); data.setDrainRate(HPDrainRate);
data.setDifficulty(overallDifficulty); data.setDifficulty(overallDifficulty);
data.setApproachRate(approachRate);
data.setCircleSize(circleSize);
data.setHitResultOffset(hitResultOffset); data.setHitResultOffset(hitResultOffset);
data.calculateDifficultyMultiplier();
} }
/** /**
@ -1491,6 +1539,7 @@ public class Game extends BasicGameState {
* @param keys the keys that are pressed * @param keys the keys that are pressed
*/ */
private void sendGameKeyPress(int keys, int x, int y, int trackPosition) { private void sendGameKeyPress(int keys, int x, int y, int trackPosition) {
System.out.println("Game Key Pressed"+keys+" "+x+" "+y+" "+objectIndex);
if (objectIndex >= hitObjects.length) // nothing to do here if (objectIndex >= hitObjects.length) // nothing to do here
return; return;

View File

@ -18,11 +18,9 @@
package itdelatrisu.opsu.states; package itdelatrisu.opsu.states;
import itdelatrisu.opsu.ErrorHandler;
import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.GameImage;
import itdelatrisu.opsu.Opsu; import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.Options; import itdelatrisu.opsu.Options;
import itdelatrisu.opsu.OsuFile;
import itdelatrisu.opsu.OsuGroupList; import itdelatrisu.opsu.OsuGroupList;
import itdelatrisu.opsu.OsuParser; import itdelatrisu.opsu.OsuParser;
import itdelatrisu.opsu.OszUnpacker; import itdelatrisu.opsu.OszUnpacker;
@ -30,11 +28,9 @@ import itdelatrisu.opsu.UI;
import itdelatrisu.opsu.Utils; import itdelatrisu.opsu.Utils;
import itdelatrisu.opsu.audio.MusicController; import itdelatrisu.opsu.audio.MusicController;
import itdelatrisu.opsu.audio.SoundController; import itdelatrisu.opsu.audio.SoundController;
import itdelatrisu.opsu.replay.Replay;
import itdelatrisu.opsu.replay.ReplayImporter; import itdelatrisu.opsu.replay.ReplayImporter;
import java.io.File; import java.io.File;
import java.io.IOException;
import org.newdawn.slick.Color; import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer; import org.newdawn.slick.GameContainer;
@ -44,7 +40,6 @@ import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException; import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState; import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame; import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.util.Log;
/** /**
* "Splash Screen" state. * "Splash Screen" state.
@ -111,6 +106,7 @@ public class Splash extends BasicGameState {
// parse song directory // parse song directory
OsuParser.parseAllFiles(beatmapDir); OsuParser.parseAllFiles(beatmapDir);
// import replays
ReplayImporter.importAllReplaysFromDir(Options.getReplayImportDir()); ReplayImporter.importAllReplaysFromDir(Options.getReplayImportDir());
// load sounds // load sounds