mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
really basic replay support
This commit is contained in:
parent
ebb6091729
commit
24c87da4fd
5 changed files with 305 additions and 22 deletions
|
|
@ -213,6 +213,13 @@ class CameraController extends Object {
|
||||||
CameraYaw = this.level.finishYaw - (this.level.timeState.currentAttemptTime - this.level.finishTime.currentAttemptTime) / -1.2;
|
CameraYaw = this.level.finishYaw - (this.level.timeState.currentAttemptTime - this.level.finishTime.currentAttemptTime) / -1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.level.isWatching) {
|
||||||
|
this.level.replay.recordCameraState(CameraPitch, CameraYaw);
|
||||||
|
} else {
|
||||||
|
CameraPitch = this.level.replay.currentPlaybackFrame.cameraPitch;
|
||||||
|
CameraYaw = this.level.replay.currentPlaybackFrame.cameraYaw;
|
||||||
|
}
|
||||||
|
|
||||||
var marblePosition = level.marble.getAbsPos().getPosition();
|
var marblePosition = level.marble.getAbsPos().getPosition();
|
||||||
var up = new Vector(0, 0, 1);
|
var up = new Vector(0, 0, 1);
|
||||||
up.transform(orientationQuat.toMatrix());
|
up.transform(orientationQuat.toMatrix());
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,8 @@ class DtsObject extends GameObject {
|
||||||
var ambientRotate = false;
|
var ambientRotate = false;
|
||||||
var ambientSpinFactor = -1 / 3 * Math.PI * 2;
|
var ambientSpinFactor = -1 / 3 * Math.PI * 2;
|
||||||
|
|
||||||
|
public var idInLevel:Int = -1;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1335,7 +1335,7 @@ class Marble extends GameObject {
|
||||||
public function update(timeState:TimeState, collisionWorld:CollisionWorld, pathedInteriors:Array<PathedInterior>) {
|
public function update(timeState:TimeState, collisionWorld:CollisionWorld, pathedInteriors:Array<PathedInterior>) {
|
||||||
var move = new Move();
|
var move = new Move();
|
||||||
move.d = new Vector();
|
move.d = new Vector();
|
||||||
if (this.controllable && this.mode != Finish && !MarbleGame.instance.paused) {
|
if (this.controllable && this.mode != Finish && !MarbleGame.instance.paused && !this.level.isWatching) {
|
||||||
if (Key.isDown(Settings.controlsSettings.forward)) {
|
if (Key.isDown(Settings.controlsSettings.forward)) {
|
||||||
move.d.x -= 1;
|
move.d.x -= 1;
|
||||||
}
|
}
|
||||||
|
|
@ -1360,9 +1360,33 @@ class Marble extends GameObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.level.isWatching) {
|
||||||
|
if (this.level.replay.currentPlaybackFrame.marbleStateFlags.has(Jumped))
|
||||||
|
move.jump = true;
|
||||||
|
if (this.level.replay.currentPlaybackFrame.marbleStateFlags.has(UsedPowerup))
|
||||||
|
move.powerup = true;
|
||||||
|
move.d = new Vector(this.level.replay.currentPlaybackFrame.marbleX, this.level.replay.currentPlaybackFrame.marbleY, 0);
|
||||||
|
} else {
|
||||||
|
this.level.replay.recordMarbleStateFlags(move.jump, move.powerup, false);
|
||||||
|
this.level.replay.recordMarbleInput(move.d.x, move.d.y);
|
||||||
|
}
|
||||||
|
|
||||||
playedSounds = [];
|
playedSounds = [];
|
||||||
advancePhysics(timeState, move, collisionWorld, pathedInteriors);
|
advancePhysics(timeState, move, collisionWorld, pathedInteriors);
|
||||||
|
|
||||||
|
if (!this.level.isWatching)
|
||||||
|
this.level.replay.recordMarbleState(this.getAbsPos().getPosition(), this.velocity, this.getRotationQuat(), this.omega);
|
||||||
|
else {
|
||||||
|
var expectedPos = this.level.replay.currentPlaybackFrame.marblePosition.clone();
|
||||||
|
var expectedVel = this.level.replay.currentPlaybackFrame.marbleVelocity.clone();
|
||||||
|
var expectedOmega = this.level.replay.currentPlaybackFrame.marbleAngularVelocity.clone();
|
||||||
|
|
||||||
|
this.getAbsPos().setPosition(expectedPos);
|
||||||
|
this.velocity = expectedVel;
|
||||||
|
this.setRotationQuat(this.level.replay.currentPlaybackFrame.marbleOrientation.clone());
|
||||||
|
this.omega = expectedOmega;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.controllable) {
|
if (this.controllable) {
|
||||||
this.camera.update(timeState.currentAttemptTime, timeState.dt);
|
this.camera.update(timeState.currentAttemptTime, timeState.dt);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package src;
|
package src;
|
||||||
|
|
||||||
|
import src.Replay;
|
||||||
import hxd.impl.Air3File.FileSeek;
|
import hxd.impl.Air3File.FileSeek;
|
||||||
import gui.Canvas;
|
import gui.Canvas;
|
||||||
import hxd.snd.Channel;
|
import hxd.snd.Channel;
|
||||||
|
|
@ -121,14 +122,19 @@ class MarbleWorld extends Scheduler {
|
||||||
var helpTextTimeState:Float = -1e8;
|
var helpTextTimeState:Float = -1e8;
|
||||||
var alertTextTimeState:Float = -1e8;
|
var alertTextTimeState:Float = -1e8;
|
||||||
|
|
||||||
|
// Orientation
|
||||||
var orientationChangeTime = -1e8;
|
var orientationChangeTime = -1e8;
|
||||||
var oldOrientationQuat = new Quat();
|
var oldOrientationQuat = new Quat();
|
||||||
|
|
||||||
var resourceLoadFuncs:Array<(() -> Void)->Void> = [];
|
|
||||||
|
|
||||||
/** The new target camera orientation quat */
|
|
||||||
public var newOrientationQuat = new Quat();
|
public var newOrientationQuat = new Quat();
|
||||||
|
|
||||||
|
// Replay
|
||||||
|
public var replay:Replay;
|
||||||
|
public var isWatching:Bool = false;
|
||||||
|
|
||||||
|
// Loading
|
||||||
|
var resourceLoadFuncs:Array<(() -> Void)->Void> = [];
|
||||||
|
|
||||||
public var _disposed:Bool = false;
|
public var _disposed:Bool = false;
|
||||||
|
|
||||||
public var _ready:Bool = false;
|
public var _ready:Bool = false;
|
||||||
|
|
@ -146,6 +152,7 @@ class MarbleWorld extends Scheduler {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.scene2d = scene2d;
|
this.scene2d = scene2d;
|
||||||
this.mission = mission;
|
this.mission = mission;
|
||||||
|
this.replay = new Replay(mission.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function init() {
|
public function init() {
|
||||||
|
|
@ -313,6 +320,10 @@ class MarbleWorld extends Scheduler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function restart() {
|
public function restart() {
|
||||||
|
if (!this.isWatching)
|
||||||
|
this.replay.clear();
|
||||||
|
else
|
||||||
|
this.replay.rewind();
|
||||||
this.timeState.currentAttemptTime = 0;
|
this.timeState.currentAttemptTime = 0;
|
||||||
this.timeState.gameplayClock = 0;
|
this.timeState.gameplayClock = 0;
|
||||||
this.bonusTime = 0;
|
this.bonusTime = 0;
|
||||||
|
|
@ -762,6 +773,7 @@ class MarbleWorld extends Scheduler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addDtsObject(obj:DtsObject, onFinish:Void->Void) {
|
public function addDtsObject(obj:DtsObject, onFinish:Void->Void) {
|
||||||
|
obj.idInLevel = this.dtsObjects.length; // Set the id of the thing
|
||||||
this.dtsObjects.push(obj);
|
this.dtsObjects.push(obj);
|
||||||
if (obj is ForceObject) {
|
if (obj is ForceObject) {
|
||||||
this.forceObjects.push(cast obj);
|
this.forceObjects.push(cast obj);
|
||||||
|
|
@ -807,8 +819,27 @@ class MarbleWorld extends Scheduler {
|
||||||
if (!_ready) {
|
if (!_ready) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!this.isWatching)
|
||||||
|
this.replay.startFrame();
|
||||||
|
else {
|
||||||
|
if (!this.replay.advance(dt)) {
|
||||||
|
if (Util.isTouchDevice()) {
|
||||||
|
MarbleGame.instance.touchInput.hideControls(@:privateAccess this.playGui.playGuiCtrl);
|
||||||
|
}
|
||||||
|
this.setCursorLock(false);
|
||||||
|
this.dispose();
|
||||||
|
var pmg = new PlayMissionGui();
|
||||||
|
PlayMissionGui.currentSelectionStatic = mission.index + 1;
|
||||||
|
MarbleGame.canvas.setContent(pmg);
|
||||||
|
#if js
|
||||||
|
pointercontainer.hidden = false;
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ProfilerUI.measure("updateTimer");
|
ProfilerUI.measure("updateTimer");
|
||||||
this.updateTimer(dt);
|
this.updateTimer(dt);
|
||||||
|
|
||||||
this.tickSchedule(timeState.currentAttemptTime);
|
this.tickSchedule(timeState.currentAttemptTime);
|
||||||
this.updateGameState();
|
this.updateGameState();
|
||||||
ProfilerUI.measure("updateDTS");
|
ProfilerUI.measure("updateDTS");
|
||||||
|
|
@ -828,12 +859,20 @@ class MarbleWorld extends Scheduler {
|
||||||
ProfilerUI.measure("updateAudio");
|
ProfilerUI.measure("updateAudio");
|
||||||
AudioManager.update(this.scene);
|
AudioManager.update(this.scene);
|
||||||
|
|
||||||
|
if (!this.isWatching)
|
||||||
|
this.replay.endFrame();
|
||||||
|
|
||||||
if (this.outOfBounds && this.finishTime == null && Key.isDown(Settings.controlsSettings.powerup)) {
|
if (this.outOfBounds && this.finishTime == null && Key.isDown(Settings.controlsSettings.powerup)) {
|
||||||
this.clearSchedule();
|
this.clearSchedule();
|
||||||
this.restart();
|
this.restart();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Key.isDown(Key.H)) {
|
||||||
|
this.isWatching = true;
|
||||||
|
this.restart();
|
||||||
|
}
|
||||||
|
|
||||||
this.updateTexts();
|
this.updateTexts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -875,32 +914,52 @@ class MarbleWorld extends Scheduler {
|
||||||
|
|
||||||
public function updateTimer(dt:Float) {
|
public function updateTimer(dt:Float) {
|
||||||
this.timeState.dt = dt;
|
this.timeState.dt = dt;
|
||||||
if (this.bonusTime != 0 && this.timeState.currentAttemptTime >= 3.5) {
|
if (!this.isWatching) {
|
||||||
this.bonusTime -= dt;
|
if (this.bonusTime != 0 && this.timeState.currentAttemptTime >= 3.5) {
|
||||||
if (this.bonusTime < 0) {
|
this.bonusTime -= dt;
|
||||||
this.timeState.gameplayClock -= this.bonusTime;
|
if (this.bonusTime < 0) {
|
||||||
this.bonusTime = 0;
|
this.timeState.gameplayClock -= this.bonusTime;
|
||||||
}
|
this.bonusTime = 0;
|
||||||
if (timeTravelSound == null) {
|
}
|
||||||
var ttsnd = ResourceLoader.getResource("data/sound/timetravelactive.wav", ResourceLoader.getAudio, this.soundResources);
|
if (timeTravelSound == null) {
|
||||||
timeTravelSound = AudioManager.playSound(ttsnd, null, true);
|
var ttsnd = ResourceLoader.getResource("data/sound/timetravelactive.wav", ResourceLoader.getAudio, this.soundResources);
|
||||||
|
timeTravelSound = AudioManager.playSound(ttsnd, null, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (timeTravelSound != null) {
|
||||||
|
timeTravelSound.stop();
|
||||||
|
timeTravelSound = null;
|
||||||
|
}
|
||||||
|
if (this.timeState.currentAttemptTime >= 3.5)
|
||||||
|
this.timeState.gameplayClock += dt;
|
||||||
|
else if (this.timeState.currentAttemptTime + dt >= 3.5) {
|
||||||
|
this.timeState.gameplayClock += (this.timeState.currentAttemptTime + dt) - 3.5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.timeState.currentAttemptTime += dt;
|
||||||
} else {
|
} else {
|
||||||
if (timeTravelSound != null) {
|
this.timeState.currentAttemptTime = this.replay.currentPlaybackFrame.time;
|
||||||
timeTravelSound.stop();
|
this.timeState.gameplayClock = this.replay.currentPlaybackFrame.clockTime;
|
||||||
timeTravelSound = null;
|
this.bonusTime = this.replay.currentPlaybackFrame.bonusTime;
|
||||||
}
|
if (this.bonusTime != 0 && this.timeState.currentAttemptTime >= 3.5) {
|
||||||
if (this.timeState.currentAttemptTime >= 3.5)
|
if (timeTravelSound == null) {
|
||||||
this.timeState.gameplayClock += dt;
|
var ttsnd = ResourceLoader.getResource("data/sound/timetravelactive.wav", ResourceLoader.getAudio, this.soundResources);
|
||||||
else if (this.timeState.currentAttemptTime + dt >= 3.5) {
|
timeTravelSound = AudioManager.playSound(ttsnd, null, true);
|
||||||
this.timeState.gameplayClock += (this.timeState.currentAttemptTime + dt) - 3.5;
|
}
|
||||||
|
} else {
|
||||||
|
if (timeTravelSound != null) {
|
||||||
|
timeTravelSound.stop();
|
||||||
|
timeTravelSound = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.timeState.currentAttemptTime += dt;
|
|
||||||
this.timeState.timeSinceLoad += dt;
|
this.timeState.timeSinceLoad += dt;
|
||||||
if (finishTime != null)
|
if (finishTime != null)
|
||||||
this.timeState.gameplayClock = finishTime.gameplayClock;
|
this.timeState.gameplayClock = finishTime.gameplayClock;
|
||||||
playGui.formatTimer(this.timeState.gameplayClock);
|
playGui.formatTimer(this.timeState.gameplayClock);
|
||||||
|
|
||||||
|
if (!this.isWatching)
|
||||||
|
this.replay.recordTimeState(timeState.currentAttemptTime, timeState.gameplayClock, this.bonusTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTexts() {
|
function updateTexts() {
|
||||||
|
|
|
||||||
191
src/Replay.hx
Normal file
191
src/Replay.hx
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
package src;
|
||||||
|
|
||||||
|
import haxe.EnumFlags;
|
||||||
|
import h3d.Quat;
|
||||||
|
import h3d.Vector;
|
||||||
|
import src.Util;
|
||||||
|
|
||||||
|
enum ReplayMarbleState {
|
||||||
|
UsedPowerup;
|
||||||
|
Jumped;
|
||||||
|
InstantTeleport;
|
||||||
|
}
|
||||||
|
|
||||||
|
@:publicFields
|
||||||
|
class ReplayFrame {
|
||||||
|
// Time
|
||||||
|
var time:Float;
|
||||||
|
var clockTime:Float;
|
||||||
|
var bonusTime:Float;
|
||||||
|
// Marble
|
||||||
|
var marblePosition:Vector;
|
||||||
|
var marbleVelocity:Vector;
|
||||||
|
var marbleOrientation:Quat;
|
||||||
|
var marbleAngularVelocity:Vector;
|
||||||
|
var marbleStateFlags:EnumFlags<ReplayMarbleState>;
|
||||||
|
// Camera
|
||||||
|
var cameraPitch:Float;
|
||||||
|
var cameraYaw:Float;
|
||||||
|
// Input
|
||||||
|
var marbleX:Float;
|
||||||
|
var marbleY:Float;
|
||||||
|
|
||||||
|
public function new() {}
|
||||||
|
|
||||||
|
public function interpolate(next:ReplayFrame, time:Float) {
|
||||||
|
var t = (time - this.time) / (next.time - this.time);
|
||||||
|
|
||||||
|
var dt = time - this.time;
|
||||||
|
|
||||||
|
var interpFrame = new ReplayFrame();
|
||||||
|
|
||||||
|
// Interpolate time
|
||||||
|
interpFrame.time = time;
|
||||||
|
interpFrame.bonusTime = this.bonusTime;
|
||||||
|
interpFrame.clockTime = this.clockTime;
|
||||||
|
if (interpFrame.bonusTime != 0 && time >= 3.5) {
|
||||||
|
if (dt <= this.bonusTime) {
|
||||||
|
interpFrame.bonusTime -= dt;
|
||||||
|
} else {
|
||||||
|
interpFrame.clockTime += dt - this.bonusTime;
|
||||||
|
interpFrame.bonusTime = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.time >= 3.5)
|
||||||
|
interpFrame.clockTime += dt;
|
||||||
|
else if (this.time + dt >= 3.5) {
|
||||||
|
interpFrame.clockTime += (this.time + dt) - 3.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolate marble
|
||||||
|
if (this.marbleStateFlags.has(InstantTeleport)) {
|
||||||
|
interpFrame.marblePosition = this.marblePosition.clone();
|
||||||
|
interpFrame.marbleVelocity = this.marbleVelocity.clone();
|
||||||
|
interpFrame.marbleOrientation = this.marbleOrientation.clone();
|
||||||
|
interpFrame.marbleAngularVelocity = this.marbleAngularVelocity.clone();
|
||||||
|
interpFrame.marbleStateFlags.set(InstantTeleport);
|
||||||
|
} else {
|
||||||
|
interpFrame.marblePosition = Util.lerpThreeVectors(this.marblePosition, next.marblePosition, t);
|
||||||
|
interpFrame.marbleVelocity = Util.lerpThreeVectors(this.marbleVelocity, next.marbleVelocity, t);
|
||||||
|
interpFrame.marbleOrientation = new Quat();
|
||||||
|
interpFrame.marbleOrientation.slerp(this.marbleOrientation, next.marbleOrientation, t);
|
||||||
|
interpFrame.marbleAngularVelocity = Util.lerpThreeVectors(this.marbleAngularVelocity, next.marbleAngularVelocity, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolate camera
|
||||||
|
if (this.marbleStateFlags.has(InstantTeleport)) {
|
||||||
|
interpFrame.cameraYaw = this.cameraYaw;
|
||||||
|
interpFrame.cameraPitch = this.cameraPitch;
|
||||||
|
} else {
|
||||||
|
interpFrame.cameraYaw = Util.lerp(this.cameraYaw, next.cameraYaw, t);
|
||||||
|
interpFrame.cameraPitch = Util.lerp(this.cameraPitch, next.cameraPitch, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// State flags
|
||||||
|
if (this.marbleStateFlags.has(UsedPowerup))
|
||||||
|
interpFrame.marbleStateFlags.set(UsedPowerup);
|
||||||
|
if (this.marbleStateFlags.has(Jumped))
|
||||||
|
interpFrame.marbleStateFlags.set(Jumped);
|
||||||
|
|
||||||
|
// Input
|
||||||
|
interpFrame.marbleX = this.marbleX;
|
||||||
|
interpFrame.marbleY = this.marbleY;
|
||||||
|
|
||||||
|
return interpFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Replay {
|
||||||
|
public var mission:String;
|
||||||
|
|
||||||
|
var frames:Array<ReplayFrame>;
|
||||||
|
|
||||||
|
var currentRecordFrame:ReplayFrame;
|
||||||
|
|
||||||
|
public var currentPlaybackFrame:ReplayFrame;
|
||||||
|
|
||||||
|
var currentPlaybackFrameIdx:Int;
|
||||||
|
var currentPlaybackTime:Float;
|
||||||
|
|
||||||
|
public function new(mission:String) {
|
||||||
|
this.mission = mission;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function startFrame() {
|
||||||
|
currentRecordFrame = new ReplayFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function endFrame() {
|
||||||
|
frames.push(currentRecordFrame);
|
||||||
|
currentRecordFrame = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function recordTimeState(time:Float, clockTime:Float, bonusTime:Float) {
|
||||||
|
currentRecordFrame.time = time;
|
||||||
|
currentRecordFrame.clockTime = clockTime;
|
||||||
|
currentRecordFrame.bonusTime = bonusTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function recordMarbleState(position:Vector, velocity:Vector, orientation:Quat, angularVelocity:Vector) {
|
||||||
|
currentRecordFrame.marblePosition = position.clone();
|
||||||
|
currentRecordFrame.marbleVelocity = velocity.clone();
|
||||||
|
currentRecordFrame.marbleOrientation = orientation.clone();
|
||||||
|
currentRecordFrame.marbleAngularVelocity = angularVelocity.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function recordMarbleStateFlags(jumped:Bool, usedPowerup:Bool, instantTeleport:Bool) {
|
||||||
|
if (jumped)
|
||||||
|
currentRecordFrame.marbleStateFlags.set(Jumped);
|
||||||
|
if (usedPowerup)
|
||||||
|
currentRecordFrame.marbleStateFlags.set(UsedPowerup);
|
||||||
|
if (instantTeleport)
|
||||||
|
currentRecordFrame.marbleStateFlags.set(InstantTeleport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function recordMarbleInput(x:Float, y:Float) {
|
||||||
|
currentRecordFrame.marbleX = x;
|
||||||
|
currentRecordFrame.marbleY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function recordCameraState(pitch:Float, yaw:Float) {
|
||||||
|
currentRecordFrame.cameraPitch = pitch;
|
||||||
|
currentRecordFrame.cameraYaw = yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clear() {
|
||||||
|
this.frames = [];
|
||||||
|
currentRecordFrame = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function advance(dt:Float) {
|
||||||
|
if (this.currentPlaybackFrame == null) {
|
||||||
|
this.currentPlaybackFrame = this.frames[this.currentPlaybackFrameIdx];
|
||||||
|
}
|
||||||
|
|
||||||
|
var nextT = this.currentPlaybackTime + dt;
|
||||||
|
var startFrame = this.frames[this.currentPlaybackFrameIdx];
|
||||||
|
if (this.currentPlaybackFrameIdx + 1 >= this.frames.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var nextFrame = this.frames[this.currentPlaybackFrameIdx + 1];
|
||||||
|
while (nextFrame.time <= nextT) {
|
||||||
|
this.currentPlaybackFrameIdx++;
|
||||||
|
if (this.currentPlaybackFrameIdx + 1 >= this.frames.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var testNextFrame = this.frames[this.currentPlaybackFrameIdx + 1];
|
||||||
|
startFrame = nextFrame;
|
||||||
|
nextFrame = testNextFrame;
|
||||||
|
}
|
||||||
|
this.currentPlaybackFrame = startFrame.interpolate(nextFrame, nextT);
|
||||||
|
this.currentPlaybackTime += dt;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rewind() {
|
||||||
|
this.currentPlaybackTime = 0;
|
||||||
|
this.currentPlaybackFrame = null;
|
||||||
|
this.currentPlaybackFrameIdx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue