Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loader can't load from file:// [$50] #3464

Closed
sftsk opened this issue Mar 28, 2018 · 25 comments · Fixed by #3864
Closed

Loader can't load from file:// [$50] #3464

sftsk opened this issue Mar 28, 2018 · 25 comments · Fixed by #3864

Comments

@sftsk
Copy link
Contributor

sftsk commented Mar 28, 2018

This Issue is about a bug in the API (v3.3.0):

I have tried wrapping a Phaser app in Cordova/ React Native.
It mostly worked but there are issues with loading files. Neither images nor json can be loaded, they fail without a proper error.

After close debugging I noticed that the "Request Type" comes up as XHR whereas with Phaser 2.x it's image/ json like it should be.

I have set up a very basic example textures/sprite sheet.js and a more complex project, both fail.

Could this be related to #2670 or #2485? Did this fix get lost in 3.x?

Any help is very appreciated, did anybody manage to wrap a Phaser 3 project with Cordova?

Cheers!

p.s.: www.zip the content of www within the Cordova app

screen shot 2018-03-28 at 7 22 35

UPDATE 29.03:
I have looked into this more. It seems like the issue has to do with the Phaser 3 loader not being able loading resources from file://. When I open the basic texture examples from Phaser 2 without being served from a server they work just fine, the Phaser 3 ones don't. Seems the loader does something differently so CORS becomes an issue.


There is a $50 open bounty on this issue. Add to the bounty at Bountysource.

@sftsk sftsk changed the title XHR issues with Loader in Cordova/ React Native Loader can't load from file:// Mar 29, 2018
@nickav
Copy link
Contributor

nickav commented Mar 29, 2018

Hello, I am able to load from file:// resources just fine in electron. Perhaps this is an issue with the browser that your game is running in?

@Mikurox
Copy link

Mikurox commented Apr 2, 2018

I'm having the same issue on my application that I tried to run under Cordova/PhoneGap.
The images do not show up, that's a big blocker for Mobile development.

@nickav
Copy link
Contributor

nickav commented Apr 2, 2018

@Mikurox have you tried moving your assets in a folder relative to your index.html and instead of a file:// path, just using relative imports? E.g. ./images/player.png (if images is a folder in the same directory as your game)

@Mikurox
Copy link

Mikurox commented Apr 2, 2018

It works when I use images in the index.html or reference them in css file.
The issue I'm seeing is that they are not loaded (I see green lines) when I try to load an image in "preload" and use it in "create" functions, e.g.

this.load.image('starfield', 'assets/images/starfield.png');
...
this.bg = this.add.tileSprite(0, 0, this.game.width, this.game.height, 'starfield');

It's working when using the "browser" platform but not "android"

@sftsk
Copy link
Contributor Author

sftsk commented Apr 3, 2018

Exactly what @Mikurox said. Using the built-in Phaser function this.load.image('starfield', 'assets/images/starfield.png') it depends which "server" is serving the files.
When using a server that deals with proper serving of files all is fine, when just opening the .html in the browser although using relative path the images don't load.

The same issue is happening with Cordova apps as it seems it does not serve the files as a "server" but just accesses them through their path from the filesystem.
Phaser 2.x didn't have an issue but something must have changed in the Phaser 3.x Loader.

@photonstorm photonstorm changed the title Loader can't load from file:// Loader can't load from file:// [$50] Apr 3, 2018
@photonstorm
Copy link
Collaborator

Yes, the v3 loader uses xhr for all files to get per-byte download feedback, per-file. I have posted a bounty on this issue as I don't have Cordova / PhoneGap set-up, so it would take a while to debug here.

@Saturate
Copy link

Saturate commented Apr 4, 2018

I might be able to take a look at this, this weekend. If you provide a example where this happens I'll save some time and might be able to do it :-)

@Huararanga
Copy link

I've tested it just in few platforms but a possible solution is to use url-loader with blobs. In your webpack.config.js
{ test: /\.(png|jpg)$/, use: [ { loader: 'url-loader', options: { limit: 0, }, }, ], }

Then import of your static file will return b64 string import sprite1png from '../../../assets/sprite1.png';
This needs to be further converted to blobs to create the link;
`const b64toBlobUrl = (data, sliceSize = 512) => {
const parts = data.split(',');
const b64Data = parts[1];
const typeAndBase = parts[0].split('data:')[1];
const contentType = typeAndBase.split(';')[0];
const byteCharacters = atob(b64Data);
const byteArrays = [];

for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
	const slice = byteCharacters.slice(offset, offset + sliceSize);

	const byteNumbers = new Array(slice.length);
	for (let i = 0; i < slice.length; i++) {
		byteNumbers[i] = slice.charCodeAt(i);
	}

	const byteArray = new Uint8Array(byteNumbers);

	byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: contentType });
return URL.createObjectURL(blob);

};`

and use it this.load.image('sprite1', b64toBlobUrl(sprite1png))

@sftsk
Copy link
Contributor Author

sftsk commented Apr 6, 2018

Cheers for all the feeback and ideas. Will look into this more after the weekend!

@Saturate just try opening a basic Phaser 3 example directly from a folder in your browser. The error will happen as it can’t load the files through xhr. Use Chrome so you get an error message in the console.

@rhg1968
Copy link

rhg1968 commented Apr 6, 2018

Not sure this helps. I haven't had a chance to try it, but there is a tutorial on line.

https://gamedevacademy.org/creating-mobile-games-with-phaser-3-and-cordova/

@rhg1968
Copy link

rhg1968 commented Apr 7, 2018

Never mind, I tried the tutorial and the graphics don't show up

