marble finish animation

This commit is contained in:
RandomityGuy 2023-06-20 01:55:33 +05:30
parent 0964fe53ca
commit b9b111bf85
4 changed files with 125 additions and 61 deletions

View file

@ -222,9 +222,8 @@ class CameraController extends Object {
if (this.finish) {
// Make the camera spin around slowly
CameraPitch = Util.lerp(this.level.finishPitch, 0.45,
Util.clamp((this.level.timeState.currentAttemptTime - this.level.finishTime.currentAttemptTime) / 0.3, 0, 1));
CameraYaw = this.level.finishYaw - (this.level.timeState.currentAttemptTime - this.level.finishTime.currentAttemptTime) / -1.2;
CameraPitch = this.level.finishPitch;
CameraYaw = this.level.finishYaw;
}
if (!this.level.isWatching) {
@ -236,7 +235,7 @@ class CameraController extends Object {
CameraYaw = this.level.replay.currentPlaybackFrame.cameraYaw;
}
var marblePosition = level.marble.getAbsPos().getPosition();
var marblePosition = level.marble.collider.transform.getPosition();
var up = new Vector(0, 0, 1);
up.transform(orientationQuat.toMatrix());
var directionVector = new Vector(1, 0, 0);

View file

@ -265,6 +265,10 @@ class Marble extends GameObject {
var helicopterSound:Channel;
var playedSounds = [];
var finishAnimVelocity:Vector;
var finishAnimPosition:Vector;
var finishAnimTime:Float = 0;
public var mode:Mode = Play;
public var startPad:StartPad;
@ -425,6 +429,7 @@ class Marble extends GameObject {
this.isUltra = isUltra;
this.collider = new SphereCollisionEntity(cast this);
this.collider.setTransform(this.getAbsPos());
this.addChild(marbleDts);
@ -512,7 +517,7 @@ class Marble extends GameObject {
A = A.multiply(0.25);
}
for (obj in level.forceObjects) {
var force = cast(obj, ForceObject).getForce(this.getAbsPos().getPosition());
var force = cast(obj, ForceObject).getForce(this.collider.transform.getPosition());
A = A.add(force.multiply(1 / _mass));
}
if (contacts.length != 0 && this.mode != Start) {
@ -850,7 +855,7 @@ class Marble extends GameObject {
function bounceEmitter(speed:Float, normal:Vector) {
if (this.bounceEmitDelay == 0 && this._minBounceSpeed <= speed) {
this.level.particleManager.createEmitter(bounceParticleOptions, this.bounceEmitterData,
this.getAbsPos().getPosition().sub(normal.multiply(_radius)), null, new Vector(1, 1, 1).add(normal.multiply(-0.8)));
this.collider.transform.getPosition().sub(normal.multiply(_radius)), null, new Vector(1, 1, 1).add(normal.multiply(-0.8)));
this.bounceEmitDelay = 0.3;
}
}
@ -911,15 +916,15 @@ class Marble extends GameObject {
function updateRollSound(time:TimeState, contactPct:Float, slipAmount:Float) {
var rSpat = rollSound.getEffect(Spatialization);
rSpat.position = this.getAbsPos().getPosition();
rSpat.position = this.collider.transform.getPosition();
if (this.rollMegaSound != null) {
var rmspat = this.rollMegaSound.getEffect(Spatialization);
rmspat.position = this.getAbsPos().getPosition();
rmspat.position = this.collider.transform.getPosition();
}
var sSpat = slipSound.getEffect(Spatialization);
sSpat.position = this.getAbsPos().getPosition();
sSpat.position = this.collider.transform.getPosition();
var rollVel = bestContact != null ? this.velocity.sub(bestContact.velocity) : this.velocity;
var scale = rollVel.length();
@ -989,7 +994,9 @@ class Marble extends GameObject {
position: position,
t: deltaT,
found: false,
foundContacts: []
foundContacts: [],
lastContactPos: null,
lastContactNormal: null
};
}
var searchbox = new Bounds();
@ -1109,6 +1116,7 @@ class Marble extends GameObject {
finalT = collisionTime;
currentFinalPos = position.add(relVel.multiply(finalT));
found = true;
lastContactPos = currentFinalPos.clone();
// iterationFound = true;
i += 3;
// Debug.drawSphere(currentFinalPos, radius);
@ -1319,7 +1327,9 @@ class Marble extends GameObject {
position: position,
t: finalT,
found: found,
foundContacts: testTriangles
foundContacts: testTriangles,
lastContactPos: lastContactPos,
lastContactNormal: position.sub(lastContactPos).normalized(),
};
}
@ -1328,7 +1338,7 @@ class Marble extends GameObject {
searchbox.addSpherePos(this.x, this.y, this.z, _radius);
searchbox.addSpherePos(this.x + velocity.x * dt * 2, this.y + velocity.y * dt * 2, this.z + velocity.z * dt * 2, _radius);
var position = this.getAbsPos().getPosition();
var position = this.collider.transform.getPosition();
var foundObjs = this.level.collisionWorld.boundingSearch(searchbox);
// var foundObjs = this.contactEntities;
@ -1618,7 +1628,7 @@ class Marble extends GameObject {
velocity.w = 0;
var pos = this.getAbsPos().getPosition();
var pos = this.collider.transform.getPosition();
this.prevPos = pos.clone();
var tdiff = timeStep;
@ -1653,43 +1663,6 @@ class Marble extends GameObject {
}
}
// var intersectT = intersectData.t;
// if (intersectData.found && intersectT > 0.001) {
// var diff = timeStep - intersectT;
// this.velocity = this.velocity.sub(A.multiply(diff));
// this.omega = this.omega.sub(a.multiply(diff));
// // var mo = new h3d.prim.Sphere();
// // mo.addNormals();
// // mo.scale(_radius);
// // var mCol = new h3d.scene.Mesh(mo);
// // mCol.setPosition(intersectData.position.x, intersectData.position.y, intersectData.position.z);
// // this.level.scene.addChild(mCol);
// timeStep = intersectT;
// }
// var posAdd = this.velocity.multiply(timeStep);
// var expectedPos = pos.add(posAdd);
// var newPos = nudgeToContacts(expectedPos, _radius);
// if (mode == Start) {
// var upVec = this.level.currentUp;
// var startpadNormal = startPad.getAbsPos().up();
// this.velocity = upVec.multiply(this.velocity.dot(upVec));
// // Apply contact forces in startPad up direction if upVec is not startpad up, fixes the weird startpad shit in pinball wizard
// if (upVec.dot(startpadNormal) < 0.95) {
// for (contact in contacts) {
// var normF = contact.normal.multiply(contact.normalForce);
// var startpadF = startpadNormal.multiply(normF.dot(startpadNormal));
// var upF = upVec.multiply(normF.dot(upVec));
// this.velocity = this.velocity.add(startpadF.multiply(timeStep / 4));
// }
// }
// }
// if (mode == Finish) {
// this.velocity = this.velocity.multiply(0.925);
// }
var rot = this.getRotationQuat();
var quat = new Quat();
quat.initRotation(omega.x * timeStep, omega.y * timeStep, omega.z * timeStep);
@ -1858,6 +1831,11 @@ class Marble extends GameObject {
this.updateTeleporterState(timeState);
this.updateFinishAnimation(timeState.dt);
if (this.mode == Finish) {
this.setPosition(this.finishAnimPosition.x, this.finishAnimPosition.y, this.finishAnimPosition.z);
}
this.trailEmitter();
if (bounceEmitDelay > 0)
bounceEmitDelay -= timeState.dt;
@ -1867,6 +1845,81 @@ class Marble extends GameObject {
// this.camera.target.load(this.getAbsPos().getPosition().toPoint());
}
public function updateFinishAnimation(dt:Float) {
if (this.mode == Finish) {
var trans = @:privateAccess this.level.endPad.getAbsPos();
var around = trans.getPosition();
var forceEffect = trans.up();
around = around.add(forceEffect);
var offset = finishAnimPosition.sub(around);
static var animTimeAccumulator = 0.0;
animTimeAccumulator += dt;
while (animTimeAccumulator >= 1 / 60.0) {
animTimeAccumulator -= (1 / 60.0);
finishAnimVelocity.scale(0.95);
finishAnimVelocity = finishAnimVelocity.add(forceEffect.multiply(0.2));
var dist = offset.length();
finishAnimVelocity = finishAnimVelocity.sub(offset.multiply(0.35));
if (dist > 1.5) {
var outward = offset.multiply(1 / dist);
var outforce = outward.dot(finishAnimVelocity);
if (outforce > 0) {
finishAnimVelocity = finishAnimVelocity.sub(outward.multiply(outforce * 0.75));
var noodles = offset.multiply(outforce * 0.5);
noodles = finishAnimVelocity.sub(noodles);
if (noodles.lengthSq() <= 0.1) {
var cross = outward.cross(forceEffect);
if (cross.lengthSq() <= 0.1) {
noodles = trans.front().clone();
} else {
noodles = cross.normalized();
}
} else {
noodles.normalize();
}
finishAnimVelocity = finishAnimVelocity.add(noodles.multiply(outforce * 0.25));
}
}
var addVel = new Vector(Math.sin(finishAnimTime * 3), Math.sin(finishAnimTime * 3 + 2.45), Math.sin(finishAnimTime * 1.5 + 1.2));
finishAnimVelocity = finishAnimVelocity.add(addVel.multiply(2.5 / 60.0));
var pos = finishAnimPosition.add(finishAnimVelocity.multiply(1 / 60.0));
var position = finishAnimPosition.clone();
var velocity = pos.sub(finishAnimPosition);
var time = 1.0;
var i = 0;
var totalTime = time;
do {
if (totalTime <= 1e-8)
break;
var tm = testMove(velocity, position, time, _radius, true);
if (!tm.found)
break;
i++;
totalTime -= tm.t;
time = totalTime;
pos = tm.position;
var norm = tm.lastContactNormal;
var newAround = norm.multiply(1.5);
newAround.scale(finishAnimVelocity.dot(norm));
finishAnimVelocity = finishAnimVelocity.sub(newAround);
} while (i < 4);
finishAnimPosition = pos;
finishAnimTime += (1 / 60.0);
}
}
}
public function updatePowerupStates(currentTime:Float, dt:Float) {
if (currentTime - this.shockAbsorberEnableTime < 5) {
this.shockabsorberSound.pause = false;
@ -1977,6 +2030,20 @@ class Marble extends GameObject {
}
}
public function setMode(mode:Mode) {
this.mode = mode;
if (mode == Finish) {
this.finishAnimPosition = this.collider.transform.getPosition().clone();
this.finishAnimVelocity = this.velocity.clone();
this.finishAnimTime = 0;
}
}
public function setMarblePosition(x:Float, y:Float, z:Float) {
this.collider.transform.setPosition(new Vector(x, y, z));
this.setPosition(x, y, z);
}
public override function reset() {
this.velocity = new Vector();
this.collider.velocity = new Vector();
@ -1997,6 +2064,7 @@ class Marble extends GameObject {
this.teleporting = false;
this.teleportDisableTime = null;
this.teleportEnableTime = null;
this.finishAnimTime = 0;
if (this._radius != this._prevRadius) {
this._radius = this._prevRadius;
this._marbleScale = this._renderScale = this._defaultScale;

View file

@ -491,10 +491,7 @@ class MarbleWorld extends Scheduler {
var startquat = this.getStartPositionAndOrientation();
this.marble.setPosition(startquat.position.x, startquat.position.y, startquat.position.z + 0.727843);
var oldtransform = this.marble.collider.transform.clone();
oldtransform.setPosition(startquat.position);
this.marble.collider.setTransform(oldtransform);
this.marble.setMarblePosition(startquat.position.x, startquat.position.y, startquat.position.z + 0.727843);
this.marble.reset();
var euler = startquat.quat.toEuler();
@ -505,7 +502,7 @@ class MarbleWorld extends Scheduler {
this.marble.camera.nextCameraYaw = euler.z + Math.PI / 2;
this.marble.camera.oob = false;
this.marble.camera.finish = false;
this.marble.mode = Start;
this.marble.setMode(Start);
this.marble.startPad = cast startquat.pad;
sky.follow = marble.camera;
@ -535,15 +532,15 @@ class MarbleWorld extends Scheduler {
return; // We will update state manually
if (this.timeState.currentAttemptTime < 0.5) {
this.playGui.setCenterText('none');
this.marble.mode = Start;
this.marble.setMode(Start);
}
if ((this.timeState.currentAttemptTime >= 0.5) && (this.timeState.currentAttemptTime < 3.5)) {
this.playGui.setCenterText('none');
this.marble.mode = Start;
this.marble.setMode(Start);
}
if (this.timeState.currentAttemptTime >= 3.5 && this.finishTime == null) {
this.playGui.setCenterText('none');
this.marble.mode = Play;
this.marble.setMode(Play);
}
}
@ -1412,7 +1409,7 @@ class MarbleWorld extends Scheduler {
} else {
this.endPad.spawnFirework(this.timeState);
this.finishTime = this.timeState.clone();
this.marble.mode = Finish;
this.marble.setMode(Finish);
this.marble.camera.finish = true;
this.finishYaw = this.marble.camera.CameraYaw;
this.finishPitch = this.marble.camera.CameraPitch;
@ -1673,7 +1670,7 @@ class MarbleWorld extends Scheduler {
// Determine where to spawn the marble
var offset = new Vector(0, 0, 0.727843);
var mpos = this.currentCheckpoint.getAbsPos().getPosition().add(offset);
this.marble.setPosition(mpos.x, mpos.y, mpos.z);
this.marble.setMarblePosition(mpos.x, mpos.y, mpos.z);
marble.velocity.load(new Vector(0, 0, 0));
marble.omega.load(new Vector(0, 0, 0));
Console.log('Respawn:');

View file

@ -85,7 +85,7 @@ class RewindManager {
public function applyFrame(rf:RewindFrame) {
level.timeState = rf.timeState.clone();
level.marble.setPosition(rf.marblePosition.x, rf.marblePosition.y, rf.marblePosition.z);
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);