How to embed an HTML5 Godot export into a React app

Viewed 55

I'm going to explain the situation:

These are the files that I end up with after exporting my Godot game in HTML5: export files

The most relevant file is "WYS 0.1.js", because is where all the other useful files, like the .pck one, are imported and used to execute the application in the HTML file.

In short, if I understand it well, it's a very huge file where the scope is to create a class named "Engine" from which is possible to execute some methods like startEngine() useful to start the game, following specific configurations that are passed as a parameter of the class. If you want to check this file here is the link: https://drive.google.com/file/d/12JYPd5ItYFFelcJcpIX3eU7kr42Y36up/view?usp=sharing (Just skip the initial wall of text to see some code that makes sense).

How the HTML file execute the game?

Simply with a <script> tag with src attribute pointing to the "WYS 0.1.js" path and another <script> tag with some inline JavaScript that create a new instance of the class Engine and deals to correctly load the game and animate the loading of the game (Moving the inline javascript to a separate js file and typing the correct path in the src attribute won't break the execution).

The game, to be correctly executed, needs to be on a server. So, I place myself in the export folder with the command line and create a simple server with this Python command: python -m http.server 8080, and everything works as it should. Just to be clear.

React Part:

After created the app with the npx create-react-app name-app command, my first attempt was to creat a React Component importing the "WYS 0.1.js" and the inline JS code moved in a separate file and, from that React Component, use the Engine to load and start the game correctly (Engine accessible by adding export before the const Engine declaration). But, what I obtained is a compile error reporting a lot of undefined variables and other stuff like that:

Line 10:990: Unexpected use of 'self'

Line 10:74354: Expected an assignment or function call and instead saw an expression

Line 10:131511: 'res' is not defined

Line 10:115986 :Unexpected use of 'addEventListener'

As you can see, these errors are located principally in the Module variable (the wall of text) and, outside of it, only a certain "define" that is placed just under the wall of text.

I also tried to simply add the <script> tags in the index.html file generated by the npx create-react-app command, but it doesn't work at all.

It's not clear to my mind why something is defined in the HTML part and suddenly became undefined when moved in a ReactApp.

Thanks in advance to everyone who will help me, also because information on this topic is very scarce.

1 Answers

I managed to execute the game in a ReactApp, I don't know if it is the best way to do it but it seems to work. here's my solution:

The godot export files have to be placed in the public folder, NOT IN A SUB FOLDER IN THE PUBLIC FOLDER, the main JS file, "WYS 0.1.js", has to be in the same directory of the index.html. Some files can be exluded, but the "WYS 0.1.js", .wasm and the .pck have to be in that directory and, even if everything seems to work without it, I would put the .worklet.js as well.

That said, to execute the game you need to copy the <script> tags in the "WYS 0.1.js" and insert them into the index.html file, generated by npx create-react-app name-app command. In truth, in this state you need to copy the entire <body> tag and put it into the index.html, because the inline JavaScript code, in the second <script> tag, needs to access to some elements in the <body> to animate the loading and to execute the game in the <canvas> tag.

Therefore, we'll jump to the reusability part now.

To enclose the execution of the game in a ReactComponent that i can render at any moment and place I want I, firstly, moved the inline JS in a separate JS file, init_godot_game.js, and imported it in the same <script> tag putting the path in the src attribute. Then, i changed a bit this code moved in this new JS file, just putting it in a function that i can call: init_game(), for example.

Now, for the React part, just create a new component and make it return all the body content of the "WYS 0.1.html" file that we pasted in the index.html, content that now you can remove from there (before starting it, you have to change a bit this code so that it can fit the JSX syntax).

From here, to execute the game you just have to add a new <script> tag int the body with calling the init_game() function, like this:

let script = document.createElement("script");
script.type = "text/javascript"
script.innerHTML = "init_game()"
document.body.appendChild(script)

You can put this piece of code in a useEffect(() => { ... }, []) or in a function that you can invoke when you want. I tried to expose the init_game() function with an export and to import it in the ReactComponent with: import { init_game } from "path", but it's not possible to import stuff outside the src folder. Moving the init_godot_game.js in the src folder will cause similar errors of my previous approach. It appears that these files must be in the same path as index.html.

Anyway, these part of the reusability and even of how you want to load the game, is pretty up to you. You can customize it as you wish, if I get it well, only a few things are needed:

  • you have to execute the method engine.startGame(), in the JS file that deals to load and initialize the game, in my example: init_godot_game(). The rest is marginal.
  • And in the ReactApp, in the component or wherever you want to run your game, must be the <canvas id="canvas"> tag, because is what the main JS file wants as the container of the the game.

Tell me what you think about it, especially if you have better solutions :)

Related