Workers P2: Szene bekommt flush() für die Rückkehr in den Tab
Die Bühne beruhigt die Regie beim Zurückkehren (alles zu Ende gespielt, alle heim, Aufzug und Effekte leer); im Standbild zeichnet flush() ein Bild. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e6bc2d938a
commit
319e731d0e
2 files changed
+53
-3
No files matched your search
@@ -35,7 +35,7 @@ const bindGlobal = (name) => (typeof globalThis[name] === 'function' ? globalThi
|
||||
function inertHandle() {
|
||||
const nop = () => {}
|
||||
return {
|
||||
destroy: nop, setState: nop, pushEvents: nop, select: nop, setPaused: nop, resize: nop, zoomBy: nop, resetView: nop,
|
||||
destroy: nop, setState: nop, pushEvents: nop, select: nop, setPaused: nop, flush: nop, resize: nop, zoomBy: nop, resetView: nop,
|
||||
locate: () => null,
|
||||
stats: () => ({ frames: 0, avgDrawMs: 0, zoom: 1 }),
|
||||
debug: () => ({ pending: 0, agents: [], lift: 'idle', fx: 0 }),
|
||||
@@ -43,12 +43,14 @@ function inertHandle() {
|
||||
}
|
||||
|
||||
/* mountTower(canvas, { onSelect, reducedMotion = false, coarsePointer = false, fontsReady, dpr = 1, raf, caf, now })
|
||||
→ { destroy(), setState(state), pushEvents(events), select(workerId|null), setPaused(bool), resize(), zoomBy(faktor),
|
||||
→ { destroy(), setState(state), pushEvents(events), select(workerId|null), setPaused(bool), flush(), resize(), zoomBy(faktor),
|
||||
resetView(), locate(workerId): { x, y } | null, stats(): { frames, avgDrawMs, zoom }, debug() }
|
||||
Rasterweite je Bild: k = Canvas-Breite / (320 / zoom). Reihenfolge je Bild: Weiß, Außenwelt, Turm, Räume, Aufzug hinten, Figuren,
|
||||
Aufzug vorn, Effekte, Pausenschleier. onSelect(id | null) kommt nur bei Klicks des Nutzers, nie bei select().
|
||||
reducedMotion (und fehlendes raf): keine Schleife; setState, pushEvents, select, resize und die Kamera zeichnen je ein Standbild,
|
||||
pushEvents spielt die Regie sofort zu Ende. fontsReady (Promise): nach dem Laden der Schrift wird einmal neu gezeichnet.
|
||||
flush() beruhigt die Regie auf einen Schlag (alles zu Ende gespielt, alle Figuren heim, Aufzug und Effekte leer): die Bühne ruft es
|
||||
beim Zurückkehren in den Tab, damit nichts aus der Zeit davor nachläuft.
|
||||
locate liefert die Mitte der Trefferfläche in CSS-Pixeln relativ zur Leinwand (null: unbekannt oder außerhalb der Ansicht).
|
||||
Nach destroy() ist jeder Aufruf wirkungslos. */
|
||||
export function mountTower(canvas, options = {}) {
|
||||
@@ -318,6 +320,13 @@ export function mountTower(canvas, options = {}) {
|
||||
}
|
||||
},
|
||||
|
||||
flush() {
|
||||
if (destroyed) return
|
||||
director.flush()
|
||||
if (still) calm()
|
||||
draw()
|
||||
},
|
||||
|
||||
setPaused(value) {
|
||||
if (destroyed) return
|
||||
const next = !!value
|
||||
|
||||
@@ -14,7 +14,7 @@ const open = async (o = {}, extra = {}) => {
|
||||
|
||||
test('Handle hat die Methoden aus Übersicht §7 und E4; Mount zeichnet sofort', async () => {
|
||||
const { sb, h } = await open()
|
||||
for (const m of ['destroy', 'setState', 'pushEvents', 'select', 'setPaused', 'resize', 'zoomBy', 'resetView', 'locate', 'stats', 'debug']) {
|
||||
for (const m of ['destroy', 'setState', 'pushEvents', 'select', 'setPaused', 'flush', 'resize', 'zoomBy', 'resetView', 'locate', 'stats', 'debug']) {
|
||||
assert.equal(typeof h[m], 'function', m)
|
||||
}
|
||||
assert.ok(sb.counts.fillRect > 100)
|
||||
@@ -575,3 +575,44 @@ test('debug() und stats(): Form', async () => {
|
||||
assert.ok(s.frames > 25)
|
||||
h.destroy()
|
||||
})
|
||||
|
||||
test('flush(): Rückkehr in den Tab beruhigt die Regie (alles heim, Aufzug und Effekte leer) und zeichnet; nach destroy wirkungslos', async () => {
|
||||
const { sb, h } = await open()
|
||||
h.setState(makeState())
|
||||
const arne = () => h.debug().agents.find((a) => a.id === 'arne')
|
||||
const home = { x: arne().x, y: arne().y, floor: arne().floor }
|
||||
h.pushEvents([ev('uebergabe', 'arne', { to: 'bea' })])
|
||||
sb.tick(3)
|
||||
assert.ok(h.debug().pending > 0)
|
||||
h.setPaused(true)
|
||||
const n = sb.counts.fillRect
|
||||
h.setPaused(false)
|
||||
h.flush()
|
||||
assert.ok(sb.counts.fillRect > n)
|
||||
assert.equal(h.debug().pending, 0)
|
||||
assert.equal(h.debug().lift, 'idle')
|
||||
assert.equal(h.debug().fx, 0)
|
||||
assert.deepEqual({ x: arne().x, y: arne().y, floor: arne().floor }, home)
|
||||
h.pushEvents([ev('uebergabe', 'arne', { to: 'bea' })])
|
||||
assert.equal(h.debug().pending, 1)
|
||||
h.destroy()
|
||||
const m = sb.counts.fillRect
|
||||
h.flush()
|
||||
assert.equal(sb.counts.fillRect, m)
|
||||
assert.equal(h.debug().pending, 1)
|
||||
})
|
||||
|
||||
test('flush() im Standbild zeichnet ein Standbild ohne Bildrückruf; ohne 2D-Kontext tut es nichts', async () => {
|
||||
const { sb, h } = await open({}, { reducedMotion: true })
|
||||
h.setState(makeState())
|
||||
const n = sb.counts.fillRect
|
||||
h.flush()
|
||||
assert.ok(sb.counts.fillRect > n)
|
||||
assert.equal(sb.rafPending(), 0)
|
||||
h.destroy()
|
||||
const bare = await createEngineSandbox()
|
||||
bare.canvas.getContext = () => null
|
||||
const g = bare.mountTower(bare.canvas, bare.opts({}))
|
||||
g.flush()
|
||||
assert.equal(bare.counts.fillRect, 0)
|
||||
})
|
||||
Reference in new issue
Block a user