Extract beforeUpdate steps
This commit is contained in:
146
src/main.js
146
src/main.js
@@ -636,6 +636,83 @@
|
|||||||
rebuildSceneBodies();
|
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", () => {
|
Events.on(engine, "afterUpdate", () => {
|
||||||
// Keep stray balls within the play area horizontally.
|
// Keep stray balls within the play area horizontally.
|
||||||
state.balls.forEach((ball) => {
|
state.balls.forEach((ball) => {
|
||||||
@@ -674,72 +751,15 @@
|
|||||||
|
|
||||||
Events.on(engine, "beforeUpdate", () => {
|
Events.on(engine, "beforeUpdate", () => {
|
||||||
// Rope-like constraint handling: allow shortening without push-back, tension when stretched.
|
// Rope-like constraint handling: allow shortening without push-back, tension when stretched.
|
||||||
if (
|
runSceneBeforeUpdateHook();
|
||||||
!state.levelWon &&
|
stepRopeConstraints();
|
||||||
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.
|
|
||||||
const dt = (engine.timing && engine.timing.delta) || 16;
|
const dt = (engine.timing && engine.timing.delta) || 16;
|
||||||
const timeScale = engine.timing?.timeScale ?? 1;
|
const timeScale = engine.timing?.timeScale ?? 1;
|
||||||
if (state.paused || state.gameOver || timeScale === 0) return;
|
if (state.paused || state.gameOver || timeScale === 0) return;
|
||||||
state.rotators.forEach((b) => {
|
// Rotate any scene rotators slowly.
|
||||||
const speed = b.plugin.rotSpeed || 0;
|
stepRotators(dt, timeScale);
|
||||||
if (speed !== 0) {
|
stepOscillators();
|
||||||
Body.rotate(b, speed * ((dt * timeScale) / 1000));
|
stepTimer();
|
||||||
}
|
|
||||||
});
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(render, "afterRender", () => {
|
Events.on(render, "afterRender", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user