@ghybs
Copy link

ghybs commented Apr 9, 2018

Hi,

@sftsk: incompatibility of Phaser 3 with direct loading through file:// protocol looks to be a design choice, as explained in the Getting Started tutorial part 1: https://phaser.io/tutorials/getting-started-phaser3

As described the solution for desktop browsers is to serve files through a server, which is a very standard practice nowadays, even for development.

As for Cordova in iOS, which is OP's described situation, the above solution is more complex to implement, but it is still a known and widely used practice as well.
There are many Cordova plugins that patch the Webview, for example:

While @Huararanga's workaround is probably valid, a drawback is that all files are now base64 strings in your code, making it much heavier.
Furthermore, browsers and Webview cache files loaded the standard way, so rendering multiple instances of them is no problem. On the contrary, performance degrades when using base64 data multiple times.

Hope this helps.

@photonstorm
Copy link
Collaborator

As I mentioned above v3 uses xhr for all files, including images. v2 used the Image tag itself to load them, however it still used xhr for all json, xml, etc. I believe under Cordova in v2 you were still able to load things like texture atlases and bitmap fonts without any issue, so xhr must have been working to some extent back then? Which makes me wonder if it's actually something else causing this.

@sftsk
Copy link
Contributor Author

sftsk commented Apr 9, 2018

I have finally had time looking into this and got into the same solution as proposed by @ghybs .

Installing https://github.com/ionic-team/cordova-plugin-ionic-webview with Cordova fixes the issue. This will only be a fix for iOS, although probably for Android exists something similar.

I don't think there is anything to be done within Phaser as this XHR Cross Origin policy seems to be a limitation that can't be easily worked around on mobile. Chrome has a flag --disable-web-security that will allow the requests, not sure if that could be an option for Android.

Anyway, thanks for all the help, issue can be closed from my point of view. Perhaps add some instructions to the manual of needing the mentioned plugin when wrapping an app with Cordova.

@Mikurox
Copy link

Mikurox commented Apr 9, 2018

Hi guys,
Thanks for investigating this, I guess if it's not a pure Phaser problem, then this can be closed.
However, I would believe that we need an "official" way of dealing with this, since we will not be the only ones having this issue. A Cordova section in tutorials or somewhere exposed should clarify how Phaser can work with Android/iOS. There might be other "tweaks" to do for mobile development as well and having a dedicated section will greatly help everyone.

@rhg1968
Copy link

rhg1968 commented Apr 9, 2018

Just as little extra info. The demo I mentioned above works fine on android. Images/Atlas load and show properly on a galaxy s8. So this definitely appears to be a an iOS issue.

@Quinten
Copy link

Quinten commented Jul 21, 2018

Adding the cordova-plugin-ionic-webview as suggested by @ghybs and @sftsk worked for me.

At least it started loading my json file then. For the spritesheets to show up i had to change:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">

to:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content: blob:;">

In the cordova index.html. Adding the blob: in at the end.

Still need to add sound to my current project though. If i need to do anything special for that i'll post it here.

@PBMCube
Copy link

PBMCube commented Jul 26, 2018

Discovered this a couple of months ago. Does this help?

Phaser v3.x.x (20180322); WARNING ANTI-PATTERN REMOVED
// CORS: Remove anti-pattern!
// - https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
// - https://enable-cors.org/
// Avoid this anti-pattern of omitting the protocols schemes in script "src";
// Cross origin requests are only supported for protocol schemes:
// http, data, chrome, chrome-extension, https.
// - anti-pattern is:
// <script src="//cdn.jsdelivr.net/npm/phaser@3.6.0/dist/phaser.min.js"></script>
- use this: <script src="https://cdn.jsdelivr.net/npm/phaser@3.10.1/dist/phaser.min.js"></script>

@photonstorm
Copy link
Collaborator

Can't see how this makes any difference tbh. All asset loading is done via a protocol.

@amidos2006
Copy link

I tried that plugin but it always through error in XCode when compiling "cordova-plugin-ionic-webview"

so I decided to try "cordova-plugin-wkwebview-file-xhr" instead, it worked but it has weird thing about splashing the background with assets and any graphics library rect fill not working correctly (flickering).

I even tried adding "cordova-plugin-wkwebview-engine" as suggested by some websites but still the same problem

Attached some pics
http://akhalifa.com/elimination/error_1.jpg
http://akhalifa.com/elimination/error_2.jpg

@chenfanggm
Copy link
Contributor

I was very excited to start a project that uses phaser3-typescript-webpack-cordova. Everything works perfectly until I start testing the cordova with the build package. The phaser assets loader isn't designed for loading assets from IOS. Really hope there's an official instruction of how to load assets from Cordova wrapped app. Thanks.

@amidos2006
Copy link

These are some of the solutions I stumbled upon, hope it is helpful:
https://phaser.discourse.group/t/troubleshoot-cordova-phaser-3-the-preloader-scene-is-being-refreshed/625/2
It is not still 100% solved. I will be happy if you found a solution to the sound problem.

@photonstorm
Copy link
Collaborator

I've just merged in a PR which should (?!) resolve this, so would be happy if someone using Cordova on iOS could build from master and test it please.

@gamer496
Copy link

Doesn't work, But there is a difference of behavior in iOS and Android. In iOS:
Game loads and is playable it's just that img doesn't load.(also maybe audio didn't test for that)
For android:
Nothing loads. It just serves a blank screen.

@h3543
Copy link

h3543 commented Jun 9, 2020

Is there any update about this problem?
I am using static files in my android project but my Phaser game's images doesnt shown.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.