mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-12-28 10:52:17 +00:00
make physics ticks match to mbu
This commit is contained in:
parent
774d15fd29
commit
2bae691c23
7 changed files with 146 additions and 33 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 = [];
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue