Repository navigation
Changed
- Render quality levels are now always on:
Rendererreads every draw-quality knob from aBGE.RenderQualitySettingspreset, seeded from the device model (fallback Medium). Games that never call the new API will look slightly different on non-Medium devices (draw distance, plane slices, fast-draw tolerances) (#251, #126). DrawablePlanealways draws to the authoredCamera3d.maxDrawDistance(device-capped), regardless of quality level, so the horizon never moves.Camera2dnow culls an object by the bounding box of its corners, so an image bigger than the view is no longer culled when all four corners are off screen (#258).Camera2d.worldPointToCanvasPoint()rounds to the nearest pixel instead of truncating, and the view snaps to whole pixels, so adjacent images no longer gap by 1px (#255, #261).Game.loadBitmap()now accepts.webp(Roku OS 9.4+),.jpeg,.bmpand.gif, and returnsfalse(and logs) when the bitmap can't be decoded instead of storinginvalid. SVG isn't supported and animated GIFs only show frame 1 (#259, #266).gameUianddebugUinow receiveonChangeScene()when the scene changes (#245).- Controller-page input now reaches
gameUi.onInput.
Added
Rendering
- Adaptive render quality: five
BGE.RenderQualityLevelpresets (Basic to Ultra),Game.enableAdaptiveQuality()to hold a target frame rate (default 20fps),Game.setQualityLevel()to pin a level,Game.renderQuality.overridePreset()to retune a level, and anonQualityChanged(level)callback on entities, the scene and UI. See the Render Quality guide (#251, #126). Camera2d.follow(entity)andCamera2d.setBounds(x, y, w, h), applied before drawing so the camera no longer runs a frame behind (#260).
Scenes
Game.changeSceneWithFade()/Game.isTransitioning()with aBGE.ScreenFadeoverlay (#260).
Collision
GameEntity.onCollisionEnter()/onCollisionExit()(#260).BGE.SolidWorld: top-down static-rectangle collision withmoveAndSlide()(maxStep/cornerNudgeoptions),addSolid()(returns an id),removeSolid(id),addBounds(),isAreaFree()andgetSolids()(typedBGE.SolidWorldSolid[]) (#256).
UI
BGE.UI.Label.wrapWidthandBGE.UI.wrapText()for word wrapping;DrawableTextsizes multi-line text by its widest line (#257).
Audio
Game.musicPlay(path, loop, restart = true)(restart = falseleaves an already-playing track alone) andGame.getMusicPath()(#290).npm run audio -- sfx|music|silences|info: ffmpeg tools for Roku-safe sound effects (mono 22kHz WAV) and music (96kbps MP3) (#290).
Utilities
- Auto-tiling in
BGE.TileMap:getNeighbourMask4(),getNeighbourMask8(),reduceBlobMask(),getBlobTileIndex()(47-tile blob sets) andgetEdgePiece3x3(), taking rows of strings or arrays of tile ids, with anoutOfBoundsMatchesoption (#272). - Releases are automated: an Initialize Release workflow opens a
release/x.y.zPR, and merging it tags, publishes to npm (trusted publishing) and creates the GitHub release (#248).
Docs
- New Tile Maps guide (#278) and Render Quality guide.
RectangleColliderdocs now sayoffset.yis the top edge (world +y up), and that edge-to-edge colliders don't collide whileonCollisionfires every frame for a persistent overlap (#280, #200).
Examples
- New
rpg("Broadsword"): a top-down adventure with sword combat, enemies, a data-driven story/dialogue/shop/save layer, a six-room dungeon, a witch boss, credits and music (#63, #256, #257, #289, #296, #290). platformer: level 7 boss fight (Venus fly trap) (#265).rendererTest:quality-levelsandnegative-scaledemos;terrainturns on adaptive quality.
Fixed
Game.handleSceneChange()crashed when entities existed before the firstchangeScene()(#244).Game.destroyAllEntities()skipped every other entity (#263).- Moving a drawable by its own
offset/rotation/scaledidn't redraw while its entity stood still (#264). directScaledbillboards now mirror correctly for a negative scale on real hardware, which only mirrorsDrawTransformedObjectat rotation 0 (#237).DrawableCircle's anchor was ignored in the plain 2D draw modes (#273).- Typed keyboard characters leaked into button input (a character's release looked like a button, e.g.
"d"as Back); they now reach onlyonECPKeyboard()(#194). FocusManager.focusWidget()now clears a held stick direction.
Full changelog: CHANGELOG.md