Extract beforeUpdate steps
This commit is contained in:
146
src/main.js
146
src/main.js
@@ -636,6 +636,83 @@
|
||||
rebuildSceneBodies();
|
||||
};
|
||||
|
||||
const runSceneBeforeUpdateHook = () => {
|
||||
if (
|
||||
state.levelWon ||
|
||||
typeof currentScene?.config?.onBeforeUpdate !== "function"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
currentScene.config.onBeforeUpdate({
|
||||
engine,
|
||||
width: state.width,
|
||||
height: state.height,
|
||||
});
|
||||
};
|
||||
|
||||
const stepRopeConstraints = () => {
|
||||
chain.constraints.forEach((c) => {
|
||||
if (!c.plugin || !c.plugin.rope) return;
|
||||
const current = Vector.magnitude(
|
||||
Vector.sub(c.bodyA.position, c.bodyB.position),
|
||||
);
|
||||
const maxLen = c.plugin.maxLength ?? c.length;
|
||||
if (current <= maxLen) {
|
||||
c.length = current;
|
||||
c.stiffness = 0;
|
||||
} else {
|
||||
c.length = maxLen;
|
||||
c.stiffness = c.plugin.baseStiffness ?? c.stiffness;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const stepRotators = (dt, timeScale) => {
|
||||
state.rotators.forEach((b) => {
|
||||
const speed = b.plugin.rotSpeed || 0;
|
||||
if (speed !== 0) {
|
||||
Body.rotate(b, speed * ((dt * timeScale) / 1000));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const stepOscillators = () => {
|
||||
state.oscillators.forEach((b) => {
|
||||
const osc = b.plugin.oscillate;
|
||||
if (!osc) return;
|
||||
if (!osc.base) {
|
||||
osc.base = { x: b.position.x, y: b.position.y };
|
||||
}
|
||||
const now = (engine.timing.timestamp || 0) / 1000;
|
||||
const amplitude = osc.amplitude ?? 0;
|
||||
const speed = osc.speed ?? 1;
|
||||
const phase = osc.phase ?? 0;
|
||||
const offset = Math.sin(now * speed + phase) * amplitude;
|
||||
const target =
|
||||
osc.axis === "x"
|
||||
? { x: osc.base.x + offset, y: osc.base.y }
|
||||
: { x: osc.base.x, y: osc.base.y + offset };
|
||||
Body.setPosition(b, target);
|
||||
Body.setVelocity(b, { x: 0, y: 0 });
|
||||
});
|
||||
};
|
||||
|
||||
const stepTimer = () => {
|
||||
if (!state.timerEndMs) return;
|
||||
const winCond = currentScene?.config?.winCondition;
|
||||
const duration = winCond?.durationSec ?? 120;
|
||||
const now = Date.now();
|
||||
const remainingMs = Math.max(0, state.timerEndMs - now);
|
||||
const remainingSec = Math.ceil(remainingMs / 1000);
|
||||
if (state.lastTimerDisplay !== remainingSec) {
|
||||
state.lastTimerDisplay = remainingSec;
|
||||
updateHud();
|
||||
}
|
||||
if (remainingMs <= 0 && !state.levelWon) {
|
||||
checkWinCondition();
|
||||
}
|
||||
};
|
||||
|
||||
Events.on(engine, "afterUpdate", () => {
|
||||
// Keep stray balls within the play area horizontally.
|
||||
state.balls.forEach((ball) => {
|
||||
@@ -674,72 +751,15 @@
|
||||
|
||||
Events.on(engine, "beforeUpdate", () => {
|
||||
// Rope-like constraint handling: allow shortening without push-back, tension when stretched.
|
||||
if (
|
||||
!state.levelWon &&
|
||||
typeof currentScene?.config?.onBeforeUpdate === "function"
|
||||
) {
|
||||
currentScene.config.onBeforeUpdate({
|
||||
engine,
|
||||
width: state.width,
|
||||
height: state.height,
|
||||
});
|
||||
}
|
||||
chain.constraints.forEach((c) => {
|
||||
if (!c.plugin || !c.plugin.rope) return;
|
||||
const current = Vector.magnitude(
|
||||
Vector.sub(c.bodyA.position, c.bodyB.position),
|
||||
);
|
||||
const maxLen = c.plugin.maxLength ?? c.length;
|
||||
if (current <= maxLen) {
|
||||
c.length = current;
|
||||
c.stiffness = 0;
|
||||
} else {
|
||||
c.length = maxLen;
|
||||
c.stiffness = c.plugin.baseStiffness ?? c.stiffness;
|
||||
}
|
||||
});
|
||||
// Rotate any scene rotators slowly.
|
||||
runSceneBeforeUpdateHook();
|
||||
stepRopeConstraints();
|
||||
const dt = (engine.timing && engine.timing.delta) || 16;
|
||||
const timeScale = engine.timing?.timeScale ?? 1;
|
||||
if (state.paused || state.gameOver || timeScale === 0) return;
|
||||
state.rotators.forEach((b) => {
|
||||
const speed = b.plugin.rotSpeed || 0;
|
||||
if (speed !== 0) {
|
||||
Body.rotate(b, speed * ((dt * timeScale) / 1000));
|
||||
}
|
||||
});
|
||||
state.oscillators.forEach((b) => {
|
||||
const osc = b.plugin.oscillate;
|
||||
if (!osc) return;
|
||||
if (!osc.base) {
|
||||
osc.base = { x: b.position.x, y: b.position.y };
|
||||
}
|
||||
const now = (engine.timing.timestamp || 0) / 1000;
|
||||
const amplitude = osc.amplitude ?? 0;
|
||||
const speed = osc.speed ?? 1;
|
||||
const phase = osc.phase ?? 0;
|
||||
const offset = Math.sin(now * speed + phase) * amplitude;
|
||||
const target =
|
||||
osc.axis === "x"
|
||||
? { x: osc.base.x + offset, y: osc.base.y }
|
||||
: { x: osc.base.x, y: osc.base.y + offset };
|
||||
Body.setPosition(b, target);
|
||||
Body.setVelocity(b, { x: 0, y: 0 });
|
||||
});
|
||||
if (state.timerEndMs) {
|
||||
const winCond = currentScene?.config?.winCondition;
|
||||
const duration = winCond?.durationSec ?? 120;
|
||||
const now = Date.now();
|
||||
const remainingMs = Math.max(0, state.timerEndMs - now);
|
||||
const remainingSec = Math.ceil(remainingMs / 1000);
|
||||
if (state.lastTimerDisplay !== remainingSec) {
|
||||
state.lastTimerDisplay = remainingSec;
|
||||
updateHud();
|
||||
}
|
||||
if (remainingMs <= 0 && !state.levelWon) {
|
||||
checkWinCondition();
|
||||
}
|
||||
}
|
||||
// Rotate any scene rotators slowly.
|
||||
stepRotators(dt, timeScale);
|
||||
stepOscillators();
|
||||
stepTimer();
|
||||
});
|
||||
|
||||
Events.on(render, "afterRender", () => {
|
||||
|
||||
Reference in New Issue
Block a user