Skip to content

v19.9.1

Latest

Choose a tag to compare

@github-actions github-actions released this 28 Jul 01:20
ad2f2bd

What's New

19.9.1 is a focused bug-fix release for the 19.9 line — 17 fixes, two long-standing open issues closed, no API additions, drop-in upgrade from 19.9.0.

The headline: video sprites no longer stall in fullscreen. Large videos (1080p/4K) dropped to ~4fps the moment the game went fullscreen while everything else kept rendering at 60 — the browser parks off-DOM video elements on a slow background timer once the page compositor idles, and a fullscreen canvas is exactly what idles it. The engine now keeps a requestVideoFrameCallback pending on the element, which forces full-rate frame delivery, and as a bonus only uploads to the GPU when the video actually presented a new frame.

Also closed: #1231 — the canvas slowly growing on every window resize (alt-tab, devtools) when its container sits inside a wrapper with no fixed CSS size. Two root causes, both fixed: the engine canvas now defaults to display: block (the browser's inline default added a baseline gap that fed back into the auto-scale measurement), and auto-scale measures the container's content box instead of its border box.

Bug Fixes

  • Video fullscreen frame stall — pending requestVideoFrameCallback keeps detached video elements at full frame rate (see above); video sprites also correctly pause on state.pause() now (the listener had a wrong event name since its introduction)
  • Canvas growth feedback loop on resize (#1231) — display: block default + content-box measurement (see above)
  • Renderables batch: onVisibilityChange fired a spurious leave/enter pair every frame for visible objects; Container/Entity destroy() passed an Arguments object to onDestroyEvent instead of the actual arguments; Container.getNextChild() returned the first child for a non-member; Text/BitmapText destroy() wiped a caller-provided string array; NineSliceSprite showed ~2px seams for region sizes not divisible by 4
  • Animation batch: a completed loop: false animation could never be replayed via play()/setCurrentAnimation(); frames with a 0 delay froze the game in an infinite loop (now advance one frame per tick)
  • Camera batch: destroyed cameras kept reacting to game reset / canvas resize (crash after destroy, one leaked camera per state switch with cameraClass — stages now destroy the cameras they construct); the bounds clamp ignored a non-zero world origin, making the far edges unreachable
  • Particles: dead particles were released to the pool while their removal was still deferred — a same-frame respawn could silently vanish, and a same-frame emitter teardown could poison the pool
  • Drag & drop: DropTarget.setCheckMethod() validated the current method instead of the new one, accepting invalid names that crashed later on drop
  • Hardening: ShaderEffect.setTexture() rejects an HTMLVideoElement with a clear TypeError instead of silently freezing on its first frame; BMFont padding was parsed with padLeft/padRight swapped; the texture cache's dead frame-dimension refinement is removed (#1489) with the first-registered-atlas behavior now explicit and test-codified

Performance

  • Video textures upload to the GPU only when a new frame was actually presented — previously a full texImage2D ran on every render tick per sprite (~2× redundant for 30fps video at 60Hz, more when several sprites share one element)

Changed

  • The engine-inserted canvas defaults to display: block; set any inline display style on the canvas to keep your own value
  • Videos now genuinely pause on state.pause() — this was always the documented behavior, but the listener never fired

Install

npm install melonjs@19.9.1

CDN:

<script type="module" src="https://cdn.jsdelivr.net/npm/melonjs@19/+esm"></script>

🤖 Generated with Claude Code