make physics ticks match to mbu

This commit is contained in:
RandomityGuy 2023-07-11 00:09:14 +05:30
parent 774d15fd29
commit 2bae691c23
7 changed files with 146 additions and 33 deletions

View file

@ -305,7 +305,7 @@ class CameraController extends Object {
CameraYaw = this.level.replay.currentPlaybackFrame.cameraYaw;
}
var marblePosition = level.marble.collider.transform.getPosition();
var marblePosition = this.finish ? level.marble.collider.transform.getPosition() : level.marble.getAbsPos().getPosition();
if (this.finish) {
// Move the target to the centre of the finish
@ -341,6 +341,10 @@ class CameraController extends Object {
var closeness = 0.1;
var rayCastOrigin = marblePosition.add(level.currentUp.multiply(marble._radius)).add(cameraVerticalTranslation);
for (pi in level.pathedInteriors) {
pi.pushTickState();
}
var processedShapes = [];
for (i in 0...3) {
var rayCastDirection = camera.pos.sub(rayCastOrigin);
@ -388,6 +392,10 @@ class CameraController extends Object {
break;
}
for (pi in level.pathedInteriors) {
pi.popTickState();
}
if (oob) {
camera.pos = lastCamPos;
camera.target = marblePosition.add(lastVertTranslation);

View file

@ -230,6 +230,11 @@ class Marble extends GameObject {
public var _mass:Float = 1;
var physicsAccumulator:Float = 0;
var oldPos:Vector;
var newPos:Vector;
var prevRot:Quat;
public var contacts:Array<CollisionInfo> = [];
public var bestContact:CollisionInfo;
public var contactEntities:Array<CollisionEntity> = [];
@ -1593,6 +1598,9 @@ class Marble extends GameObject {
var passedTime = timeState.currentAttemptTime;
oldPos = this.collider.transform.getPosition();
prevRot = this.getRotationQuat().clone();
if (this.controllable) {
for (interior in pathedInteriors) {
// interior.pushTickState();
@ -1604,7 +1612,7 @@ class Marble extends GameObject {
if (timeRemaining <= 0)
break;
var timeStep = 0.004;
var timeStep = 0.008;
if (timeRemaining < timeStep)
timeStep = timeRemaining;
@ -1691,13 +1699,13 @@ class Marble extends GameObject {
var quat = new Quat();
quat.initRotation(omega.x * timeStep, omega.y * timeStep, omega.z * timeStep);
quat.multiply(quat, rot);
this.setRotationQuat(quat);
// this.setRotationQuat(quat);
var totMatrix = quat.toMatrix();
newPos.w = 1; // Fix shit blowing up
totMatrix.setPosition(newPos);
this.setPosition(newPos.x, newPos.y, newPos.z);
// this.setPosition(newPos.x, newPos.y, newPos.z);
this.collider.setTransform(totMatrix);
this.collider.velocity = this.velocity;
@ -1746,6 +1754,7 @@ class Marble extends GameObject {
}
this.queuedContacts = [];
newPos = this.collider.transform.getPosition();
this.updateRollSound(timeState, contactTime / timeState.dt, this._slipAmount);
}
@ -1796,8 +1805,32 @@ class Marble extends GameObject {
}
}
physicsAccumulator += timeState.dt;
playedSounds = [];
advancePhysics(timeState, move, collisionWorld, pathedInteriors);
while (physicsAccumulator > 0.032) {
var adt = timeState.clone();
adt.dt = 0.032;
advancePhysics(adt, move, collisionWorld, pathedInteriors);
physicsAccumulator -= 0.032;
}
if (oldPos != null && newPos != null) {
var deltaT = physicsAccumulator / 0.032;
var renderPos = Util.lerpThreeVectors(this.oldPos, this.newPos, deltaT);
this.setPosition(renderPos.x, renderPos.y, renderPos.z);
var rot = this.prevRot;
var quat = new Quat();
quat.initRotation(omega.x * physicsAccumulator, omega.y * physicsAccumulator, omega.z * physicsAccumulator);
quat.multiply(quat, rot);
this.setRotationQuat(quat);
var adt = timeState.clone();
adt.dt = physicsAccumulator;
for (pi in pathedInteriors) {
pi.update(adt);
}
}
if (this.controllable) {
if (!this.level.isWatching) {
@ -1983,13 +2016,14 @@ class Marble extends GameObject {
public function useBlast() {
if (this.level.blastAmount < 0.25 || this.level.game != "ultra")
return;
return false;
var impulse = this.level.currentUp.multiply(this.level.blastAmount * 8);
this.applyImpulse(impulse);
AudioManager.playSound(ResourceLoader.getResource('data/sound/use_blast.wav', ResourceLoader.getAudio, this.soundResources));
this.blastWave.doSequenceOnceBeginTime = this.level.timeState.timeSinceLoad;
this.blastUseTime = this.level.timeState.currentAttemptTime;
this.level.blastAmount = 0;
return true;
}
public function applyImpulse(impulse:Vector, contactImpulse:Bool = false) {
@ -2071,6 +2105,10 @@ class Marble extends GameObject {
this.teleportDisableTime = null;
this.teleportEnableTime = null;
this.finishAnimTime = 0;
this.physicsAccumulator = 0;
this.prevRot = this.getRotationQuat().clone();
this.oldPos = this.getAbsPos().getPosition();
this.newPos = this.getAbsPos().getPosition();
if (this._radius != this._prevRadius) {
this._radius = this._prevRadius;
this._marbleScale = this._renderScale = this._defaultScale;

View file

@ -1017,14 +1017,15 @@ class MarbleWorld extends Scheduler {
this.tickSchedule(timeState.currentAttemptTime);
if (Key.isPressed(Settings.controlsSettings.blast)
if (Key.isDown(Settings.controlsSettings.blast)
|| (MarbleGame.instance.touchInput.blastbutton.pressed)
|| Gamepad.isPressed(Settings.gamepadSettings.blast)
|| Gamepad.isDown(Settings.gamepadSettings.blast)
&& !this.isWatching
&& this.game == "ultra") {
this.marble.useBlast();
if (this.isRecording) {
this.replay.recordMarbleStateFlags(false, false, false, true);
if (this.marble.useBlast()) {
if (this.isRecording) {
this.replay.recordMarbleStateFlags(false, false, false, true);
}
}
}

View file

@ -44,9 +44,15 @@ class PathedInterior extends InteriorObject {
var baseOrientation:Quat;
var baseScale:Vector;
var prevPosition:Vector;
var position:Vector;
public var velocity:Vector;
var _storedColliderTransform:Matrix;
var stopped:Bool = false;
var stoppedPosition:Vector;
var soundChannel:Channel;
@ -133,8 +139,25 @@ class PathedInterior extends InteriorObject {
onFinish();
}
public function pushTickState() {
this._storedColliderTransform = this.collider.transform.clone();
var tform = this.getAbsPos();
if (this.isCollideable) {
collider.setTransform(tform);
collisionWorld.updateTransform(this.collider);
}
}
public function popTickState() {
if (this.isCollideable) {
collider.setTransform(this._storedColliderTransform);
collisionWorld.updateTransform(this.collider);
}
}
public function computeNextPathStep(timeDelta:Float) {
stopped = false;
prevPosition = this.position.clone();
if (currentTime == targetTime) {
velocity.set(0, 0, 0);
} else {
@ -158,10 +181,10 @@ class PathedInterior extends InteriorObject {
currentTime += delta;
}
var curTform = this.getAbsPos();
var curTform = this.position;
var tForm = getTransformAtTime(currentTime);
var displaceDelta = tForm.getPosition().sub(curTform.getPosition());
var displaceDelta = tForm.getPosition().sub(curTform);
velocity.set(displaceDelta.x / timeDelta, displaceDelta.y / timeDelta, displaceDelta.z / timeDelta);
this.collider.velocity = velocity.clone();
}
@ -172,9 +195,17 @@ class PathedInterior extends InteriorObject {
return;
if (this.velocity.length() == 0)
return;
var newp = this.getAbsPos().getPosition().add(velocity.multiply(timeDelta));
this.setPosition(newp.x, newp.y, newp.z);
this.setTransform(this.getTransform());
velocity.w = 0;
var newp = position.add(velocity.multiply(timeDelta));
var tform = this.getAbsPos().clone();
tform.setPosition(newp);
// this.setPosition(newp.x, newp.y, newp.z);
if (this.isCollideable) {
collider.setTransform(tform);
collisionWorld.updateTransform(this.collider);
}
// this.setTransform(this.getTransform());
this.position = newp;
if (this.soundChannel != null) {
var spat = this.soundChannel.getEffect(Spatialization);
@ -182,12 +213,22 @@ class PathedInterior extends InteriorObject {
}
}
public function update(timeState:TimeState) {}
public function update(timeState:TimeState) {
if (!stopped)
this.setPosition(prevPosition.x
+ velocity.x * timeState.dt, prevPosition.y
+ velocity.y * timeState.dt,
prevPosition.z
+ velocity.z * timeState.dt);
else
this.setPosition(stoppedPosition.x, stoppedPosition.y, stoppedPosition.z);
}
public function setStopped(stopped:Bool = true) {
// if (!this.stopped)
// this.stopTime = currentTime;
this.stopped = stopped;
this.stoppedPosition = this.position.clone();
}
function computeDuration() {
@ -205,6 +246,8 @@ class PathedInterior extends InteriorObject {
function updatePosition() {
var newp = this.getAbsPos().getPosition();
this.position = newp;
this.prevPosition = newp;
this.setPosition(newp.x, newp.y, newp.z);
this.collider.setTransform(this.getTransform());
this.collider.velocity = this.velocity;

View file

@ -94,7 +94,7 @@ class GuiXboxListButton extends GuiControl {
_prevMousePos = mouseState.position.clone();
}
if (selected && !disabled) {
if (Key.isDown(Key.MOUSE_LEFT)) {
if (Key.isDown(Key.MOUSE_LEFT) && renderRect.inRect(mouseState.position)) {
this.button.anim.currentFrame = 1;
this.buttonIcon.anim.currentFrame = 1;
buttonText.text.textColor = 0x101010;

View file

@ -1,5 +1,6 @@
package rewind;
import h3d.Matrix;
import mis.MissionElement.MissionElementBase;
import triggers.CheckpointTrigger;
import src.PathedInterior.PIState;
@ -13,7 +14,10 @@ import shapes.Gem;
@:publicFields
class RewindFrame {
var timeState:TimeState;
var marblePosition:Vector;
var marbleColliderTransform:Matrix;
var marblePrevPosition:Vector;
var marbleNextPosition:Vector;
var marblePhysicsAccmulator:Float;
var marbleOrientation:Quat;
var marbleVelocity:Vector;
var marbleAngularVelocity:Vector;
@ -22,7 +26,9 @@ class RewindFrame {
var mpStates:Array<{
curState:PIState,
stopped:Bool,
position:Vector
stoppedPosition:Vector,
prevPosition:Vector,
position:Vector,
}>;
var gemCount:Int;
var gemStates:Array<Bool>;
@ -52,7 +58,10 @@ class RewindFrame {
public function clone() {
var c = new RewindFrame();
c.timeState = timeState.clone();
c.marblePosition = marblePosition.clone();
c.marbleColliderTransform = marbleColliderTransform.clone();
c.marblePrevPosition = marblePrevPosition.clone();
c.marbleNextPosition = marbleNextPosition.clone();
c.marblePhysicsAccmulator = marblePhysicsAccmulator;
c.marbleOrientation = marbleOrientation.clone();
c.marbleVelocity = marbleVelocity.clone();
c.marbleAngularVelocity = marbleAngularVelocity.clone();
@ -75,6 +84,8 @@ class RewindFrame {
},
stopped: s.stopped,
position: s.position.clone(),
prevPosition: s.prevPosition.clone(),
stoppedPosition: s.stoppedPosition != null ? s.stoppedPosition.clone() : null,
});
}
c.trapdoorStates = [];

View file

@ -21,8 +21,11 @@ class RewindManager {
public function recordFrame() {
var rf = new RewindFrame();
rf.timeState = level.timeState.clone();
rf.marblePosition = level.marble.getAbsPos().getPosition().clone();
rf.marbleOrientation = level.marble.getRotationQuat().clone();
rf.marbleColliderTransform = level.marble.collider.transform.clone();
rf.marblePrevPosition = @:privateAccess level.marble.oldPos.clone();
rf.marbleNextPosition = @:privateAccess level.marble.newPos.clone();
rf.marbleOrientation = @:privateAccess level.marble.prevRot.clone();
rf.marblePhysicsAccmulator = @:privateAccess level.marble.physicsAccumulator;
rf.marbleVelocity = level.marble.velocity.clone();
rf.marbleAngularVelocity = level.marble.omega.clone();
rf.marblePowerup = level.marble.heldPowerup;
@ -40,7 +43,9 @@ class RewindManager {
velocity: x.velocity.clone(),
},
stopped: @:privateAccess x.stopped,
position: x.getAbsPos().getPosition().clone(),
position: @:privateAccess x.position.clone(),
prevPosition: @:privateAccess x.prevPosition.clone(),
stoppedPosition: @:privateAccess x.stoppedPosition != null ? @:privateAccess x.stoppedPosition.clone() : null,
}
});
rf.powerupStates = [];
@ -82,10 +87,15 @@ class RewindManager {
public function applyFrame(rf:RewindFrame) {
level.timeState = rf.timeState.clone();
level.marble.setMarblePosition(rf.marblePosition.x, rf.marblePosition.y, rf.marblePosition.z);
level.marble.setRotationQuat(rf.marbleOrientation.clone());
level.marble.velocity.set(rf.marbleVelocity.x, rf.marbleVelocity.y, rf.marbleVelocity.z);
level.marble.omega.set(rf.marbleAngularVelocity.x, rf.marbleAngularVelocity.y, rf.marbleAngularVelocity.z);
@:privateAccess level.marble.oldPos.load(rf.marblePrevPosition);
@:privateAccess level.marble.newPos.load(rf.marbleNextPosition);
@:privateAccess level.marble.collider.transform.load(rf.marbleColliderTransform);
@:privateAccess level.marble.physicsAccumulator = rf.marblePhysicsAccmulator;
@:privateAccess level.marble.prevRot.load(rf.marbleOrientation);
// level.marble.setMarblePosition(rf.marblePosition.x, rf.marblePosition.y, rf.marblePosition.z);
// level.marble.setRotationQuat(rf.marbleOrientation.clone());
level.marble.velocity.load(rf.marbleVelocity);
level.marble.omega.load(rf.marbleAngularVelocity);
if (level.marble.heldPowerup == null) {
if (rf.marblePowerup != null) {
@ -123,15 +133,17 @@ class RewindManager {
@:privateAccess level.orientationChangeTime = -1e8;
}
level.currentUp.set(rf.currentUp.x, rf.currentUp.y, rf.currentUp.z);
level.marble.lastContactNormal.set(rf.lastContactNormal.x, rf.lastContactNormal.y, rf.lastContactNormal.z);
level.currentUp.load(rf.currentUp);
level.marble.lastContactNormal.load(rf.lastContactNormal);
for (i in 0...rf.mpStates.length) {
level.pathedInteriors[i].currentTime = rf.mpStates[i].curState.currentTime;
level.pathedInteriors[i].targetTime = rf.mpStates[i].curState.targetTime;
level.pathedInteriors[i].velocity.set(rf.mpStates[i].curState.velocity.x, rf.mpStates[i].curState.velocity.y, rf.mpStates[i].curState.velocity.z);
level.pathedInteriors[i].velocity.load(rf.mpStates[i].curState.velocity);
@:privateAccess level.pathedInteriors[i].stopped = rf.mpStates[i].stopped;
level.pathedInteriors[i].setPosition(rf.mpStates[i].position.x, rf.mpStates[i].position.y, rf.mpStates[i].position.z);
level.pathedInteriors[i].setTransform(level.pathedInteriors[i].getTransform());
@:privateAccess level.pathedInteriors[i].position.load(rf.mpStates[i].position);
@:privateAccess level.pathedInteriors[i].prevPosition.load(rf.mpStates[i].prevPosition);
@:privateAccess level.pathedInteriors[i].stoppedPosition = rf.mpStates[i].stoppedPosition;
// level.pathedInteriors[i].setTransform(level.pathedInteriors[i].getTransform());
}
var pstates = rf.powerupStates.copy();
var lmstates = rf.landMineStates.copy();