20
\$\begingroup\$

I can put the HTML and JavaScript together in the same .html file, but the images need to be separate files. The only solution that comes to my mind is to give to the user a .zip folder.

This is not pretty though... How else can I do this?

\$\endgroup\$
  • 8
    \$\begingroup\$ The "standard" isn't to make JS games downloadable; they only work in a browser. There may be some obscure way to do it, but frankly why force it: use the right tool for the job. \$\endgroup\$ – jhocking Sep 29 '14 at 12:39
20
\$\begingroup\$

You can embed images in the HTML document using the dataurl-syntax which allows to put the base64 representation of the binary image data as the src-attribute of an image. This also works on any other kind of media file.

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9EFBAoYMhVvMQIAAAAtSURBVHicY/z//z8DHoBH+v///yy4FDEyMjIwMDDhM3lgpaEuh7gTEzDiDxYA9HEPDF90e5YAAAAASUVORK5CYII=">

When you use CSS stylesheets, you can create these completely procedural in JavaScript.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ of course base64 takes up more space, quadrupling the file size... \$\endgroup\$ – Tobias Kienzler Sep 30 '14 at 10:57
  • 10
    \$\begingroup\$ @TobiasKienzler: 64*4=256 does not mean it takes 4 times as many data to encode a single byte, but that you only use 6 bits (2**6=64) out of every 8 in each byte. That means that it takes 4 bytes to encode 3 bytes, which gives a 33% increase of size (not counting padding when necessary). Hardly quadrupling. The only case in which data size is quadrupled is when encoding a single byte, which requires 2 data bytes plus 2 padding bytes. \$\endgroup\$ – Panda Pajama Sep 30 '14 at 11:19
  • 2
    \$\begingroup\$ @PandaPajama My bad, I intended to say "increases by a quarter" (due to the 2/8 = 1/4 wasted bits). Though obviously I made a mistake there anyway, the 33% you derive are correct. Still, it is an overhead, also "famous" from email attachments \$\endgroup\$ – Tobias Kienzler Sep 30 '14 at 12:01
  • 1
    \$\begingroup\$ Will that base 64 inline encoding work for other resources like .wav, .ogg, .m4a, and in general any file? \$\endgroup\$ – DrZ214 Dec 23 '16 at 9:17
  • 1
    \$\begingroup\$ @DrZ214 I haven't tried, but AFAIK it should work anywhere where an URL works. \$\endgroup\$ – Philipp Dec 23 '16 at 9:21
30
\$\begingroup\$

Just putting all the files into a .zip file isn't a viable solution because most web-applications need a web-server so that they can access resources via HTTP-requests. On some systems you can access files via the file:// URI-scheme, but that's not guaranteed to work everywhere because of security-reasons and will fail for things such as AJAX requests.

It might work for a very simple app where you have most resources inline but this really isn't the approach I'd recommend to anybody. There are alternatives though, such as:

Build a native application

You can package your web-application as a native app using Node-Webkit. You can even use this to add native desktop features (such as local save-games) to your game.

This isn't a "package and done" approach though.. you'll probably have to rewrite portions of your application and write different loaders (eg. with a desktop app you'll rather load the files via filesystem, whereas you use HTTP-Requests in a browser/online-game).

Use HTML5 features to allow offline access of your app

If your primary goal is to allow the player to play your game offline, then you can also use application-cache to allow offline access of your app. This is a feature that works in most modern browsers. The added benefit is that the user doesn't have to download anything and can just use a bookmark to play your game even when offline.

For resources that are being loaded asynchronously (AJAX) you'll also have to implement separate loading mechanisms. You could make use of local-storage to save these resources for offline use.

|improve this answer|||||
\$\endgroup\$
  • 2
    \$\begingroup\$ Node-Webkit is pretty large, and you'll end up with something like 60MB for a "hello world" JS game if you include it. \$\endgroup\$ – ashes999 Sep 29 '14 at 19:05
  • 1
    \$\begingroup\$ This is the right answer if your application is even remotely complicated. \$\endgroup\$ – Vaughan Hilts Sep 29 '14 at 19:09
  • 1
    \$\begingroup\$ @ashes999 I agree with you, yet 60MB is still pretty small for a desktop app nowadays. A lot of the general-purpose frameworks create some file-size overhead (take Unity as a prominent example). With ever increasing storage space, convenience wins over file-size ;) \$\endgroup\$ – bummzack Sep 29 '14 at 19:58
  • 2
    \$\begingroup\$ @bummzack I don't disagree. It's just depressing to take a ~100kb JS game and see it become 60MB, before you add any art or audio. Hopefully someone will come up with a better way. +1 btw \$\endgroup\$ – ashes999 Sep 29 '14 at 21:13
  • 1
    \$\begingroup\$ While there is a lot of useful info in this answer, the lead sentence is plain wrong. You can put game data in JavaScript files, modern browsers should be able to handle at least a few MB of JavaScript, and as long as you don't try to read the image data from a canvas there is nothing wrong with using image files either. Last time I checked, all the modern browsers allow the file:/// protocol to access localStorage, which works for saving. It will scale to do anything one can do in an HTML game, except online play. \$\endgroup\$ – aaaaaaaaaaaa Sep 30 '14 at 16:12
