Skip to content

Platforms

Olivier Biot edited this page Nov 13, 2026 · 1 revision

Platforms

A melonJS game is a web page, so it runs anywhere a browser does. It can also go further: into native apps, into game portals that run it inside their own app, and into runtimes that have no web page at all. This section has a page for each.

Platform What it is Where players find the game Page
YouTube Playables a game portal the YouTube app and website YouTube Playables
Facebook Instant Games a game portal the Facebook app, facebook.com/gaming, Messenger Facebook Instant Games
WeChat Mini Games a mini-game runtime, with an adapter standing in for the web page the WeChat app WeChat Mini Games
Capacitor a native app wrapper the App Store and Google Play Capacitor
Cordova a native app wrapper, older the App Store and Google Play Cordova
nx.js a runtime for Nintendo Switch homebrew, with no web page the Switch (homebrew) Nintendo Switch (nx.js)
Web Workers drawing from a worker thread any browser Web Workers

Running with no web page, on nx.js or in a worker, needs melonJS 20.14 or later. WeChat Mini Games and the portal integrations below need melonJS 20.15 or later.

When the platform is in charge

A game portal or a native wrapper decides things a browser tab leaves to the game: when the game is paused, where progress is saved, whether sound is on. melonJS has one way of handing each of these over, the same on every platform.

Loading the platform's SDK

A portal's SDK is a script it hosts, loaded by index.html before the game. Don't bundle it with your game: portals check for that.

Pausing when the platform says so

melonJS pauses a game when the player switches away. Two settings are involved:

  • Who reports it: the browser window, by default. device.setFocusEvents(false) stops that, so the platform can report it instead, by emitting event.BLUR and event.FOCUS from its own callbacks.
  • What the game does about it: the application's pauseOnBlur, stopOnBlur and resumeOnFocus flags. With stopOnBlur, the game loop and the rendering stop, the music pauses, the sound effects are muted and held keys are released. On resume, melonJS undoes exactly that.
device.setFocusEvents(false);
app.stopOnBlur = true;
app.pauseOnBlur = false;
platform.onPause(() => event.emit(event.BLUR));
platform.onResume(() => event.emit(event.FOCUS));

Turning the flags off instead would not work: they apply to the platform's events as well, so its pause would do nothing.

Saving where the platform says

melonJS's save uses localStorage by default. save.setStorage() points it somewhere else:

  • For a cloud save, which loads and saves asynchronously (YouTube, Facebook), save.createCloudStorage() makes the storage: load the save first, then hand over what was loaded and how to save it back. It keeps everything in memory, saves in the background one save at a time, and flush() saves at once.

    const cloud = save.createCloudStorage({
        data: await platform.loadSave(),
        write: (items) => platform.writeSave(items),
    });
    save.setStorage(cloud);
  • For a storage that answers straight away, such as a native wrapper's, hand setStorage() its three calls: getItem, setItem and removeItem.

WeChat needs neither: its adapter's localStorage is WeChat's own storage.

The game itself keeps using save as usual.

Sound

A platform with its own mute setting (YouTube) expects the game to follow it: audio.muteAll() and audio.unmuteAll() from its callback. Its mute then replaces any mute button of the game's own.

Loading screens and readiness

Portals often draw their own loading screen and want to know how far along the game is, or when it can be played:

  • event.LOADER_PROGRESS reports the loader's progress, from 0 to 1.
  • event.GAME_AFTER_DRAW fires after each frame is drawn: the first one while state.LOADING is current is the first frame of the loading screen.
  • A screen's onResetEvent() is where the game becomes playable.

The screen size

A portal's frame can start with no size at all and get its real size later, or change once the game starts. Start the application at a fixed size, let its scaling ("fit" or "flex") follow the frame, and call app.resize() if the frame changes without telling the page.

Running with no web page

nx.js and Web Workers have no document: no page to put a canvas in. melonJS runs there from 20.14: give the application the canvas to draw to, with the canvas setting.

const app = new Application(1280, 720, {
    canvas: theCanvas,       // the runtime's display canvas
    renderer: video.AUTO,
    scale: 1,
});
await app.init();

What changes without a page (sizing, Tiled maps, fonts, sound) is on each runtime's page.

WeChat Mini Games have no page either, but WeChat's adapter stands in for one, with a document, an Image and the on-screen canvas: see WeChat Mini Games.

Other platforms

Other portals, such as Poki or CrazyGames, have SDKs of the same kind: their own pause, save and ad calls. The pattern above should apply to them too, but their pages aren't written yet, since each SDK needs checking first.

Clone this wiki locally