use the hitdata for replay hitresults and show per player acc
This commit is contained in:
parent
9af2b01657
commit
8fed11ba86
|
@ -170,7 +170,7 @@ public class GameData {
|
||||||
HIT_ANIMATION_RESULT = 12; // not a hit result
|
HIT_ANIMATION_RESULT = 12; // not a hit result
|
||||||
|
|
||||||
/** Hit result-related images (indexed by HIT_* constants to HIT_MAX). */
|
/** Hit result-related images (indexed by HIT_* constants to HIT_MAX). */
|
||||||
protected Image[] hitResults;
|
public static Image[] hitResults;
|
||||||
|
|
||||||
/** Counts of each hit result so far (indexed by HIT_* constants to HIT_MAX). */
|
/** Counts of each hit result so far (indexed by HIT_* constants to HIT_MAX). */
|
||||||
private int[] hitResultCount;
|
private int[] hitResultCount;
|
||||||
|
|
|
@ -733,7 +733,7 @@ public class Game extends ComplexOpsuState {
|
||||||
float h = replayPlayback.getHeight();
|
float h = replayPlayback.getHeight();
|
||||||
ypos += h;
|
ypos += h;
|
||||||
//if (h > 0f) {
|
//if (h > 0f) {
|
||||||
replayPlayback.render(beatmap, hitResultOffset, displayContainer.renderDelta, g, ypos, trackPosition);
|
replayPlayback.render(displayContainer.renderDelta, g, ypos, trackPosition);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1581,9 +1581,6 @@ public class Game extends ComplexOpsuState {
|
||||||
}
|
}
|
||||||
|
|
||||||
gameObjects = new GameObject[beatmap.objects.length];
|
gameObjects = new GameObject[beatmap.objects.length];
|
||||||
for (ReplayPlayback replayPlayback : replays) {
|
|
||||||
replayPlayback.gameObjects = new GameObject[gameObjects.length];
|
|
||||||
}
|
|
||||||
playbackSpeed = PlaybackSpeed.NORMAL;
|
playbackSpeed = PlaybackSpeed.NORMAL;
|
||||||
|
|
||||||
// reset game data
|
// reset game data
|
||||||
|
@ -1630,9 +1627,6 @@ public class Game extends ComplexOpsuState {
|
||||||
} else if (hitObject.isSpinner()) {
|
} else if (hitObject.isSpinner()) {
|
||||||
gameObjects[i] = new Spinner(hitObject, this, data);
|
gameObjects[i] = new Spinner(hitObject, this, data);
|
||||||
}
|
}
|
||||||
for (ReplayPlayback replayPlayback : replays) {
|
|
||||||
replayPlayback.gameObjects[i] = gameObjects[i].clone(replayPlayback.gdata);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String message = String.format("Failed to create %s at index %d:\n%s", hitObject.getTypeName(), i, hitObject.toString());
|
String message = String.format("Failed to create %s at index %d:\n%s", hitObject.getTypeName(), i, hitObject.toString());
|
||||||
Log.error(message, e);
|
Log.error(message, e);
|
||||||
|
|
|
@ -18,10 +18,6 @@
|
||||||
package yugecin.opsudance;
|
package yugecin.opsudance;
|
||||||
|
|
||||||
import itdelatrisu.opsu.GameData;
|
import itdelatrisu.opsu.GameData;
|
||||||
import itdelatrisu.opsu.beatmap.Beatmap;
|
|
||||||
import itdelatrisu.opsu.beatmap.HitObject;
|
|
||||||
import itdelatrisu.opsu.objects.GameObject;
|
|
||||||
import itdelatrisu.opsu.objects.curves.Curve;
|
|
||||||
import itdelatrisu.opsu.replay.Replay;
|
import itdelatrisu.opsu.replay.Replay;
|
||||||
import itdelatrisu.opsu.replay.ReplayFrame;
|
import itdelatrisu.opsu.replay.ReplayFrame;
|
||||||
import itdelatrisu.opsu.ui.Cursor;
|
import itdelatrisu.opsu.ui.Cursor;
|
||||||
|
@ -36,7 +32,6 @@ import yugecin.opsudance.core.Entrypoint;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ReplayPlayback {
|
public class ReplayPlayback {
|
||||||
|
|
||||||
|
@ -55,14 +50,13 @@ public class ReplayPlayback {
|
||||||
private String player;
|
private String player;
|
||||||
private String mods;
|
private String mods;
|
||||||
private int playerwidth;
|
private int playerwidth;
|
||||||
private int textwidth;
|
private int modwidth;
|
||||||
|
private String currentAcc;
|
||||||
|
private int currentAccWidth;
|
||||||
|
private final int ACCMAXWIDTH;
|
||||||
|
|
||||||
public GameObject[] gameObjects;
|
|
||||||
private int objectIndex = 0;
|
|
||||||
private int lastkeys = 0;
|
|
||||||
private Image hitImage;
|
private Image hitImage;
|
||||||
private int hitImageTimer = 0;
|
private int hitImageTimer = 0;
|
||||||
public GData gdata = new GData();
|
|
||||||
private boolean missed;
|
private boolean missed;
|
||||||
|
|
||||||
private static final Color missedColor = new Color(0.4f, 0.4f, 0.4f, 1f);
|
private static final Color missedColor = new Color(0.4f, 0.4f, 0.4f, 1f);
|
||||||
|
@ -78,9 +72,11 @@ public class ReplayPlayback {
|
||||||
cursor = new Cursor(cursorcolor);
|
cursor = new Cursor(cursorcolor);
|
||||||
keydelay = new int[4];
|
keydelay = new int[4];
|
||||||
this.player = replay.playerName;
|
this.player = replay.playerName;
|
||||||
this.textwidth = Fonts.SMALLBOLD.getWidth(this.player);
|
this.playerwidth = Fonts.SMALLBOLD.getWidth(this.player);
|
||||||
this.playerwidth = this.textwidth;
|
|
||||||
this.mods = "";
|
this.mods = "";
|
||||||
|
this.currentAcc = "100,00%";
|
||||||
|
this.currentAccWidth = Fonts.SMALLBOLD.getWidth(currentAcc);
|
||||||
|
this.ACCMAXWIDTH = currentAccWidth + 10;
|
||||||
if ((replay.mods & 0x1) > 0) {
|
if ((replay.mods & 0x1) > 0) {
|
||||||
this.mods += "NF";
|
this.mods += "NF";
|
||||||
}
|
}
|
||||||
|
@ -117,7 +113,7 @@ public class ReplayPlayback {
|
||||||
}
|
}
|
||||||
if (this.mods.length() > 0) {
|
if (this.mods.length() > 0) {
|
||||||
this.mods = " +" + this.mods;
|
this.mods = " +" + this.mods;
|
||||||
this.textwidth += Fonts.SMALLBOLD.getWidth(this.mods);
|
this.modwidth = Fonts.SMALLBOLD.getWidth(this.mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,43 +123,13 @@ public class ReplayPlayback {
|
||||||
nextFrame = replay.frames[frameIndex];
|
nextFrame = replay.frames[frameIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendKeys(Beatmap beatmap, int trackPosition) {
|
|
||||||
if (objectIndex >= gameObjects.length) // nothing to do here
|
|
||||||
return;
|
|
||||||
|
|
||||||
HitObject hitObject = beatmap.objects[objectIndex];
|
|
||||||
|
|
||||||
// circles
|
|
||||||
if (hitObject.isCircle() && gameObjects[objectIndex].mousePressed(currentFrame.getScaledX(), currentFrame.getScaledY(), trackPosition))
|
|
||||||
objectIndex++; // circle hit
|
|
||||||
|
|
||||||
// sliders
|
|
||||||
else if (hitObject.isSlider())
|
|
||||||
gameObjects[objectIndex].mousePressed(currentFrame.getScaledX(), currentFrame.getScaledY(), trackPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void update(int trackPosition, Beatmap beatmap, int[] hitResultOffset, int delta) {
|
|
||||||
boolean keyPressed = currentFrame.getKeys() != ReplayFrame.KEY_NONE;
|
|
||||||
while (objectIndex < gameObjects.length && trackPosition > beatmap.objects[objectIndex].getTime()) {
|
|
||||||
// check if we've already passed the next object's start time
|
|
||||||
boolean overlap = (objectIndex + 1 < gameObjects.length &&
|
|
||||||
trackPosition > beatmap.objects[objectIndex + 1].getTime() - hitResultOffset[GameData.HIT_50]);
|
|
||||||
|
|
||||||
// update hit object and check completion status
|
|
||||||
if (gameObjects[objectIndex].update(overlap, delta, currentFrame.getScaledX(), currentFrame.getScaledY(), keyPressed, trackPosition)) {
|
|
||||||
objectIndex++; // done, so increment object index
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int HITIMAGETIMEREXPAND = 200;
|
private int HITIMAGETIMEREXPAND = 200;
|
||||||
private int HITIMAGETIMERFADESTART = 500;
|
private int HITIMAGETIMERFADESTART = 500;
|
||||||
private int HITIMAGETIMERFADEEND = 700;
|
private int HITIMAGETIMERFADEEND = 700;
|
||||||
private float HITIMAGETIMERFADEDELTA = HITIMAGETIMERFADEEND - HITIMAGETIMERFADESTART;
|
private float HITIMAGETIMERFADEDELTA = HITIMAGETIMERFADEEND - HITIMAGETIMERFADESTART;
|
||||||
private int HITIMAGEDEADFADE = 10000;
|
private int HITIMAGEDEADFADE = 10000;
|
||||||
private float SHRINKTIME = 500f;
|
private float SHRINKTIME = 500f;
|
||||||
private void showHitImage(int renderdelta, float ypos) {
|
private void showHitImage(int renderdelta, int xpos, float ypos) {
|
||||||
if (hitImage == null) {
|
if (hitImage == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +157,7 @@ public class ReplayPlayback {
|
||||||
scale = AnimationEquation.OUT_EXPO.calc((float) hitImageTimer / HITIMAGETIMEREXPAND);
|
scale = AnimationEquation.OUT_EXPO.calc((float) hitImageTimer / HITIMAGETIMEREXPAND);
|
||||||
offset = UNITHEIGHT / 2f * (1f - scale);
|
offset = UNITHEIGHT / 2f * (1f - scale);
|
||||||
}
|
}
|
||||||
hitImage.draw(SQSIZE * 5 + textwidth + SQSIZE + offset, ypos + offset, scale, color);
|
hitImage.draw(xpos + offset, ypos + offset, scale, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getHeight() {
|
public float getHeight() {
|
||||||
|
@ -204,24 +170,10 @@ public class ReplayPlayback {
|
||||||
return UNITHEIGHT * (1f - AnimationEquation.OUT_QUART.calc((hitImageTimer - HITIMAGEDEADFADE) / SHRINKTIME));
|
return UNITHEIGHT * (1f - AnimationEquation.OUT_QUART.calc((hitImageTimer - HITIMAGEDEADFADE) / SHRINKTIME));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(Beatmap beatmap, int[] hitResultOffset, int renderdelta, Graphics g, float ypos, int time) {
|
public void render(int renderdelta, Graphics g, float ypos, int time) {
|
||||||
/*
|
|
||||||
if (objectIndex >= gameObjects.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (nextFrame != null && nextFrame.getTime() < time) {
|
while (nextFrame != null && nextFrame.getTime() < time) {
|
||||||
currentFrame = nextFrame;
|
currentFrame = nextFrame;
|
||||||
|
|
||||||
int keys = currentFrame.getKeys();
|
|
||||||
int deltaKeys = (keys & ~lastkeys); // keys that turned on
|
|
||||||
if (deltaKeys != ReplayFrame.KEY_NONE) { // send a key press
|
|
||||||
sendKeys(beatmap, currentFrame.getTime());
|
|
||||||
} else if (keys == lastkeys) {
|
|
||||||
update(time, beatmap, hitResultOffset, currentFrame.getTimeDiff());
|
|
||||||
}
|
|
||||||
lastkeys = keys;
|
|
||||||
|
|
||||||
processKeys();
|
processKeys();
|
||||||
frameIndex++;
|
frameIndex++;
|
||||||
if (frameIndex >= replay.frames.length) {
|
if (frameIndex >= replay.frames.length) {
|
||||||
|
@ -231,7 +183,6 @@ public class ReplayPlayback {
|
||||||
nextFrame = replay.frames[frameIndex];
|
nextFrame = replay.frames[frameIndex];
|
||||||
}
|
}
|
||||||
processKeys();
|
processKeys();
|
||||||
*/
|
|
||||||
g.setColor(color);
|
g.setColor(color);
|
||||||
if (!missed) {
|
if (!missed) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
|
@ -240,12 +191,42 @@ public class ReplayPlayback {
|
||||||
}
|
}
|
||||||
keydelay[i] -= renderdelta;
|
keydelay[i] -= renderdelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!hitdata.acc.isEmpty() && hitdata.acc.getFirst().time <= time) {
|
||||||
|
currentAcc = String.format("%.2f%%", hitdata.acc.removeFirst().acc).replace('.', ',');
|
||||||
|
currentAccWidth = Fonts.SMALLBOLD.getWidth(currentAcc);
|
||||||
}
|
}
|
||||||
Fonts.SMALLBOLD.drawString(SQSIZE * 5, ypos, this.player, color);
|
|
||||||
|
while (!hitdata.time100.isEmpty() && hitdata.time100.getFirst() <= time) {
|
||||||
|
hitdata.time100.removeFirst();
|
||||||
|
hitImageTimer = 0;
|
||||||
|
hitImage = GameData.hitResults[GameData.HIT_100].getScaledCopy(SQSIZE + 5, SQSIZE + 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!hitdata.time50.isEmpty() && hitdata.time50.getFirst() <= time) {
|
||||||
|
hitdata.time50.removeFirst();
|
||||||
|
hitImageTimer = 0;
|
||||||
|
hitImage = GameData.hitResults[GameData.HIT_100].getScaledCopy(SQSIZE + 5, SQSIZE + 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time >= hitdata.combobreaktime) {
|
||||||
|
missed = true;
|
||||||
|
color = new Color(missedColor);
|
||||||
|
hitImageTimer = 0;
|
||||||
|
hitImage = GameData.hitResults[GameData.HIT_MISS].getScaledCopy(SQSIZE + 5, SQSIZE + 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int xpos = SQSIZE * 5;
|
||||||
|
Fonts.SMALLBOLD.drawString(xpos + ACCMAXWIDTH - currentAccWidth - 10, ypos, currentAcc, new Color(.4f, .4f, .4f, color.a));
|
||||||
|
xpos += ACCMAXWIDTH;
|
||||||
|
Fonts.SMALLBOLD.drawString(xpos, ypos, this.player, color);
|
||||||
|
xpos += playerwidth;
|
||||||
if (!this.mods.isEmpty()) {
|
if (!this.mods.isEmpty()) {
|
||||||
Fonts.SMALLBOLD.drawString(SQSIZE * 5 + playerwidth, ypos, this.mods, new Color(1f, 1f, 1f, color.a));
|
Fonts.SMALLBOLD.drawString(xpos, ypos, this.mods, new Color(1f, 1f, 1f, color.a));
|
||||||
|
xpos += modwidth;
|
||||||
}
|
}
|
||||||
showHitImage(renderdelta, ypos);
|
xpos += 10;
|
||||||
|
showHitImage(renderdelta, xpos, ypos);
|
||||||
if (missed) {
|
if (missed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -274,70 +255,6 @@ public class ReplayPlayback {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GData extends GameData {
|
|
||||||
|
|
||||||
public GData() {
|
|
||||||
super();
|
|
||||||
this.loadImages();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendSliderRepeatResult(int time, float x, float y, Color color, Curve curve, HitObjectType type) {
|
|
||||||
// ?
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendSliderStartResult(int time, float x, float y, Color color, Color mirrorColor, boolean expand) {
|
|
||||||
// ?
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendSliderTickResult(int time, int result, float x, float y, HitObject hitObject, int repeat) {
|
|
||||||
if (result == HIT_SLIDER30 || result == HIT_SLIDER10) {
|
|
||||||
incrementComboStreak();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendHitResult(int time, int result, float x, float y, Color color, boolean end, HitObject hitObject, HitObjectType hitResultType, boolean expand, int repeat, Curve curve, boolean sliderHeldToEnd) {
|
|
||||||
sendHitResult(time, result, x, y, color, end, hitObject, hitResultType, expand, repeat, curve, sliderHeldToEnd, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendHitResult(int time, int result, float x, float y, Color color, boolean end, HitObject hitObject, HitObjectType hitResultType, boolean expand, int repeat, Curve curve, boolean sliderHeldToEnd, boolean handleResult) {
|
|
||||||
if (curve == null || sliderHeldToEnd) {
|
|
||||||
incrementComboStreak();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (missed || result == HIT_300) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
missed = this.getComboStreak() > replay.combo;
|
|
||||||
if (missed) {
|
|
||||||
result = HIT_MISS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == HIT_MISS) {
|
|
||||||
if (!missed) {
|
|
||||||
result = HIT_50;
|
|
||||||
} else {
|
|
||||||
ReplayPlayback.this.color = new Color(missedColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result < hitResults.length) {
|
|
||||||
hitImageTimer = 0;
|
|
||||||
hitImage = hitResults[result].getScaledCopy(SQSIZE + 5, SQSIZE + 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addHitError(int time, int x, int y, int timeDiff) {
|
|
||||||
//?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class HitData {
|
public static class HitData {
|
||||||
|
|
||||||
int combobreaktime = -1;
|
int combobreaktime = -1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user