fix some rewind bugs and add replay support for rewind

This commit is contained in:
RandomityGuy 2023-05-08 01:10:58 +05:30
parent 4974586c31
commit e581be7c08
4 changed files with 75 additions and 14 deletions

View file

@ -158,6 +158,9 @@ class MarbleWorld extends Scheduler {
var textureResources:Array<Resource<h3d.mat.Texture>> = []; var textureResources:Array<Resource<h3d.mat.Texture>> = [];
var soundResources:Array<Resource<Sound>> = []; var soundResources:Array<Resource<Sound>> = [];
var oobSchedule:Float;
var oobSchedule2:Float;
var lock:Bool = false; var lock:Bool = false;
public function new(scene:Scene, scene2d:h2d.Scene, mission:Mission, record:Bool = false) { public function new(scene:Scene, scene2d:h2d.Scene, mission:Mission, record:Bool = false) {
@ -909,8 +912,22 @@ class MarbleWorld extends Scheduler {
if (!_ready) { if (!_ready) {
return; return;
} }
if (!this.isWatching) {
var realDt = dt;
if (Key.isDown(Settings.controlsSettings.rewind) && Settings.optionsSettings.rewindEnabled && !this.isWatching) {
this.rewinding = true;
} else {
this.rewinding = false;
if (Key.isReleased(Settings.controlsSettings.rewind)) {
if (this.isRecording) { if (this.isRecording) {
this.replay.spliceReplay(timeState.currentAttemptTime);
}
}
}
if (!this.isWatching) {
if (this.isRecording && !this.rewinding) {
this.replay.startFrame(); this.replay.startFrame();
} }
} else { } else {
@ -931,15 +948,7 @@ class MarbleWorld extends Scheduler {
} }
} }
var realDt = dt; if (this.rewinding && !this.isWatching) {
if (Key.isDown(Key.R)) {
this.rewinding = true;
} else {
this.rewinding = false;
}
if (this.rewinding) {
var rframe = rewindManager.getNextRewindFrame(timeState.currentAttemptTime - dt * rewindManager.timeScale); var rframe = rewindManager.getNextRewindFrame(timeState.currentAttemptTime - dt * rewindManager.timeScale);
if (rframe != null) { if (rframe != null) {
var actualDt = timeState.currentAttemptTime - rframe.timeState.currentAttemptTime - dt * rewindManager.timeScale; var actualDt = timeState.currentAttemptTime - rframe.timeState.currentAttemptTime - dt * rewindManager.timeScale;
@ -981,12 +990,12 @@ class MarbleWorld extends Scheduler {
AudioManager.update(this.scene); AudioManager.update(this.scene);
if (!this.isWatching) { if (!this.isWatching) {
if (this.isRecording) { if (this.isRecording && !this.rewinding) {
this.replay.endFrame(); this.replay.endFrame();
} }
} }
if (!this.rewinding) if (!this.rewinding && Settings.optionsSettings.rewindEnabled)
this.rewindManager.recordFrame(); this.rewindManager.recordFrame();
if (this.outOfBounds if (this.outOfBounds
@ -1462,11 +1471,11 @@ class MarbleWorld extends Scheduler {
playGui.setCenterText('outofbounds'); playGui.setCenterText('outofbounds');
AudioManager.playSound(ResourceLoader.getResource('data/sound/whoosh.wav', ResourceLoader.getAudio, this.soundResources)); AudioManager.playSound(ResourceLoader.getResource('data/sound/whoosh.wav', ResourceLoader.getAudio, this.soundResources));
// if (this.replay.mode != = 'playback') // if (this.replay.mode != = 'playback')
this.schedule(this.timeState.currentAttemptTime + 2, () -> { this.oobSchedule = this.schedule(this.timeState.currentAttemptTime + 2, () -> {
playGui.setCenterText('none'); playGui.setCenterText('none');
return null; return null;
}); });
this.schedule(this.timeState.currentAttemptTime + 2.5, () -> { this.oobSchedule2 = this.schedule(this.timeState.currentAttemptTime + 2.5, () -> {
this.restart(); this.restart();
return null; return null;
}); });

View file

@ -223,12 +223,16 @@ class Replay {
} }
public function recordTimeState(time:Float, clockTime:Float, bonusTime:Float) { public function recordTimeState(time:Float, clockTime:Float, bonusTime:Float) {
if (currentRecordFrame == null)
return;
currentRecordFrame.time = time; currentRecordFrame.time = time;
currentRecordFrame.clockTime = clockTime; currentRecordFrame.clockTime = clockTime;
currentRecordFrame.bonusTime = bonusTime; currentRecordFrame.bonusTime = bonusTime;
} }
public function recordMarbleState(position:Vector, velocity:Vector, orientation:Quat, angularVelocity:Vector) { public function recordMarbleState(position:Vector, velocity:Vector, orientation:Quat, angularVelocity:Vector) {
if (currentRecordFrame == null)
return;
currentRecordFrame.marblePosition = position.clone(); currentRecordFrame.marblePosition = position.clone();
currentRecordFrame.marbleVelocity = velocity.clone(); currentRecordFrame.marbleVelocity = velocity.clone();
currentRecordFrame.marbleOrientation = orientation.clone(); currentRecordFrame.marbleOrientation = orientation.clone();
@ -236,6 +240,8 @@ class Replay {
} }
public function recordMarbleStateFlags(jumped:Bool, usedPowerup:Bool, instantTeleport:Bool) { public function recordMarbleStateFlags(jumped:Bool, usedPowerup:Bool, instantTeleport:Bool) {
if (currentRecordFrame == null)
return;
if (jumped) if (jumped)
currentRecordFrame.marbleStateFlags.set(Jumped); currentRecordFrame.marbleStateFlags.set(Jumped);
if (usedPowerup) if (usedPowerup)
@ -245,26 +251,36 @@ class Replay {
} }
public function recordMarbleInput(x:Float, y:Float) { public function recordMarbleInput(x:Float, y:Float) {
if (currentRecordFrame == null)
return;
currentRecordFrame.marbleX = x; currentRecordFrame.marbleX = x;
currentRecordFrame.marbleY = y; currentRecordFrame.marbleY = y;
} }
public function recordCameraState(pitch:Float, yaw:Float) { public function recordCameraState(pitch:Float, yaw:Float) {
if (currentRecordFrame == null)
return;
currentRecordFrame.cameraPitch = pitch; currentRecordFrame.cameraPitch = pitch;
currentRecordFrame.cameraYaw = yaw; currentRecordFrame.cameraYaw = yaw;
} }
public function recordTrapdoorState(lastContactTime:Float, lastDirection:Int, lastCompletion:Float) { public function recordTrapdoorState(lastContactTime:Float, lastDirection:Int, lastCompletion:Float) {
if (currentRecordFrame == null)
return;
initialState.trapdoorLastContactTimes.push(lastContactTime); initialState.trapdoorLastContactTimes.push(lastContactTime);
initialState.trapdoorLastDirections.push(lastDirection); initialState.trapdoorLastDirections.push(lastDirection);
initialState.trapdoorLastCompletions.push(lastCompletion); initialState.trapdoorLastCompletions.push(lastCompletion);
} }
public function recordLandMineState(disappearTime:Float) { public function recordLandMineState(disappearTime:Float) {
if (currentRecordFrame == null)
return;
initialState.landMineDisappearTimes.push(disappearTime); initialState.landMineDisappearTimes.push(disappearTime);
} }
public function recordPushButtonState(lastContactTime:Float) { public function recordPushButtonState(lastContactTime:Float) {
if (currentRecordFrame == null)
return;
initialState.pushButtonContactTimes.push(lastContactTime); initialState.pushButtonContactTimes.push(lastContactTime);
} }
@ -320,6 +336,24 @@ class Replay {
this.currentPlaybackFrameIdx = 0; this.currentPlaybackFrameIdx = 0;
} }
public function spliceReplay(cutAfterTime:Float) {
if (this.frames.length > 0) {
var curframe = this.frames[this.frames.length - 1];
while (curframe.time > cutAfterTime && this.frames.length > 0) {
this.frames.pop();
curframe = this.frames[this.frames.length - 1];
}
}
if (this.initialState.randomGenTimes.length > 0) {
var rtimeIdx = this.initialState.randomGenTimes.length - 1;
while (this.initialState.randomGenTimes[rtimeIdx] > cutAfterTime && this.initialState.randomGenTimes.length > 0) {
this.initialState.randomGenTimes.pop();
this.initialState.randomGens.pop();
rtimeIdx = this.initialState.randomGenTimes.length - 1;
}
}
}
public function write() { public function write() {
var bw = new BytesWriter(); var bw = new BytesWriter();

View file

@ -33,6 +33,7 @@ typedef OptionsSettings = {
var soundVolume:Float; var soundVolume:Float;
var vsync:Bool; var vsync:Bool;
var fovX:Int; var fovX:Int;
var rewindEnabled:Bool;
} }
typedef ControlsSettings = { typedef ControlsSettings = {
@ -89,6 +90,7 @@ class Settings {
musicVolume: 1, musicVolume: 1,
soundVolume: 0.7, soundVolume: 0.7,
fovX: 90, fovX: 90,
rewindEnabled: false,
vsync: #if js true #end vsync: #if js true #end
#if hl #if hl
false false
@ -249,16 +251,24 @@ class Settings {
optionsSettings = json.options; optionsSettings = json.options;
if (optionsSettings.fovX == 0 #if js || optionsSettings.fovX == null #end) if (optionsSettings.fovX == 0 #if js || optionsSettings.fovX == null #end)
optionsSettings.fovX = 90; optionsSettings.fovX = 90;
if (optionsSettings.rewindEnabled == false #if js || optionsSettings.rewindEnabled == null #end)
optionsSettings.rewindEnabled = false;
controlsSettings = json.controls; controlsSettings = json.controls;
if (json.touch != null) { if (json.touch != null) {
touchSettings = json.touch; touchSettings = json.touch;
} }
if (controlsSettings.rewind == 0) {
controlsSettings.rewind = Key.R;
}
if (json.gamepad != null) { if (json.gamepad != null) {
gamepadSettings = json.gamepad; gamepadSettings = json.gamepad;
} }
if (controlsSettings.rewind == null) { if (controlsSettings.rewind == null) {
controlsSettings.rewind = Key.R; controlsSettings.rewind = Key.R;
} }
if (optionsSettings.rewindEnabled == null) {
optionsSettings.rewindEnabled = false;
}
progression = json.progression; progression = json.progression;
highscoreName = json.highscoreName; highscoreName = json.highscoreName;
} else { } else {

View file

@ -204,6 +204,14 @@ class RewindManager {
td.lastContactTime = tdState.lastContactTime; td.lastContactTime = tdState.lastContactTime;
} }
} }
if (!rf.oobState.oob) {
@:privateAccess level.cancel(level.oobSchedule);
@:privateAccess level.cancel(level.oobSchedule2);
} else {
level.goOutOfBounds();
}
level.outOfBounds = rf.oobState.oob; level.outOfBounds = rf.oobState.oob;
level.marble.camera.oob = rf.oobState.oob; level.marble.camera.oob = rf.oobState.oob;
level.outOfBoundsTime = rf.oobState.timeState != null ? rf.oobState.timeState.clone() : null; level.outOfBoundsTime = rf.oobState.timeState != null ? rf.oobState.timeState.clone() : null;