ball stage tilt

This commit is contained in:
Brandon Johnson
2026-02-02 17:46:10 -05:00
parent b630e9df33
commit 6827063904
5 changed files with 41 additions and 12 deletions

View File

@@ -372,6 +372,7 @@ export class Game {
};
public simTick: number;
public netplayRttMs: number | null;
public suppressVisualEffects: boolean;
public inputFeed: (QuantizedStick | QuantizedInput)[] | null;
public inputFeedIndex: number;
public inputRecord: QuantizedStick[] | null;
@@ -495,6 +496,7 @@ export class Game {
};
this.simTick = 0;
this.netplayRttMs = null;
this.suppressVisualEffects = false;
this.inputFeed = null;
this.inputFeedIndex = 0;
this.inputRecord = null;
@@ -609,11 +611,23 @@ export class Game {
},
advanceFrame: (inputs) => {
if (!perf.enabled) {
this.advanceOneFrame(inputs);
const prev = this.suppressVisualEffects;
this.suppressVisualEffects = true;
try {
this.advanceOneFrame(inputs);
} finally {
this.suppressVisualEffects = prev;
}
return;
}
const t0 = nowMs();
this.advanceOneFrame(inputs);
const prev = this.suppressVisualEffects;
this.suppressVisualEffects = true;
try {
this.advanceOneFrame(inputs);
} finally {
this.suppressVisualEffects = prev;
}
const dt = nowMs() - t0;
perf.lastAdvanceMs = dt;
perf.advanceMs += dt;
@@ -2746,6 +2760,7 @@ export class Game {
smb2LoadInFrames,
stageBall,
stageCamera,
!this.suppressVisualEffects,
);
if (localPlayer.goalTimerFrames > 0) {
localPlayer.goalTimerFrames -= 1;
@@ -2821,7 +2836,7 @@ export class Game {
if (ball.state !== BALL_STATES.PLAY && ball.state !== BALL_STATES.GOAL_MAIN) {
continue;
}
stepBall(ball, this.stageRuntime, player.world);
stepBall(ball, this.stageRuntime, player.world, !this.suppressVisualEffects);
if (ball.wormholeTransform) {
player.camera.applyWormholeTransform(ball.wormholeTransform);
ball.wormholeTransform = null;

View File

@@ -36,6 +36,7 @@ export type RenderContext = {
};
opaqueInstList: GfxRenderInstList;
translucentInstList: GfxRenderInstList;
viewFromWorld?: mat4;
};
export type BallRenderState = {

View File

@@ -634,7 +634,8 @@ class BallInst {
rp.sort = RenderSort.Translucent;
rp.lighting = state.lighting;
mat4.fromRotationTranslationScale(this.modelFromBall, this.rotation, this.pos, this.scale);
mat4.mul(rp.viewFromModel, ctx.viewerInput.camera.viewMatrix, this.modelFromBall);
const viewFromWorld = ctx.viewFromWorld ?? ctx.viewerInput.camera.viewMatrix;
mat4.mul(rp.viewFromModel, viewFromWorld, this.modelFromBall);
for (let i = 0; i < this.models.length; i++) {
rp.depthOffset = this.modelDepthOffsets[i] ?? 0;
@@ -1393,8 +1394,9 @@ export class World {
this.fgObjects[i].prepareToRenderWithViewMatrix(this.worldState, stageCtx, viewFromWorldTilted);
}
this.background.prepareToRender(this.worldState, bgCtx);
const ballCtx = ctx.skipStageTilt ? stageCtx : { ...stageCtx, viewFromWorld: viewFromWorldTilted };
for (let i = 0; i < this.balls.length; i++) {
this.balls[i].prepareToRender(this.worldState, stageCtx);
this.balls[i].prepareToRender(this.worldState, ballCtx);
}
}

View File

@@ -730,7 +730,7 @@ function handleBallRotationalKinematics(ball, physBall, animGroups, stageRuntime
}
}
export function stepBall(ball, stageRuntime, world) {
export function stepBall(ball, stageRuntime, world, allowEffects = true) {
const stage = stageRuntime.stage;
const animGroups = stageRuntime.animGroups;
if (ball.state === BALL_STATES.GOAL_MAIN) {
@@ -823,7 +823,7 @@ export function stepBall(ball, stageRuntime, world) {
}
}
if (stageRuntime.effects) {
if (allowEffects && stageRuntime.effects) {
const onGround = (physBall.flags & COLI_FLAGS.OCCURRED) !== 0 && physBall.hardestColiPlane.normal.y > 0;
const rng = stageRuntime.visualRng;
spawnMovementSparks(stageRuntime.effects, ball, onGround, rng);

View File

@@ -1524,7 +1524,16 @@ export class StageRuntime {
}
}
advance(frameDelta, paused, world, animTimerOverride = null, smb2LoadInFrames = null, ball = null, camera = null) {
advance(
frameDelta,
paused,
world,
animTimerOverride = null,
smb2LoadInFrames = null,
ball = null,
camera = null,
includeVisuals = true,
) {
if (paused) {
return;
}
@@ -1538,7 +1547,7 @@ export class StageRuntime {
}
this.updateAnimGroups(this.timerFrames / 60, frameDelta, smb2LoadInFrames);
if (world) {
this.updateObjects(world, ball, camera);
this.updateObjects(world, ball, camera, includeVisuals);
}
}
@@ -1945,7 +1954,7 @@ export class StageRuntime {
}
}
updateObjects(world, ball = null, camera = null) {
updateObjects(world, ball = null, camera = null, includeVisuals = true) {
const animGroups = this.animGroups;
const gravity = world.gravity ?? { x: 0, y: -1, z: 0 };
const stack = this.matrixStack;
@@ -1986,8 +1995,10 @@ export class StageRuntime {
for (const bag of this.goalBags) {
updateGoalBag(bag, animGroups, gravity, this.goalHoldOpen, stack, this.simRng);
}
updateConfetti(this, gravity);
updateBallEffects(this.effects, gravity, this, this.visualRng);
if (includeVisuals) {
updateConfetti(this, gravity);
updateBallEffects(this.effects, gravity, this, this.visualRng);
}
for (let i = 0; i < animGroups.length; i += 1) {
const bumperStates = this.bumpers[i];
for (const bumper of bumperStates) {