Hopefully fixes most of the bugs of the replay change.

This commit is contained in:
fd 2015-03-18 19:40:47 -04:00
parent 2877d9bc3d
commit f67ca79ea7

View File

@ -46,8 +46,6 @@ import itdelatrisu.opsu.replay.Replay;
import itdelatrisu.opsu.replay.ReplayFrame; import itdelatrisu.opsu.replay.ReplayFrame;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Stack; import java.util.Stack;
@ -167,9 +165,6 @@ public class Game extends BasicGameState {
/** The replay cursor coordinates. */ /** The replay cursor coordinates. */
private int replayX, replayY; private int replayX, replayY;
/** The replay keys pressed. */
private int replayKeys;
/** Whether a replay key is currently pressed. */ /** Whether a replay key is currently pressed. */
private boolean replayKeyPressed; private boolean replayKeyPressed;
@ -179,6 +174,9 @@ public class Game extends BasicGameState {
/** The last replay frame time. */ /** The last replay frame time. */
private int lastReplayTime = 0; private int lastReplayTime = 0;
/** The keys from the previous replayFrame */
private int lastReplayKeys = 0;
/** The last game keys pressed. */ /** The last game keys pressed. */
private int lastKeysPressed = ReplayFrame.KEY_NONE; private int lastKeysPressed = ReplayFrame.KEY_NONE;
@ -513,14 +511,15 @@ public class Game extends BasicGameState {
cursorCirclePulse.drawCentered(pausedMouseX, pausedMouseY); cursorCirclePulse.drawCentered(pausedMouseX, pausedMouseY);
} }
if (GameMod.AUTO.isActive()) if (isReplay)
UI.draw(g, replayX, replayY, replayKeyPressed);
else if (GameMod.AUTO.isActive())
UI.draw(g, autoMouseX, autoMouseY, autoMousePressed); UI.draw(g, autoMouseX, autoMouseY, autoMousePressed);
else if (GameMod.AUTOPILOT.isActive()) else if (GameMod.AUTOPILOT.isActive())
UI.draw(g, autoMouseX, autoMouseY, Utils.isGameKeyPressed()); UI.draw(g, autoMouseX, autoMouseY, Utils.isGameKeyPressed());
else if (!isReplay)
UI.draw(g);
else else
UI.draw(g, replayX, replayY, replayKeyPressed); UI.draw(g);
} }
@Override @Override
@ -528,42 +527,41 @@ public class Game extends BasicGameState {
throws SlickException { throws SlickException {
UI.update(delta); UI.update(delta);
int mouseX, mouseY; int mouseX, mouseY;
mouseX = input.getMouseX();
mouseY = input.getMouseY();
if (isLeadIn()) { // stop updating during song lead-in if (isLeadIn()) { // stop updating during song lead-in
leadInTime -= delta; leadInTime -= delta;
if (!isLeadIn()) if (!isLeadIn())
MusicController.resume(); MusicController.resume();
return; return;
} }
//hover updates only the real mouse position
//but doesn't hover the replays
skipButton.hoverUpdate(delta, mouseX, mouseY);
int trackPosition = MusicController.getPosition(); int trackPosition = MusicController.getPosition();
if (GameMod.AUTO.isActive() || GameMod.AUTOPILOT.isActive()) { if (!isReplay) {
mouseX = autoMouseX; addReplayFrameAndRun(mouseX, mouseY, lastKeysPressed, trackPosition);
mouseY = autoMouseY;
frameAndRun(mouseX, mouseY, lastKeysPressed, trackPosition);
} else if (!isReplay) {
mouseX = input.getMouseX();
mouseY = input.getMouseY();
frameAndRun(mouseX, mouseY, lastKeysPressed, trackPosition);
} else { } else {
//out of frames, use previous data
if (replayIndex >= replay.frames.length){
updateGame(replayX, replayY, delta, MusicController.getPosition(), lastKeysPressed);
}
while (replayIndex < replay.frames.length && trackPosition >= replay.frames[replayIndex].getTime()) { while (replayIndex < replay.frames.length && trackPosition >= replay.frames[replayIndex].getTime()) {
ReplayFrame frame = replay.frames[replayIndex]; ReplayFrame frame = replay.frames[replayIndex];
runFrame(frame);
replayX = frame.getScaledX(); replayX = frame.getScaledX();
replayY = frame.getScaledY(); replayY = frame.getScaledY();
replayKeyPressed = frame.isKeyPressed(); replayKeyPressed = frame.isKeyPressed();
lastKeysPressed = frame.getKeys(); lastKeysPressed = frame.getKeys();
runReplayFrame(frame);
replayIndex++; replayIndex++;
} }
mouseX = replayX; mouseX = replayX;
mouseY = replayY; mouseY = replayY;
if (replayIndex >= replay.frames.length){
updateGame(replayX, replayY, delta, MusicController.getPosition(), lastKeysPressed);
}
} }
}
public void updateGame(int mouseX, int mouseY, int delta, int trackPosition, int keysPressed){
//if (!isReplay)
// addReplayFrame(mouseX, mouseY, keysPressed, trackPosition);
skipButton.hoverUpdate(delta, mouseX, mouseY);
// "flashlight" mod: calculate visible area radius // "flashlight" mod: calculate visible area radius
if (GameMod.FLASHLIGHT.isActive()) { if (GameMod.FLASHLIGHT.isActive()) {
@ -646,6 +644,32 @@ public class Game extends BasicGameState {
return; return;
} }
data.updateDisplays(delta);
// replays
if (isReplay) {
// skip intro
if (replaySkipTime > 0 && trackPosition > replaySkipTime) {
skipIntro();
replaySkipTime = -1;
}
}
// pause game if focus lost
if (!container.hasFocus() && !GameMod.AUTO.isActive() && !isReplay) {
if (pauseTime < 0) {
pausedMouseX = mouseX;
pausedMouseY = mouseY;
pausePulse = 0f;
}
if (MusicController.isPlaying() || isLeadIn())
pauseTime = trackPosition;
game.enterState(Opsu.STATE_GAMEPAUSEMENU);
}
}
public void updateGame(int mouseX, int mouseY, int delta, int trackPosition, int keysPressed){
// "Easy" mod: multiple "lives" // "Easy" mod: multiple "lives"
if (GameMod.EASY.isActive() && deathTime > -1) { if (GameMod.EASY.isActive() && deathTime > -1) {
if (data.getHealth() < 99f) if (data.getHealth() < 99f)
@ -656,7 +680,6 @@ public class Game extends BasicGameState {
} }
} }
data.updateDisplays(delta);
// map complete! // map complete!
if (objectIndex >= hitObjects.length || (MusicController.trackEnded() && objectIndex > 0)) { if (objectIndex >= hitObjects.length || (MusicController.trackEnded() && objectIndex > 0)) {
@ -709,15 +732,6 @@ public class Game extends BasicGameState {
} }
} }
// replays
if (isReplay) {
// skip intro
if (replaySkipTime > 0 && trackPosition > replaySkipTime) {
skipIntro();
replaySkipTime = -1;
}
}
// song beginning // song beginning
if (objectIndex == 0 && trackPosition < osu.objects[0].getTime()) if (objectIndex == 0 && trackPosition < osu.objects[0].getTime())
return; // nothing to do here return; // nothing to do here
@ -742,18 +756,6 @@ public class Game extends BasicGameState {
} }
} }
// pause game if focus lost
if (!container.hasFocus() && !GameMod.AUTO.isActive() && !isReplay) {
if (pauseTime < 0) {
pausedMouseX = mouseX;
pausedMouseY = mouseY;
pausePulse = 0f;
}
if (MusicController.isPlaying() || isLeadIn())
pauseTime = trackPosition;
game.enterState(Opsu.STATE_GAMEPAUSEMENU);
}
// drain health // drain health
data.changeHealth(delta * -1 * GameData.HP_DRAIN_MULTIPLIER); data.changeHealth(delta * -1 * GameData.HP_DRAIN_MULTIPLIER);
if (!data.isAlive()) { if (!data.isAlive()) {
@ -799,15 +801,13 @@ public class Game extends BasicGameState {
// game keys // game keys
int mouseX = input.getMouseX(); int mouseX = input.getMouseX();
int mouseY = input.getMouseY(); int mouseY = input.getMouseY();
if (!Keyboard.isRepeatEvent() && !isReplay) { if (!Keyboard.isRepeatEvent()) {
if (key == Options.getGameKeyLeft()){ int keys = 0;
lastKeysPressed |= ReplayFrame.KEY_K1; if (key == Options.getGameKeyLeft())
frameAndRun(mouseX, mouseY, lastKeysPressed, trackPosition); keys = ReplayFrame.KEY_K1;
} else if (key == Options.getGameKeyRight())
else if (key == Options.getGameKeyRight()){ keys = ReplayFrame.KEY_K2;
lastKeysPressed |= ReplayFrame.KEY_K2; gameKeyPressed(keys, mouseX, mouseY, trackPosition);
frameAndRun(mouseX, mouseY, lastKeysPressed, trackPosition);
}
} }
switch (key) { switch (key) {
@ -882,6 +882,7 @@ public class Game extends BasicGameState {
osu.objects[objectIndex++].getTime() <= checkpoint) osu.objects[objectIndex++].getTime() <= checkpoint)
; ;
objectIndex--; objectIndex--;
lastReplayTime = osu.objects[objectIndex].getTime();
} catch (SlickException e) { } catch (SlickException e) {
ErrorHandler.error("Failed to load checkpoint.", e, false); ErrorHandler.error("Failed to load checkpoint.", e, false);
} }
@ -932,10 +933,15 @@ public class Game extends BasicGameState {
return; return;
} }
if(!isReplay && (button == Input.MOUSE_LEFT_BUTTON || button == Input.MOUSE_RIGHT_BUTTON)) {
lastKeysPressed |= (button == Input.MOUSE_LEFT_BUTTON) ? ReplayFrame.KEY_M1 : ReplayFrame.KEY_M2; int keys = 0;
frameAndRun(x, y, lastKeysPressed, MusicController.getPosition()); if (button == Input.MOUSE_LEFT_BUTTON)
} keys = ReplayFrame.KEY_M1;
else if (button == Input.MOUSE_RIGHT_BUTTON)
keys = ReplayFrame.KEY_M2;
gameKeyPressed(keys, x, y, MusicController.getPosition());
} }
/** /**
@ -961,40 +967,19 @@ public class Game extends BasicGameState {
return; return;
} }
if (objectIndex >= hitObjects.length) // nothing left to do here
return;
OsuHitObject hitObject = osu.objects[objectIndex];
// skip beginning // skip beginning
if (skipButton.contains(x, y)) { if (skipButton.contains(x, y)) {
if (skipIntro()) if (skipIntro())
return; // successfully skipped return; // successfully skipped
} }
// "auto" and "relax" mods: ignore user actions if(!isReplay && keys > 0) {
if (GameMod.AUTO.isActive() || GameMod.RELAX.isActive()) lastKeysPressed |= keys; //sets keys bits
return; addReplayFrameAndRun(x, y, lastKeysPressed, trackPosition);
// "autopilot" mod: ignore actual cursor coordinates
int cx, cy;
if (GameMod.AUTOPILOT.isActive()) {
cx = autoMouseX;
cy = autoMouseY;
} else {
cx = x;
cy = y;
} }
// circles
if (hitObject.isCircle() && hitObjects[objectIndex].mousePressed(cx, cy, trackPosition))
objectIndex++; // circle hit
// sliders
else if (hitObject.isSlider())
hitObjects[objectIndex].mousePressed(cx, cy, trackPosition);
} }
@Override @Override
public void mouseReleased(int button, int x, int y) { public void mouseReleased(int button, int x, int y) {
if (Options.isMouseDisabled()) if (Options.isMouseDisabled())
@ -1003,17 +988,34 @@ public class Game extends BasicGameState {
if (button == Input.MOUSE_MIDDLE_BUTTON) if (button == Input.MOUSE_MIDDLE_BUTTON)
return; return;
if (!isReplay && button == Input.MOUSE_LEFT_BUTTON || button == Input.MOUSE_RIGHT_BUTTON) { int keys = 0;
lastKeysPressed &= ~((button == Input.MOUSE_LEFT_BUTTON) ? ReplayFrame.KEY_M1 : ReplayFrame.KEY_M2); if (button == Input.MOUSE_LEFT_BUTTON)
frameAndRun(x, y, lastKeysPressed, MusicController.getPosition()); keys = ReplayFrame.KEY_M1;
} else if (button == Input.MOUSE_RIGHT_BUTTON)
keys = ReplayFrame.KEY_M2;
gameKeyReleased(keys, x, y, MusicController.getPosition());
} }
@Override @Override
public void keyReleased(int key, char c) { public void keyReleased(int key, char c) {
if (!isReplay && (key == Options.getGameKeyLeft() || key == Options.getGameKeyRight())) { int keys = 0;
lastKeysPressed &= ~((key == Options.getGameKeyLeft()) ? ReplayFrame.KEY_K1 : ReplayFrame.KEY_K2); if (key == Options.getGameKeyLeft())
frameAndRun(input.getMouseX(), input.getMouseY(), lastKeysPressed, MusicController.getPosition()); keys = ReplayFrame.KEY_K1;
else if (key == Options.getGameKeyRight())
keys = ReplayFrame.KEY_K2;
gameKeyReleased(keys, input.getMouseX(), input.getMouseY(), MusicController.getPosition());
}
/**
* Handles a game key Released event.
* @param keys the game keys released
* @param x the mouse x coordinate
* @param y the mouse y coordinate
* @param trackPosition the track Position
*/
private void gameKeyReleased(int keys, int x, int y, int trackPosition) {
if (!isReplay && keys > 0) {
lastKeysPressed &= ~keys; //clears keys bits
addReplayFrameAndRun(x, y, lastKeysPressed, trackPosition);
} }
} }
@ -1108,7 +1110,6 @@ public class Game extends BasicGameState {
// load initial data // load initial data
replayX = container.getWidth() / 2; replayX = container.getWidth() / 2;
replayY = container.getHeight() / 2; replayY = container.getHeight() / 2;
replayKeys = ReplayFrame.KEY_NONE;
replayKeyPressed = false; replayKeyPressed = false;
replaySkipTime = -1; replaySkipTime = -1;
for (replayIndex = 0; replayIndex < replay.frames.length; replayIndex++) { for (replayIndex = 0; replayIndex < replay.frames.length; replayIndex++) {
@ -1119,12 +1120,10 @@ public class Game extends BasicGameState {
} else if (frame.getTime() == 0) { } else if (frame.getTime() == 0) {
replayX = frame.getScaledX(); replayX = frame.getScaledX();
replayY = frame.getScaledY(); replayY = frame.getScaledY();
replayKeys = frame.getKeys();
replayKeyPressed = frame.isKeyPressed(); replayKeyPressed = frame.isKeyPressed();
} else } else
break; break;
} }
} }
// initialize replay-recording structures // initialize replay-recording structures
@ -1384,33 +1383,64 @@ public class Game extends BasicGameState {
} }
} }
public synchronized void frameAndRun(int x, int y, int keys, int time){
ReplayFrame frame = addReplayFrame(x, y, keys, time);
if(frame != null)
runFrame(frame);
}
int prevRunKeys = 0;
private void runFrame(ReplayFrame frame){
int keys = frame.getKeys();
int replayX = frame.getScaledX();
int replayY = frame.getScaledY();
int deltaKeys = (keys & ~prevRunKeys );
if (deltaKeys > 0) { // send a key press
gameKeyPressed(deltaKeys, replayX, replayY, frame.getTime());
} else if(keys != prevRunKeys){
} else {
updateGame(replayX, replayY, frame.getTimeDiff(), frame.getTime(), keys);
}
prevRunKeys = keys;
}
/** /**
* Adds a replay frame to the list. * Adds a replay frame to the list if able and runs it.
* @param x the cursor x coordinate * @param x the cursor x coordinate
* @param y the cursor y coordinate * @param y the cursor y coordinate
* @param keys the keys pressed * @param keys the keys pressed
* @param trackPosition the track Position * @param time the time of the replay Frame
*/
public synchronized void addReplayFrameAndRun(int x, int y, int keys, int time){
if (GameMod.AUTO.isActive() || GameMod.AUTOPILOT.isActive()) {
x = autoMouseX;
y = autoMouseY;
}
ReplayFrame frame = addReplayFrame(x, y, keys, time);
if(frame != null)
runReplayFrame(frame);
}
/**
* Runs a replay Frame
* @param frame the frame to run
*/
private void runReplayFrame(ReplayFrame frame){
int keys = frame.getKeys();
int replayX = frame.getScaledX();
int replayY = frame.getScaledY();
int deltaKeys = (keys & ~lastReplayKeys ); //keys that turned on
if (deltaKeys > 0) { // send a key press
updateGameKeyPress(deltaKeys, replayX, replayY, frame.getTime());
} else if(keys != lastReplayKeys){
} else {
updateGame(replayX, replayY, frame.getTimeDiff(), frame.getTime(), keys);
}
lastReplayKeys = keys;
}
private void updateGameKeyPress(int keys, int x, int y, int trackPosition) {
if (objectIndex >= hitObjects.length) // nothing left to do here
return;
OsuHitObject hitObject = osu.objects[objectIndex];
// circles
if (hitObject.isCircle() && hitObjects[objectIndex].mousePressed(x, y, trackPosition))
objectIndex++; // circle hit
// sliders
else if (hitObject.isSlider())
hitObjects[objectIndex].mousePressed(x, y, trackPosition);
}
/**
* Adds a replay frame to the list if able.
* @param x the cursor x coordinate
* @param y the cursor y coordinate
* @param keys the keys pressed
* @param time the time of the replay Frame
* @return a Replay Frame representing the data
*/ */
private ReplayFrame addReplayFrame(int x, int y, int keys, int time) { private ReplayFrame addReplayFrame(int x, int y, int keys, int time) {
int timeDiff = time - lastReplayTime; int timeDiff = time - lastReplayTime;