7
\$\begingroup\$

For a Chrome-based solution to make the game run offline and enjoy some native functionality, you can consider making a Chrome App.

This way, you can distribute it in Chrome Web Store for added visibility, you can enjoy some powerful APIs, and make it look more like a standalone app.

The downside is, of course, requiring Chrome.

|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ Firefox (and Firefos OS) has OpenWebApps (developer.mozilla.org/en/Apps/Quickstart/Build/…) which is similar to this: the web application id downloaded as installed as an application. Both solutions should converge to a common standard: html5doctor.com/web-manifest-specification. See as well: code.google.com/p/chromium/issues/detail?id=366145 \$\endgroup\$ – ysdx Sep 30 '14 at 12:53
  • \$\begingroup\$ @ysdx The converging standard you mention is for what Chrome calls "hosted apps", as opposed to a true self-contained, downloadable app, also called "packaged app". Same terminology applies to Firefox. Unfortunately, packaged apps are architecturally very different and unlikely to converge. \$\endgroup\$ – Xan Sep 30 '14 at 12:57
  • \$\begingroup\$ @Xan what is a packaged app? Are both 'hosted' and 'packaged' apps available in the Firefox and Chrome app stores? \$\endgroup\$ – Qsigma Sep 30 '14 at 20:51
  • 1
    \$\begingroup\$ @Qsigma A packaged app is a mostly self-contained HTML5 app with access to powerful APIs like local filesystem access; it's "packaged" because it contains it own resources in a download. A "hosted" app is basically a link to a website with some metadata. Think of it as a cross between a shortcut and a bookmark. I can't tell about Firefox store, but the documentation from the first comment describes how to write packaged apps. \$\endgroup\$ – Xan Sep 30 '14 at 21:18
  • \$\begingroup\$ What's the difference between clicking and having the app run offline without further downloads with more quotas and permissions and clicking and having the app run without further downloads with more quotas and permissions? While technically they have differences, those differences are superficial, to the user there's no difference. Packaging a properly designed hosted app should be quite trivial with the right manifests. The downside with packaged app is that it cannot update itself without an external package manager, with hosted app the browser itself is the package manager. \$\endgroup\$ – Lie Ryan Oct 1 '14 at 1:15
0
\$\begingroup\$

Well it depends on how much work you really want to put into it. Using the current set of Web APIs you can:

  • Create a Progressive Web App (PWA) (Sadly PWAs are only for mobile phones and Chrome OS, but I've heard that Chrome for Desktop will soon have support for it soon. For now, it hides behind a flag) since the old Application Cache is now deprecated
  • Convert everything into text (images and audio). And either encourage the user to save the web page as is (using Cmd+S or Ctrl+S in browser) or cache the page as a PWA. Just know that, on mobile, dataURIs don't perform very well.
  • You can create a Chrome App, but that won't work on any Chrome version that isn't running on Chrome OS. This means it's better for you to create an extension instead
  • Most games come under 10 MB, with that said you can cache all your game's data into the local storage. How you do this is up to you: you can do the above (convert everything to text), use Blob api, etc. Though I highly discourage this, as some mobile phones could clear your whole game from memory. Which means you have to check that everything is ok (if your code is still in memory), which means longer load times and also could crash the user phone. If you do choose to go down this path though, you'll definitely benefit from using LocalForage
  • Using Electron or NW.js, you can use your html, css, and js to create a desktop app. Similar methods can be used to create mobile apps as well (using something like Cordova or a Cordova dependant like PhoneGap). You'd do this and allow the user to download the full game if they wanted to.
  • If you still want to continue with a zip file, checkout JSZip. I have no idea how you can use it, but I'm sure someone can come up with a good idea (maybe zip your file and then convert the binary data to string and place it inline into the html).
  • This weird hack allows you to load any textual data as something known as a data block. This is just another tool you can use to embed assets into an html file.
|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.