float-diagonal Posted January 15, 2018 Share Posted January 15, 2018 When trying to use Phaser 3 Beta 15 with Electron I get errors about the names WEBGL_RENDERER and CANVAS_RENDERER being undefined as soon as I try to instantiate a Phaser.Game. This doesn't happen in a normal browser. To sidestep the issues I was able to simply set values to window.WEBGL_RENDERER and window.CANVAS_RENDERER prior to loading phaser.js. This will at least get the Phaser init message in the console. Should this be submitted as a Github issue? I don't know where Electron support falls on the spectrum and I don't know enough about the Phaser internals to say how much of an issue it would be to fix it. Link to comment Share on other sites More sharing options...
TomC Posted January 15, 2018 Share Posted January 15, 2018 How have you loaded the phaser library into your code? This shouldn't be an issue if you've imported the phaser library as a module into your main.js file. Link to comment Share on other sites More sharing options...
rich Posted January 15, 2018 Share Posted January 15, 2018 Those two settings are global defines that webpack uses during the build stage. Surely if you were packaging a game for Electron you'd build it first, then the Electron package would just be the build files + assets? Link to comment Share on other sites More sharing options...
float-diagonal Posted January 15, 2018 Author Share Posted January 15, 2018 There are only two JS files in the project at the moment, src/main.js and src/renderer.js. The former is the Electron entry point which creates the main window for src/index.html and the latter is require()'d from src/index.html inside the window. Phaser is loaded via a call to require('phaser') inside src/renderer.js. From what I can tell this is loading node_modules/phaser/dist/phaser.js from the project root that was built by doing npm install && npm run build from inside node_modules/phaser. NOTE: The build instructions listed in the docs didn't work for me because it complained that Webpack was missing (even if Webpack was installed globally), so I had to add the npm install step. Link to comment Share on other sites More sharing options...
float-diagonal Posted January 15, 2018 Author Share Posted January 15, 2018 4 hours ago, rich said: Those two settings are global defines that webpack uses during the build stage. Surely if you were packaging a game for Electron you'd build it first, then the Electron package would just be the build files + assets? I'm not sure when or if I will be using any build system for this project. I don't see any immediate benefit from it. It is being built on Electron from the ground up because it needs direct access to local system functionality (and possibly other Node features) and is not headed to the browser right now. All the JS files will be available locally and can be accessed using Node's built-in CommonJS support, and I don't need to use any language features other than those already supported by Node/Electron. (I am, however, using Typescript indirectly via the // @ts-check directive in plain JS files) Also, not to be rude, but I do not understand how bundling my project code with Phaser would resolve the issue of the names appearing in the compiled bundle. Wouldn't the same thing still be happening anyway? Link to comment Share on other sites More sharing options...
rich Posted January 15, 2018 Share Posted January 15, 2018 If you're not bundling the app before including it into Electron then it's almost certainly just trying to load the Phaser source files directly as a result of the call to require, and not the dist files, because the dist files don't have those globals in them. Here is what happens if you build a dist version of Phaser, all of the render calls that use the globals change from this: if (WEBGL_RENDERER) { renderWebGL = require('./BlitterWebGLRenderer'); } if (CANVAS_RENDERER) { renderCanvas = require('./BlitterCanvasRenderer'); } to this: if (true) { renderWebGL = __webpack_require__(1098); } if (true) { renderCanvas = __webpack_require__(1099); } (this is taken from dist/phaser.js) Which is why usually you'd build your app into a single bundle, and then only the bundle file (which is your game + Phaser + whatever else you need) is packaged by Electron. Hope that makes a bit more sense. Link to comment Share on other sites More sharing options...
float-diagonal Posted January 15, 2018 Author Share Posted January 15, 2018 7 minutes ago, rich said: If you're not bundling the app before including it into Electron then it's almost certainly just trying to load the Phaser source files directly as a result of the call to require, and not the dist files, because the dist files don't have those globals in them. Here is what happens if you build a dist version of Phaser, all of the render calls that use the globals change from this: if (WEBGL_RENDERER) { renderWebGL = require('./BlitterWebGLRenderer'); } if (CANVAS_RENDERER) { renderCanvas = require('./BlitterCanvasRenderer'); } to this: if (true) { renderWebGL = __webpack_require__(1098); } if (true) { renderCanvas = __webpack_require__(1099); } (this is taken from dist/phaser.js) Which is why usually you'd build your app into a single bundle, and then only the bundle file (which is your game + Phaser + whatever else you need) is packaged by Electron. Hope that makes a bit more sense. Yes, thanks! That does appear to be the case. This was a failure of my understanding of Node's import rules. I am not familiar with how packaging a stand-alone Electron app works generally. For the time being I seem to be able to be able to resolve the issue by calling require('phaser/dist/phaser'). Do you foresee that causing any problems or would it be better to just setup a command for building the package? Link to comment Share on other sites More sharing options...
rich Posted January 15, 2018 Share Posted January 15, 2018 If it works, go for it. In future however you'd likely want to use a custom bundle so you don't get everything + the kitchen sink included in your build, and only what you need. Link to comment Share on other sites More sharing options...
float-diagonal Posted January 15, 2018 Author Share Posted January 15, 2018 Thank you for your advice! I'll probably get to that point eventually. Also, I just wanted to say that you're totally awesome for running this project. I remember using your work from the early Flixel days and it's really inspiring to see how far you've come since then. Link to comment Share on other sites More sharing options...
rich Posted January 15, 2018 Share Posted January 15, 2018 Ahh Flixel... how time flies Link to comment Share on other sites More sharing options...
float-diagonal Posted January 25, 2018 Author Share Posted January 25, 2018 (edited) So, I ended up having to use Webpack after all and now I'm having a unique problem. Before incorporating Webpack, Phaser didn't seem to have any problems using XMLHttpRequest for loading assets from the render thread even though it was using local filesystem paths. After switching to using the electron-webpack package, however, the dev console is suddenly complaining that the "file://" protocol is not supported by XMLHttpRequest. This is of course is normal behavior, but it begs the question why it was working before when it isn't now. In any case I feel like the "correct" solution here would be to convince Phaser to use Node's built-in "fs" module to load files asynchronously. I've already tested that the data can be loaded from the rendering thread this way, so now I'm trying to determine if there is a way to override the asset loader with a custom version that uses fs. (I'm going through dev logs, examples, and source code looking for clues.) Edited January 25, 2018 by float-diagonal Corrected "webpack-electron" to "electron-webpack" Link to comment Share on other sites More sharing options...
float-diagonal Posted January 26, 2018 Author Share Posted January 26, 2018 I was unable to find a way to use create and properly install a custom loader class, so I had to settle for a monkey-patch. It tricks the standard loader into using Node's fs module when it tries to use XHR. It's definitely a fragile and sub-optimal solution but I needed to move on to other problems. The XHR wrapper: fs-xml-http-request.js To use it, you can do this: import Phaser from 'phaser'; import FSXHR from './fs-xml-http-request'; // Monkey-patches LoaderPlugin to use fs.readFile() when it tries to perform XHR FSXHR.install(Phaser.Loader.LoaderPlugin.prototype, 'processLoadQueue'); const game = new Phaser.Game({ ... scene: { preload() { // This will end up loading a local file this.load.image('foo', 'C:\\Data\\foo.png'); } ... } }); Link to comment Share on other sites More sharing options...
Recommended Posts