diff --git a/CHANGELOG.md b/CHANGELOG.md index 23be962d9ed2..9e5d87f47e68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正 - Fix: Encode RSS urls with escape sequences before fetching allowing query parameters to be used - Fix: リンク切れを修正 +- Fix: Ensure physics run the same across different framerates ### Server - Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 3226a554a93b..f16fd989a646 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -50,7 +50,7 @@ "insert-text-at-cursor": "0.3.0", "is-file-animated": "1.0.2", "json5": "2.2.3", - "matter-js": "0.19.0", + "matter-js": "0.20.0", "mfm-js": "0.24.0", "misskey-bubble-game": "workspace:*", "misskey-js": "workspace:*", diff --git a/packages/frontend/src/pages/drop-and-fusion.game.vue b/packages/frontend/src/pages/drop-and-fusion.game.vue index fb4d599c2856..8d369101affc 100644 --- a/packages/frontend/src/pages/drop-and-fusion.game.vue +++ b/packages/frontend/src/pages/drop-and-fusion.game.vue @@ -557,7 +557,7 @@ let bgmNodes: ReturnType | null = null; let renderer: Matter.Render | null = null; let monoTextures: Record = {}; let monoTextureUrls: Record = {}; -let tickRaf: number | null = null; +let tickInterval: number | null = null; let game = new DropAndFusionGame({ seed: seed, gameMode: props.gameMode, @@ -663,13 +663,20 @@ function getTextureImageUrl(mono: Mono) { } } +function startTicking(tickFunction: () => void) { + tickInterval = window.setInterval(tickFunction, game.TICK_DELTA); +} + +function stopTicking() { + if (tickInterval !== null) { + window.clearInterval(tickInterval); + tickInterval = null; + } +} + function tick() { const hasNextTick = game.tick(); - if (hasNextTick) { - tickRaf = window.requestAnimationFrame(tick); - } else { - tickRaf = null; - } + if (!hasNextTick) stopTicking(); } function tickReplay() { @@ -700,11 +707,7 @@ function tickReplay() { if (!hasNextTick) break; } - if (hasNextTick) { - tickRaf = window.requestAnimationFrame(tickReplay); - } else { - tickRaf = null; - } + if (!hasNextTick) stopTicking(); } async function start() { @@ -716,7 +719,7 @@ async function start() { }); Matter.Render.run(renderer); game.start(); - window.requestAnimationFrame(tick); + startTicking(tick); gameLoaded.value = true; @@ -803,9 +806,7 @@ function reset() { function dispose() { game.dispose(); if (renderer) Matter.Render.stop(renderer); - if (tickRaf) { - window.cancelAnimationFrame(tickRaf); - } + stopTicking(); } function backToTitle() { @@ -829,7 +830,7 @@ function replay() { }); Matter.Render.run(renderer); game.start(); - window.requestAnimationFrame(tickReplay); + startTicking(tickReplay); }); } diff --git a/packages/misskey-bubble-game/src/game.ts b/packages/misskey-bubble-game/src/game.ts index 7f230e39cb8f..ff43488c7d00 100644 --- a/packages/misskey-bubble-game/src/game.ts +++ b/packages/misskey-bubble-game/src/game.ts @@ -51,7 +51,7 @@ export class DropAndFusionGame extends EventEmitter<{ public readonly DROP_COOLTIME = 30; // frame public readonly PLAYAREA_MARGIN = 25; private STOCK_MAX = 4; - private TICK_DELTA = 1000 / 60; // 60fps + public readonly TICK_DELTA = 1000 / 60; // 60fps public frame = 0; public engine: Matter.Engine; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1312e8c88642..cd0d3bc346b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -791,8 +791,8 @@ importers: specifier: 2.2.3 version: 2.2.3 matter-js: - specifier: 0.19.0 - version: 0.19.0 + specifier: 0.20.0 + version: 0.20.0 mfm-js: specifier: 0.24.0 version: 0.24.0 @@ -8462,6 +8462,9 @@ packages: matter-js@0.19.0: resolution: {integrity: sha512-v2huwvQGOHTGOkMqtHd2hercCG3f6QAObTisPPHg8TZqq2lz7eIY/5i/5YUV8Ibf3mEioFEmwibcPUF2/fnKKQ==} + matter-js@0.20.0: + resolution: {integrity: sha512-iC9fYR7zVT3HppNnsFsp9XOoQdQN2tUyfaKg4CHLH8bN+j6GT4Gw7IH2rP0tflAebrHFw730RR3DkVSZRX8hwA==} + mdast-util-find-and-replace@3.0.1: resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} @@ -11433,6 +11436,9 @@ packages: vue-component-type-helpers@2.1.6: resolution: {integrity: sha512-ng11B8B/ZADUMMOsRbqv0arc442q7lifSubD0v8oDXIFoMg/mXwAPUunrroIDkY+mcD0dHKccdaznSVp8EoX3w==} + vue-component-type-helpers@2.1.8: + resolution: {integrity: sha512-ii36gDzrYAfOQIkOlo44yceDdT5269gKmNGxf07Qx6seH2U50+tQ2ol02XLhYPmxrh6YabAsOdte8WDrpaO6Tw==} + vue-demi@0.14.7: resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==} engines: {node: '>=12'} @@ -15155,7 +15161,7 @@ snapshots: ts-dedent: 2.2.0 type-fest: 2.19.0 vue: 3.5.11(typescript@5.6.2) - vue-component-type-helpers: 2.1.6 + vue-component-type-helpers: 2.1.8 '@swc/cli@0.3.12(@swc/core@1.6.6)(chokidar@3.5.3)': dependencies: @@ -20680,6 +20686,8 @@ snapshots: matter-js@0.19.0: {} + matter-js@0.20.0: {} + mdast-util-find-and-replace@3.0.1: dependencies: '@types/mdast': 4.0.3 @@ -24025,6 +24033,8 @@ snapshots: vue-component-type-helpers@2.1.6: {} + vue-component-type-helpers@2.1.8: {} + vue-demi@0.14.7(vue@3.5.11(typescript@5.6.2)): dependencies: vue: 3.5.11(typescript@5.6.2)