Repository navigation
Nintendo Switch
nx.js runs JavaScript homebrew on the Nintendo Switch. It implements the web APIs a game uses (Canvas 2D, WebGL 2, fetch, createImageBitmap, Web Audio, gamepads, touch) but has no web page around them: no document, no HTML elements, no CSS.
melonJS runs there from melonJS 20.14. Support is experimental.
There is no page to create a canvas in, so give the application the one to draw to. On nx.js that is the global screen, the Switch's 1280 × 720 display:
import { Application, video } from "melonjs";
const app = new Application(1280, 720, {
canvas: screen, // nx.js's display
renderer: video.AUTO, // WebGL 2 where available, otherwise Canvas
scale: 1,
});
await app.init();Set up the nx.js project itself as its documentation describes.
-
Size: design the game at the display's size. There is no page to fit, so
scale: "auto"has nothing to measure, and the game is drawn at the scale it is given. The console scales the picture itself when docked. -
No page features:
app.parentElementisundefined, and fullscreen and pointer lock do nothing. -
Assets load through
fetchandcreateImageBitmap, as in a browser, and a relative path is read from the app's RomFS. Two exceptions:-
Tiled maps must be JSON (
.tmjand.tsj): XML needsDOMParser, which nx.js doesn't have. - The
videoandscriptasset types need a page, and fail.
-
Tiled maps must be JSON (
-
Input: touches on the screen reach the game as pointer events, as usual. There is no mouse. The Joy-Con are standard gamepads, and keyboard events only come from a USB keyboard.
-
Sound needs no tap or click to start. nx.js can't say which formats it decodes, so melonJS uses the first extension given to
audio.init(): name one it decodes first, such asaudio.init("ogg,mp3"). Plain playback, volume and stereo panning work, but nx.js's Web Audio has noPannerNode,OscillatorNodeorBiquadFilterNode, so 3D positional sound,audio.tone()/audio.noise()and the reverb, echo and compressor effects throw. -
Fonts: nx.js's
FontFaceonly takes the font's bytes, so afontfaceasset (a URL) fails. Load the bytes yourself, and add the face before aTextuses it. It is ready once made; don't call itsload(), which throws on nx.js:const bytes = await (await fetch("font.ttf")).arrayBuffer(); fonts.add(new FontFace("Pixel", bytes));
-
Saves:
saveuseslocalStorageas usual. If the app declares user save data (userAccountSaveDataSizein its NACP), the first time melonJS readslocalStorageis when the Switch asks the player to pick a user. An app that saves nothing should leave that size at 0, so no picker appears.
- nx.js
- Web Workers: the other place melonJS runs without a page
- melonJS's own test,
nxjs-compatibility.spec.js, which runs a game in a worker set up like nx.js: the reference for what is expected to work